bashkit 0.1.1 → 0.1.2

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
@@ -122,7 +122,7 @@ await sandbox.destroy();
122
122
 
123
123
  ## Sub-agents with Task Tool
124
124
 
125
- The Task tool spawns new `generateText` calls for complex subtasks:
125
+ The Task tool spawns new agents for complex subtasks:
126
126
 
127
127
  ```typescript
128
128
  import { createTaskTool } from "bashkit";
@@ -157,6 +157,40 @@ The parent agent calls Task like any other tool:
157
157
  }}
158
158
  ```
159
159
 
160
+ ### Streaming Sub-agent Activity to UI
161
+
162
+ Pass a `streamWriter` to stream real-time sub-agent activity:
163
+
164
+ ```typescript
165
+ import { createUIMessageStream } from "ai";
166
+
167
+ const stream = createUIMessageStream({
168
+ execute: async ({ writer }) => {
169
+ const taskTool = createTaskTool({
170
+ model,
171
+ tools: sandboxTools,
172
+ streamWriter: writer, // Enable real-time streaming
173
+ subagentTypes: { ... },
174
+ });
175
+
176
+ const result = streamText({
177
+ model,
178
+ tools: { Task: taskTool },
179
+ ...
180
+ });
181
+
182
+ writer.merge(result.toUIMessageStream());
183
+ },
184
+ });
185
+ ```
186
+
187
+ When `streamWriter` is provided:
188
+ - Uses `streamText` internally (instead of `generateText`)
189
+ - Emits `data-subagent` events: `start`, `tool-call`, `done`, `complete`
190
+ - Events appear in `message.parts` as `{ type: "data-subagent", data: SubagentEventData }`
191
+
192
+ **Note:** TaskOutput does NOT include messages (to avoid context bloat). The UI accesses the full conversation via the streamed `complete` event.
193
+
160
194
  ## Prompt Caching
161
195
 
162
196
  Enable Anthropic prompt caching to reduce costs on repeated prefixes:
package/README.md CHANGED
@@ -219,7 +219,7 @@ const { tools, planModeState } = createAgentTools(sandbox, {
219
219
 
220
220
  ## Sub-agents with Task Tool
221
221
 
222
- The Task tool spawns new `generateText` calls for complex subtasks:
222
+ The Task tool spawns new agents for complex subtasks:
223
223
 
224
224
  ```typescript
225
225
  import { createTaskTool } from 'bashkit';
@@ -254,6 +254,46 @@ The parent agent calls Task like any other tool:
254
254
  }}
255
255
  ```
256
256
 
257
+ ### Streaming Sub-agent Activity to UI
258
+
259
+ Pass a `streamWriter` to stream real-time sub-agent activity to the UI:
260
+
261
+ ```typescript
262
+ import { createUIMessageStream } from 'ai';
263
+
264
+ const stream = createUIMessageStream({
265
+ execute: async ({ writer }) => {
266
+ const taskTool = createTaskTool({
267
+ model,
268
+ tools: sandboxTools,
269
+ streamWriter: writer, // Enable real-time streaming
270
+ subagentTypes: { ... },
271
+ });
272
+
273
+ // Use with streamText
274
+ const result = streamText({
275
+ model,
276
+ tools: { Task: taskTool },
277
+ ...
278
+ });
279
+
280
+ writer.merge(result.toUIMessageStream());
281
+ },
282
+ });
283
+ ```
284
+
285
+ When `streamWriter` is provided:
286
+ - Uses `streamText` internally (instead of `generateText`)
287
+ - Emits `data-subagent` events to the UI stream:
288
+ - `start` - Sub-agent begins work
289
+ - `tool-call` - Each tool the sub-agent uses (with args)
290
+ - `done` - Sub-agent finished
291
+ - `complete` - Full messages array for UI access
292
+
293
+ These appear in `message.parts` on the client as `{ type: "data-subagent", data: SubagentEventData }`.
294
+
295
+ **Important:** The TaskOutput returned to the lead agent does NOT include messages (to avoid context bloat). The UI accesses the full conversation via the streamed `complete` event.
296
+
257
297
  ## Context Management
258
298
 
259
299
  ### Conversation Compaction
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
+ export type { UIMessageStreamWriter } from "ai";
1
2
  export { anthropicPromptCacheMiddleware } from "./middleware";
2
3
  export type { E2BSandboxConfig, LocalSandboxConfig, VercelSandboxConfig, } from "./sandbox";
3
4
  export { createE2BSandbox, createLocalSandbox, createVercelSandbox, } from "./sandbox";
4
5
  export type { ExecOptions, ExecResult, Sandbox } from "./sandbox/interface";
5
- 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, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, TodoItem, TodoState, TodoWriteError, TodoWriteOutput, WebFetchError, WebFetchOutput, WebFetchToolConfig, WebSearchError, WebSearchOutput, WebSearchResult, WebSearchToolConfig, WriteError, WriteOutput, } from "./tools";
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, WebFetchToolConfig, WebSearchError, WebSearchOutput, WebSearchResult, WebSearchToolConfig, WriteError, WriteOutput, } from "./tools";
6
7
  export { createAgentTools, createAskUserTool, createBashTool, createEditTool, createEnterPlanModeTool, createExitPlanModeTool, createGlobTool, createGrepTool, createReadTool, createSkillTool, createTaskTool, createTodoWriteTool, createWebFetchTool, createWebSearchTool, createWriteTool, } from "./tools";
