bashkit 0.3.2 → 0.4.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/AGENTS.md CHANGED
@@ -98,12 +98,14 @@ This is useful for:
98
98
 
99
99
  | Tool | Purpose | Key Inputs |
100
100
  |------|---------|------------|
101
- | `Bash` | Execute shell commands | `command`, `timeout?`, `description?` |
102
- | `Read` | Read files or list directories | `file_path`, `offset?`, `limit?` |
101
+ | `Bash` | Execute shell commands | `command`, `timeout`, `description` |
102
+ | `Read` | Read files or list directories | `file_path`, `offset`, `limit` |
103
103
  | `Write` | Create/overwrite files | `file_path`, `content` |
104
- | `Edit` | Replace strings in files | `file_path`, `old_string`, `new_string`, `replace_all?` |
105
- | `Glob` | Find files by pattern | `pattern`, `path?` |
106
- | `Grep` | Search file contents | `pattern`, `path?`, `output_mode?`, `-i?`, `-C?` |
104
+ | `Edit` | Replace strings in files | `file_path`, `old_string`, `new_string`, `replace_all` |
105
+ | `Glob` | Find files by pattern | `pattern`, `path` |
106
+ | `Grep` | Search file contents | `pattern`, `path`, `output_mode`, `-i`, `-C` |
107
+
108
+ > **Note on nullable types:** Optional parameters use `T | null` (not `T | undefined`) for OpenAI structured outputs compatibility. AI models should send explicit `null` for parameters they don't want to set. This works with both OpenAI and Anthropic models.
107
109
 
108
110
  ### Optional Tools (via config)
109
111
 
package/README.md CHANGED
@@ -19,6 +19,32 @@ Agentic coding tools for Vercel AI SDK. Give AI agents the ability to execute co
19
19
  - Search the web and fetch URLs
