billion-context 0.1.44 → 0.1.45
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 +22 -0
- package/dist/agent/omp.js +182 -0
- package/dist/agent/omp.js.map +1 -0
- package/dist/agent/pi.js +187 -0
- package/dist/agent/pi.js.map +1 -0
- package/dist/index.js +733 -242
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +63 -18
- package/dist/mcp.js.map +1 -1
- package/package.json +7 -2
package/dist/mcp.js
CHANGED
|
@@ -3,18 +3,46 @@ const require = __biliCreateRequire(import.meta.url);
|
|
|
3
3
|
|
|
4
4
|
// src/mcp.ts
|
|
5
5
|
import fs from "fs";
|
|
6
|
-
import
|
|
6
|
+
import path2 from "path";
|
|
7
7
|
import { fileURLToPath } from "url";
|
|
8
|
+
|
|
9
|
+
// src/paths.ts
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
import path from "path";
|
|
12
|
+
function xdg(envVar, fallback) {
|
|
13
|
+
const v = process.env[envVar];
|
|
14
|
+
if (v && v.length > 0) return path.resolve(v);
|
|
15
|
+
return path.join(homedir(), fallback);
|
|
16
|
+
}
|
|
17
|
+
function stateDir() {
|
|
18
|
+
return path.join(xdg("XDG_STATE_HOME", ".local/state"), "billion-context");
|
|
19
|
+
}
|
|
20
|
+
function proxyOriginFile() {
|
|
21
|
+
return path.join(stateDir(), "proxy-origin");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/mcp.ts
|
|
8
25
|
var VERSION = (() => {
|
|
9
26
|
try {
|
|
10
27
|
const here = fileURLToPath(import.meta.url);
|
|
11
|
-
const pkg =
|
|
28
|
+
const pkg = path2.join(path2.dirname(here), "..", "package.json");
|
|
12
29
|
return JSON.parse(fs.readFileSync(pkg, "utf8")).version ?? "dev";
|
|
13
30
|
} catch {
|
|
14
31
|
return "dev";
|
|
15
32
|
}
|
|
16
33
|
})();
|
|
17
|
-
var
|
|
34
|
+
var DEFAULT_PROXY_ORIGIN = "http://127.0.0.1:8787";
|
|
35
|
+
function resolveProxyOrigin() {
|
|
36
|
+
const fromEnv = process.env.BILI_MCP_PROXY?.trim();
|
|
37
|
+
if (fromEnv && fromEnv.length > 0) return fromEnv;
|
|
38
|
+
try {
|
|
39
|
+
const discovered = fs.readFileSync(proxyOriginFile(), "utf8").trim();
|
|
40
|
+
if (/^https?:\/\/\S+$/.test(discovered)) return discovered;
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
return DEFAULT_PROXY_ORIGIN;
|
|
44
|
+
}
|
|
45
|
+
var TOOL_TIMEOUT_MS = 6e4;
|
|
18
46
|
var CONVERSATION_FROM_ENV = process.env.CLAUDE_CODE_SESSION_ID?.trim() || process.env.BILI_CONVERSATION_ID?.trim() || void 0;
|
|
19
47
|
var IDENTITY_BINDING = Boolean(process.env.CLAUDE_CODE_SESSION_ID?.trim());
|
|
20
48
|
var manifestTools = [];
|
|
@@ -33,19 +61,34 @@ function sendError(id, code, message) {
|
|
|
33
61
|
send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
34
62
|
}
|
|
35
63
|
async function fetchManifest() {
|
|
36
|
-
const res = await fetch(`${
|
|
64
|
+
const res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/manifest`, { signal: AbortSignal.timeout(5e3) });
|
|
37
65
|
if (!res.ok) throw new Error(`manifest fetch failed: ${res.status}`);
|
|
38
66
|
const data = await res.json();
|
|
39
67
|
const anthropic = data.tools?.anthropic ?? [];
|
|
40
68
|
manifestTools = anthropic.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));
|
|
41
69
|
if (manifestTools.length === 0) throw new Error("manifest served no anthropic tools");
|
|
42
70
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
71
|
+
var manifestPromise = null;
|
|
72
|
+
function ensureManifest() {
|
|
73
|
+
manifestPromise ??= fetchManifest().catch((err) => {
|
|
74
|
+
manifestPromise = null;
|
|
75
|
+
throw err;
|
|
48
76
|
});
|
|
77
|
+
return manifestPromise;
|
|
78
|
+
}
|
|
79
|
+
async function forwardTool(tool, args, timeoutMs = TOOL_TIMEOUT_MS) {
|
|
80
|
+
let res;
|
|
81
|
+
try {
|
|
82
|
+
res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/tool`, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: { "content-type": "application/json" },
|
|
85
|
+
body: JSON.stringify({ conversationId, tool, args }),
|
|
86
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
87
|
+
});
|
|
88
|
+
} catch (err) {
|
|
89
|
+
if (err instanceof Error && err.name === "TimeoutError") throw new Error(`tool forward timed out after ${timeoutMs}ms: ${tool}`);
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
49
92
|
const data = await res.json();
|
|
50
93
|
if (!res.ok || !data.ok) throw new Error(data.error ?? `tool forward failed: ${res.status}`);
|
|
51
94
|
return data.result ?? "";
|
|
@@ -60,10 +103,11 @@ async function handleMessage(msg) {
|
|
|
60
103
|
if (fromMeta) conversationId ??= fromMeta;
|
|
61
104
|
initialized = true;
|
|
62
105
|
if (conversationId && !registered) {
|
|
63
|
-
const registerFetch = fetch(`${
|
|
106
|
+
const registerFetch = fetch(`${resolveProxyOrigin()}/__bili/plugin/register`, {
|
|
64
107
|
method: "POST",
|
|
65
108
|
headers: { "content-type": "application/json" },
|
|
66
|
-
body: JSON.stringify({ conversationId, agent: "mcp", identity: IDENTITY_BINDING })
|
|
109
|
+
body: JSON.stringify({ conversationId, agent: "mcp", identity: IDENTITY_BINDING }),
|
|
110
|
+
signal: AbortSignal.timeout(5e3)
|
|
67
111
|
});
|
|
68
112
|
registered = true;
|
|
69
113
|
if (IDENTITY_BINDING) {
|
|
@@ -88,7 +132,12 @@ async function handleMessage(msg) {
|
|
|
88
132
|
sendError(id, -32002, "server not initialized");
|
|
89
133
|
return;
|
|
90
134
|
}
|
|
91
|
-
|
|
135
|
+
try {
|
|
136
|
+
await ensureManifest();
|
|
137
|
+
sendResult(id, { tools: manifestTools });
|
|
138
|
+
} catch (err) {
|
|
139
|
+
sendError(id, -32003, `bili proxy unreachable at ${resolveProxyOrigin()} (${err instanceof Error ? err.message : String(err)}) \u2014 start bili or set BILI_MCP_PROXY`);
|
|
140
|
+
}
|
|
92
141
|
return;
|
|
93
142
|
}
|
|
94
143
|
case "tools/call": {
|
|
@@ -119,12 +168,6 @@ async function handleMessage(msg) {
|
|
|
119
168
|
}
|
|
120
169
|
}
|
|
121
170
|
async function mcpMain() {
|
|
122
|
-
try {
|
|
123
|
-
await fetchManifest();
|
|
124
|
-
} catch (err) {
|
|
125
|
-
console.error(`bili-mcp: ${err instanceof Error ? err.message : String(err)} (proxy at ${PROXY_ORIGIN})`);
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
171
|
let buf = "";
|
|
129
172
|
process.stdin.setEncoding("utf8");
|
|
130
173
|
process.stdin.on("data", (chunk) => {
|
|
@@ -154,6 +197,8 @@ if (process.argv[1] && /(?:^|[\\/])mcp\.(?:ts|js)$/.test(process.argv[1])) {
|
|
|
154
197
|
void mcpMain();
|
|
155
198
|
}
|
|
156
199
|
export {
|
|
200
|
+
forwardTool,
|
|
201
|
+
resolveProxyOrigin,
|
|
157
202
|
runMcpStdio
|
|
158
203
|
};
|
|
159
204
|
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["// MCP stdio thin shell for launcher mode (#162): a single \"bili\" MCP server\n// the hosts load via --mcp-config / -c mcp_servers.bili. It fetches the\n// proxy's plugin manifest (single source of truth — zero schema drift),\n// exposes the 4 ACP tools over stdio JSON-RPC, and forwards executes to\n// POST /__bili/plugin/tool. Claude Code passes its session id via the MCP\n// initialize request's _meta.ui.sessionId (documented SessionStart context);\n// we also accept BILI_CONVERSATION_ID env (codex spawn-time registration).\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst VERSION = (() => {\n try {\n const here = fileURLToPath(import.meta.url);\n const pkg = path.join(path.dirname(here), \"..\", \"package.json\");\n return (JSON.parse(fs.readFileSync(pkg, \"utf8\")).version as string) ?? \"dev\";\n } catch {\n return \"dev\";\n }\n})();\ntype JsonRpcId = string | number | null;\n\ntype McpToolDef = {\n name: string;\n description?: string;\n inputSchema: unknown;\n};\n// Claude Code passes the session id as an env var to MCP children (verified\n// against claude 2.1.227: CLAUDE_CODE_SESSION_ID) — and puts the SAME id on\n// every model request (x-claude-code-session-id), so binding is by identity.\n// BILI_CONVERSATION_ID (launcher-spawned hosts like codex) has no matching\n// request id — binding is headless (next NEW session).\nconst PROXY_ORIGIN = process.env.BILI_MCP_PROXY ?? \"http://127.0.0.1:8787\";\nconst CONVERSATION_FROM_ENV = process.env.CLAUDE_CODE_SESSION_ID?.trim() || process.env.BILI_CONVERSATION_ID?.trim() || undefined;\nconst IDENTITY_BINDING = Boolean(process.env.CLAUDE_CODE_SESSION_ID?.trim());\nlet manifestTools: McpToolDef[] = [];\nlet conversationId = CONVERSATION_FROM_ENV;\nlet registered = false;\nlet initialized = false;\nfunction send(msg: unknown): void {\n process.stdout.write(JSON.stringify(msg) + \"\\n\");\n}\n\nfunction sendResult(id: JsonRpcId, result: unknown): void {\n if (id === null) return; // notification — no response expected\n send({ jsonrpc: \"2.0\", id, result });\n}\n\nfunction sendError(id: JsonRpcId, code: number, message: string): void {\n if (id === null) return;\n send({ jsonrpc: \"2.0\", id, error: { code, message } });\n}\n\nasync function fetchManifest(): Promise<void> {\n const res = await fetch(`${PROXY_ORIGIN}/__bili/plugin/manifest`);\n if (!res.ok) throw new Error(`manifest fetch failed: ${res.status}`);\n const data = (await res.json()) as { tools?: Record<string, { name: string; description?: string; input_schema?: unknown }[]> };\n // Anthropic wire shape is the canonical MCP-compatible schema source.\n const anthropic = data.tools?.anthropic ?? [];\n manifestTools = anthropic.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));\n if (manifestTools.length === 0) throw new Error(\"manifest served no anthropic tools\");\n}\n\nasync function forwardTool(tool: string, args: unknown): Promise<string> {\n const res = await fetch(`${PROXY_ORIGIN}/__bili/plugin/tool`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ conversationId, tool, args }),\n });\n const data = (await res.json()) as { ok?: boolean; result?: string; error?: string };\n if (!res.ok || !data.ok) throw new Error(data.error ?? `tool forward failed: ${res.status}`);\n return data.result ?? \"\";\n}\n\nconst ERR_TOOL = -32602;\n\nasync function handleMessage(msg: {\n id?: JsonRpcId;\n method?: string;\n params?: {\n _meta?: { ui?: { sessionId?: string } };\n [k: string]: unknown;\n };\n}): Promise<void> {\n const { id = null, method } = msg;\n const params = typeof msg.params === \"object\" && msg.params !== null ? msg.params : {};\n switch (method) {\n case \"initialize\": {\n // Session id arrives as an env var on the child process (claude)\n // or is injected at spawn time (launcher hosts). The MCP spec\n // guarantees the host waits for this response before calling\n // tools, and claude -p fires its first model request around the\n // same time — registering here is still the earliest we can be.\n // Identity-mode registrations bind on any later request, so the\n // race only matters for headless mode.\n const fromMeta = params._meta?.ui?.sessionId?.trim();\n if (fromMeta) conversationId ??= fromMeta;\n initialized = true;\n if (conversationId && !registered) {\n const registerFetch = fetch(`${PROXY_ORIGIN}/__bili/plugin/register`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ conversationId, agent: \"mcp\", identity: IDENTITY_BINDING }),\n });\n registered = true; // issue-once: a repeated initialize must not re-register\n if (IDENTITY_BINDING) {\n // Identity-mode binding survives any arrival order —\n // respond immediately so pipelined hosts are not stuck\n // behind the register round-trip.\n void registerFetch.catch(() => {});\n } else {\n // Headless binding is order-sensitive: the register MUST\n // land before the host's first model request, and hosts\n // that pipeline tools/list would otherwise race past it.\n await registerFetch.catch(() => {});\n }\n }\n sendResult(id, {\n protocolVersion: \"2025-06-18\",\n serverInfo: { name: \"bili\", version: VERSION },\n capabilities: { tools: {} },\n });\n return;\n }\n case \"notifications/initialized\":\n return;\n case \"tools/list\": {\n if (!initialized) {\n sendError(id, -32002, \"server not initialized\");\n return;\n }\n sendResult(id, { tools: manifestTools });\n return;\n }\n case \"tools/call\": {\n const tool = typeof params.name === \"string\" ? params.name : \"\";\n const args = params.arguments && typeof params.arguments === \"object\" ? params.arguments : {};\n if (!tool) {\n sendError(id, ERR_TOOL, \"params.name is required\");\n return;\n }\n if (!conversationId) {\n sendError(id, ERR_TOOL, \"no conversation id (set BILI_CONVERSATION_ID or connect via Claude Code MCP session meta)\");\n return;\n }\n try {\n const text = await forwardTool(tool, args);\n sendResult(id, { content: [{ type: \"text\", text }], isError: false });\n } catch (err) {\n // Tool-level failures are results (isError), not JSON-RPC\n // errors, so the host surfaces them to the model.\n sendResult(id, { content: [{ type: \"text\", text: `bili tool error: ${err instanceof Error ? err.message : String(err)}` }], isError: true });\n }\n return;\n }\n case \"ping\":\n sendResult(id, {});\n return;\n default:\n if (method?.startsWith(\"notifications/\")) return;\n sendError(id, -32601, `method not found: ${method ?? \"(none)\"}`);\n }\n}\nasync function mcpMain(): Promise<void> {\n try {\n await fetchManifest();\n } catch (err) {\n console.error(`bili-mcp: ${err instanceof Error ? err.message : String(err)} (proxy at ${PROXY_ORIGIN})`);\n process.exit(1);\n }\n let buf = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk: string) => {\n buf += chunk;\n let nl: number;\n while ((nl = buf.indexOf(\"\\n\")) >= 0) {\n const line = buf.slice(0, nl).trim();\n buf = buf.slice(nl + 1);\n if (!line) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n continue;\n }\n if (parsed && typeof parsed === \"object\") {\n void handleMessage(parsed as Parameters<typeof handleMessage>[0]);\n }\n }\n });\n process.stdin.on(\"end\", () => process.exit(0));\n}\n\n/** CLI entry (`bili mcp`): the stdio loop keeps the process alive. */\nexport function runMcpStdio(): void {\n void mcpMain();\n}\n\n// Direct entry (dist/mcp.js spawned by the injected MCP config, or the ts\n// source under tsx in tests): run only when invoked as the script itself,\n// never when imported by the CLI.\nif (process.argv[1] && /(?:^|[\\\\/])mcp\\.(?:ts|js)$/.test(process.argv[1])) {\n void mcpMain();\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp.ts","../src/paths.ts"],"sourcesContent":["// MCP stdio thin shell for launcher mode (#162): a single \"bili\" MCP server\n// the hosts load via --mcp-config / -c mcp_servers.bili. It fetches the\n// proxy's plugin manifest (single source of truth — zero schema drift),\n// exposes the 4 ACP tools over stdio JSON-RPC, and forwards executes to\n// POST /__bili/plugin/tool. Claude Code passes its session id via the MCP\n// initialize request's _meta.ui.sessionId (documented SessionStart context);\n// we also accept BILI_CONVERSATION_ID env (codex spawn-time registration).\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { proxyOriginFile } from \"./paths.js\";\n\nconst VERSION = (() => {\n try {\n const here = fileURLToPath(import.meta.url);\n const pkg = path.join(path.dirname(here), \"..\", \"package.json\");\n return (JSON.parse(fs.readFileSync(pkg, \"utf8\")).version as string) ?? \"dev\";\n } catch {\n return \"dev\";\n }\n})();\ntype JsonRpcId = string | number | null;\n\ntype McpToolDef = {\n name: string;\n description?: string;\n inputSchema: unknown;\n};\n// Claude Code passes the session id as an env var to MCP children (verified\n// against claude 2.1.227: CLAUDE_CODE_SESSION_ID) — and puts the SAME id on\n// every model request (x-claude-code-session-id), so binding is by identity.\n// BILI_CONVERSATION_ID (launcher-spawned hosts like codex) has no matching\n// request id — binding is headless (next NEW session).\nconst DEFAULT_PROXY_ORIGIN = \"http://127.0.0.1:8787\";\n\nexport function resolveProxyOrigin(): string {\n const fromEnv = process.env.BILI_MCP_PROXY?.trim();\n if (fromEnv && fromEnv.length > 0) return fromEnv;\n try {\n const discovered = fs.readFileSync(proxyOriginFile(), \"utf8\").trim();\n if (/^https?:\\/\\/\\S+$/.test(discovered)) return discovered;\n } catch {\n }\n return DEFAULT_PROXY_ORIGIN;\n}\n\nconst TOOL_TIMEOUT_MS = 60_000;\nconst CONVERSATION_FROM_ENV = process.env.CLAUDE_CODE_SESSION_ID?.trim() || process.env.BILI_CONVERSATION_ID?.trim() || undefined;\nconst IDENTITY_BINDING = Boolean(process.env.CLAUDE_CODE_SESSION_ID?.trim());\nlet manifestTools: McpToolDef[] = [];\nlet conversationId = CONVERSATION_FROM_ENV;\nlet registered = false;\nlet initialized = false;\nfunction send(msg: unknown): void {\n process.stdout.write(JSON.stringify(msg) + \"\\n\");\n}\n\nfunction sendResult(id: JsonRpcId, result: unknown): void {\n if (id === null) return; // notification — no response expected\n send({ jsonrpc: \"2.0\", id, result });\n}\n\nfunction sendError(id: JsonRpcId, code: number, message: string): void {\n if (id === null) return;\n send({ jsonrpc: \"2.0\", id, error: { code, message } });\n}\n\nasync function fetchManifest(): Promise<void> {\n const res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/manifest`, { signal: AbortSignal.timeout(5000) });\n if (!res.ok) throw new Error(`manifest fetch failed: ${res.status}`);\n const data = (await res.json()) as { tools?: Record<string, { name: string; description?: string; input_schema?: unknown }[]> };\n // Anthropic wire shape is the canonical MCP-compatible schema source.\n const anthropic = data.tools?.anthropic ?? [];\n manifestTools = anthropic.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));\n if (manifestTools.length === 0) throw new Error(\"manifest served no anthropic tools\");\n}\n\nlet manifestPromise: Promise<void> | null = null;\nfunction ensureManifest(): Promise<void> {\n manifestPromise ??= fetchManifest().catch((err) => {\n manifestPromise = null;\n throw err;\n });\n return manifestPromise;\n}\n\nexport async function forwardTool(tool: string, args: unknown, timeoutMs: number = TOOL_TIMEOUT_MS): Promise<string> {\n let res: Response;\n try {\n res = await fetch(`${resolveProxyOrigin()}/__bili/plugin/tool`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ conversationId, tool, args }),\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"TimeoutError\") throw new Error(`tool forward timed out after ${timeoutMs}ms: ${tool}`);\n throw err;\n }\n const data = (await res.json()) as { ok?: boolean; result?: string; error?: string };\n if (!res.ok || !data.ok) throw new Error(data.error ?? `tool forward failed: ${res.status}`);\n return data.result ?? \"\";\n}\n\nconst ERR_TOOL = -32602;\n\nasync function handleMessage(msg: {\n id?: JsonRpcId;\n method?: string;\n params?: {\n _meta?: { ui?: { sessionId?: string } };\n [k: string]: unknown;\n };\n}): Promise<void> {\n const { id = null, method } = msg;\n const params = typeof msg.params === \"object\" && msg.params !== null ? msg.params : {};\n switch (method) {\n case \"initialize\": {\n // Session id arrives as an env var on the child process (claude)\n // or is injected at spawn time (launcher hosts). The MCP spec\n // guarantees the host waits for this response before calling\n // tools, and claude -p fires its first model request around the\n // same time — registering here is still the earliest we can be.\n // Identity-mode registrations bind on any later request, so the\n // race only matters for headless mode.\n const fromMeta = params._meta?.ui?.sessionId?.trim();\n if (fromMeta) conversationId ??= fromMeta;\n initialized = true;\n if (conversationId && !registered) {\n const registerFetch = fetch(`${resolveProxyOrigin()}/__bili/plugin/register`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ conversationId, agent: \"mcp\", identity: IDENTITY_BINDING }),\n signal: AbortSignal.timeout(5000),\n });\n registered = true; // issue-once: a repeated initialize must not re-register\n if (IDENTITY_BINDING) {\n // Identity-mode binding survives any arrival order —\n // respond immediately so pipelined hosts are not stuck\n // behind the register round-trip.\n void registerFetch.catch(() => {});\n } else {\n // Headless binding is order-sensitive: the register MUST\n // land before the host's first model request, and hosts\n // that pipeline tools/list would otherwise race past it.\n await registerFetch.catch(() => {});\n }\n }\n sendResult(id, {\n protocolVersion: \"2025-06-18\",\n serverInfo: { name: \"bili\", version: VERSION },\n capabilities: { tools: {} },\n });\n return;\n }\n case \"notifications/initialized\":\n return;\n case \"tools/list\": {\n if (!initialized) {\n sendError(id, -32002, \"server not initialized\");\n return;\n }\n try {\n await ensureManifest();\n sendResult(id, { tools: manifestTools });\n } catch (err) {\n sendError(id, -32003, `bili proxy unreachable at ${resolveProxyOrigin()} (${err instanceof Error ? err.message : String(err)}) — start bili or set BILI_MCP_PROXY`);\n }\n return;\n }\n case \"tools/call\": {\n const tool = typeof params.name === \"string\" ? params.name : \"\";\n const args = params.arguments && typeof params.arguments === \"object\" ? params.arguments : {};\n if (!tool) {\n sendError(id, ERR_TOOL, \"params.name is required\");\n return;\n }\n if (!conversationId) {\n sendError(id, ERR_TOOL, \"no conversation id (set BILI_CONVERSATION_ID or connect via Claude Code MCP session meta)\");\n return;\n }\n try {\n const text = await forwardTool(tool, args);\n sendResult(id, { content: [{ type: \"text\", text }], isError: false });\n } catch (err) {\n // Tool-level failures are results (isError), not JSON-RPC\n // errors, so the host surfaces them to the model.\n sendResult(id, { content: [{ type: \"text\", text: `bili tool error: ${err instanceof Error ? err.message : String(err)}` }], isError: true });\n }\n return;\n }\n case \"ping\":\n sendResult(id, {});\n return;\n default:\n if (method?.startsWith(\"notifications/\")) return;\n sendError(id, -32601, `method not found: ${method ?? \"(none)\"}`);\n }\n}\nasync function mcpMain(): Promise<void> {\n let buf = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk: string) => {\n buf += chunk;\n let nl: number;\n while ((nl = buf.indexOf(\"\\n\")) >= 0) {\n const line = buf.slice(0, nl).trim();\n buf = buf.slice(nl + 1);\n if (!line) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n continue;\n }\n if (parsed && typeof parsed === \"object\") {\n void handleMessage(parsed as Parameters<typeof handleMessage>[0]);\n }\n }\n });\n process.stdin.on(\"end\", () => process.exit(0));\n}\n\n/** CLI entry (`bili mcp`): the stdio loop keeps the process alive. */\nexport function runMcpStdio(): void {\n void mcpMain();\n}\n\n// Direct entry (dist/mcp.js spawned by the injected MCP config, or the ts\n// source under tsx in tests): run only when invoked as the script itself,\n// never when imported by the CLI.\nif (process.argv[1] && /(?:^|[\\\\/])mcp\\.(?:ts|js)$/.test(process.argv[1])) {\n void mcpMain();\n}\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\n\n/** XDG base-directory paths for billion-context.\n *\n * Follows the XDG Base Directory Specification so the proxy lands in the\n * conventional Linux/macOS locations instead of a bespoke ~/.bili/:\n *\n * config (user-edited, dotfile-managed):\n * $XDG_CONFIG_HOME/billion-context/billion-context.json\n * default: ~/.config/billion-context/billion-context.json\n *\n * data (persisted session state, grows over time):\n * $XDG_DATA_HOME/billion-context/sessions/\n * default: ~/.local/share/billion-context/sessions/\n *\n * Env overrides (highest priority) are kept so test runners and container\n * setups can relocate everything without touching the config file. */\n\nfunction xdg(envVar: string, fallback: string): string {\n const v = process.env[envVar];\n if (v && v.length > 0) return path.resolve(v);\n return path.join(homedir(), fallback);\n}\n\n/** Root config dir: user-editable configuration lives here. */\nexport function configDir(): string {\n return path.join(xdg(\"XDG_CONFIG_HOME\", \".config\"), \"billion-context\");\n}\n\n/** Main config file path. */\nexport function configFile(): string {\n const env = process.env.BILI_CONFIG_FILE;\n if (env && env.length > 0) return path.resolve(env);\n return path.join(configDir(), \"billion-context.json\");\n}\n\n/** Root data dir: persistent session state lives here. */\nexport function dataDir(): string {\n return path.join(xdg(\"XDG_DATA_HOME\", \".local/share\"), \"billion-context\");\n}\n\n/** Sessions dir: one JSON file per session. */\nexport function sessionsDir(): string {\n const env = process.env.BILI_SESSIONS_DIR;\n if (env && env.length > 0) return path.resolve(env);\n return path.join(dataDir(), \"sessions\");\n}\n\n/** Root cache dir: transient/ephemeral data (update-check throttle, etc.). */\nexport function cacheDir(): string {\n return path.join(xdg(\"XDG_CACHE_HOME\", \".cache\"), \"billion-context\");\n}\n\n/** Root state dir: log files and other per-host state. */\nexport function stateDir(): string {\n return path.join(xdg(\"XDG_STATE_HOME\", \".local/state\"), \"billion-context\");\n}\n\n/** Default log file path. */\nexport function defaultLogFile(): string {\n return path.join(stateDir(), \"bili.log\");\n}\n\n/** Origin of the most recently started proxy (best-effort discovery file for\n * host-spawned MCP shells that have no env passthrough: opencode/claude/codex). */\nexport function proxyOriginFile(): string {\n return path.join(stateDir(), \"proxy-origin\");\n}\n\n/** CA dir: root CA + dynamically-signed host certificates for MITM mode.\n * Lives under the data dir (the private key is sensitive but regenerable).\n * Created lazily by ca.ts on first MITM use. */\nexport function caDir(): string {\n return path.join(dataDir(), \"ca\");\n}\n"],"mappings":"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","names":["path","path"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "billion-context",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.45",
|
|
4
4
|
"description": "Universal context-compression proxy for AI coding agents. Sits between any agent and its model API, rewriting Anthropic/OpenAI streams with acp-kernel compression. Any agent that can set a base URL (Claude Code, Codex, Cursor, Aider) works out of the box.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^22.0.0",
|
|
43
43
|
"@types/node-forge": "^1.3.14",
|
|
44
|
-
"acp-kernel": "0.0.
|
|
44
|
+
"acp-kernel": "0.0.32",
|
|
45
45
|
"fzstd": "0.1.1",
|
|
46
46
|
"node-forge": "^1.4.0",
|
|
47
47
|
"tar": "^7.5.22",
|
|
@@ -58,6 +58,11 @@
|
|
|
58
58
|
"README.md",
|
|
59
59
|
"LICENSE"
|
|
60
60
|
],
|
|
61
|
+
"pi": {
|
|
62
|
+
"extensions": [
|
|
63
|
+
"./dist/agent/pi.js"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
61
66
|
"publishConfig": {
|
|
62
67
|
"access": "public",
|
|
63
68
|
"registry": "https://registry.npmjs.org"
|