7
8
  export type { AgentConfig, AskUserConfig, SkillConfig, ToolConfig, WebFetchConfig, WebSearchConfig, } from "./types";
8
9
  export { DEFAULT_CONFIG } from "./types";
package/dist/index.js CHANGED
@@ -1139,6 +1139,7 @@ function createWriteTool(sandbox, config) {
1139
1139
  // src/tools/task.ts
1140
1140
  import {
1141
1141
  generateText as generateText2,
1142
+ streamText,
1142
1143
  stepCountIs,
1143
1144
  tool as tool13,
1144
1145
  zodSchema as zodSchema13
@@ -1149,6 +1150,10 @@ var taskInputSchema = z13.object({
1149
1150
  prompt: z13.string().describe("The task for the agent to perform"),
1150
1151
  subagent_type: z13.string().describe("The type of specialized agent to use for this task")
1151
1152
  });
1153
+ var eventCounter = 0;
1154
+ function generateEventId() {
1155
+ return `subagent-${Date.now()}-${++eventCounter}`;
1156
+ }
1152
1157
  function filterTools(allTools, allowedTools) {
1153
1158
  if (!allowedTools)
1154
1159
  return allTools;
@@ -1165,10 +1170,9 @@ function createTaskTool(config) {
1165
1170
  model: defaultModel,
1166
1171
  tools: allTools,
1167
1172
  subagentTypes = {},
1168
- costPerInputToken = 0.000003,
1169
- costPerOutputToken = 0.000015,
1170
1173
  defaultStopWhen,
1171
- defaultOnStepFinish
1174
+ defaultOnStepFinish,
1175
+ streamWriter
1172
1176
  } = config;
1173
1177
  return tool13({
1174
1178
  description: "Launches a new agent to handle complex, multi-step tasks autonomously. Use this for tasks that require multiple steps, research, or specialized expertise.",
@@ -1184,13 +1188,88 @@ function createTaskTool(config) {
1184
1188
  const model = typeConfig.model || defaultModel;
1185
1189
  const tools = filterTools(allTools, typeConfig.tools);
1186
1190
  const systemPrompt = typeConfig.systemPrompt;
1187
- const result = await generateText2({
1191
+ const commonOptions = {
1188
1192
  model,
1189
1193
  tools,
1190
1194
  system: systemPrompt,
1191
1195
  prompt,
1192
1196
  stopWhen: typeConfig.stopWhen ?? defaultStopWhen ?? stepCountIs(15),
1193
- prepareStep: typeConfig.prepareStep,
1197
+ prepareStep: typeConfig.prepareStep
1198
+ };
1199
+ if (streamWriter) {
1200
+ const startId = generateEventId();
1201
+ streamWriter.write({
1202
+ type: "data-subagent",
1203
+ id: startId,
1204
+ data: {
1205
+ event: "start",
1206
+ subagent: subagent_type,
1207
+ description
1208
+ }
1209
+ });
1210
+ const result2 = streamText({
1211
+ ...commonOptions,
1212
+ onStepFinish: async (step) => {
1213
+ if (step.toolCalls?.length) {
1214
+ for (const tc of step.toolCalls) {
1215
+ const eventId = generateEventId();
1216
+ streamWriter.write({
1217
+ type: "data-subagent",
1218
+ id: eventId,
1219
+ data: {
1220
+ event: "tool-call",
1221
+ subagent: subagent_type,
1222
+ description,
1223
+ toolName: tc.toolName,
1224
+ args: tc.input
1225
+ }
1226
+ });
1227
+ }
1228
+ }
1229
+ await typeConfig.onStepFinish?.(step);
1230
+ await defaultOnStepFinish?.({
1231
+ subagentType: subagent_type,
1232
+ description,
1233
+ step
1234
+ });
1235
+ }
1236
+ });
1237
+ const text = await result2.text;
1238
+ const usage2 = await result2.usage;
1239
+ const response = await result2.response;
1240
+ streamWriter.write({
1241
+ type: "data-subagent",
1242
+ id: generateEventId(),
1243
+ data: {
1244
+ event: "done",
1245
+ subagent: subagent_type,
1246
+ description
1247
+ }
1248
+ });
1249
+ streamWriter.write({
1250
+ type: "data-subagent",
1251
+ id: generateEventId(),
1252
+ data: {
1253
+ event: "complete",
1254
+ subagent: subagent_type,
1255
+ description,
1256
+ messages: response.messages
1257
+ }
1258
+ });
1259
+ const durationMs2 = Math.round(performance.now() - startTime);
1260
+ return {
1261
+ result: text,
1262
+ usage: usage2.inputTokens !== undefined && usage2.outputTokens !== undefined ? {
1263
+ input_tokens: usage2.inputTokens,
1264
+ output_tokens: usage2.outputTokens
1265
+ } : undefined,
1266
+ duration_ms: durationMs2,
1267
+ subagent: subagent_type,
1268
+ description
1269
+ };
1270
+ }
1271
+ const result = await generateText2({
1272
+ ...commonOptions,
1194
1273
  onStepFinish: async (step) => {
1195
1274
  await typeConfig.onStepFinish?.(step);
1196
1275
  await defaultOnStepFinish?.({
@@ -1205,20 +1284,16 @@ function createTaskTool(config) {
1205
1284
  input_tokens: result.usage.inputTokens,
1206
1285
  output_tokens: result.usage.outputTokens
1207
1286
  } : undefined;
1208
- let totalCostUsd;
1209
- if (usage) {
1210
- totalCostUsd = usage.input_tokens * costPerInputToken + usage.output_tokens * costPerOutputToken;
1211
- }
1212
1287
  return {
1213
1288
  result: result.text,
1214
1289
  usage,
1215
- total_cost_usd: totalCostUsd,
1216
- duration_ms: durationMs
1290
+ duration_ms: durationMs,
1291
+ subagent: subagent_type,
1292
+ description
1217
1293
  };
1218
1294
  } catch (error) {
1219
- return {
1220
- error: error instanceof Error ? error.message : "Unknown error"
1221
- };
1295
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
1296
+ return { error: errorMessage };
1222
1297
  }
1223
1298
  }
1224
1299
  });
@@ -65,7 +65,7 @@ export type { ReadDirectoryOutput, ReadError, ReadOutput, ReadTextOutput, } from
65
65
  export { createReadTool } from "./read";
66
66
  export type { SkillError, SkillOutput, SkillToolConfig } from "./skill";
67
67
  export { createSkillTool } from "./skill";
68
- export type { SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, } from "./task";
68
+ export type { SubagentEventData, SubagentStepEvent, SubagentTypeConfig, TaskError, TaskOutput, TaskToolConfig, } from "./task";
69
69
  export { createTaskTool } from "./task";
70
70
  export type { TodoItem, TodoState, TodoWriteError, TodoWriteOutput, } from "./todo-write";
71
71
  export { createTodoWriteTool } from "./todo-write";
@@ -1,12 +1,13 @@
1
- import { type LanguageModel, type PrepareStepFunction, type StepResult, type StopCondition, type Tool, type ToolSet } from "ai";
1
+ import { type ModelMessage, type LanguageModel, type PrepareStepFunction, type StepResult, type StopCondition, type UIMessageStreamWriter, type Tool, type ToolSet } from "ai";
2
2
  export interface TaskOutput {
3
3
  result: string;
4
4
  usage?: {
5
5
  input_tokens: number;
6
6
  output_tokens: number;
7
7
  };
8
- total_cost_usd?: number;
9
8
  duration_ms?: number;
9
+ subagent?: string;
10
+ description?: string;
10
11
  }
11
12
  export interface TaskError {
12
13
  error: string;
@@ -17,6 +18,15 @@ export interface SubagentStepEvent {
17
18
  description: string;
18
19
  step: StepResult<ToolSet>;
19
20
  }
21
+ /** Data format for streamed subagent events (appears in message.parts as type: "data-subagent") */
22
+ export interface SubagentEventData {
23
+ event: "start" | "tool-call" | "done" | "complete";
24
+ subagent: string;
25
+ description: string;
26
+ toolName?: string;
27
+ args?: Record<string, unknown>;
28
+ messages?: ModelMessage[];
29
+ }
20
30
  export interface SubagentTypeConfig {
21
31
  /** Model to use for this subagent type */
22
32
  model?: LanguageModel;
@@ -38,13 +48,11 @@ export interface TaskToolConfig {
38
48
  tools: ToolSet;
39
49
  /** Configuration for each subagent type */
40
50
  subagentTypes?: Record<string, SubagentTypeConfig>;
41
- /** Cost per input token for usage tracking */
42
- costPerInputToken?: number;
43
- /** Cost per output token for usage tracking */
44
- costPerOutputToken?: number;
45
51
  /** Default stop condition for subagents (default: stepCountIs(15)) */
46
52
  defaultStopWhen?: StopCondition<ToolSet>;
47
53
  /** Default callback for each step any subagent takes */
48
54
  defaultOnStepFinish?: (event: SubagentStepEvent) => void | Promise<void>;
55
+ /** Optional stream writer for real-time subagent activity (uses streamText instead of generateText) */
56
+ streamWriter?: UIMessageStreamWriter;
49
57
  }
50
58
  export declare function createTaskTool(config: TaskToolConfig): Tool;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bashkit",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Agentic coding tools for the Vercel AI SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,94 +0,0 @@
1
- /**
2
- * A diagnostic (error/warning) from the language server.
3
- */
4
- export interface LspDiagnostic {
5
- file: string;
6
- line: number;
7
- column: number;
8
- endLine?: number;
9
- endColumn?: number;
10
- severity: "error" | "warning" | "info" | "hint";
11
- message: string;
12
- source?: string;
13
- code?: string | number;
14
- }
15
- /**
16
- * A location in the codebase (for go-to-definition, references, etc.)
17
- */
18
- export interface LspLocation {
19
- file: string;
20
- line: number;
21
- column: number;
22
- endLine?: number;
23
- endColumn?: number;
24
- preview?: string;
25
- }
26
- /**
27
- * Hover information for a symbol.
28
- */
29
- export interface LspHoverInfo {
30
- contents: string;
31
- range?: {
32
- startLine: number;
33
- startColumn: number;
34
- endLine: number;
35
- endColumn: number;
36
- };
37
- }
38
- /**
39
- * Interface that LSP providers must implement.
40
- * This abstracts over different LSP implementations (vscode, standalone servers, etc.)
41
- */
42
- export interface LspProvider {
43
- /** Get diagnostics for a file or the entire workspace */
44
- getDiagnostics(file?: string): Promise<LspDiagnostic[]>;
45
- /** Go to definition of symbol at position */
46
- getDefinition(file: string, line: number, column: number): Promise<LspLocation[]>;
47
- /** Find all references to symbol at position */
48
- getReferences(file: string, line: number, column: number): Promise<LspLocation[]>;
49
- /** Get hover information for symbol at position */
50
- getHover(file: string, line: number, column: number): Promise<LspHoverInfo | null>;
51
- /** Get available actions at position (optional) */
52
- getCodeActions?(file: string, line: number, column: number): Promise<Array<{
53
- title: string;
54
- kind?: string;
55
- }>>;
56
- }
57
- export interface LspDiagnosticsOutput {
58
- type: "diagnostics";
59
- diagnostics: LspDiagnostic[];
60
- counts: {
61
- errors: number;
62
- warnings: number;
63
- info: number;
64
- hints: number;
65
- };
66
- }
67
- export interface LspDefinitionOutput {
68
- type: "definition";
69
- locations: LspLocation[];
70
- }
71
- export interface LspReferencesOutput {
72
- type: "references";
73
- locations: LspLocation[];
74
- count: number;
75
- }
76
- export interface LspHoverOutput {
77
- type: "hover";
78
- info: LspHoverInfo | null;
79
- }
80
- export interface LspError {
81
- error: string;
82
- }
83
- export type LspOutput = LspDiagnosticsOutput | LspDefinitionOutput | LspReferencesOutput | LspHoverOutput | LspError;
84
- /**
85
- * Creates an LSP tool for code intelligence operations.
86
- *
87
- * @param provider - An implementation of LspProvider that interfaces with language servers
88
- */
89
- export declare function createLspTool(provider: LspProvider): import("ai").Tool<{
90
- action: "diagnostics" | "definition" | "references" | "hover";
91
- file?: string | undefined;
92
- line?: number | undefined;
93
- column?: number | undefined;
94
- }, LspOutput>;