20
20
  - Load skills on-demand via the [Agent Skills](https://agentskills.io) standard
21
21
 
22
+ ## Breaking Changes in v0.4.0
23
+
24
+ ### Nullable Types for OpenAI Compatibility
25
+
26
+ All optional tool parameters now use `.nullable()` instead of `.optional()` in Zod schemas. This change enables compatibility with OpenAI's structured outputs, which require all properties to be in the `required` array.
27
+
28
+ **What changed:**
29
+ - Tool input types changed from `T | undefined` to `T | null`
30
+ - Exported interfaces (`QuestionOption`, `StructuredQuestion`) use `T | null`
31
+ - AI models will send explicit `null` values instead of omitting properties
32
+
33
+ **Migration:**
34
+ ```typescript
35
+ // Before v0.4.0
36
+ const option: QuestionOption = { label: "test", description: undefined };
37
+
38
+ // v0.4.0+
39
+ const option: QuestionOption = { label: "test", description: null };
40
+ ```
41
+
42
+ **Why this matters:**
43
+ - Works with both OpenAI and Anthropic models
44
+ - OpenAI structured outputs require nullable (not optional) fields
45
+ - Anthropic/Claude handles nullable fields correctly
46
+ - The `??` operator handles both `null` and `undefined`, so runtime behavior is unchanged
47
+
22
48
  ## Installation
23
49
 
24
50
  ```bash
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { anthropicPromptCacheMiddleware, anthropicPromptCacheMiddlewareV2, } fro
3
3
  export type { E2BSandboxConfig, LocalSandboxConfig, VercelSandboxConfig, } from "./sandbox";
4
4
  export { createE2BSandbox, createLocalSandbox, createVercelSandbox, ensureSandboxTools, } from "./sandbox";
5
5
  export type { ExecOptions, ExecResult, Sandbox } from "./sandbox/interface";
6
- export type { AgentToolsResult, AskUserError, AskUserOutput, AskUserResponseHandler, BashError, BashOutput, EditError, EditOutput, EnterPlanModeError, EnterPlanModeOutput, ExitPlanModeError, ExitPlanModeOutput, PlanModeState, GlobError, GlobOutput, GrepContentOutput, GrepCountOutput, GrepError, GrepFilesOutput, GrepMatch, GrepOutput, ReadDirectoryOutput, ReadError, ReadOutput, ReadTextOutput, SkillError, SkillOutput, SkillToolConfig, SubagentEventData, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, TodoItem, TodoState, TodoWriteError, TodoWriteOutput, WebFetchError, WebFetchOutput, WebSearchError, WebSearchOutput, WebSearchResult, WriteError, WriteOutput, } from "./tools";
6
+ export type { AgentToolsResult, AskUserError, AskUserOutput, AskUserResponseHandler, QuestionOption, StructuredQuestion, BashError, BashOutput, EditError, EditOutput, EnterPlanModeError, EnterPlanModeOutput, ExitPlanModeError, ExitPlanModeOutput, PlanModeState, GlobError, GlobOutput, GrepContentOutput, GrepCountOutput, GrepError, GrepFilesOutput, GrepMatch, GrepOutput, ReadDirectoryOutput, ReadError, ReadOutput, ReadTextOutput, SkillError, SkillOutput, SkillToolConfig, SubagentEventData, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, TodoItem, TodoState, TodoWriteError, TodoWriteOutput, WebFetchError, WebFetchOutput, WebSearchError, WebSearchOutput, WebSearchResult, WriteError, WriteOutput, } from "./tools";
7
7
  export { createAgentTools, createAskUserTool, createBashTool, createEditTool, createEnterPlanModeTool, createExitPlanModeTool, createGlobTool, createGrepTool, createReadTool, createSkillTool, createTaskTool, createTodoWriteTool, createWebFetchTool, createWebSearchTool, createWriteTool, } from "./tools";
8
8
  export type { AgentConfig, AskUserConfig, CacheConfig, SkillConfig, ToolConfig, WebFetchConfig, WebSearchConfig, } from "./types";
9
9
  export { DEFAULT_CONFIG } from "./types";
package/dist/index.js CHANGED
@@ -795,17 +795,17 @@ function reinitDebugMode() {
795
795
  // src/tools/ask-user.ts
796
796
  var questionOptionSchema = z.object({
797
797
  label: z.string().describe("The display text for this option. Should be concise (1-5 words). Add '(Recommended)' suffix for suggested options."),
798
- description: z.string().optional().describe("Explanation of what this option means or its implications.")
798
+ description: z.string().nullable().default(null).describe("Explanation of what this option means or its implications.")
799
799
  });
800
800
  var structuredQuestionSchema = z.object({
801
- header: z.string().optional().describe("Very short label displayed as a chip/tag (max 12 chars). Examples: 'Auth method', 'Library', 'Approach'."),
801
+ header: z.string().nullable().default(null).describe("Very short label displayed as a chip/tag (max 12 chars). Examples: 'Auth method', 'Library', 'Approach'."),
802
802
  question: z.string().describe("The complete question to ask the user. Should be clear and specific."),
803
- options: z.array(questionOptionSchema).min(2).max(4).optional().describe("Available choices for this question. 2-4 options. An 'Other' option is automatically available to users."),
804
- multiSelect: z.boolean().optional().describe("Set to true to allow the user to select multiple options instead of just one.")
803
+ options: z.array(questionOptionSchema).min(2).max(4).nullable().default(null).describe("Available choices for this question. 2-4 options. An 'Other' option is automatically available to users."),
804
+ multiSelect: z.boolean().nullable().default(null).describe("Set to true to allow the user to select multiple options instead of just one.")
805
805
  });
806
806
  var askUserInputSchema = z.object({
807
- question: z.string().optional().describe("Simple question string (for backward compatibility). Use 'questions' for structured multi-choice."),
808
- questions: z.array(structuredQuestionSchema).min(1).max(4).optional().describe("Structured questions with options (1-4 questions).")
807
+ question: z.string().nullable().default(null).describe("Simple question string (for backward compatibility). Use 'questions' for structured multi-choice."),
808
+ questions: z.array(structuredQuestionSchema).min(1).max(4).nullable().default(null).describe("Structured questions with options (1-4 questions).")
809
809
  });
810
810
  var ASK_USER_DESCRIPTION = `Use this tool when you need to ask the user questions during execution.
811
811
 
@@ -930,9 +930,9 @@ import { tool as tool2, zodSchema as zodSchema2 } from "ai";
930
930
  import { z as z2 } from "zod";
931
931
  var bashInputSchema = z2.object({
932
932
  command: z2.string().describe("The command to execute"),
933
- timeout: z2.number().optional().describe("Optional timeout in milliseconds (max 600000)"),
934
- description: z2.string().optional().describe("Clear, concise description of what this command does in 5-10 words"),
935
- run_in_background: z2.boolean().optional().describe("Set to true to run this command in the background")
933
+ timeout: z2.number().nullable().default(null).describe("Optional timeout in milliseconds (max 600000)"),
934
+ description: z2.string().nullable().default(null).describe("Clear, concise description of what this command does in 5-10 words"),
935
+ run_in_background: z2.boolean().nullable().default(null).describe("Set to true to run this command in the background")
936
936
  });
937
937
  var BASH_DESCRIPTION = `Executes a bash command in a persistent shell session with optional timeout.
938
938
 
@@ -1049,7 +1049,7 @@ var editInputSchema = z3.object({
1049
1049
  file_path: z3.string().describe("The absolute path to the file to modify"),
1050
1050
  old_string: z3.string().describe("The text to replace"),
1051
1051
  new_string: z3.string().describe("The text to replace it with (must be different from old_string)"),
1052
- replace_all: z3.boolean().optional().describe("Replace all occurrences of old_string (default false)")
1052
+ replace_all: z3.boolean().nullable().default(null).describe("Replace all occurrences of old_string (default false)")
1053
1053
  });
1054
1054
  var EDIT_DESCRIPTION = `Performs exact string replacements in files.
1055
1055
 
@@ -1079,8 +1079,9 @@ function createEditTool(sandbox, config) {
1079
1079
  file_path,
1080
1080
  old_string,
1081
1081
  new_string,
1082
- replace_all = false
1082
+ replace_all: rawReplaceAll
1083
1083
  }) => {
1084
+ const replace_all = rawReplaceAll ?? false;
1084
1085
  const startTime = performance.now();
1085
1086
  const debugId = isDebugEnabled() ? debugStart("edit", {
1086
1087
  file_path,
@@ -1330,7 +1331,7 @@ import { tool as tool6, zodSchema as zodSchema6 } from "ai";
1330
1331
  import { z as z6 } from "zod";
1331
1332
  var globInputSchema = z6.object({
1332
1333
  pattern: z6.string().describe('Glob pattern to match files (e.g., "**/*.ts", "src/**/*.js", "*.md")'),
1333
- path: z6.string().optional().describe("Directory to search in (defaults to working directory)")
1334
+ path: z6.string().nullable().default(null).describe("Directory to search in (defaults to working directory)")
1334
1335
  });
1335
1336
  var GLOB_DESCRIPTION = `
1336
1337
  - Fast file pattern matching tool that works with any codebase size
@@ -1351,7 +1352,7 @@ function createGlobTool(sandbox, config) {
1351
1352
  pattern,
1352
1353
  path
1353
1354
  }) => {
1354
- const searchPath = path || ".";
1355
+ const searchPath = path ?? ".";
1355
1356
  const startTime = performance.now();
1356
1357
  const debugId = isDebugEnabled() ? debugStart("glob", { pattern, path: searchPath }) : "";
1357
1358
  if (config?.allowedPaths) {
@@ -1403,18 +1404,18 @@ import { tool as tool7, zodSchema as zodSchema7 } from "ai";
1403
1404
  import { z as z7 } from "zod";
1404
1405
  var grepInputSchema = z7.object({
1405
1406
  pattern: z7.string().describe("The regular expression pattern to search for in file contents"),
1406
- path: z7.string().optional().describe("File or directory to search in (defaults to cwd)"),
1407
- glob: z7.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}")'),
1408
- type: z7.string().optional().describe('File type to search (e.g. "js", "py", "rust")'),
1409
- output_mode: z7.enum(["content", "files_with_matches", "count"]).optional().describe('Output mode: "content" shows matching lines, "files_with_matches" shows file paths (default), "count" shows match counts'),
1410
- "-i": z7.boolean().optional().describe("Case insensitive search"),
1411
- "-n": z7.boolean().optional().describe("Show line numbers in output. Requires output_mode: 'content'. Defaults to true."),
1412
- "-B": z7.number().optional().describe("Number of lines to show before each match. Requires output_mode: 'content'."),
1413
- "-A": z7.number().optional().describe("Number of lines to show after each match. Requires output_mode: 'content'."),
1414
- "-C": z7.number().optional().describe("Number of lines to show before and after each match. Requires output_mode: 'content'."),
1415
- head_limit: z7.number().optional().describe("Limit output to first N lines/entries. Works across all output modes. Defaults to 0 (unlimited)."),
1416
- offset: z7.number().optional().describe("Skip first N lines/entries before applying head_limit. Works across all output modes. Defaults to 0."),
1417
- multiline: z7.boolean().optional().describe("Enable multiline mode where patterns can span lines. Default: false.")
1407
+ path: z7.string().nullable().default(null).describe("File or directory to search in (defaults to cwd)"),
1408
+ glob: z7.string().nullable().default(null).describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}")'),
1409
+ type: z7.string().nullable().default(null).describe('File type to search (e.g. "js", "py", "rust")'),
1410
+ output_mode: z7.enum(["content", "files_with_matches", "count"]).nullable().default(null).describe('Output mode: "content" shows matching lines, "files_with_matches" shows file paths (default), "count" shows match counts'),
1411
+ "-i": z7.boolean().nullable().default(null).describe("Case insensitive search"),
1412
+ "-n": z7.boolean().nullable().default(null).describe("Show line numbers in output. Requires output_mode: 'content'. Defaults to true."),
1413
+ "-B": z7.number().nullable().default(null).describe("Number of lines to show before each match. Requires output_mode: 'content'."),
1414
+ "-A": z7.number().nullable().default(null).describe("Number of lines to show after each match. Requires output_mode: 'content'."),
1415
+ "-C": z7.number().nullable().default(null).describe("Number of lines to show before and after each match. Requires output_mode: 'content'."),
1416
+ head_limit: z7.number().nullable().default(null).describe("Limit output to first N lines/entries. Works across all output modes. Defaults to 0 (unlimited)."),
1417
+ offset: z7.number().nullable().default(null).describe("Skip first N lines/entries before applying head_limit. Works across all output modes. Defaults to 0."),
1418
+ multiline: z7.boolean().nullable().default(null).describe("Enable multiline mode where patterns can span lines. Default: false.")
1418
1419
  });
1419
1420
  var GREP_DESCRIPTION = `A powerful content search tool built on ripgrep with regex support.
1420
1421
 
@@ -1449,15 +1450,17 @@ function createGrepTool(sandbox, config) {
1449
1450
  path,
1450
1451
  glob,
1451
1452
  type,
1452
- output_mode = "files_with_matches",
1453
+ output_mode: rawOutputMode,
1453
1454
  "-i": caseInsensitive,
1454
1455
  "-B": beforeContext,
1455
1456
  "-A": afterContext,
1456
1457
  "-C": context,
1457
1458
  head_limit,
1458
- offset = 0,
1459
+ offset: rawOffset,
1459
1460
  multiline
1460
1461
  } = input;
1462
+ const output_mode = rawOutputMode ?? "files_with_matches";
1463
+ const offset = rawOffset ?? 0;
1461
1464
  const searchPath = path || ".";
1462
1465
  const startTime = performance.now();
1463
1466
  const debugId = isDebugEnabled() ? debugStart("grep", {
@@ -1607,7 +1610,7 @@ function parseCountOutput(stdout) {
1607
1610
  total
1608
1611
  };
1609
1612
  }
1610
- function parseContentOutput(stdout, head_limit, offset = 0) {
1613
+ function parseContentOutput(stdout, head_limit, offset) {
1611
1614
  const fileData = new Map;
1612
1615
  for (const line of stdout.split(`
1613
1616
  `).filter(Boolean)) {
@@ -1704,8 +1707,8 @@ import { tool as tool8, zodSchema as zodSchema8 } from "ai";
1704
1707
  import { z as z8 } from "zod";
1705
1708
  var readInputSchema = z8.object({
1706
1709
  file_path: z8.string().describe("Absolute path to file or directory"),
1707
- offset: z8.number().optional().describe("Line number to start reading from (1-indexed)"),
1708
- limit: z8.number().optional().describe("Maximum number of lines to read")
1710
+ offset: z8.number().nullable().default(null).describe("Line number to start reading from (1-indexed)"),
1711
+ limit: z8.number().nullable().default(null).describe("Maximum number of lines to read")
1709
1712
  });
1710
1713
  var READ_DESCRIPTION = `Reads a file from the local filesystem. You can access any file directly by using this tool.
1711
1714
  Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned.
@@ -2118,8 +2121,8 @@ async function searchContent(apiKey, provider, options) {
2118
2121
  }
2119
2122
  var webSearchInputSchema = z11.object({
2120
2123
  query: z11.string().describe("The search query to use"),
2121
- allowed_domains: z11.array(z11.string()).optional().describe("Only include results from these domains"),
2122
- blocked_domains: z11.array(z11.string()).optional().describe("Never include results from these domains")
2124
+ allowed_domains: z11.array(z11.string()).nullable().default(null).describe("Only include results from these domains"),
2125
+ blocked_domains: z11.array(z11.string()).nullable().default(null).describe("Never include results from these domains")
2123
2126
  });
2124
2127
  var WEB_SEARCH_DESCRIPTION = `Searches the web and returns results with links. Use this for accessing up-to-date information beyond your knowledge cutoff.
2125
2128
 
@@ -2283,8 +2286,8 @@ var taskInputSchema = z13.object({
2283
2286
  description: z13.string().describe("A short (3-5 word) description of the task"),
2284
2287
  prompt: z13.string().describe("The task for the agent to perform"),
2285
2288
  subagent_type: z13.string().describe("The type of specialized agent to use for this task"),
2286
- system_prompt: z13.string().optional().describe("Optional custom system prompt for this agent. If provided, overrides the default system prompt for the subagent type. Use this to create dynamic, specialized agents on the fly."),
2287
- tools: z13.array(z13.string()).optional().describe("Optional list of tool names this agent can use (e.g., ['Read', 'Grep', 'WebSearch']). If provided, overrides the default tools for the subagent type. Use this to restrict or expand the agent's capabilities.")
2289
+ system_prompt: z13.string().nullable().default(null).describe("Optional custom system prompt for this agent. If provided, overrides the default system prompt for the subagent type. Use this to create dynamic, specialized agents on the fly."),
2290
+ tools: z13.array(z13.string()).nullable().default(null).describe("Optional list of tool names this agent can use (e.g., ['Read', 'Grep', 'WebSearch']). If provided, overrides the default tools for the subagent type. Use this to restrict or expand the agent's capabilities.")
2288
2291
  });
2289
2292
  var TASK_DESCRIPTION = `Launch a new agent to handle complex, multi-step tasks autonomously.
2290
2293
 
@@ -1,12 +1,12 @@
1
1
  export interface QuestionOption {
2
2
  label: string;
3
- description?: string;
3
+ description: string | null;
4
4
  }
5
5
  export interface StructuredQuestion {
6
- header?: string;
6
+ header: string | null;
7
7
  question: string;
8
- options?: QuestionOption[];
9
- multiSelect?: boolean;
8
+ options: QuestionOption[] | null;
9
+ multiSelect: boolean | null;
10
10
  }
11
11
  export interface AskUserSimpleOutput {
12
12
  question: string;
@@ -40,14 +40,14 @@ export interface AskUserToolConfig {
40
40
  * @param config - Configuration with optional handlers for questions
41
41
  */
42
42
  export declare function createAskUserTool(config?: AskUserToolConfig | AskUserResponseHandler): import("ai").Tool<{
43
- question?: string | undefined;
44
- questions?: {
43
+ question: string | null;
44
+ questions: {
45
+ header: string | null;
45
46
  question: string;
46
- header?: string | undefined;
47
- options?: {
47
+ options: {
48
48
  label: string;
49
- description?: string | undefined;
50
- }[] | undefined;
51
- multiSelect?: boolean | undefined;
52
- }[] | undefined;
49
+ description: string | null;
50
+ }[] | null;
51
+ multiSelect: boolean | null;
52
+ }[] | null;
53
53
  }, AskUserOutput | AskUserError | AskUserAnswerOutput>;
@@ -12,7 +12,7 @@ export interface BashError {
12
12
  }
13
13
  export declare function createBashTool(sandbox: Sandbox, config?: ToolConfig): import("ai").Tool<{
14
14
  command: string;
15
- timeout?: number | undefined;
16
- description?: string | undefined;
17
- run_in_background?: boolean | undefined;
15
+ timeout: number | null;
16
+ description: string | null;
17
+ run_in_background: boolean | null;
18
18
  }, BashOutput | BashError>;
@@ -12,5 +12,5 @@ export declare function createEditTool(sandbox: Sandbox, config?: ToolConfig): i
12
12
  file_path: string;
13
13
  old_string: string;
14
14
  new_string: string;
15
- replace_all?: boolean | undefined;
15
+ replace_all: boolean | null;
16
16
  }, EditOutput | EditError>;
@@ -10,5 +10,5 @@ export interface GlobError {
10
10
  }
11
11
  export declare function createGlobTool(sandbox: Sandbox, config?: ToolConfig): import("ai").Tool<{
12
12
  pattern: string;
13
- path?: string | undefined;
13
+ path: string | null;
14
14
  }, GlobOutput | GlobError>;
@@ -28,16 +28,16 @@ export interface GrepError {
28
28
  export type GrepOutput = GrepContentOutput | GrepFilesOutput | GrepCountOutput | GrepError;
29
29
  export declare function createGrepTool(sandbox: Sandbox, config?: GrepToolConfig): import("ai").Tool<{
30
30
  pattern: string;
31
- path?: string | undefined;
32
- glob?: string | undefined;
33
- type?: string | undefined;
34
- output_mode?: "content" | "count" | "files_with_matches" | undefined;
35
- "-i"?: boolean | undefined;
36
- "-n"?: boolean | undefined;
37
- "-B"?: number | undefined;
38
- "-A"?: number | undefined;
39
- "-C"?: number | undefined;
40
- head_limit?: number | undefined;
41
- offset?: number | undefined;
42
- multiline?: boolean | undefined;
31
+ path: string | null;
32
+ glob: string | null;
33
+ type: string | null;
34
+ output_mode: "content" | "count" | "files_with_matches" | null;
35
+ "-i": boolean | null;
36
+ "-n": boolean | null;
37
+ "-B": number | null;
38
+ "-A": number | null;
39
+ "-C": number | null;
40
+ head_limit: number | null;
41
+ offset: number | null;
42
+ multiline: boolean | null;
43
43
  }, GrepOutput>;
@@ -47,7 +47,7 @@ export interface AgentToolsResult {
47
47
  * });
48
48
  */
49
49
  export declare function createAgentTools(sandbox: Sandbox, config?: AgentConfig): AgentToolsResult;
50
- export type { AskUserError, AskUserOutput, AskUserResponseHandler, } from "./ask-user";
50
+ export type { AskUserError, AskUserOutput, AskUserResponseHandler, QuestionOption, StructuredQuestion, } from "./ask-user";
51
51
  export { createAskUserTool } from "./ask-user";
52
52
  export type { BashError, BashOutput } from "./bash";
53
53
  export { createBashTool } from "./bash";
@@ -20,6 +20,6 @@ export interface ReadError {
20
20
  export type ReadOutput = ReadTextOutput | ReadDirectoryOutput | ReadError;
21
21
  export declare function createReadTool(sandbox: Sandbox, config?: ToolConfig): import("ai").Tool<{
22
22
  file_path: string;
23
- offset?: number | undefined;
24
- limit?: number | undefined;
23
+ offset: number | null;
24
+ limit: number | null;
25
25
  }, ReadOutput>;
@@ -17,8 +17,8 @@ declare const taskInputSchema: z.ZodObject<{
17
17
  description: z.ZodString;
18
18
  prompt: z.ZodString;
19
19
  subagent_type: z.ZodString;
20
- system_prompt: z.ZodOptional<z.ZodString>;
21
- tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
20
+ system_prompt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
21
+ tools: z.ZodDefault<z.ZodNullable<z.ZodArray<z.ZodString>>>;
22
22
  }, z.core.$strip>;
23
23
  type TaskInput = z.infer<typeof taskInputSchema>;
24
24
  /** Event emitted for each step a subagent takes */
@@ -17,6 +17,6 @@ export interface WebSearchError {
17
17
  }
18
18
  export declare function createWebSearchTool(config: WebSearchConfig): import("ai").Tool<{
19
19
  query: string;
20
- allowed_domains?: string[] | undefined;
21
- blocked_domains?: string[] | undefined;
20
+ allowed_domains: string[] | null;
21
+ blocked_domains: string[] | null;
22
22
  }, WebSearchOutput | WebSearchError>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bashkit",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Agentic coding tools for the Vercel AI SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,6 +26,9 @@
26
26
  "build:cli": "bun build src/cli/init.ts --outdir dist/cli --target node --format esm --external @clack/prompts && chmod +x dist/cli/init.js",
27
27
  "build:types": "tsc -p tsconfig.build.json",
28
28
  "typecheck": "tsc --noEmit",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest watch",
31
+ "test:coverage": "vitest run --coverage",
29
32
  "format": "biome format --write .",
30
33
  "format:check": "biome format .",
31
34
  "lint": "biome lint --write .",
@@ -61,9 +64,11 @@
61
64
  "@types/bun": "latest",
62
65
  "@types/node": "^24.10.0",
63
66
  "@vercel/sandbox": "^1.0.4",
67
+ "@vitest/coverage-v8": "^3.0.0",
64
68
  "ai": "^6.0.0",
65
69
  "parallel-web": "^0.2.4",
66
- "typescript": "^5.9.3"
70
+ "typescript": "^5.9.3",
71
+ "vitest": "^3.0.0"
67
72
  },
68
73
  "peerDependencies": {
69
74
  "ai": ">=5.0.0",