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 +230 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-bridge.d.ts +13 -0
- package/dist/mcp-bridge.d.ts.map +1 -0
- package/dist/mcp-bridge.js +67 -0
- package/dist/mcp-bridge.js.map +1 -0
- package/dist/provider.d.ts +19 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +492 -0
- package/dist/provider.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +35 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +107 -0
- package/dist/utils.js.map +1 -0
- package/package.json +47 -0
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
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|
package/dist/provider.js
ADDED
|
@@ -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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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -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":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe;IACrD,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,iCAAiC;IAExD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,4BAA4B,EAAE,CAAC,CAAC;YACtF,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,aAAkB;IACpD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,aAAa,CAAC;IAClE,MAAM,MAAM,GAA4B,EAAE,IAAI,EAAE,CAAC;IAEjD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,GAAU,CAAC;YACxB,MAAM,KAAK,GAA4B,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACtC,IAAI,IAAI,CAAC,WAAW;gBAAE,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;YAC3D,IAAI,IAAI,CAAC,IAAI;gBAAE,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACtC,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7D,IAAI,IAAI,CAAC,KAAK;gBAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACzC,IAAI,IAAI,CAAC,KAAK;gBAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACzC,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC1B,CAAC;QACD,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;IAED,IAAI,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACzC,IAAI,WAAW;QAAE,MAAM,CAAC,WAAW,GAAG,WAAW,CAAC;IAElD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,CAAC;QACb,WAAW,EAAE,CAAC;QACd,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;KACrE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAKjC;IACC,IAAI,CAAC,GAAG;QAAE,OAAO,UAAU,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,IAAI,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,GAAG,CAAC,uBAAuB,IAAI,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,GAAG,CAAC,2BAA2B,IAAI,CAAC,CAAC;IACxD,OAAO;QACL,KAAK;QACL,MAAM;QACN,SAAS;QACT,UAAU;QACV,WAAW,EAAE,KAAK,GAAG,MAAM;QAC3B,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;KACrE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAwD;IACzF,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC;aAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAK,CAAC;aACnB,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
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
|
+
}
|