bs-agent 0.0.10 → 0.0.12
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/dist/core/index.cjs +67 -35
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +6 -5
- package/dist/core/index.d.ts +6 -5
- package/dist/core/index.js +67 -35
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +87 -37
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +8 -3
- package/dist/react/index.d.ts +8 -3
- package/dist/react/index.js +87 -37
- package/dist/react/index.js.map +1 -1
- package/dist/{types-vhptH472.d.cts → types-DryLPWU9.d.cts} +11 -3
- package/dist/{types-vhptH472.d.ts → types-DryLPWU9.d.ts} +11 -3
- package/package.json +5 -2
package/dist/core/index.cjs
CHANGED
|
@@ -29,6 +29,16 @@ __export(core_exports, {
|
|
|
29
29
|
module.exports = __toCommonJS(core_exports);
|
|
30
30
|
|
|
31
31
|
// src/core/stream.ts
|
|
32
|
+
function tryParseJSON(value) {
|
|
33
|
+
if (typeof value === "string") {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(value);
|
|
36
|
+
} catch {
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
32
42
|
var FatalStreamError = class extends Error {
|
|
33
43
|
constructor(message, statusCode) {
|
|
34
44
|
super(message);
|
|
@@ -63,7 +73,8 @@ async function executeStream(options) {
|
|
|
63
73
|
});
|
|
64
74
|
const sessionId = response.headers.get("X-BuildShip-Agent-Session-ID");
|
|
65
75
|
if (sessionId && onSessionId) {
|
|
66
|
-
|
|
76
|
+
const sessionName = response.headers.get("X-BuildShip-Agent-Session-Name") || void 0;
|
|
77
|
+
onSessionId(sessionId, sessionName);
|
|
67
78
|
}
|
|
68
79
|
onResponse?.(response);
|
|
69
80
|
if (!response.ok) {
|
|
@@ -80,9 +91,8 @@ async function executeStream(options) {
|
|
|
80
91
|
throw error;
|
|
81
92
|
}
|
|
82
93
|
if (!response.body) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
throw error;
|
|
94
|
+
callbacks.onComplete?.(fullText);
|
|
95
|
+
return;
|
|
86
96
|
}
|
|
87
97
|
const reader = response.body.getReader();
|
|
88
98
|
const decoder = new TextDecoder();
|
|
@@ -95,9 +105,17 @@ async function executeStream(options) {
|
|
|
95
105
|
const parts = buffer.split("\n\n");
|
|
96
106
|
buffer = parts.pop() || "";
|
|
97
107
|
for (const part of parts) {
|
|
98
|
-
const
|
|
99
|
-
if (!
|
|
100
|
-
|
|
108
|
+
const trimmedPart = part.trim();
|
|
109
|
+
if (!trimmedPart) continue;
|
|
110
|
+
let jsonStr = "";
|
|
111
|
+
for (const line of trimmedPart.split("\n")) {
|
|
112
|
+
if (line.startsWith("data: ")) {
|
|
113
|
+
jsonStr += line.slice(6);
|
|
114
|
+
} else if (line.startsWith("data:")) {
|
|
115
|
+
jsonStr += line.slice(5);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
jsonStr = jsonStr.trim();
|
|
101
119
|
if (!jsonStr) continue;
|
|
102
120
|
let raw;
|
|
103
121
|
try {
|
|
@@ -105,9 +123,9 @@ async function executeStream(options) {
|
|
|
105
123
|
} catch {
|
|
106
124
|
continue;
|
|
107
125
|
}
|
|
108
|
-
const
|
|
126
|
+
const streamEvent = normalizeEvent(raw);
|
|
109
127
|
handleEvent(
|
|
110
|
-
|
|
128
|
+
streamEvent,
|
|
111
129
|
fullText,
|
|
112
130
|
callbacks,
|
|
113
131
|
clientTools,
|
|
@@ -115,39 +133,41 @@ async function executeStream(options) {
|
|
|
115
133
|
onAutoResume,
|
|
116
134
|
pendingAutoResumes
|
|
117
135
|
);
|
|
118
|
-
if (
|
|
119
|
-
fullText +=
|
|
136
|
+
if (streamEvent.type === "text_delta") {
|
|
137
|
+
fullText += streamEvent.data;
|
|
120
138
|
}
|
|
121
139
|
}
|
|
122
140
|
}
|
|
123
141
|
if (buffer.trim()) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
let jsonStr = "";
|
|
143
|
+
for (const line of buffer.trim().split("\n")) {
|
|
144
|
+
if (line.startsWith("data: ")) {
|
|
145
|
+
jsonStr += line.slice(6);
|
|
146
|
+
} else if (line.startsWith("data:")) {
|
|
147
|
+
jsonStr += line.slice(5);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
jsonStr = jsonStr.trim();
|
|
151
|
+
if (jsonStr) {
|
|
152
|
+
try {
|
|
153
|
+
const raw = JSON.parse(jsonStr);
|
|
154
|
+
const streamEvent = normalizeEvent(raw);
|
|
155
|
+
handleEvent(
|
|
156
|
+
streamEvent,
|
|
157
|
+
fullText,
|
|
158
|
+
callbacks,
|
|
159
|
+
clientTools,
|
|
160
|
+
onPaused,
|
|
161
|
+
onAutoResume,
|
|
162
|
+
pendingAutoResumes
|
|
163
|
+
);
|
|
164
|
+
if (streamEvent.type === "text_delta") {
|
|
165
|
+
fullText += streamEvent.data;
|
|
143
166
|
}
|
|
167
|
+
} catch {
|
|
144
168
|
}
|
|
145
169
|
}
|
|
146
170
|
}
|
|
147
|
-
if (pendingAutoResumes.length > 0) {
|
|
148
|
-
await Promise.allSettled(pendingAutoResumes);
|
|
149
|
-
}
|
|
150
|
-
callbacks.onComplete?.(fullText);
|
|
151
171
|
} catch (err) {
|
|
152
172
|
if (err instanceof Error && err.name === "AbortError") {
|
|
153
173
|
throw err;
|
|
@@ -156,6 +176,10 @@ async function executeStream(options) {
|
|
|
156
176
|
callbacks.onError?.(error);
|
|
157
177
|
throw error;
|
|
158
178
|
}
|
|
179
|
+
if (pendingAutoResumes.length > 0) {
|
|
180
|
+
await Promise.allSettled(pendingAutoResumes);
|
|
181
|
+
}
|
|
182
|
+
callbacks.onComplete?.(fullText);
|
|
159
183
|
}
|
|
160
184
|
function normalizeEvent(raw) {
|
|
161
185
|
const typeMap = {
|
|
@@ -183,7 +207,8 @@ function handleEvent(event, _fullText, callbacks, clientTools, onPaused, onAutoR
|
|
|
183
207
|
break;
|
|
184
208
|
}
|
|
185
209
|
case "tool_call_start": {
|
|
186
|
-
const { callId, toolName, toolType, inputs, paused } = event.data;
|
|
210
|
+
const { callId, toolName, toolType, inputs: rawInputs, paused } = event.data;
|
|
211
|
+
const inputs = tryParseJSON(rawInputs);
|
|
187
212
|
callbacks.onToolStart?.(toolName, toolType);
|
|
188
213
|
if (toolType === "client") {
|
|
189
214
|
const tool = clientTools.get(toolName);
|
|
@@ -220,6 +245,13 @@ function handleEvent(event, _fullText, callbacks, clientTools, onPaused, onAutoR
|
|
|
220
245
|
callbacks.onToolEnd?.(toolName, result, error);
|
|
221
246
|
break;
|
|
222
247
|
}
|
|
248
|
+
case "run_error": {
|
|
249
|
+
const { message, code } = event.data;
|
|
250
|
+
const error = new Error(message);
|
|
251
|
+
if (code != null) error.code = code;
|
|
252
|
+
callbacks.onError?.(error);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
223
255
|
}
|
|
224
256
|
}
|
|
225
257
|
|
package/dist/core/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/index.ts","../../src/core/stream.ts","../../src/core/session.ts","../../src/core/agent.ts"],"sourcesContent":["// ─── Classes ─────────────────────────────────────────────────────────────────\nexport { BuildShipAgent } from \"./agent\";\nexport { AgentSession } from \"./session\";\n\n// ─── Stream executor ─────────────────────────────────────────────────────────\nexport { executeStream } from \"./stream\";\n\n// ─── Zod (re-exported for convenience) ───────────────────────────────────────\nexport { z, toJSONSchema } from \"zod\";\nexport type { ZodSchema } from \"zod\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\nexport type {\n AgentConfig,\n SessionId,\n ToolType,\n StreamCallbacks,\n StreamOptions,\n ExecuteRequestBody,\n ClientTool,\n PausedToolInfo,\n // Stream event types (for advanced consumers)\n StreamEvent,\n StreamEventMeta,\n TextDeltaEvent,\n ReasoningDeltaEvent,\n AgentHandoffEvent,\n ToolCallStartEvent,\n ToolCallEndEvent,\n} from \"./types\";\n","import type { StreamEvent, StreamOptions, SessionId } from \"./types\";\n\n/**\n * Fatal error — will NOT be retried.\n */\nclass FatalStreamError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message);\n this.name = \"FatalStreamError\";\n }\n}\n\n/**\n * Opens an SSE connection to the BuildShip agent endpoint using native fetch,\n * parses events, and dispatches to the appropriate callbacks.\n *\n * Works in both Node.js (18+) and browsers — no browser-only dependencies.\n *\n * @internal\n */\nexport async function executeStream(options: StreamOptions): Promise<void> {\n const {\n url,\n body,\n headers,\n callbacks,\n clientTools,\n signal,\n onSessionId,\n onPaused,\n onAutoResume,\n onResponse,\n } = options;\n\n let fullText = \"\";\n\n // Track pending auto-resume operations so we don't call onComplete prematurely\n const pendingAutoResumes: Promise<void>[] = [];\n\n // ── Make the POST request ──────────────────────────────────────────\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n ...headers,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n // ── Extract session ID from response headers ───────────────────────\n const sessionId = response.headers.get(\"X-BuildShip-Agent-Session-ID\");\n if (sessionId && onSessionId) {\n onSessionId(sessionId as SessionId);\n }\n\n // ── Expose the raw Response object ─────────────────────────────────\n onResponse?.(response);\n\n // ── Handle HTTP errors ─────────────────────────────────────────────\n if (!response.ok) {\n let errorBody = \"\";\n try {\n errorBody = await response.text();\n } catch {\n // ignore\n }\n const error = new FatalStreamError(\n `HTTP ${response.status}: ${errorBody || response.statusText}`,\n response.status,\n );\n callbacks.onError?.(error);\n throw error;\n }\n\n // ── Read the SSE stream ────────────────────────────────────────────\n if (!response.body) {\n const error = new Error(\"Response body is null — streaming not supported\");\n callbacks.onError?.(error);\n throw error;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n // Keep the last (potentially incomplete) part in the buffer\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const dataLine = part.split(\"\\n\").find((line) => line.startsWith(\"data:\"));\n\n if (!dataLine) continue;\n\n const jsonStr = dataLine.slice(5).trim(); // strip \"data:\" prefix\n if (!jsonStr) continue;\n\n let raw: any;\n try {\n raw = JSON.parse(jsonStr);\n } catch {\n // Skip malformed events\n continue;\n }\n\n // Normalize backend event type names (llm_text_delta → text_delta, etc.)\n const event = normalizeEvent(raw) as StreamEvent;\n\n handleEvent(\n event,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n\n // Accumulate text\n if (event.type === \"text_delta\") {\n fullText += event.data;\n }\n }\n }\n\n // Flush any remaining buffer\n if (buffer.trim()) {\n const dataLine = buffer.split(\"\\n\").find((line) => line.startsWith(\"data:\"));\n if (dataLine) {\n const jsonStr = dataLine.slice(5).trim();\n if (jsonStr) {\n try {\n const event = normalizeEvent(JSON.parse(jsonStr)) as StreamEvent;\n handleEvent(\n event,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n if (event.type === \"text_delta\") {\n fullText += event.data;\n }\n } catch {\n // skip\n }\n }\n }\n }\n\n // Wait for any pending auto-resume handlers before signaling completion\n if (pendingAutoResumes.length > 0) {\n await Promise.allSettled(pendingAutoResumes);\n }\n\n // Stream complete\n callbacks.onComplete?.(fullText);\n } catch (err) {\n // AbortError — just rethrow\n if (err instanceof Error && err.name === \"AbortError\") {\n throw err;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n callbacks.onError?.(error);\n throw error;\n }\n}\n\n/**\n * Normalize backend event type names.\n * The backend sends `llm_text_delta` / `llm_reasoning_delta` but the SDK\n * exposes them as `text_delta` / `reasoning_delta`.\n * @internal\n */\nfunction normalizeEvent(raw: any): any {\n const typeMap: Record<string, string> = {\n llm_text_delta: \"text_delta\",\n llm_reasoning_delta: \"reasoning_delta\",\n };\n if (raw && typeof raw.type === \"string\" && typeMap[raw.type]) {\n raw.type = typeMap[raw.type];\n }\n return raw;\n}\n\n/**\n * Dispatch a parsed stream event to the appropriate callbacks.\n * @internal\n */\nfunction handleEvent(\n event: StreamEvent,\n _fullText: string,\n callbacks: StreamOptions[\"callbacks\"],\n clientTools: StreamOptions[\"clientTools\"],\n onPaused: StreamOptions[\"onPaused\"],\n onAutoResume: StreamOptions[\"onAutoResume\"],\n pendingAutoResumes: Promise<void>[],\n): void {\n // Notify raw event consumers\n callbacks.onEvent?.(event);\n\n switch (event.type) {\n case \"text_delta\": {\n callbacks.onText?.(event.data);\n break;\n }\n\n case \"reasoning_delta\": {\n callbacks.onReasoning?.(event.data.delta, event.data.index);\n break;\n }\n\n case \"agent_handoff\": {\n callbacks.onAgentHandoff?.(event.data.agentName);\n break;\n }\n\n case \"tool_call_start\": {\n const { callId, toolName, toolType, inputs, paused } = event.data;\n\n // Notify callback\n callbacks.onToolStart?.(toolName, toolType);\n\n // Handle client tools\n if (toolType === \"client\") {\n const tool = clientTools.get(toolName);\n if (tool) {\n if (paused && tool.handler) {\n // Blocking tool with handler → auto-execute and resume\n const handlerPromise = (async () => {\n try {\n const result = await tool.handler!(inputs);\n await onAutoResume?.(callId, result);\n } catch {\n // If handler fails, still call onPaused so user can decide\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n })();\n pendingAutoResumes.push(handlerPromise);\n } else if (paused) {\n // Blocking tool without handler → pause for user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n } else if (tool.handler) {\n // Fire-and-forget tool with handler\n try {\n tool.handler(inputs);\n } catch {\n // Swallow errors on fire-and-forget\n }\n }\n } else if (paused) {\n // No registered tool but paused — notify user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n }\n break;\n }\n\n case \"tool_call_end\": {\n const { toolName, result, error } = event.data;\n callbacks.onToolEnd?.(toolName, result, error);\n break;\n }\n }\n}\n","import type {\n SessionId,\n StreamCallbacks,\n PausedToolInfo,\n ExecuteRequestBody,\n} from \"./types\";\nimport type { BuildShipAgent } from \"./agent\";\nimport { executeStream } from \"./stream\";\nimport { toJSONSchema, type ZodSchema } from \"zod\";\n\n/**\n * Represents a conversation session with a BuildShip agent.\n *\n * Sessions maintain history across multiple turns and support\n * pause/resume for blocking client tools.\n */\nexport class AgentSession {\n /** @internal */ private _agent: BuildShipAgent;\n /** @internal */ private _sessionId: SessionId | undefined;\n /** @internal */ private _paused = false;\n /** @internal */ private _pausedToolInfo: PausedToolInfo | null = null;\n /** @internal */ private _abortController: AbortController | null = null;\n\n /** @internal */\n constructor(agent: BuildShipAgent, sessionId?: SessionId) {\n this._agent = agent;\n this._sessionId = sessionId;\n }\n\n // ─── Public API ────────────────────────────────────────────────────\n\n /**\n * Send a message in this session.\n *\n * @param message - The message to send\n * @param callbacks - Event handlers for the stream\n * @param context - Optional additional context data\n * @returns This session (for chaining)\n */\n async execute(\n message: string,\n callbacks: StreamCallbacks,\n context?: Record<string, any>,\n ): Promise<AgentSession> {\n this._paused = false;\n this._pausedToolInfo = null;\n\n const body: ExecuteRequestBody = {\n input: message,\n stream: true,\n };\n\n // Attach context as top-level properties if provided\n if (context) {\n Object.assign(body, context);\n }\n\n // Include client tool definitions\n const clientToolDefs = this._getClientToolDefs();\n if (clientToolDefs.length > 0) {\n body.clientTools = clientToolDefs;\n }\n\n await this._run(body, callbacks);\n return this;\n }\n\n /**\n * Resume a paused session with a tool result.\n *\n * @param result - The result to send back to the agent\n * @param callbacks - Event handlers for the resumed stream\n * @returns This session (for chaining)\n */\n async resume(result: any, callbacks: StreamCallbacks): Promise<AgentSession> {\n if (!this._paused || !this._pausedToolInfo) {\n throw new Error(\n \"AgentSession.resume(): session is not paused. Check isPaused() first.\",\n );\n }\n\n const body: ExecuteRequestBody = {\n stream: true,\n toolCallResult: {\n callId: this._pausedToolInfo.callId,\n result,\n },\n };\n\n // Include client tool definitions for resume requests too\n const clientToolDefs = this._getClientToolDefs();\n if (clientToolDefs.length > 0) {\n body.clientTools = clientToolDefs;\n }\n\n this._paused = false;\n this._pausedToolInfo = null;\n\n await this._run(body, callbacks);\n return this;\n }\n\n /**\n * Check if this session is waiting for a tool result.\n */\n isPaused(): boolean {\n return this._paused;\n }\n\n /**\n * Get information about the paused tool call.\n * Returns `null` if the session is not paused.\n */\n getPausedTool(): PausedToolInfo | null {\n return this._pausedToolInfo;\n }\n\n /**\n * Get the session ID.\n * May be `undefined` if the session hasn't executed yet.\n */\n getSessionId(): SessionId {\n if (!this._sessionId) {\n throw new Error(\n \"AgentSession.getSessionId(): session ID not yet available. Call execute() first.\",\n );\n }\n return this._sessionId;\n }\n\n /**\n * Cancel the current streaming operation.\n */\n abort(): void {\n this._abortController?.abort();\n this._abortController = null;\n }\n\n // ─── Private helpers ───────────────────────────────────────────────\n\n /** @internal */\n private async _run(\n body: ExecuteRequestBody,\n callbacks: StreamCallbacks,\n ): Promise<void> {\n // Create a fresh abort controller for this run\n this._abortController = new AbortController();\n\n await executeStream({\n url: this._agent._url,\n body,\n headers: this._agent._buildHeaders(this._sessionId),\n callbacks,\n clientTools: this._agent._clientTools,\n signal: this._abortController.signal,\n\n onSessionId: (id) => {\n this._sessionId = id;\n },\n\n onPaused: (info) => {\n this._paused = true;\n this._pausedToolInfo = info;\n },\n\n onAutoResume: async (callId, result) => {\n // Auto-resume: send the tool result back immediately\n const resumeBody: ExecuteRequestBody = {\n stream: true,\n toolCallResult: { callId, result },\n };\n\n const clientToolDefs = this._getClientToolDefs();\n if (clientToolDefs.length > 0) {\n resumeBody.clientTools = clientToolDefs;\n }\n\n await this._run(resumeBody, callbacks);\n },\n });\n }\n\n /** @internal */\n private _getClientToolDefs() {\n const defs: ExecuteRequestBody[\"clientTools\"] = [];\n for (const tool of this._agent._clientTools.values()) {\n defs.push({\n name: tool.name,\n description: tool.description,\n parameters: resolveParameters(tool.parameters),\n await: tool.await,\n });\n }\n return defs;\n }\n}\n\n/**\n * Convert tool parameters to a JSON Schema object.\n * - If it's a Zod schema, uses Zod's built-in `toJSONSchema` to convert.\n * - Always ensures `additionalProperties: false` is set (required by the backend).\n * - Always ensures `required` includes every key in `properties` (Gemini requirement).\n * @internal\n */\nfunction resolveParameters(params: any): Record<string, any> {\n let schema: Record<string, any>;\n\n // Detect Zod schema: ZodType instances have a `_def` property\n if (params && typeof params === \"object\" && \"_def\" in params) {\n schema = toJSONSchema(params as ZodSchema) as Record<string, any>;\n // Remove $schema key if present\n delete schema.$schema;\n } else {\n schema = { ...params };\n }\n\n if (schema.type === \"object\") {\n // Backend requires additionalProperties: false\n schema.additionalProperties = false;\n\n // Gemini requires `required` to include every key in `properties`\n if (schema.properties) {\n schema.required = Object.keys(schema.properties);\n }\n }\n\n return schema;\n}\n","import type {\n AgentConfig,\n ClientTool,\n SessionId,\n StreamCallbacks,\n} from \"./types\";\nimport { AgentSession } from \"./session\";\n\nconst DEFAULT_BASE_URL = \"https://api.buildship.run\";\n\n/**\n * Main entry point for interacting with a BuildShip agent.\n *\n * @example\n * ```ts\n * import { BuildShipAgent } from \"buildship-agent-sdk/core\";\n *\n * const agent = new BuildShipAgent({\n * agentId: \"your-agent-id\",\n * accessKey: \"your-access-key\",\n * });\n *\n * const session = await agent.execute(\"Hello!\", {\n * onText: (text) => console.log(text),\n * onComplete: (fullText) => console.log(\"Done!\", fullText),\n * });\n * ```\n */\nexport class BuildShipAgent {\n /** @internal */ readonly _agentId: string;\n /** @internal */ readonly _accessKey?: string;\n /** @internal */ readonly _baseUrl: string;\n /** @internal */ readonly _clientTools = new Map<string, ClientTool>();\n\n constructor(config: AgentConfig) {\n if (!config.agentId) {\n throw new Error(\"BuildShipAgent: agentId is required\");\n }\n this._agentId = config.agentId;\n this._accessKey = config.accessKey;\n this._baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n }\n\n /**\n * The URL for the agent's execute endpoint.\n * @internal\n */\n get _url(): string {\n return `${this._baseUrl}/executeAgent/${this._agentId}`;\n }\n\n /**\n * Build the authorization / common headers.\n * @internal\n */\n _buildHeaders(sessionId?: SessionId): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this._accessKey) {\n headers[\"Authorization\"] = `Bearer ${this._accessKey}`;\n }\n if (sessionId) {\n headers[\"X-BuildShip-Agent-Session-ID\"] = sessionId;\n }\n return headers;\n }\n\n // ─── Public API ────────────────────────────────────────────────────\n\n /**\n * Start a new conversation.\n *\n * Creates a fresh session and sends the first message.\n *\n * @param message - The message to send\n * @param callbacks - Event handlers for the stream\n * @param context - Optional additional context data\n * @returns The new session\n */\n async execute(\n message: string,\n callbacks: StreamCallbacks,\n context?: Record<string, any>,\n ): Promise<AgentSession> {\n const session = new AgentSession(this);\n await session.execute(message, callbacks, context);\n return session;\n }\n\n /**\n * Get an existing session by ID to continue a conversation.\n *\n * @param sessionId - The session ID from a previous conversation\n * @returns The session object\n */\n session(sessionId: SessionId | string): AgentSession {\n if (!sessionId) {\n throw new Error(\"BuildShipAgent.session(): sessionId is required\");\n }\n return new AgentSession(this, sessionId as SessionId);\n }\n\n /**\n * Register a client-side tool that the agent can call.\n */\n registerClientTool(tool: ClientTool): void {\n if (!tool.name) {\n throw new Error(\"registerClientTool: tool.name is required\");\n }\n this._clientTools.set(tool.name, tool);\n }\n\n /**\n * Remove a registered client tool.\n */\n unregisterClientTool(name: string): void {\n this._clientTools.delete(name);\n }\n}\n"],"mappings":"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","names":["import_zod"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts","../../src/core/stream.ts","../../src/core/session.ts","../../src/core/agent.ts"],"sourcesContent":["// ─── Classes ─────────────────────────────────────────────────────────────────\nexport { BuildShipAgent } from \"./agent\";\nexport { AgentSession } from \"./session\";\n\n// ─── Stream executor ─────────────────────────────────────────────────────────\nexport { executeStream } from \"./stream\";\n\n// ─── Zod (re-exported for convenience) ───────────────────────────────────────\nexport { z, toJSONSchema } from \"zod\";\nexport type { ZodSchema } from \"zod\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\nexport type {\n AgentConfig,\n SessionId,\n ToolType,\n StreamCallbacks,\n StreamOptions,\n ExecuteRequestBody,\n ClientTool,\n PausedToolInfo,\n // Stream event types (for advanced consumers)\n StreamEvent,\n StreamEventMeta,\n TextDeltaEvent,\n ReasoningDeltaEvent,\n AgentHandoffEvent,\n ToolCallStartEvent,\n ToolCallEndEvent,\n RunErrorEvent,\n} from \"./types\";\n","import type { StreamEvent, StreamOptions, SessionId } from \"./types\";\n\n/** Safely parse a value as JSON if it's a string, otherwise return as-is. */\nfunction tryParseJSON(value: unknown): any {\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n return value;\n}\n\n/**\n * Fatal error — will NOT be retried.\n */\nclass FatalStreamError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message);\n this.name = \"FatalStreamError\";\n }\n}\n\n/**\n * Opens an SSE connection to the BuildShip agent endpoint using native\n * `fetch` + `ReadableStream`, parses events, and dispatches to the\n * appropriate callbacks.\n *\n * Zero runtime dependencies — works in both browser and Node.js.\n *\n * @internal\n */\nexport async function executeStream(options: StreamOptions): Promise<void> {\n const {\n url,\n body,\n headers,\n callbacks,\n clientTools,\n signal,\n onSessionId,\n onPaused,\n onAutoResume,\n onResponse,\n } = options;\n\n let fullText = \"\";\n\n // Track pending auto-resume operations so we don't call onComplete prematurely\n const pendingAutoResumes: Promise<void>[] = [];\n\n // ── Make the request ────────────────────────────────────────────────\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n ...headers,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n // ── Extract session ID and name from response headers ──────────────\n const sessionId = response.headers.get(\"X-BuildShip-Agent-Session-ID\");\n if (sessionId && onSessionId) {\n const sessionName = response.headers.get(\"X-BuildShip-Agent-Session-Name\") || undefined;\n onSessionId(sessionId as SessionId, sessionName);\n }\n\n // Expose the raw Response object\n onResponse?.(response);\n\n // ── Handle HTTP errors ─────────────────────────────────────────────\n if (!response.ok) {\n let errorBody = \"\";\n try {\n errorBody = await response.text();\n } catch {\n // ignore\n }\n const error = new FatalStreamError(\n `HTTP ${response.status}: ${errorBody || response.statusText}`,\n response.status,\n );\n callbacks.onError?.(error);\n throw error;\n }\n\n // ── Read the SSE stream ────────────────────────────────────────────\n if (!response.body) {\n callbacks.onComplete?.(fullText);\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const trimmedPart = part.trim();\n if (!trimmedPart) continue;\n\n // Extract the data field from SSE format\n let jsonStr = \"\";\n for (const line of trimmedPart.split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n jsonStr += line.slice(6);\n } else if (line.startsWith(\"data:\")) {\n jsonStr += line.slice(5);\n }\n }\n\n jsonStr = jsonStr.trim();\n if (!jsonStr) continue;\n\n let raw: any;\n try {\n raw = JSON.parse(jsonStr);\n } catch {\n // Skip malformed events\n continue;\n }\n\n // Normalize backend event type names (llm_text_delta → text_delta, etc.)\n const streamEvent = normalizeEvent(raw) as StreamEvent;\n\n handleEvent(\n streamEvent,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n\n // Accumulate text\n if (streamEvent.type === \"text_delta\") {\n fullText += streamEvent.data;\n }\n }\n }\n\n // Process any remaining data in buffer\n if (buffer.trim()) {\n let jsonStr = \"\";\n for (const line of buffer.trim().split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n jsonStr += line.slice(6);\n } else if (line.startsWith(\"data:\")) {\n jsonStr += line.slice(5);\n }\n }\n\n jsonStr = jsonStr.trim();\n if (jsonStr) {\n try {\n const raw = JSON.parse(jsonStr);\n const streamEvent = normalizeEvent(raw) as StreamEvent;\n handleEvent(\n streamEvent,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n if (streamEvent.type === \"text_delta\") {\n fullText += streamEvent.data;\n }\n } catch {\n // Skip malformed trailing data\n }\n }\n }\n } catch (err) {\n // AbortError — re-throw\n if (err instanceof Error && err.name === \"AbortError\") {\n throw err;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n callbacks.onError?.(error);\n throw error;\n }\n\n // Wait for any pending auto-resume handlers before signaling completion\n if (pendingAutoResumes.length > 0) {\n await Promise.allSettled(pendingAutoResumes);\n }\n\n callbacks.onComplete?.(fullText);\n}\n\n/**\n * Normalize backend event type names.\n * The backend sends `llm_text_delta` / `llm_reasoning_delta` but the SDK\n * exposes them as `text_delta` / `reasoning_delta`.\n * @internal\n */\nfunction normalizeEvent(raw: any): any {\n const typeMap: Record<string, string> = {\n llm_text_delta: \"text_delta\",\n llm_reasoning_delta: \"reasoning_delta\",\n };\n if (raw && typeof raw.type === \"string\" && typeMap[raw.type]) {\n raw.type = typeMap[raw.type];\n }\n return raw;\n}\n\n/**\n * Dispatch a parsed stream event to the appropriate callbacks.\n * @internal\n */\nfunction handleEvent(\n event: StreamEvent,\n _fullText: string,\n callbacks: StreamOptions[\"callbacks\"],\n clientTools: StreamOptions[\"clientTools\"],\n onPaused: StreamOptions[\"onPaused\"],\n onAutoResume: StreamOptions[\"onAutoResume\"],\n pendingAutoResumes: Promise<void>[],\n): void {\n // Notify raw event consumers\n callbacks.onEvent?.(event);\n\n switch (event.type) {\n case \"text_delta\": {\n callbacks.onText?.(event.data);\n break;\n }\n\n case \"reasoning_delta\": {\n callbacks.onReasoning?.(event.data.delta, event.data.index);\n break;\n }\n\n case \"agent_handoff\": {\n callbacks.onAgentHandoff?.(event.data.agentName);\n break;\n }\n\n case \"tool_call_start\": {\n const { callId, toolName, toolType, inputs: rawInputs, paused } = event.data;\n // Backend sends toolCall.arguments as a JSON string — parse it\n const inputs = tryParseJSON(rawInputs);\n\n // Notify callback\n callbacks.onToolStart?.(toolName, toolType);\n\n // Handle client tools\n if (toolType === \"client\") {\n const tool = clientTools.get(toolName);\n if (tool) {\n if (paused && tool.handler) {\n // Blocking tool with handler → auto-execute and resume\n const handlerPromise = (async () => {\n try {\n const result = await tool.handler!(inputs);\n await onAutoResume?.(callId, result);\n } catch {\n // If handler fails, still call onPaused so user can decide\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n })();\n pendingAutoResumes.push(handlerPromise);\n } else if (paused) {\n // Blocking tool without handler → pause for user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n } else if (tool.handler) {\n // Fire-and-forget tool with handler\n try {\n tool.handler(inputs);\n } catch {\n // Swallow errors on fire-and-forget\n }\n }\n } else if (paused) {\n // No registered tool but paused — notify user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n }\n break;\n }\n\n case \"tool_call_end\": {\n const { toolName, result, error } = event.data;\n callbacks.onToolEnd?.(toolName, result, error);\n break;\n }\n\n case \"run_error\": {\n const { message, code } = event.data;\n const error = new Error(message);\n if (code != null) (error as any).code = code;\n callbacks.onError?.(error);\n break;\n }\n }\n}\n","import type {\n SessionId,\n StreamCallbacks,\n PausedToolInfo,\n ExecuteRequestBody,\n} from \"./types\";\nimport type { BuildShipAgent } from \"./agent\";\nimport { executeStream } from \"./stream\";\nimport { toJSONSchema, type ZodSchema } from \"zod\";\n\n/**\n * Represents a conversation session with a BuildShip agent.\n *\n * Sessions maintain history across multiple turns and support\n * pause/resume for blocking client tools.\n */\nexport class AgentSession {\n /** @internal */ private _agent: BuildShipAgent;\n /** @internal */ private _sessionId: SessionId | undefined;\n /** @internal */ private _paused = false;\n /** @internal */ private _pausedToolInfo: PausedToolInfo | null = null;\n /** @internal */ private _abortController: AbortController | null = null;\n\n /** @internal */\n constructor(agent: BuildShipAgent, sessionId?: SessionId) {\n this._agent = agent;\n this._sessionId = sessionId;\n }\n\n // ─── Public API ────────────────────────────────────────────────────\n\n /**\n * Send a message in this session.\n *\n * @param message - The message to send\n * @param callbacks - Event handlers for the stream\n * @param context - Optional additional context data\n * @returns This session (for chaining)\n */\n async execute(\n message: string,\n callbacks: StreamCallbacks,\n context?: Record<string, any>,\n ): Promise<AgentSession> {\n this._paused = false;\n this._pausedToolInfo = null;\n\n const body: ExecuteRequestBody = {\n input: message,\n stream: true,\n };\n\n // Attach context as top-level properties if provided\n if (context) {\n Object.assign(body, context);\n }\n\n // Include client tool definitions\n const clientToolDefs = this._getClientToolDefs();\n if (clientToolDefs.length > 0) {\n body.clientTools = clientToolDefs;\n }\n\n await this._run(body, callbacks);\n return this;\n }\n\n /**\n * Resume a paused session with a tool result.\n *\n * @param result - The result to send back to the agent\n * @param callbacks - Event handlers for the resumed stream\n * @returns This session (for chaining)\n */\n async resume(result: any, callbacks: StreamCallbacks): Promise<AgentSession> {\n if (!this._paused || !this._pausedToolInfo) {\n throw new Error(\n \"AgentSession.resume(): session is not paused. Check isPaused() first.\",\n );\n }\n\n const body: ExecuteRequestBody = {\n stream: true,\n toolCallResult: {\n callId: this._pausedToolInfo.callId,\n result,\n },\n };\n\n // Include client tool definitions for resume requests too\n const clientToolDefs = this._getClientToolDefs();\n if (clientToolDefs.length > 0) {\n body.clientTools = clientToolDefs;\n }\n\n this._paused = false;\n this._pausedToolInfo = null;\n\n await this._run(body, callbacks);\n return this;\n }\n\n /**\n * Check if this session is waiting for a tool result.\n */\n isPaused(): boolean {\n return this._paused;\n }\n\n /**\n * Get information about the paused tool call.\n * Returns `null` if the session is not paused.\n */\n getPausedTool(): PausedToolInfo | null {\n return this._pausedToolInfo;\n }\n\n /**\n * Get the session ID.\n * May be `undefined` if the session hasn't executed yet.\n */\n getSessionId(): SessionId {\n if (!this._sessionId) {\n throw new Error(\n \"AgentSession.getSessionId(): session ID not yet available. Call execute() first.\",\n );\n }\n return this._sessionId;\n }\n\n /**\n * Cancel the current streaming operation.\n */\n abort(): void {\n this._abortController?.abort();\n this._abortController = null;\n }\n\n // ─── Private helpers ───────────────────────────────────────────────\n\n /** @internal */\n private async _run(\n body: ExecuteRequestBody,\n callbacks: StreamCallbacks,\n ): Promise<void> {\n // Create a fresh abort controller for this run\n this._abortController = new AbortController();\n\n await executeStream({\n url: this._agent._url,\n body,\n headers: this._agent._buildHeaders(this._sessionId),\n callbacks,\n clientTools: this._agent._clientTools,\n signal: this._abortController.signal,\n\n onSessionId: (id) => {\n this._sessionId = id;\n },\n\n onPaused: (info) => {\n this._paused = true;\n this._pausedToolInfo = info;\n },\n\n onAutoResume: async (callId, result) => {\n // Auto-resume: send the tool result back immediately\n const resumeBody: ExecuteRequestBody = {\n stream: true,\n toolCallResult: { callId, result },\n };\n\n const clientToolDefs = this._getClientToolDefs();\n if (clientToolDefs.length > 0) {\n resumeBody.clientTools = clientToolDefs;\n }\n\n await this._run(resumeBody, callbacks);\n },\n });\n }\n\n /** @internal */\n private _getClientToolDefs() {\n const defs: ExecuteRequestBody[\"clientTools\"] = [];\n for (const tool of this._agent._clientTools.values()) {\n defs.push({\n name: tool.name,\n description: tool.description,\n parameters: resolveParameters(tool.parameters),\n await: tool.await,\n });\n }\n return defs;\n }\n}\n\n/**\n * Convert tool parameters to a JSON Schema object.\n * - If it's a Zod schema, uses Zod's built-in `toJSONSchema` to convert.\n * - Always ensures `additionalProperties: false` is set (required by the backend).\n * - Always ensures `required` includes every key in `properties` (Gemini requirement).\n * @internal\n */\nfunction resolveParameters(params: any): Record<string, any> {\n let schema: Record<string, any>;\n\n // Detect Zod schema: ZodType instances have a `_def` property\n if (params && typeof params === \"object\" && \"_def\" in params) {\n schema = toJSONSchema(params as ZodSchema) as Record<string, any>;\n // Remove $schema key if present\n delete schema.$schema;\n } else {\n schema = { ...params };\n }\n\n if (schema.type === \"object\") {\n // Backend requires additionalProperties: false\n schema.additionalProperties = false;\n\n // Gemini requires `required` to include every key in `properties`\n if (schema.properties) {\n schema.required = Object.keys(schema.properties);\n }\n }\n\n return schema;\n}\n","import type {\n AgentConfig,\n ClientTool,\n SessionId,\n StreamCallbacks,\n} from \"./types\";\nimport { AgentSession } from \"./session\";\n\nconst DEFAULT_BASE_URL = \"https://api.buildship.run\";\n\n/**\n * Main entry point for interacting with a BuildShip agent.\n *\n * @example\n * ```ts\n * import { BuildShipAgent } from \"buildship-agent-sdk/core\";\n *\n * const agent = new BuildShipAgent({\n * agentId: \"your-agent-id\",\n * accessKey: \"your-access-key\",\n * });\n *\n * const session = await agent.execute(\"Hello!\", {\n * onText: (text) => console.log(text),\n * onComplete: (fullText) => console.log(\"Done!\", fullText),\n * });\n * ```\n */\nexport class BuildShipAgent {\n /** @internal */ readonly _agentId: string;\n /** @internal */ readonly _accessKey?: string;\n /** @internal */ readonly _baseUrl: string;\n /** @internal */ readonly _clientTools = new Map<string, ClientTool>();\n\n constructor(config: AgentConfig) {\n if (!config.agentId) {\n throw new Error(\"BuildShipAgent: agentId is required\");\n }\n this._agentId = config.agentId;\n this._accessKey = config.accessKey;\n this._baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n }\n\n /**\n * The URL for the agent's execute endpoint.\n * @internal\n */\n get _url(): string {\n return `${this._baseUrl}/executeAgent/${this._agentId}`;\n }\n\n /**\n * Build the authorization / common headers.\n * @internal\n */\n _buildHeaders(sessionId?: SessionId): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this._accessKey) {\n headers[\"Authorization\"] = `Bearer ${this._accessKey}`;\n }\n if (sessionId) {\n headers[\"X-BuildShip-Agent-Session-ID\"] = sessionId;\n }\n return headers;\n }\n\n // ─── Public API ────────────────────────────────────────────────────\n\n /**\n * Start a new conversation.\n *\n * Creates a fresh session and sends the first message.\n *\n * @param message - The message to send\n * @param callbacks - Event handlers for the stream\n * @param context - Optional additional context data\n * @returns The new session\n */\n async execute(\n message: string,\n callbacks: StreamCallbacks,\n context?: Record<string, any>,\n ): Promise<AgentSession> {\n const session = new AgentSession(this);\n await session.execute(message, callbacks, context);\n return session;\n }\n\n /**\n * Get an existing session by ID to continue a conversation.\n *\n * @param sessionId - The session ID from a previous conversation\n * @returns The session object\n */\n session(sessionId: SessionId | string): AgentSession {\n if (!sessionId) {\n throw new Error(\"BuildShipAgent.session(): sessionId is required\");\n }\n return new AgentSession(this, sessionId as SessionId);\n }\n\n /**\n * Register a client-side tool that the agent can call.\n */\n registerClientTool(tool: ClientTool): void {\n if (!tool.name) {\n throw new Error(\"registerClientTool: tool.name is required\");\n }\n this._clientTools.set(tool.name, tool);\n }\n\n /**\n * Remove a registered client tool.\n */\n unregisterClientTool(name: string): void {\n this._clientTools.delete(name);\n }\n}\n"],"mappings":"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","names":["import_zod"]}
|
package/dist/core/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SessionId, a as StreamCallbacks, P as PausedToolInfo, C as ClientTool, A as AgentConfig, b as StreamOptions } from '../types-
|
|
2
|
-
export { f as AgentHandoffEvent, E as ExecuteRequestBody, R as ReasoningDeltaEvent, c as StreamEvent, d as StreamEventMeta, e as TextDeltaEvent, h as ToolCallEndEvent, g as ToolCallStartEvent, T as ToolType } from '../types-
|
|
1
|
+
import { S as SessionId, a as StreamCallbacks, P as PausedToolInfo, C as ClientTool, A as AgentConfig, b as StreamOptions } from '../types-DryLPWU9.cjs';
|
|
2
|
+
export { f as AgentHandoffEvent, E as ExecuteRequestBody, R as ReasoningDeltaEvent, i as RunErrorEvent, c as StreamEvent, d as StreamEventMeta, e as TextDeltaEvent, h as ToolCallEndEvent, g as ToolCallStartEvent, T as ToolType } from '../types-DryLPWU9.cjs';
|
|
3
3
|
export { ZodSchema, toJSONSchema, z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -120,10 +120,11 @@ declare class BuildShipAgent {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
* Opens an SSE connection to the BuildShip agent endpoint using native
|
|
124
|
-
* parses events, and dispatches to the
|
|
123
|
+
* Opens an SSE connection to the BuildShip agent endpoint using native
|
|
124
|
+
* `fetch` + `ReadableStream`, parses events, and dispatches to the
|
|
125
|
+
* appropriate callbacks.
|
|
125
126
|
*
|
|
126
|
-
*
|
|
127
|
+
* Zero runtime dependencies — works in both browser and Node.js.
|
|
127
128
|
*
|
|
128
129
|
* @internal
|
|
129
130
|
*/
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SessionId, a as StreamCallbacks, P as PausedToolInfo, C as ClientTool, A as AgentConfig, b as StreamOptions } from '../types-
|
|
2
|
-
export { f as AgentHandoffEvent, E as ExecuteRequestBody, R as ReasoningDeltaEvent, c as StreamEvent, d as StreamEventMeta, e as TextDeltaEvent, h as ToolCallEndEvent, g as ToolCallStartEvent, T as ToolType } from '../types-
|
|
1
|
+
import { S as SessionId, a as StreamCallbacks, P as PausedToolInfo, C as ClientTool, A as AgentConfig, b as StreamOptions } from '../types-DryLPWU9.js';
|
|
2
|
+
export { f as AgentHandoffEvent, E as ExecuteRequestBody, R as ReasoningDeltaEvent, i as RunErrorEvent, c as StreamEvent, d as StreamEventMeta, e as TextDeltaEvent, h as ToolCallEndEvent, g as ToolCallStartEvent, T as ToolType } from '../types-DryLPWU9.js';
|
|
3
3
|
export { ZodSchema, toJSONSchema, z } from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -120,10 +120,11 @@ declare class BuildShipAgent {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
* Opens an SSE connection to the BuildShip agent endpoint using native
|
|
124
|
-
* parses events, and dispatches to the
|
|
123
|
+
* Opens an SSE connection to the BuildShip agent endpoint using native
|
|
124
|
+
* `fetch` + `ReadableStream`, parses events, and dispatches to the
|
|
125
|
+
* appropriate callbacks.
|
|
125
126
|
*
|
|
126
|
-
*
|
|
127
|
+
* Zero runtime dependencies — works in both browser and Node.js.
|
|
127
128
|
*
|
|
128
129
|
* @internal
|
|
129
130
|
*/
|
package/dist/core/index.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
// src/core/stream.ts
|
|
2
|
+
function tryParseJSON(value) {
|
|
3
|
+
if (typeof value === "string") {
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(value);
|
|
6
|
+
} catch {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
2
12
|
var FatalStreamError = class extends Error {
|
|
3
13
|
constructor(message, statusCode) {
|
|
4
14
|
super(message);
|
|
@@ -33,7 +43,8 @@ async function executeStream(options) {
|
|
|
33
43
|
});
|
|
34
44
|
const sessionId = response.headers.get("X-BuildShip-Agent-Session-ID");
|
|
35
45
|
if (sessionId && onSessionId) {
|
|
36
|
-
|
|
46
|
+
const sessionName = response.headers.get("X-BuildShip-Agent-Session-Name") || void 0;
|
|
47
|
+
onSessionId(sessionId, sessionName);
|
|
37
48
|
}
|
|
38
49
|
onResponse?.(response);
|
|
39
50
|
if (!response.ok) {
|
|
@@ -50,9 +61,8 @@ async function executeStream(options) {
|
|
|
50
61
|
throw error;
|
|
51
62
|
}
|
|
52
63
|
if (!response.body) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
throw error;
|
|
64
|
+
callbacks.onComplete?.(fullText);
|
|
65
|
+
return;
|
|
56
66
|
}
|
|
57
67
|
const reader = response.body.getReader();
|
|
58
68
|
const decoder = new TextDecoder();
|
|
@@ -65,9 +75,17 @@ async function executeStream(options) {
|
|
|
65
75
|
const parts = buffer.split("\n\n");
|
|
66
76
|
buffer = parts.pop() || "";
|
|
67
77
|
for (const part of parts) {
|
|
68
|
-
const
|
|
69
|
-
if (!
|
|
70
|
-
|
|
78
|
+
const trimmedPart = part.trim();
|
|
79
|
+
if (!trimmedPart) continue;
|
|
80
|
+
let jsonStr = "";
|
|
81
|
+
for (const line of trimmedPart.split("\n")) {
|
|
82
|
+
if (line.startsWith("data: ")) {
|
|
83
|
+
jsonStr += line.slice(6);
|
|
84
|
+
} else if (line.startsWith("data:")) {
|
|
85
|
+
jsonStr += line.slice(5);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
jsonStr = jsonStr.trim();
|
|
71
89
|
if (!jsonStr) continue;
|
|
72
90
|
let raw;
|
|
73
91
|
try {
|
|
@@ -75,9 +93,9 @@ async function executeStream(options) {
|
|
|
75
93
|
} catch {
|
|
76
94
|
continue;
|
|
77
95
|
}
|
|
78
|
-
const
|
|
96
|
+
const streamEvent = normalizeEvent(raw);
|
|
79
97
|
handleEvent(
|
|
80
|
-
|
|
98
|
+
streamEvent,
|
|
81
99
|
fullText,
|
|
82
100
|
callbacks,
|
|
83
101
|
clientTools,
|
|
@@ -85,39 +103,41 @@ async function executeStream(options) {
|
|
|
85
103
|
onAutoResume,
|
|
86
104
|
pendingAutoResumes
|
|
87
105
|
);
|
|
88
|
-
if (
|
|
89
|
-
fullText +=
|
|
106
|
+
if (streamEvent.type === "text_delta") {
|
|
107
|
+
fullText += streamEvent.data;
|
|
90
108
|
}
|
|
91
109
|
}
|
|
92
110
|
}
|
|
93
111
|
if (buffer.trim()) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
let jsonStr = "";
|
|
113
|
+
for (const line of buffer.trim().split("\n")) {
|
|
114
|
+
if (line.startsWith("data: ")) {
|
|
115
|
+
jsonStr += line.slice(6);
|
|
116
|
+
} else if (line.startsWith("data:")) {
|
|
117
|
+
jsonStr += line.slice(5);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
jsonStr = jsonStr.trim();
|
|
121
|
+
if (jsonStr) {
|
|
122
|
+
try {
|
|
123
|
+
const raw = JSON.parse(jsonStr);
|
|
124
|
+
const streamEvent = normalizeEvent(raw);
|
|
125
|
+
handleEvent(
|
|
126
|
+
streamEvent,
|
|
127
|
+
fullText,
|
|
128
|
+
callbacks,
|
|
129
|
+
clientTools,
|
|
130
|
+
onPaused,
|
|
131
|
+
onAutoResume,
|
|
132
|
+
pendingAutoResumes
|
|
133
|
+
);
|
|
134
|
+
if (streamEvent.type === "text_delta") {
|
|
135
|
+
fullText += streamEvent.data;
|
|
113
136
|
}
|
|
137
|
+
} catch {
|
|
114
138
|
}
|
|
115
139
|
}
|
|
116
140
|
}
|
|
117
|
-
if (pendingAutoResumes.length > 0) {
|
|
118
|
-
await Promise.allSettled(pendingAutoResumes);
|
|
119
|
-
}
|
|
120
|
-
callbacks.onComplete?.(fullText);
|
|
121
141
|
} catch (err) {
|
|
122
142
|
if (err instanceof Error && err.name === "AbortError") {
|
|
123
143
|
throw err;
|
|
@@ -126,6 +146,10 @@ async function executeStream(options) {
|
|
|
126
146
|
callbacks.onError?.(error);
|
|
127
147
|
throw error;
|
|
128
148
|
}
|
|
149
|
+
if (pendingAutoResumes.length > 0) {
|
|
150
|
+
await Promise.allSettled(pendingAutoResumes);
|
|
151
|
+
}
|
|
152
|
+
callbacks.onComplete?.(fullText);
|
|
129
153
|
}
|
|
130
154
|
function normalizeEvent(raw) {
|
|
131
155
|
const typeMap = {
|
|
@@ -153,7 +177,8 @@ function handleEvent(event, _fullText, callbacks, clientTools, onPaused, onAutoR
|
|
|
153
177
|
break;
|
|
154
178
|
}
|
|
155
179
|
case "tool_call_start": {
|
|
156
|
-
const { callId, toolName, toolType, inputs, paused } = event.data;
|
|
180
|
+
const { callId, toolName, toolType, inputs: rawInputs, paused } = event.data;
|
|
181
|
+
const inputs = tryParseJSON(rawInputs);
|
|
157
182
|
callbacks.onToolStart?.(toolName, toolType);
|
|
158
183
|
if (toolType === "client") {
|
|
159
184
|
const tool = clientTools.get(toolName);
|
|
@@ -190,6 +215,13 @@ function handleEvent(event, _fullText, callbacks, clientTools, onPaused, onAutoR
|
|
|
190
215
|
callbacks.onToolEnd?.(toolName, result, error);
|
|
191
216
|
break;
|
|
192
217
|
}
|
|
218
|
+
case "run_error": {
|
|
219
|
+
const { message, code } = event.data;
|
|
220
|
+
const error = new Error(message);
|
|
221
|
+
if (code != null) error.code = code;
|
|
222
|
+
callbacks.onError?.(error);
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
193
225
|
}
|
|
194
226
|
}
|
|
195
227
|
|