cli-pipe-provider 0.1.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/README.md ADDED
@@ -0,0 +1,230 @@
1
+ # cli-pipe-provider
2
+
3
+ A [pi-ai](https://github.com/badlogic/pi-mono) provider for CLI tools that produce `stream-json` output, with built-in MCP tool bridge support.
4
+
5
+ ## Prerequisites
6
+
7
+ - A CLI that supports `-p --output-format stream-json` (pipe mode with JSON streaming)
8
+ - Node.js >= 20
9
+ - `@mariozechner/pi-ai` `^0.54.0` (peer dependency)
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install cli-pipe-provider
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ There are two modes: **simple streaming** (no tools) and **streaming with MCP tool bridge**.
20
+
21
+ ### Simple streaming (no tools)
22
+
23
+ If you just need text/thinking streaming without tool use:
24
+
25
+ ```ts
26
+ import { createCliPipeProvider } from "cli-pipe-provider";
27
+
28
+ const pipe = createCliPipeProvider({
29
+ command: "claude",
30
+ bridgeEntryPoint: "/dev/null", // not used when tools are disabled
31
+ mcpServerName: "unused",
32
+ });
33
+
34
+ pipe.register();
35
+
36
+ const model = pipe.createModel({ modelId: "claude-sonnet-4-6" });
37
+
38
+ const stream = pipe.stream(
39
+ model,
40
+ {
41
+ systemPrompt: "You are a helpful assistant.",
42
+ messages: [{ role: "user", content: "Hello!" }],
43
+ },
44
+ { enableTools: false },
45
+ );
46
+
47
+ for await (const event of stream) {
48
+ if (event.type === "text_delta") {
49
+ process.stdout.write(event.delta);
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Streaming with tool use
55
+
56
+ To give the CLI access to your tools, you need two files:
57
+
58
+ #### 1. Write a bridge entry script
59
+
60
+ This is a standalone Node.js file that the CLI spawns as an MCP server. It exposes your tools over the MCP protocol.
61
+
62
+ **Using `serveMcpBridge` with pi-ai agent tools:**
63
+
64
+ ```ts
65
+ // bridge.ts
66
+ import { serveMcpBridge } from "cli-pipe-provider";
67
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
68
+
69
+ const tools: AgentTool[] = [
70
+ {
71
+ name: "get_weather",
72
+ description: "Get the weather for a city",
73
+ parameters: Type.Object({
74
+ city: Type.String({ description: "City name" }),
75
+ }),
76
+ async execute(callId, args) {
77
+ return {
78
+ content: [{ type: "text", text: `Weather in ${args.city}: sunny, 22°C` }],
79
+ };
80
+ },
81
+ },
82
+ ];
83
+
84
+ await serveMcpBridge(tools, { serverName: "my-app" });
85
+ ```
86
+
87
+ **Or using a raw MCP server with `@modelcontextprotocol/sdk`:**
88
+
89
+ ```ts
90
+ // bridge.ts
91
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
92
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
93
+
94
+ const server = new McpServer({ name: "my-tools", version: "1.0.0" });
95
+
96
+ server.tool("get_weather", { city: { type: "string" } }, async ({ city }) => ({
97
+ content: [{ type: "text", text: `Weather in ${city}: sunny, 22°C` }],
98
+ }));
99
+
100
+ const transport = new StdioServerTransport();
101
+ await server.connect(transport);
102
+ ```
103
+
104
+ #### 2. Create the provider and stream
105
+
106
+ Point `bridgeEntryPoint` at the compiled bridge script:
107
+
108
+ ```ts
109
+ import { createCliPipeProvider } from "cli-pipe-provider";
110
+
111
+ const pipe = createCliPipeProvider({
112
+ command: "claude",
113
+ bridgeEntryPoint: "/absolute/path/to/dist/bridge.js",
114
+ mcpServerName: "my-app",
115
+ });
116
+
117
+ pipe.register();
118
+
119
+ const model = pipe.createModel({ modelId: "claude-sonnet-4-6" });
120
+
121
+ const stream = pipe.stream(
122
+ model,
123
+ {
124
+ systemPrompt: "You have a get_weather tool. Use it to answer questions.",
125
+ messages: [{ role: "user", content: "What's the weather in Tokyo?" }],
126
+ },
127
+ );
128
+
129
+ for await (const event of stream) {
130
+ if (event.type === "text_delta") {
131
+ process.stdout.write(event.delta);
132
+ }
133
+ if (event.type === "toolcall_end") {
134
+ console.log("\nTool called:", event.toolCall.name, event.toolCall.arguments);
135
+ }
136
+ }
137
+ ```
138
+
139
+ The provider writes a temporary MCP config, spawns the CLI with `--mcp-config`, and the CLI discovers and calls your tools during its agentic loop. The config is cleaned up automatically when the stream ends.
140
+
141
+ ## Stream options
142
+
143
+ ```ts
144
+ pipe.stream(model, context, {
145
+ // Enable/disable MCP tool bridge (default: true)
146
+ enableTools: true,
147
+
148
+ // Thinking/reasoning level
149
+ reasoning: "high",
150
+
151
+ // Additional CLI args for the bridge script
152
+ bridgeArgs: ["--verbose"],
153
+
154
+ // Session ID for conversation continuity
155
+ sessionId: "my-session",
156
+
157
+ // Abort signal
158
+ signal: controller.signal,
159
+ });
160
+ ```
161
+
162
+ ## Events emitted
163
+
164
+ | Event | Description |
165
+ |---|---|
166
+ | `start` | Stream opened, partial output available |
167
+ | `text_start` / `text_delta` / `text_end` | Text content streaming |
168
+ | `thinking_start` / `thinking_delta` / `thinking_end` | Reasoning/thinking blocks |
169
+ | `toolcall_start` / `toolcall_delta` / `toolcall_end` | Tool use blocks |
170
+ | `done` | Stream completed successfully |
171
+ | `error` | Stream ended with an error |
172
+
173
+ ## API
174
+
175
+ ### `createCliPipeProvider(options)`
176
+
177
+ Factory that returns a provider object with `register()`, `createModel()`, `stream()`, and `streamSimple()`.
178
+
179
+ ```ts
180
+ const pipe = createCliPipeProvider({
181
+ command: string; // CLI binary to spawn
182
+ bridgeEntryPoint: string; // absolute path to compiled bridge script
183
+ mcpServerName: string; // used for --allowedTools glob
184
+ bridgeArgs?: string[]; // default CLI args passed to bridge script
185
+ resolveBridgeArgs?: (model) => string[]; // dynamic args from model metadata
186
+ });
187
+ ```
188
+
189
+ Args are merged in order: `resolveBridgeArgs(model)` + provider `bridgeArgs` + per-stream `bridgeArgs`.
190
+
191
+ ### `serveMcpBridge(tools, options?)`
192
+
193
+ Start an MCP stdio server that exposes the given `AgentTool[]` array. Called from your bridge entry script.
194
+
195
+ ```ts
196
+ await serveMcpBridge(tools, {
197
+ serverName: "my-app", // default: "cli-pipe-provider"
198
+ serverVersion: "1.0.0", // default: "0.1.0"
199
+ });
200
+ ```
201
+
202
+ ### `checkCliAvailable(command)`
203
+
204
+ Check whether the CLI binary is installed and accessible.
205
+
206
+ ```ts
207
+ import { checkCliAvailable } from "cli-pipe-provider";
208
+
209
+ const { available, version, error } = await checkCliAvailable("claude");
210
+ if (!available) {
211
+ console.error("CLI not found:", error);
212
+ }
213
+ ```
214
+
215
+ ### `typeboxToJsonSchema(schema)`
216
+
217
+ Utility to convert a TypeBox schema to a clean JSON Schema object (strips TypeBox-internal symbols). Used internally by `serveMcpBridge` but exported for convenience.
218
+
219
+ ## How it works
220
+
221
+ 1. Registers a custom `cli-pipe` provider with pi-ai
222
+ 2. On each `stream()` call, writes a temporary MCP config pointing at your bridge entry script
223
+ 3. Spawns the CLI in pipe mode with `--output-format stream-json --mcp-config <config> --allowedTools "mcp__<name>__*"`
224
+ 4. The CLI spawns your bridge script, discovers tools via MCP, and calls them during its agentic loop
225
+ 5. Text, thinking, and tool-use events are parsed from stdout and emitted as standard pi-ai `AssistantMessageEvent`s
226
+ 6. The temporary MCP config is cleaned up when the stream ends
227
+
228
+ ## License
229
+
230
+ MIT
@@ -0,0 +1,5 @@
1
+ export { serveMcpBridge } from "./mcp-bridge.js";
2
+ export { createCliPipeProvider, CLI_PIPE_API } from "./provider.js";
3
+ export { checkCliAvailable, typeboxToJsonSchema } from "./utils.js";
4
+ export type { CliPipeProviderOptions, CliPipeStreamOptions, CliPipeProvider, McpBridgeOptions, McpConfig, } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACpE,YAAY,EACV,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,SAAS,GACV,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { serveMcpBridge } from "./mcp-bridge.js";
2
+ export { createCliPipeProvider, CLI_PIPE_API } from "./provider.js";
3
+ export { checkCliAvailable, typeboxToJsonSchema } from "./utils.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
2
+ import type { McpBridgeOptions } from "./types.js";
3
+ /**
4
+ * Start an MCP stdio server that exposes the given tools.
5
+ *
6
+ * Called from a consumer's bridge entry script:
7
+ * import { serveMcpBridge } from "cli-pipe-provider";
8
+ * await serveMcpBridge(myTools, { serverName: "my-app" });
9
+ *
10
+ * The CLI spawns this process and discovers tools via the MCP protocol.
11
+ */
12
+ export declare function serveMcpBridge(tools: AgentTool[], options?: McpBridgeOptions): Promise<void>;
13
+ //# sourceMappingURL=mcp-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-bridge.d.ts","sourceRoot":"","sources":["../src/mcp-bridge.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CA6Df"}
@@ -0,0 +1,67 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
+ import { typeboxToJsonSchema } from "./utils.js";
5
+ /**
6
+ * Start an MCP stdio server that exposes the given tools.
7
+ *
8
+ * Called from a consumer's bridge entry script:
9
+ * import { serveMcpBridge } from "cli-pipe-provider";
10
+ * await serveMcpBridge(myTools, { serverName: "my-app" });
11
+ *
12
+ * The CLI spawns this process and discovers tools via the MCP protocol.
13
+ */
14
+ export async function serveMcpBridge(tools, options) {
15
+ const serverName = options?.serverName ?? "cli-pipe-provider";
16
+ const serverVersion = options?.serverVersion ?? "0.1.0";
17
+ // Build a lookup map
18
+ const toolMap = new Map();
19
+ for (const tool of tools) {
20
+ toolMap.set(tool.name, tool);
21
+ }
22
+ // Create MCP server
23
+ const server = new Server({ name: serverName, version: serverVersion }, { capabilities: { tools: {} } });
24
+ // Handle tools/list
25
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
26
+ return {
27
+ tools: tools.map((tool) => ({
28
+ name: tool.name,
29
+ description: tool.description ?? "",
30
+ inputSchema: typeboxToJsonSchema(tool.parameters),
31
+ })),
32
+ };
33
+ });
34
+ // Handle tools/call
35
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
36
+ const { name, arguments: args } = request.params;
37
+ const tool = toolMap.get(name);
38
+ if (!tool) {
39
+ return {
40
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
41
+ isError: true,
42
+ };
43
+ }
44
+ try {
45
+ const callId = `mcp-${Date.now()}`;
46
+ const result = await tool.execute(callId, args ?? {});
47
+ return {
48
+ content: result.content.map((c) => ({
49
+ type: (c.type ?? "text"),
50
+ text: c.text ?? "",
51
+ })),
52
+ isError: false,
53
+ };
54
+ }
55
+ catch (err) {
56
+ return {
57
+ content: [{ type: "text", text: `Tool error: ${err.message}` }],
58
+ isError: true,
59
+ };
60
+ }
61
+ });
62
+ // Connect to stdio transport
63
+ const transport = new StdioServerTransport();
64
+ await server.connect(transport);
65
+ process.stderr.write(`MCP bridge: serving ${tools.length} tools (${serverName})\n`);
66
+ }
67
+ //# sourceMappingURL=mcp-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-bridge.js","sourceRoot":"","sources":["../src/mcp-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Api } from "@mariozechner/pi-ai";
2
+ import type { CliPipeProviderOptions, CliPipeProvider } from "./types.js";
3
+ /** Custom API identifier for cli-pipe */
4
+ export declare const CLI_PIPE_API: Api;
5
+ /**
6
+ * Create a cli-pipe provider that wraps CLI pipe mode with MCP tool bridge support.
7
+ *
8
+ * ```ts
9
+ * const pipe = createCliPipeProvider({
10
+ * command: "claude", // or any CLI that supports -p --output-format stream-json
11
+ * bridgeEntryPoint: "/path/to/my-bridge.js",
12
+ * mcpServerName: "my-app",
13
+ * });
14
+ * pipe.register();
15
+ * const model = pipe.createModel({ modelId: "claude-sonnet-4-6" });
16
+ * ```
17
+ */
18
+ export declare function createCliPipeProvider(options: CliPipeProviderOptions): CliPipeProvider;
19
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,GAAG,EAOJ,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,sBAAsB,EAMtB,eAAe,EAGhB,MAAM,YAAY,CAAC;AAUpB,yCAAyC;AACzC,eAAO,MAAM,YAAY,EAAiB,GAAG,CAAC;AAsd9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAwDtF"}
@@ -0,0 +1,492 @@
1
+ import { spawn } from "node:child_process";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import * as os from "node:os";
5
+ import { createAssistantMessageEventStream, registerApiProvider } from "@mariozechner/pi-ai";
6
+ import { emptyUsage, parseUsageFromRaw, extractTextContent } from "./utils.js";
7
+ function findLastIndex(arr, predicate) {
8
+ for (let i = arr.length - 1; i >= 0; i--) {
9
+ if (predicate(arr[i]))
10
+ return i;
11
+ }
12
+ return -1;
13
+ }
14
+ /** Custom API identifier for cli-pipe */
15
+ export const CLI_PIPE_API = "cli-pipe";
16
+ // ─── MCP Config Generation ───
17
+ function writeMcpConfig(bridgeEntryPoint, mcpServerName, bridgeArgs) {
18
+ const config = {
19
+ mcpServers: {
20
+ [mcpServerName]: {
21
+ command: "node",
22
+ args: [bridgeEntryPoint, ...bridgeArgs],
23
+ },
24
+ },
25
+ };
26
+ const tmpDir = os.tmpdir();
27
+ const configPath = path.join(tmpDir, `${mcpServerName}-mcp-${Date.now()}.json`);
28
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
29
+ return configPath;
30
+ }
31
+ function cleanupMcpConfig(configPath) {
32
+ try {
33
+ fs.unlinkSync(configPath);
34
+ }
35
+ catch {
36
+ // Best effort cleanup
37
+ }
38
+ }
39
+ // ─── CLI arg building ───
40
+ function buildCliArgs(model, mcpServerName, options, mcpConfigPath) {
41
+ const args = ["-p", "--output-format", "stream-json"];
42
+ if (model.id && model.id !== "default") {
43
+ args.push("--model", model.id);
44
+ }
45
+ if (options?.sessionId) {
46
+ args.push("--session-id", options.sessionId);
47
+ }
48
+ // MCP tool bridge
49
+ if (mcpConfigPath) {
50
+ args.push("--mcp-config", mcpConfigPath);
51
+ args.push("--allowedTools", `mcp__${mcpServerName}__*`);
52
+ }
53
+ return args;
54
+ }
55
+ function buildStdinPayload(context) {
56
+ const parts = [];
57
+ if (context.systemPrompt) {
58
+ parts.push(context.systemPrompt);
59
+ parts.push("\n---\n");
60
+ }
61
+ // Include conversation history for continuity
62
+ // CLI pipe mode is stateless, so we must pass the full context
63
+ if (context.messages.length > 1) {
64
+ parts.push("## Conversation History\n");
65
+ const history = context.messages.slice(0, -1);
66
+ for (const msg of history) {
67
+ if (msg.role === "user") {
68
+ const text = extractTextContent(msg.content);
69
+ parts.push(`User: ${text}`);
70
+ }
71
+ else if (msg.role === "assistant") {
72
+ const content = msg.content;
73
+ const text = extractTextContent(content);
74
+ parts.push(`Assistant: ${text}`);
75
+ }
76
+ }
77
+ parts.push("\n---\n");
78
+ }
79
+ // The last message is the current prompt
80
+ const lastMsg = context.messages[context.messages.length - 1];
81
+ if (lastMsg?.role === "user") {
82
+ parts.push(extractTextContent(lastMsg.content));
83
+ }
84
+ return parts.join("\n");
85
+ }
86
+ // ─── Stream function factory ───
87
+ function createStreamFunction(providerOpts) {
88
+ return (model, context, options) => {
89
+ const eventStream = createAssistantMessageEventStream();
90
+ // Merge bridge args: resolved from model + provider defaults + per-call overrides
91
+ const bridgeArgs = [
92
+ ...(providerOpts.resolveBridgeArgs?.(model) ?? []),
93
+ ...(providerOpts.bridgeArgs ?? []),
94
+ ...(options?.bridgeArgs ?? []),
95
+ ];
96
+ // Generate MCP config if tools are enabled
97
+ const enableTools = options?.enableTools !== false;
98
+ let mcpConfigPath;
99
+ if (enableTools) {
100
+ mcpConfigPath = writeMcpConfig(providerOpts.bridgeEntryPoint, providerOpts.mcpServerName, bridgeArgs);
101
+ }
102
+ const args = buildCliArgs(model, providerOpts.mcpServerName, options, mcpConfigPath);
103
+ const stdin = buildStdinPayload(context);
104
+ // Remove nesting-detection env var to avoid nested invocation errors
105
+ const env = { ...process.env };
106
+ delete env.CLAUDECODE; // runtime env var set by the CLI
107
+ const command = providerOpts.command;
108
+ // onPayload callback
109
+ options?.onPayload?.({ command, args, stdin });
110
+ // Single mutable output object — mutated throughout the stream
111
+ const output = {
112
+ role: "assistant",
113
+ content: [],
114
+ api: CLI_PIPE_API,
115
+ provider: "cli-pipe",
116
+ model: model.id,
117
+ usage: emptyUsage(),
118
+ stopReason: "stop",
119
+ timestamp: Date.now(),
120
+ };
121
+ const proc = spawn(command, args, {
122
+ stdio: ["pipe", "pipe", "pipe"],
123
+ env,
124
+ });
125
+ // Abort handling — kill the process on signal
126
+ if (options?.signal) {
127
+ if (options.signal.aborted) {
128
+ proc.kill("SIGTERM");
129
+ }
130
+ else {
131
+ options.signal.addEventListener("abort", () => {
132
+ proc.kill("SIGTERM");
133
+ });
134
+ }
135
+ }
136
+ // Write input and close stdin
137
+ proc.stdin.write(stdin);
138
+ proc.stdin.end();
139
+ // Async IIFE — mirrors the standard streaming pattern
140
+ (async () => {
141
+ try {
142
+ // Emit start immediately before any stdout data
143
+ eventStream.push({ type: "start", partial: output });
144
+ function rebuildOutputContent(tracked) {
145
+ return tracked.map((b) => {
146
+ if (b.type === "text")
147
+ return { type: "text", text: b.text ?? "" };
148
+ if (b.type === "tool_use")
149
+ return { type: "toolCall", id: b.id ?? "", name: b.name ?? "", arguments: JSON.parse(b.inputJson ?? "{}") };
150
+ return { type: "thinking", thinking: b.thinking ?? "" };
151
+ });
152
+ }
153
+ const blocks = [];
154
+ let sessionId = options?.sessionId;
155
+ let buffer = "";
156
+ let stderrOutput = "";
157
+ // Collect stderr
158
+ proc.stderr.on("data", (data) => {
159
+ stderrOutput += data.toString();
160
+ });
161
+ // Process stdout as a promise that resolves on close, rejects on error
162
+ await new Promise((resolve, reject) => {
163
+ proc.stdout.on("data", (data) => {
164
+ buffer += data.toString();
165
+ const lines = buffer.split("\n");
166
+ buffer = lines.pop() ?? "";
167
+ for (const line of lines) {
168
+ const trimmed = line.trim();
169
+ if (!trimmed)
170
+ continue;
171
+ let event;
172
+ try {
173
+ event = JSON.parse(trimmed);
174
+ }
175
+ catch {
176
+ continue; // Skip malformed JSON lines
177
+ }
178
+ if (event.type === "system" && event.subtype === "init") {
179
+ sessionId = event.session_id;
180
+ }
181
+ else if (event.type === "assistant") {
182
+ const assistantEvent = event;
183
+ // Accumulate usage from assistant events
184
+ if (assistantEvent.message?.usage) {
185
+ const parsed = parseUsageFromRaw(assistantEvent.message.usage);
186
+ output.usage.input = parsed.input;
187
+ output.usage.output = parsed.output;
188
+ output.usage.cacheRead = parsed.cacheRead;
189
+ output.usage.cacheWrite = parsed.cacheWrite;
190
+ output.usage.totalTokens = parsed.totalTokens;
191
+ }
192
+ const contentArray = assistantEvent.message?.content ?? [];
193
+ for (let i = 0; i < contentArray.length; i++) {
194
+ const block = contentArray[i];
195
+ if (i >= blocks.length) {
196
+ // New block — emit *_start + initial *_delta
197
+ if (block.type === "text") {
198
+ const tracked = { type: "text", started: true, ended: false, text: block.text };
199
+ blocks.push(tracked);
200
+ output.content = rebuildOutputContent(blocks);
201
+ eventStream.push({ type: "text_start", contentIndex: i, partial: output });
202
+ if (block.text) {
203
+ eventStream.push({ type: "text_delta", contentIndex: i, delta: block.text, partial: output });
204
+ }
205
+ }
206
+ else if (block.type === "tool_use") {
207
+ const inputJson = JSON.stringify(block.input);
208
+ const tracked = { type: "tool_use", started: true, ended: false, id: block.id, name: block.name, inputJson };
209
+ blocks.push(tracked);
210
+ output.content = rebuildOutputContent(blocks);
211
+ eventStream.push({ type: "toolcall_start", contentIndex: i, partial: output });
212
+ eventStream.push({ type: "toolcall_delta", contentIndex: i, delta: inputJson, partial: output });
213
+ }
214
+ else if (block.type === "thinking") {
215
+ const tracked = { type: "thinking", started: true, ended: false, thinking: block.thinking };
216
+ blocks.push(tracked);
217
+ output.content = rebuildOutputContent(blocks);
218
+ eventStream.push({ type: "thinking_start", contentIndex: i, partial: output });
219
+ if (block.thinking) {
220
+ eventStream.push({ type: "thinking_delta", contentIndex: i, delta: block.thinking, partial: output });
221
+ }
222
+ }
223
+ }
224
+ else {
225
+ // Existing block — emit deltas for changes
226
+ const tracked = blocks[i];
227
+ // Type changed at this index — CLI reset content array (new turn)
228
+ // End all open blocks and treat remaining CLI blocks as new appended blocks
229
+ if (block.type !== tracked.type) {
230
+ for (let j = 0; j < blocks.length; j++) {
231
+ const tb = blocks[j];
232
+ if (tb.started && !tb.ended) {
233
+ tb.ended = true;
234
+ if (tb.type === "text") {
235
+ eventStream.push({ type: "text_end", contentIndex: j, content: tb.text ?? "", partial: output });
236
+ }
237
+ else if (tb.type === "tool_use") {
238
+ eventStream.push({
239
+ type: "toolcall_end",
240
+ contentIndex: j,
241
+ toolCall: { type: "toolCall", id: tb.id ?? "", name: tb.name ?? "", arguments: JSON.parse(tb.inputJson ?? "{}") },
242
+ partial: output,
243
+ });
244
+ }
245
+ else if (tb.type === "thinking") {
246
+ eventStream.push({ type: "thinking_end", contentIndex: j, content: tb.thinking ?? "", partial: output });
247
+ }
248
+ }
249
+ }
250
+ // Mark turn boundary — remaining CLI content blocks (from index i onward) get appended
251
+ // as new blocks at the end of our blocks array
252
+ for (let k = i; k < contentArray.length; k++) {
253
+ const newBlock = contentArray[k];
254
+ const newIdx = blocks.length;
255
+ if (newBlock.type === "text") {
256
+ blocks.push({ type: "text", started: true, ended: false, text: newBlock.text });
257
+ output.content = rebuildOutputContent(blocks);
258
+ eventStream.push({ type: "text_start", contentIndex: newIdx, partial: output });
259
+ if (newBlock.text)
260
+ eventStream.push({ type: "text_delta", contentIndex: newIdx, delta: newBlock.text, partial: output });
261
+ }
262
+ else if (newBlock.type === "tool_use") {
263
+ const inputJson = JSON.stringify(newBlock.input);
264
+ blocks.push({ type: "tool_use", started: true, ended: false, id: newBlock.id, name: newBlock.name, inputJson });
265
+ output.content = rebuildOutputContent(blocks);
266
+ eventStream.push({ type: "toolcall_start", contentIndex: newIdx, partial: output });
267
+ eventStream.push({ type: "toolcall_delta", contentIndex: newIdx, delta: inputJson, partial: output });
268
+ }
269
+ else if (newBlock.type === "thinking") {
270
+ blocks.push({ type: "thinking", started: true, ended: false, thinking: newBlock.thinking });
271
+ output.content = rebuildOutputContent(blocks);
272
+ eventStream.push({ type: "thinking_start", contentIndex: newIdx, partial: output });
273
+ if (newBlock.thinking)
274
+ eventStream.push({ type: "thinking_delta", contentIndex: newIdx, delta: newBlock.thinking, partial: output });
275
+ }
276
+ }
277
+ break; // We processed all remaining CLI blocks above
278
+ }
279
+ if (block.type === "text" && tracked.type === "text") {
280
+ const prevText = tracked.text ?? "";
281
+ const newText = block.text;
282
+ if (newText.startsWith(prevText) && newText.length > prevText.length) {
283
+ const delta = newText.slice(prevText.length);
284
+ tracked.text = newText;
285
+ output.content = rebuildOutputContent(blocks);
286
+ eventStream.push({ type: "text_delta", contentIndex: i, delta, partial: output });
287
+ }
288
+ else if (!newText.startsWith(prevText)) {
289
+ // New turn — text doesn't continue from previous
290
+ eventStream.push({ type: "text_end", contentIndex: i, content: prevText, partial: output });
291
+ tracked.text = newText;
292
+ output.content = rebuildOutputContent(blocks);
293
+ eventStream.push({ type: "text_start", contentIndex: i, partial: output });
294
+ if (newText) {
295
+ eventStream.push({ type: "text_delta", contentIndex: i, delta: newText, partial: output });
296
+ }
297
+ }
298
+ }
299
+ else if (block.type === "tool_use" && tracked.type === "tool_use") {
300
+ const newInputJson = JSON.stringify(block.input);
301
+ if (newInputJson !== tracked.inputJson) {
302
+ tracked.inputJson = newInputJson;
303
+ tracked.id = block.id;
304
+ tracked.name = block.name;
305
+ output.content = rebuildOutputContent(blocks);
306
+ eventStream.push({ type: "toolcall_delta", contentIndex: i, delta: newInputJson, partial: output });
307
+ }
308
+ }
309
+ else if (block.type === "thinking" && tracked.type === "thinking") {
310
+ const prevThinking = tracked.thinking ?? "";
311
+ const newThinking = block.thinking;
312
+ if (newThinking.startsWith(prevThinking) && newThinking.length > prevThinking.length) {
313
+ const delta = newThinking.slice(prevThinking.length);
314
+ tracked.thinking = newThinking;
315
+ output.content = rebuildOutputContent(blocks);
316
+ eventStream.push({ type: "thinking_delta", contentIndex: i, delta, partial: output });
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }
322
+ else if (event.type === "result") {
323
+ const resultEvent = event;
324
+ const resultText = resultEvent.result;
325
+ // Update the last text block with result text, or create one
326
+ if (resultText) {
327
+ const lastTextIdx = findLastIndex(blocks, (b) => b.type === "text");
328
+ if (lastTextIdx >= 0) {
329
+ blocks[lastTextIdx].text = resultText;
330
+ }
331
+ else {
332
+ // No text blocks yet — create one
333
+ const tracked = { type: "text", started: false, ended: false, text: resultText };
334
+ blocks.push(tracked);
335
+ }
336
+ output.content = rebuildOutputContent(blocks);
337
+ }
338
+ // Emit text_start/delta for result-only responses (no prior assistant events)
339
+ const resultTextIdx = findLastIndex(blocks, (b) => b.type === "text");
340
+ if (resultTextIdx >= 0 && !blocks[resultTextIdx].started && resultText) {
341
+ blocks[resultTextIdx].started = true;
342
+ eventStream.push({ type: "text_start", contentIndex: resultTextIdx, partial: output });
343
+ eventStream.push({
344
+ type: "text_delta",
345
+ contentIndex: resultTextIdx,
346
+ delta: resultText,
347
+ partial: output,
348
+ });
349
+ }
350
+ if (resultEvent.session_id) {
351
+ sessionId = resultEvent.session_id;
352
+ }
353
+ // Result event usage overwrites with final totals
354
+ const usage = parseUsageFromRaw(resultEvent.usage);
355
+ if (resultEvent.total_cost_usd) {
356
+ usage.cost.total = resultEvent.total_cost_usd;
357
+ }
358
+ output.usage = usage;
359
+ output.stopReason = resultEvent.is_error ? "error" : "stop";
360
+ if (resultEvent.is_error) {
361
+ output.errorMessage = resultText;
362
+ }
363
+ // End all open blocks
364
+ for (let i = 0; i < blocks.length; i++) {
365
+ const tracked = blocks[i];
366
+ if (tracked.started && !tracked.ended) {
367
+ tracked.ended = true;
368
+ if (tracked.type === "text") {
369
+ eventStream.push({ type: "text_end", contentIndex: i, content: tracked.text ?? "", partial: output });
370
+ }
371
+ else if (tracked.type === "tool_use") {
372
+ eventStream.push({
373
+ type: "toolcall_end",
374
+ contentIndex: i,
375
+ toolCall: { type: "toolCall", id: tracked.id ?? "", name: tracked.name ?? "", arguments: JSON.parse(tracked.inputJson ?? "{}") },
376
+ partial: output,
377
+ });
378
+ }
379
+ else if (tracked.type === "thinking") {
380
+ eventStream.push({ type: "thinking_end", contentIndex: i, content: tracked.thinking ?? "", partial: output });
381
+ }
382
+ }
383
+ }
384
+ }
385
+ }
386
+ });
387
+ proc.on("error", (err) => {
388
+ reject(err);
389
+ });
390
+ proc.on("close", (code) => {
391
+ const hasContent = blocks.some((b) => b.type === "text" ? (b.text ?? "").length > 0 : true);
392
+ if (code !== 0 && !hasContent) {
393
+ const msg = stderrOutput || `CLI process exited with code ${code}`;
394
+ reject(new Error(msg));
395
+ }
396
+ else {
397
+ resolve();
398
+ }
399
+ });
400
+ });
401
+ // After processing completes: check abort
402
+ if (options?.signal?.aborted) {
403
+ throw new Error("Request was aborted");
404
+ }
405
+ // Success path: push done event using output.stopReason
406
+ if (output.stopReason === "error" || output.stopReason === "aborted") {
407
+ eventStream.push({ type: "error", reason: output.stopReason, error: output });
408
+ }
409
+ else {
410
+ eventStream.push({ type: "done", reason: output.stopReason, message: output });
411
+ }
412
+ eventStream.end();
413
+ }
414
+ catch (error) {
415
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
416
+ output.errorMessage = error instanceof Error ? error.message : String(error);
417
+ eventStream.push({ type: "error", reason: output.stopReason, error: output });
418
+ eventStream.end();
419
+ }
420
+ finally {
421
+ if (mcpConfigPath)
422
+ cleanupMcpConfig(mcpConfigPath);
423
+ }
424
+ })();
425
+ return eventStream;
426
+ };
427
+ }
428
+ // ─── Public factory ───
429
+ /**
430
+ * Create a cli-pipe provider that wraps CLI pipe mode with MCP tool bridge support.
431
+ *
432
+ * ```ts
433
+ * const pipe = createCliPipeProvider({
434
+ * command: "claude", // or any CLI that supports -p --output-format stream-json
435
+ * bridgeEntryPoint: "/path/to/my-bridge.js",
436
+ * mcpServerName: "my-app",
437
+ * });
438
+ * pipe.register();
439
+ * const model = pipe.createModel({ modelId: "claude-sonnet-4-6" });
440
+ * ```
441
+ */
442
+ export function createCliPipeProvider(options) {
443
+ const streamFn = createStreamFunction(options);
444
+ // streamSimple — explicitly map SimpleStreamOptions fields
445
+ const streamSimpleFn = (model, context, opts) => {
446
+ if (!opts)
447
+ return streamFn(model, context);
448
+ const mapped = {
449
+ temperature: opts.temperature,
450
+ maxTokens: opts.maxTokens,
451
+ signal: opts.signal,
452
+ apiKey: opts.apiKey,
453
+ transport: opts.transport,
454
+ cacheRetention: opts.cacheRetention,
455
+ sessionId: opts.sessionId,
456
+ onPayload: opts.onPayload,
457
+ headers: opts.headers,
458
+ maxRetryDelayMs: opts.maxRetryDelayMs,
459
+ metadata: opts.metadata,
460
+ reasoning: opts.reasoning,
461
+ };
462
+ return streamFn(model, context, mapped);
463
+ };
464
+ return {
465
+ api: CLI_PIPE_API,
466
+ stream: streamFn,
467
+ streamSimple: streamSimpleFn,
468
+ register() {
469
+ registerApiProvider({
470
+ api: CLI_PIPE_API,
471
+ stream: streamFn,
472
+ streamSimple: streamSimpleFn,
473
+ });
474
+ },
475
+ createModel(opts) {
476
+ const modelId = opts?.modelId ?? "claude-sonnet-4-6";
477
+ return {
478
+ id: modelId,
479
+ name: `${modelId} via CLI pipe`,
480
+ api: CLI_PIPE_API,
481
+ provider: "cli-pipe",
482
+ baseUrl: "",
483
+ reasoning: true,
484
+ input: ["text", "image"],
485
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
486
+ contextWindow: 200000,
487
+ maxTokens: 16384,
488
+ };
489
+ },
490
+ };
491
+ }
492
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import type { Api, Model, StreamOptions, ThinkingLevel } from "@mariozechner/pi-ai";
2
+ export interface CliPipeProviderOptions {
3
+ /** CLI binary to spawn (e.g. "claude") */
4
+ command: string;
5
+ /** Absolute path to the bridge entry script (the file that calls serveMcpBridge()) */
6
+ bridgeEntryPoint: string;
7
+ /** MCP server name — used for --allowedTools glob (e.g. "mcp__<name>__*") */
8
+ mcpServerName: string;
9
+ /** Default CLI args passed to the bridge script */
10
+ bridgeArgs?: string[];
11
+ /**
12
+ * Optional callback to resolve bridge args from the model at stream time.
13
+ * Useful when bridge args depend on metadata attached to the model object.
14
+ * Returned args are prepended before bridgeArgs from provider and stream options.
15
+ */
16
+ resolveBridgeArgs?: (model: Model<Api>) => string[];
17
+ }
18
+ export interface CliPipeStreamOptions extends StreamOptions {
19
+ reasoning?: ThinkingLevel;
20
+ /** CLI args passed to the bridge script (merged with provider defaults) */
21
+ bridgeArgs?: string[];
22
+ /** Whether to enable MCP tool bridge (default: true) */
23
+ enableTools?: boolean;
24
+ }
25
+ export interface McpBridgeOptions {
26
+ /** Server name reported during MCP handshake */
27
+ serverName?: string;
28
+ /** Server version reported during MCP handshake */
29
+ serverVersion?: string;
30
+ }
31
+ export interface McpConfig {
32
+ mcpServers: Record<string, {
33
+ command: string;
34
+ args: string[];
35
+ }>;
36
+ }
37
+ export interface CliPipeProvider {
38
+ /** The custom API identifier */
39
+ api: Api;
40
+ /** The stream function for full options */
41
+ stream: (model: Model<Api>, context: any, options?: CliPipeStreamOptions) => any;
42
+ /** The stream function for simple options */
43
+ streamSimple: (model: Model<Api>, context: any, options?: any) => any;
44
+ /** Register this provider with pi-ai */
45
+ register: () => void;
46
+ /** Create a model instance for this provider */
47
+ createModel: (opts?: {
48
+ modelId?: string;
49
+ }) => Model<Api>;
50
+ }
51
+ export interface CliSystemEvent {
52
+ type: "system";
53
+ subtype: "init";
54
+ session_id: string;
55
+ model?: string;
56
+ }
57
+ export type CliContentBlock = {
58
+ type: "text";
59
+ text: string;
60
+ } | {
61
+ type: "tool_use";
62
+ id: string;
63
+ name: string;
64
+ input: Record<string, unknown>;
65
+ } | {
66
+ type: "thinking";
67
+ thinking: string;
68
+ };
69
+ export interface CliAssistantEvent {
70
+ type: "assistant";
71
+ message: {
72
+ content: CliContentBlock[];
73
+ usage?: {
74
+ input_tokens?: number;
75
+ output_tokens?: number;
76
+ cache_read_input_tokens?: number;
77
+ cache_creation_input_tokens?: number;
78
+ };
79
+ };
80
+ session_id: string;
81
+ }
82
+ export interface CliResultEvent {
83
+ type: "result";
84
+ subtype: string;
85
+ is_error: boolean;
86
+ result: string;
87
+ session_id: string;
88
+ total_cost_usd?: number;
89
+ usage?: {
90
+ input_tokens?: number;
91
+ output_tokens?: number;
92
+ cache_read_input_tokens?: number;
93
+ cache_creation_input_tokens?: number;
94
+ };
95
+ }
96
+ export type CliStreamEvent = CliSystemEvent | CliAssistantEvent | CliResultEvent | {
97
+ type: string;
98
+ [key: string]: unknown;
99
+ };
100
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import type { Usage } from "@mariozechner/pi-ai";
2
+ /**
3
+ * Check whether the CLI is available on the system.
4
+ */
5
+ export declare function checkCliAvailable(command: string): Promise<{
6
+ available: boolean;
7
+ version?: string;
8
+ error?: string;
9
+ }>;
10
+ /**
11
+ * Convert a TypeBox schema to a clean JSON Schema object for MCP.
12
+ * TypeBox schemas ARE JSON Schema — we just strip internal TypeBox symbols.
13
+ */
14
+ export declare function typeboxToJsonSchema(typeboxSchema: any): Record<string, unknown>;
15
+ /**
16
+ * Create an empty Usage object.
17
+ */
18
+ export declare function emptyUsage(): Usage;
19
+ /**
20
+ * Parse raw token usage from CLI stream-json events into a pi-ai Usage object.
21
+ */
22
+ export declare function parseUsageFromRaw(raw?: {
23
+ input_tokens?: number;
24
+ output_tokens?: number;
25
+ cache_read_input_tokens?: number;
26
+ cache_creation_input_tokens?: number;
27
+ }): Usage;
28
+ /**
29
+ * Extract text from a content array or string.
30
+ */
31
+ export declare function extractTextContent(content: string | Array<{
32
+ type: string;
33
+ text?: string;
34
+ }>): string;
35
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB1H;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwB/E;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,KAAK,CASlC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC,GAAG,KAAK,CAcR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CASnG"}
package/dist/utils.js ADDED
@@ -0,0 +1,107 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * Check whether the CLI is available on the system.
4
+ */
5
+ export async function checkCliAvailable(command) {
6
+ const env = { ...process.env };
7
+ delete env.CLAUDECODE; // runtime env var set by the CLI
8
+ return new Promise((resolve) => {
9
+ const proc = spawn(command, ["--version"], { stdio: ["pipe", "pipe", "pipe"], env });
10
+ let stdout = "";
11
+ let stderr = "";
12
+ proc.stdout.on("data", (data) => { stdout += data.toString(); });
13
+ proc.stderr.on("data", (data) => { stderr += data.toString(); });
14
+ proc.on("error", () => {
15
+ resolve({ available: false, error: "CLI not found" });
16
+ });
17
+ proc.on("close", (code) => {
18
+ if (code === 0) {
19
+ resolve({ available: true, version: stdout.trim() });
20
+ }
21
+ else {
22
+ resolve({ available: false, error: stderr.trim() || "CLI --version check failed" });
23
+ }
24
+ });
25
+ });
26
+ }
27
+ /**
28
+ * Convert a TypeBox schema to a clean JSON Schema object for MCP.
29
+ * TypeBox schemas ARE JSON Schema — we just strip internal TypeBox symbols.
30
+ */
31
+ export function typeboxToJsonSchema(typeboxSchema) {
32
+ const { type, properties, required, description } = typeboxSchema;
33
+ const schema = { type };
34
+ if (properties) {
35
+ const cleanProps = {};
36
+ for (const [key, val] of Object.entries(properties)) {
37
+ const prop = val;
38
+ const clean = {};
39
+ if (prop.type)
40
+ clean.type = prop.type;
41
+ if (prop.description)
42
+ clean.description = prop.description;
43
+ if (prop.enum)
44
+ clean.enum = prop.enum;
45
+ if (prop.default !== undefined)
46
+ clean.default = prop.default;
47
+ if (prop.anyOf)
48
+ clean.anyOf = prop.anyOf;
49
+ if (prop.items)
50
+ clean.items = prop.items;
51
+ cleanProps[key] = clean;
52
+ }
53
+ schema.properties = cleanProps;
54
+ }
55
+ if (required)
56
+ schema.required = required;
57
+ if (description)
58
+ schema.description = description;
59
+ return schema;
60
+ }
61
+ /**
62
+ * Create an empty Usage object.
63
+ */
64
+ export function emptyUsage() {
65
+ return {
66
+ input: 0,
67
+ output: 0,
68
+ cacheRead: 0,
69
+ cacheWrite: 0,
70
+ totalTokens: 0,
71
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
72
+ };
73
+ }
74
+ /**
75
+ * Parse raw token usage from CLI stream-json events into a pi-ai Usage object.
76
+ */
77
+ export function parseUsageFromRaw(raw) {
78
+ if (!raw)
79
+ return emptyUsage();
80
+ const input = raw.input_tokens ?? 0;
81
+ const output = raw.output_tokens ?? 0;
82
+ const cacheRead = raw.cache_read_input_tokens ?? 0;
83
+ const cacheWrite = raw.cache_creation_input_tokens ?? 0;
84
+ return {
85
+ input,
86
+ output,
87
+ cacheRead,
88
+ cacheWrite,
89
+ totalTokens: input + output,
90
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
91
+ };
92
+ }
93
+ /**
94
+ * Extract text from a content array or string.
95
+ */
96
+ export function extractTextContent(content) {
97
+ if (typeof content === "string")
98
+ return content;
99
+ if (Array.isArray(content)) {
100
+ return content
101
+ .filter((c) => c.type === "text" && c.text)
102
+ .map((c) => c.text)
103
+ .join("\n");
104
+ }
105
+ return "";
106
+ }
107
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "cli-pipe-provider",
3
+ "version": "0.1.0",
4
+ "description": "pi-ai provider for CLI tools that speak the stream-json format, with MCP tool bridge support",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/robzolkos/cli-pipe-provider.git"
9
+ },
10
+ "type": "module",
11
+ "main": "dist/index.js",
12
+ "types": "dist/index.d.ts",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "test": "vitest --run",
26
+ "test:watch": "vitest",
27
+ "prepublishOnly": "npm run build && npm test"
28
+ },
29
+ "peerDependencies": {
30
+ "@mariozechner/pi-ai": "^0.54.0",
31
+ "@mariozechner/pi-agent-core": "^0.54.0"
32
+ },
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.26.0"
35
+ },
36
+ "devDependencies": {
37
+ "@mariozechner/pi-ai": "^0.54.0",
38
+ "@mariozechner/pi-agent-core": "^0.54.0",
39
+ "@sinclair/typebox": "^0.34.41",
40
+ "@types/node": "^22.0.0",
41
+ "typescript": "^5.7.3",
42
+ "vitest": "^3.2.4"
43
+ },
44
+ "engines": {
45
+ "node": ">=20.0.0"
46
+ }
47
+ }