@rynfar/meridian 1.47.0 → 1.48.1
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 +17 -0
- package/dist/{cli-1v1narm9.js → cli-vhrprwj4.js} +278 -48
- package/dist/cli.js +1 -1
- package/dist/proxy/adapters/cherry.d.ts +38 -0
- package/dist/proxy/adapters/cherry.d.ts.map +1 -0
- package/dist/proxy/adapters/detect.d.ts.map +1 -1
- package/dist/proxy/messages.d.ts +15 -4
- package/dist/proxy/messages.d.ts.map +1 -1
- package/dist/proxy/passthroughEarlyStop.d.ts +55 -0
- package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -0
- package/dist/proxy/sdkFeatures.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/tools.d.ts +14 -0
- package/dist/proxy/tools.d.ts.map +1 -1
- package/dist/proxy/transform.d.ts +10 -0
- package/dist/proxy/transform.d.ts.map +1 -1
- package/dist/proxy/transforms/cherry.d.ts +15 -0
- package/dist/proxy/transforms/cherry.d.ts.map +1 -0
- package/dist/proxy/transforms/registry.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -222,11 +222,14 @@ MERIDIAN_PASSTHROUGH=0 meridian # force internal
|
|
|
222
222
|
|
|
223
223
|
For large tool sets (>15 tools), non-core tools are automatically deferred via the SDK's ToolSearch mechanism. Core tools (read, write, edit, bash, glob, grep) are always loaded eagerly. The deferral threshold is configurable with `MERIDIAN_DEFER_TOOL_THRESHOLD`.
|
|
224
224
|
|
|
225
|
+
**Digest-turn elimination** — after a tool call is captured, the SDK would normally invoke the model one more time to "digest" the denial before ending the turn. That extra invocation is discarded by the proxy but fully billed — measured at ~400+ wasted output tokens and 2–3× extra latency per tool step (and on always-thinking models like Fable, a full thinking pass each time). Meridian now aborts the SDK query the moment every tool call's denial is persisted, so the digest turn never generates. Sessions remain resumable and tool-result attribution is unaffected. Kill switch: `MERIDIAN_PASSTHROUGH_EARLY_STOP=0` restores the old behavior.
|
|
226
|
+
|
|
225
227
|
### Known limitations
|
|
226
228
|
|
|
227
229
|
- **Single tool round-trip per request** — in passthrough mode, the SDK is configured with `maxTurns=2` (or 3 for deferred tools). Multi-step agentic loops where Claude needs several consecutive tool calls require the client to re-send after each round.
|
|
228
230
|
- **Blocked tools** — 13 built-in SDK tools (Read, Write, Bash, etc.) are blocked to prevent conflicts with the client's own tools. 15 additional Claude Code-only tools (CronCreate, EnterWorktree, Agent, etc.) are blocked because they require capabilities that external clients don't support.
|
|
229
231
|
- **Subagent extraction** — Meridian parses the client's Task tool description to extract subagent names and build SDK AgentDefinitions. If the client's agent framework uses a non-standard format, subagent routing may not work automatically.
|
|
232
|
+
- **Anthropic server tools not supported** — native server-side tools (`web_search_*`, `web_fetch_*`) are a raw Anthropic API feature (billed to an API key) that emits `server_tool_use` / `web_search_tool_result` blocks the Claude Max / Agent SDK path cannot produce. A request carrying one is rejected with a `400` explaining the fix. If a plugin needs server-side web search (e.g. [`opencode-websearch`](https://github.com/emilsvennesson/opencode-websearch)), give it its **own** provider pointed at `https://api.anthropic.com` with your `ANTHROPIC_API_KEY` — don't route that call through Meridian.
|
|
230
233
|
|
|
231
234
|
## Multi-Profile Support
|
|
232
235
|
|
|
@@ -473,6 +476,20 @@ Point any OpenAI-compatible tool at `http://127.0.0.1:3456` with any API key val
|
|
|
473
476
|
|
|
474
477
|
> **Note:** Multi-turn conversations work by packing prior turns into the system prompt. Each request is a fresh SDK session — OpenAI clients replay full history themselves and don't use Meridian's session resumption.
|
|
475
478
|
|
|
479
|
+
### Cherry Studio
|
|
480
|
+
|
|
481
|
+
[Cherry Studio](https://github.com/CherryHQ/cherry-studio) is a desktop chat client. Point it at Meridian by setting the Anthropic API base URL to `http://127.0.0.1:3456` (any API key value works).
|
|
482
|
+
|
|
483
|
+
Because Cherry Studio is a chat client rather than a coding agent, select the `cherry` adapter so Claude's **built-in web search** is available (coding-agent adapters block it in favour of their own):
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
MERIDIAN_DEFAULT_AGENT=cherry meridian
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
The `cherry` adapter runs in internal mode: Claude executes `WebSearch`/`WebFetch` itself and Meridian returns the grounded answer — the internal tool calls are hidden from the client. This resolves the "no WebSearch/WebFetch tool exposed" error (#481).
|
|
490
|
+
|
|
491
|
+
> Cherry Studio doesn't send a Meridian-specific header, so set `MERIDIAN_DEFAULT_AGENT=cherry` on a Meridian dedicated to it, or send `x-meridian-agent: cherry` if your setup allows custom headers.
|
|
492
|
+
|
|
476
493
|
### ForgeCode
|
|
477
494
|
|
|
478
495
|
Add a custom provider to `~/forge/.forge.toml`:
|
|
@@ -1326,6 +1326,9 @@ var init_sdkFeatures = __esm(() => {
|
|
|
1326
1326
|
},
|
|
1327
1327
|
openai: {
|
|
1328
1328
|
codeSystemPrompt: false
|
|
1329
|
+
},
|
|
1330
|
+
cherry: {
|
|
1331
|
+
codeSystemPrompt: false
|
|
1329
1332
|
}
|
|
1330
1333
|
};
|
|
1331
1334
|
VALID_CLAUDE_MD_VALUES = new Set(["off", "project", "full"]);
|
|
@@ -8181,6 +8184,119 @@ function normalizeToolInput(input, clientSchema) {
|
|
|
8181
8184
|
return normalized;
|
|
8182
8185
|
}
|
|
8183
8186
|
|
|
8187
|
+
// src/proxy/tools.ts
|
|
8188
|
+
var BLOCKED_BUILTIN_TOOLS = [
|
|
8189
|
+
"Read",
|
|
8190
|
+
"Write",
|
|
8191
|
+
"Edit",
|
|
8192
|
+
"Bash",
|
|
8193
|
+
"Glob",
|
|
8194
|
+
"Grep",
|
|
8195
|
+
"NotebookEdit",
|
|
8196
|
+
"WebFetch",
|
|
8197
|
+
"WebSearch",
|
|
8198
|
+
"TodoWrite"
|
|
8199
|
+
];
|
|
8200
|
+
var CLAUDE_CODE_ONLY_TOOLS = [
|
|
8201
|
+
"CronCreate",
|
|
8202
|
+
"CronDelete",
|
|
8203
|
+
"CronList",
|
|
8204
|
+
"EnterPlanMode",
|
|
8205
|
+
"ExitPlanMode",
|
|
8206
|
+
"EnterWorktree",
|
|
8207
|
+
"ExitWorktree",
|
|
8208
|
+
"Monitor",
|
|
8209
|
+
"NotebookEdit",
|
|
8210
|
+
"PushNotification",
|
|
8211
|
+
"RemoteTrigger",
|
|
8212
|
+
"ScheduleWakeup",
|
|
8213
|
+
"TodoWrite",
|
|
8214
|
+
"AskUserQuestion",
|
|
8215
|
+
"Skill",
|
|
8216
|
+
"Agent",
|
|
8217
|
+
"TaskOutput",
|
|
8218
|
+
"TaskStop",
|
|
8219
|
+
"WebSearch"
|
|
8220
|
+
];
|
|
8221
|
+
var SERVER_TOOL_TYPE = /^web_(search|fetch)_\d+$/;
|
|
8222
|
+
function detectServerTools(tools) {
|
|
8223
|
+
if (!Array.isArray(tools))
|
|
8224
|
+
return [];
|
|
8225
|
+
const found = [];
|
|
8226
|
+
for (const tool of tools) {
|
|
8227
|
+
const type = tool?.type;
|
|
8228
|
+
if (typeof type === "string" && SERVER_TOOL_TYPE.test(type) && !found.includes(type)) {
|
|
8229
|
+
found.push(type);
|
|
8230
|
+
}
|
|
8231
|
+
}
|
|
8232
|
+
return found;
|
|
8233
|
+
}
|
|
8234
|
+
function serverToolErrorMessage(types2) {
|
|
8235
|
+
const list = types2.join(", ");
|
|
8236
|
+
return `Anthropic server tools (${list}) can't run through Meridian. ` + `Server-side web search/fetch is a raw Anthropic API feature (billed to an API key) ` + `that produces server_tool_use / web_search_tool_result blocks the Claude Max / Agent SDK path cannot emit. ` + `Point the plugin making this call at the real API instead — configure it with a separate provider using ` + `baseURL "https://api.anthropic.com" and your own ANTHROPIC_API_KEY, rather than routing it through Meridian.`;
|
|
8237
|
+
}
|
|
8238
|
+
var MCP_SERVER_NAME = "opencode";
|
|
8239
|
+
var ALLOWED_MCP_TOOLS = [
|
|
8240
|
+
`mcp__${MCP_SERVER_NAME}__read`,
|
|
8241
|
+
`mcp__${MCP_SERVER_NAME}__write`,
|
|
8242
|
+
`mcp__${MCP_SERVER_NAME}__edit`,
|
|
8243
|
+
`mcp__${MCP_SERVER_NAME}__bash`,
|
|
8244
|
+
`mcp__${MCP_SERVER_NAME}__glob`,
|
|
8245
|
+
`mcp__${MCP_SERVER_NAME}__grep`
|
|
8246
|
+
];
|
|
8247
|
+
|
|
8248
|
+
// src/proxy/passthroughEarlyStop.ts
|
|
8249
|
+
var CLIENT_TOOL_PREFIX = "mcp__oc__";
|
|
8250
|
+
var INTERNAL_TOOLS = new Set(["ToolSearch"]);
|
|
8251
|
+
function createEarlyStopTracker() {
|
|
8252
|
+
return { expected: new Set, resolved: new Set, fired: false };
|
|
8253
|
+
}
|
|
8254
|
+
function isClientForwardedToolUse(block) {
|
|
8255
|
+
const b = block;
|
|
8256
|
+
if (!b || b.type !== "tool_use")
|
|
8257
|
+
return false;
|
|
8258
|
+
if (typeof b.id !== "string" || b.id.length === 0)
|
|
8259
|
+
return false;
|
|
8260
|
+
if (typeof b.name !== "string")
|
|
8261
|
+
return false;
|
|
8262
|
+
if (INTERNAL_TOOLS.has(b.name))
|
|
8263
|
+
return false;
|
|
8264
|
+
if (b.name.startsWith("mcp__") && !b.name.startsWith(CLIENT_TOOL_PREFIX))
|
|
8265
|
+
return false;
|
|
8266
|
+
return true;
|
|
8267
|
+
}
|
|
8268
|
+
function noteAssistantContent(tracker, content) {
|
|
8269
|
+
if (!Array.isArray(content))
|
|
8270
|
+
return;
|
|
8271
|
+
for (const block of content) {
|
|
8272
|
+
if (isClientForwardedToolUse(block)) {
|
|
8273
|
+
tracker.expected.add(block.id);
|
|
8274
|
+
}
|
|
8275
|
+
}
|
|
8276
|
+
}
|
|
8277
|
+
function noteUserContent(tracker, content) {
|
|
8278
|
+
if (!Array.isArray(content))
|
|
8279
|
+
return;
|
|
8280
|
+
for (const block of content) {
|
|
8281
|
+
const b = block;
|
|
8282
|
+
if (b?.type === "tool_result" && typeof b.tool_use_id === "string" && tracker.expected.has(b.tool_use_id)) {
|
|
8283
|
+
tracker.resolved.add(b.tool_use_id);
|
|
8284
|
+
}
|
|
8285
|
+
}
|
|
8286
|
+
}
|
|
8287
|
+
function shouldEarlyStop(tracker) {
|
|
8288
|
+
if (tracker.fired)
|
|
8289
|
+
return false;
|
|
8290
|
+
if (tracker.expected.size === 0)
|
|
8291
|
+
return false;
|
|
8292
|
+
for (const id of tracker.expected) {
|
|
8293
|
+
if (!tracker.resolved.has(id))
|
|
8294
|
+
return false;
|
|
8295
|
+
}
|
|
8296
|
+
tracker.fired = true;
|
|
8297
|
+
return true;
|
|
8298
|
+
}
|
|
8299
|
+
|
|
8184
8300
|
// src/proxy/agentDefs.ts
|
|
8185
8301
|
var FALLBACK_AGENT_NAME = "general";
|
|
8186
8302
|
var DEFAULT_AGENT_TYPES = {
|
|
@@ -10052,6 +10168,38 @@ function consolidateMultimodalOntoLastUser(structured) {
|
|
|
10052
10168
|
return result;
|
|
10053
10169
|
}
|
|
10054
10170
|
var TOOL_TARGET_KEYS = ["filePath", "file_path", "path", "command", "pattern", "query", "url"];
|
|
10171
|
+
var CONTENT_SUMMARY_MAX = 120;
|
|
10172
|
+
function summarizeContent(value) {
|
|
10173
|
+
if (typeof value !== "string" || value.length === 0)
|
|
10174
|
+
return;
|
|
10175
|
+
const collapsed = value.replace(/\s+/g, " ").trim();
|
|
10176
|
+
if (!collapsed)
|
|
10177
|
+
return;
|
|
10178
|
+
return collapsed.length > CONTENT_SUMMARY_MAX ? collapsed.slice(0, CONTENT_SUMMARY_MAX) + "..." : collapsed;
|
|
10179
|
+
}
|
|
10180
|
+
function extractContentSummary(name, input) {
|
|
10181
|
+
if (!input || typeof input !== "object")
|
|
10182
|
+
return;
|
|
10183
|
+
const rec = input;
|
|
10184
|
+
switch (name.toLowerCase()) {
|
|
10185
|
+
case "edit":
|
|
10186
|
+
return summarizeContent(rec.newString ?? rec.new_string);
|
|
10187
|
+
case "write":
|
|
10188
|
+
return summarizeContent(rec.content);
|
|
10189
|
+
case "multiedit": {
|
|
10190
|
+
const edits = rec.edits;
|
|
10191
|
+
if (!Array.isArray(edits) || edits.length === 0)
|
|
10192
|
+
return;
|
|
10193
|
+
const first = edits[0];
|
|
10194
|
+
const firstSummary = summarizeContent(first?.newString ?? first?.new_string);
|
|
10195
|
+
if (!firstSummary)
|
|
10196
|
+
return;
|
|
10197
|
+
return edits.length > 1 ? `${edits.length} edits; first: ${firstSummary}` : firstSummary;
|
|
10198
|
+
}
|
|
10199
|
+
default:
|
|
10200
|
+
return;
|
|
10201
|
+
}
|
|
10202
|
+
}
|
|
10055
10203
|
function buildToolUseIndex(messages) {
|
|
10056
10204
|
const index = new Map;
|
|
10057
10205
|
for (const m of messages) {
|
|
@@ -10071,13 +10219,18 @@ function buildToolUseIndex(messages) {
|
|
|
10071
10219
|
}
|
|
10072
10220
|
}
|
|
10073
10221
|
}
|
|
10074
|
-
index.set(block.id, {
|
|
10222
|
+
index.set(block.id, {
|
|
10223
|
+
name: block.name,
|
|
10224
|
+
target,
|
|
10225
|
+
contentSummary: extractContentSummary(block.name, input)
|
|
10226
|
+
});
|
|
10075
10227
|
}
|
|
10076
10228
|
}
|
|
10077
10229
|
return index;
|
|
10078
10230
|
}
|
|
10079
10231
|
function describeToolCall(info) {
|
|
10080
|
-
|
|
10232
|
+
const head = info.target ? `your ${info.name} ${info.target}` : `your ${info.name}`;
|
|
10233
|
+
return info.contentSummary ? `[${head} → "${info.contentSummary}"]` : `[${head}]`;
|
|
10081
10234
|
}
|
|
10082
10235
|
|
|
10083
10236
|
// src/proxy/auth.ts
|
|
@@ -10269,50 +10422,6 @@ ${text.slice(0, 2000)}` : text.slice(0, 2000);
|
|
|
10269
10422
|
return createHash("sha256").update(seed).digest("hex").slice(0, 16);
|
|
10270
10423
|
}
|
|
10271
10424
|
|
|
10272
|
-
// src/proxy/tools.ts
|
|
10273
|
-
var BLOCKED_BUILTIN_TOOLS = [
|
|
10274
|
-
"Read",
|
|
10275
|
-
"Write",
|
|
10276
|
-
"Edit",
|
|
10277
|
-
"Bash",
|
|
10278
|
-
"Glob",
|
|
10279
|
-
"Grep",
|
|
10280
|
-
"NotebookEdit",
|
|
10281
|
-
"WebFetch",
|
|
10282
|
-
"WebSearch",
|
|
10283
|
-
"TodoWrite"
|
|
10284
|
-
];
|
|
10285
|
-
var CLAUDE_CODE_ONLY_TOOLS = [
|
|
10286
|
-
"CronCreate",
|
|
10287
|
-
"CronDelete",
|
|
10288
|
-
"CronList",
|
|
10289
|
-
"EnterPlanMode",
|
|
10290
|
-
"ExitPlanMode",
|
|
10291
|
-
"EnterWorktree",
|
|
10292
|
-
"ExitWorktree",
|
|
10293
|
-
"Monitor",
|
|
10294
|
-
"NotebookEdit",
|
|
10295
|
-
"PushNotification",
|
|
10296
|
-
"RemoteTrigger",
|
|
10297
|
-
"ScheduleWakeup",
|
|
10298
|
-
"TodoWrite",
|
|
10299
|
-
"AskUserQuestion",
|
|
10300
|
-
"Skill",
|
|
10301
|
-
"Agent",
|
|
10302
|
-
"TaskOutput",
|
|
10303
|
-
"TaskStop",
|
|
10304
|
-
"WebSearch"
|
|
10305
|
-
];
|
|
10306
|
-
var MCP_SERVER_NAME = "opencode";
|
|
10307
|
-
var ALLOWED_MCP_TOOLS = [
|
|
10308
|
-
`mcp__${MCP_SERVER_NAME}__read`,
|
|
10309
|
-
`mcp__${MCP_SERVER_NAME}__write`,
|
|
10310
|
-
`mcp__${MCP_SERVER_NAME}__edit`,
|
|
10311
|
-
`mcp__${MCP_SERVER_NAME}__bash`,
|
|
10312
|
-
`mcp__${MCP_SERVER_NAME}__glob`,
|
|
10313
|
-
`mcp__${MCP_SERVER_NAME}__grep`
|
|
10314
|
-
];
|
|
10315
|
-
|
|
10316
10425
|
// src/proxy/transforms/opencode.ts
|
|
10317
10426
|
var openCodeTransforms = [
|
|
10318
10427
|
{
|
|
@@ -11112,6 +11221,34 @@ var openAiAdapter = {
|
|
|
11112
11221
|
name: "openai"
|
|
11113
11222
|
};
|
|
11114
11223
|
|
|
11224
|
+
// src/proxy/adapters/cherry.ts
|
|
11225
|
+
var CHERRY_WEB_TOOLS = ["WebSearch", "WebFetch"];
|
|
11226
|
+
var isWebTool = (t) => CHERRY_WEB_TOOLS.includes(t);
|
|
11227
|
+
var CHERRY_BLOCKED_BUILTIN_TOOLS = BLOCKED_BUILTIN_TOOLS.filter((t) => !isWebTool(t));
|
|
11228
|
+
var CHERRY_INCOMPATIBLE_TOOLS = CLAUDE_CODE_ONLY_TOOLS.filter((t) => !isWebTool(t));
|
|
11229
|
+
var cherryAdapter = {
|
|
11230
|
+
...openCodeAdapter,
|
|
11231
|
+
name: "cherry",
|
|
11232
|
+
usesPassthrough() {
|
|
11233
|
+
return false;
|
|
11234
|
+
},
|
|
11235
|
+
supportsThinking() {
|
|
11236
|
+
return false;
|
|
11237
|
+
},
|
|
11238
|
+
getBlockedBuiltinTools() {
|
|
11239
|
+
return CHERRY_BLOCKED_BUILTIN_TOOLS;
|
|
11240
|
+
},
|
|
11241
|
+
getAgentIncompatibleTools() {
|
|
11242
|
+
return CHERRY_INCOMPATIBLE_TOOLS;
|
|
11243
|
+
},
|
|
11244
|
+
getAllowedMcpTools() {
|
|
11245
|
+
return [...CHERRY_WEB_TOOLS];
|
|
11246
|
+
},
|
|
11247
|
+
getCoreToolNames() {
|
|
11248
|
+
return [];
|
|
11249
|
+
}
|
|
11250
|
+
};
|
|
11251
|
+
|
|
11115
11252
|
// src/proxy/adapters/detect.ts
|
|
11116
11253
|
var ADAPTER_MAP = {
|
|
11117
11254
|
opencode: openCodeAdapter,
|
|
@@ -11122,6 +11259,8 @@ var ADAPTER_MAP = {
|
|
|
11122
11259
|
forgecode: forgeCodeAdapter,
|
|
11123
11260
|
"claude-code": claudeCodeAdapter,
|
|
11124
11261
|
claudecode: claudeCodeAdapter,
|
|
11262
|
+
cherry: cherryAdapter,
|
|
11263
|
+
cherrystudio: cherryAdapter,
|
|
11125
11264
|
openai: openAiAdapter
|
|
11126
11265
|
};
|
|
11127
11266
|
var envDefault = process.env.MERIDIAN_DEFAULT_AGENT || "";
|
|
@@ -17043,6 +17182,27 @@ function structuredOutputText(value) {
|
|
|
17043
17182
|
return JSON.stringify(value);
|
|
17044
17183
|
}
|
|
17045
17184
|
|
|
17185
|
+
// src/proxy/transforms/cherry.ts
|
|
17186
|
+
var cherryTransforms = [
|
|
17187
|
+
{
|
|
17188
|
+
name: "cherry-core",
|
|
17189
|
+
adapters: ["cherry"],
|
|
17190
|
+
onRequest(ctx) {
|
|
17191
|
+
return {
|
|
17192
|
+
...ctx,
|
|
17193
|
+
blockedTools: CHERRY_BLOCKED_BUILTIN_TOOLS,
|
|
17194
|
+
incompatibleTools: CHERRY_INCOMPATIBLE_TOOLS,
|
|
17195
|
+
allowedMcpTools: [...CHERRY_WEB_TOOLS],
|
|
17196
|
+
coreToolNames: [],
|
|
17197
|
+
passthrough: false,
|
|
17198
|
+
hidesInternalTools: true,
|
|
17199
|
+
supportsThinking: false,
|
|
17200
|
+
shouldTrackFileChanges: false
|
|
17201
|
+
};
|
|
17202
|
+
}
|
|
17203
|
+
}
|
|
17204
|
+
];
|
|
17205
|
+
|
|
17046
17206
|
// src/proxy/transforms/registry.ts
|
|
17047
17207
|
var ADAPTER_TRANSFORMS = {
|
|
17048
17208
|
opencode: openCodeTransforms,
|
|
@@ -17051,6 +17211,7 @@ var ADAPTER_TRANSFORMS = {
|
|
|
17051
17211
|
pi: piTransforms,
|
|
17052
17212
|
forgecode: forgeCodeTransforms,
|
|
17053
17213
|
passthrough: passthroughTransforms,
|
|
17214
|
+
cherry: cherryTransforms,
|
|
17054
17215
|
openai: openCodeTransforms
|
|
17055
17216
|
};
|
|
17056
17217
|
function getAdapterTransforms(adapterName) {
|
|
@@ -18204,6 +18365,10 @@ function createProxyServer(config = {}) {
|
|
|
18204
18365
|
if (body.messages.length === 0) {
|
|
18205
18366
|
return c.json({ type: "error", error: { type: "invalid_request_error", message: "messages: Cannot be empty — at least one message is required" } }, 400);
|
|
18206
18367
|
}
|
|
18368
|
+
const serverTools = detectServerTools(body.tools);
|
|
18369
|
+
if (serverTools.length > 0) {
|
|
18370
|
+
return c.json({ type: "error", error: { type: "invalid_request_error", message: serverToolErrorMessage(serverTools) } }, 400);
|
|
18371
|
+
}
|
|
18207
18372
|
const parsedOutputFormat = parseOutputFormat(body.output_config, body.tools);
|
|
18208
18373
|
if (!parsedOutputFormat.ok) {
|
|
18209
18374
|
return c.json({ type: "error", error: { type: "invalid_request_error", message: parsedOutputFormat.message } }, 400);
|
|
@@ -18426,6 +18591,9 @@ function createProxyServer(config = {}) {
|
|
|
18426
18591
|
const capturedSignatures = new Set;
|
|
18427
18592
|
const capturedToolNames = new Set;
|
|
18428
18593
|
let sawDuplicateToolUse = false;
|
|
18594
|
+
const earlyStopEnabled = passthrough && process.env.MERIDIAN_PASSTHROUGH_EARLY_STOP !== "0";
|
|
18595
|
+
const earlyStop = createEarlyStopTracker();
|
|
18596
|
+
let earlyStopFired = false;
|
|
18429
18597
|
const toolChoice = body.tool_choice;
|
|
18430
18598
|
const forceSingleToolUse = !!toolChoice && (toolChoice.type === "tool" || toolChoice.disable_parallel_tool_use === true);
|
|
18431
18599
|
const fileChanges = [];
|
|
@@ -18788,6 +18956,19 @@ function createProxyServer(config = {}) {
|
|
|
18788
18956
|
claudeLog("passthrough.loop_break", { mode: "non_stream", assistantMessages, captured: capturedToolUses.length });
|
|
18789
18957
|
break;
|
|
18790
18958
|
}
|
|
18959
|
+
if (earlyStopEnabled) {
|
|
18960
|
+
if (message.type === "assistant") {
|
|
18961
|
+
noteAssistantContent(earlyStop, message.message?.content);
|
|
18962
|
+
} else if (message.type === "user") {
|
|
18963
|
+
noteUserContent(earlyStop, message.message?.content);
|
|
18964
|
+
if (shouldEarlyStop(earlyStop)) {
|
|
18965
|
+
earlyStopFired = true;
|
|
18966
|
+
claudeLog("passthrough.early_stop", { mode: "non_stream", captured: capturedToolUses.length });
|
|
18967
|
+
requestAbort.abort("passthrough turn complete");
|
|
18968
|
+
break;
|
|
18969
|
+
}
|
|
18970
|
+
}
|
|
18971
|
+
}
|
|
18791
18972
|
if (message.type === "assistant") {
|
|
18792
18973
|
assistantMessages += 1;
|
|
18793
18974
|
if (message.uuid) {
|
|
@@ -18811,6 +18992,16 @@ function createProxyServer(config = {}) {
|
|
|
18811
18992
|
claudeLog("passthrough.toolsearch_filtered", { mode: "non_stream" });
|
|
18812
18993
|
continue;
|
|
18813
18994
|
}
|
|
18995
|
+
if (pipelineCtx.hidesInternalTools) {
|
|
18996
|
+
if (b.type === "tool_use") {
|
|
18997
|
+
claudeLog("internal_tool.hidden", { mode: "non_stream", name: b.name });
|
|
18998
|
+
continue;
|
|
18999
|
+
}
|
|
19000
|
+
if ((b.type === "thinking" || b.type === "redacted_thinking") && !sdkFeatures.thinkingPassthrough) {
|
|
19001
|
+
claudeLog("internal_tool.thinking_stripped", { mode: "non_stream", type: b.type });
|
|
19002
|
+
continue;
|
|
19003
|
+
}
|
|
19004
|
+
}
|
|
18814
19005
|
if (passthrough && !pipelineCtx.supportsThinking && !sdkFeatures.thinkingPassthrough && (b.type === "thinking" || b.type === "redacted_thinking")) {
|
|
18815
19006
|
claudeLog("passthrough.thinking_stripped", { mode: "non_stream", type: b.type });
|
|
18816
19007
|
continue;
|
|
@@ -19022,6 +19213,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
19022
19213
|
let textEventsForwarded = 0;
|
|
19023
19214
|
let bytesSent = 0;
|
|
19024
19215
|
let streamClosed = false;
|
|
19216
|
+
let awaitingEarlyStopDrain = false;
|
|
19025
19217
|
claudeLog("upstream.start", { mode: "stream", model });
|
|
19026
19218
|
const safeEnqueue = (payload, source) => {
|
|
19027
19219
|
if (streamClosed)
|
|
@@ -19315,7 +19507,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
19315
19507
|
}));
|
|
19316
19508
|
try {
|
|
19317
19509
|
for await (const message of guardedResponse) {
|
|
19318
|
-
if (streamClosed) {
|
|
19510
|
+
if (streamClosed && !awaitingEarlyStopDrain) {
|
|
19319
19511
|
break;
|
|
19320
19512
|
}
|
|
19321
19513
|
if (message.session_id) {
|
|
@@ -19324,6 +19516,34 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
19324
19516
|
if (message.type === "assistant" && message.uuid) {
|
|
19325
19517
|
sdkUuidMap.push(message.uuid);
|
|
19326
19518
|
}
|
|
19519
|
+
if (earlyStopEnabled) {
|
|
19520
|
+
if (message.type === "assistant") {
|
|
19521
|
+
noteAssistantContent(earlyStop, message.message?.content);
|
|
19522
|
+
} else if (message.type === "user") {
|
|
19523
|
+
noteUserContent(earlyStop, message.message?.content);
|
|
19524
|
+
if (shouldEarlyStop(earlyStop) && streamedToolUseIds.size > 0) {
|
|
19525
|
+
earlyStopFired = true;
|
|
19526
|
+
claudeLog("passthrough.early_stop", { mode: "stream", captured: capturedToolUses.length, drained: awaitingEarlyStopDrain });
|
|
19527
|
+
safeEnqueue(encoder.encode(`event: message_delta
|
|
19528
|
+
data: ${JSON.stringify({ type: "message_delta", delta: { stop_reason: "tool_use", stop_sequence: null }, usage: { output_tokens: lastUsage?.output_tokens ?? 0 } })}
|
|
19529
|
+
|
|
19530
|
+
`), "early_stop");
|
|
19531
|
+
safeEnqueue(encoder.encode(`event: message_stop
|
|
19532
|
+
data: ${JSON.stringify({ type: "message_stop" })}
|
|
19533
|
+
|
|
19534
|
+
`), "early_stop");
|
|
19535
|
+
requestAbort.abort("passthrough turn complete");
|
|
19536
|
+
awaitingEarlyStopDrain = false;
|
|
19537
|
+
if (!streamClosed) {
|
|
19538
|
+
streamClosed = true;
|
|
19539
|
+
try {
|
|
19540
|
+
controller.close();
|
|
19541
|
+
} catch {}
|
|
19542
|
+
}
|
|
19543
|
+
break;
|
|
19544
|
+
}
|
|
19545
|
+
}
|
|
19546
|
+
}
|
|
19327
19547
|
if (message.type === "result") {
|
|
19328
19548
|
const resultUsage = message.usage;
|
|
19329
19549
|
if (resultUsage)
|
|
@@ -19388,6 +19608,12 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
19388
19608
|
}
|
|
19389
19609
|
if (eventType === "content_block_start") {
|
|
19390
19610
|
const block = event.content_block;
|
|
19611
|
+
if (pipelineCtx.hidesInternalTools && (block?.type === "tool_use" || (block?.type === "thinking" || block?.type === "redacted_thinking") && !sdkFeatures.thinkingPassthrough)) {
|
|
19612
|
+
if (eventIndex !== undefined)
|
|
19613
|
+
skipBlockIndices.add(eventIndex);
|
|
19614
|
+
claudeLog("internal_tool.hidden", { mode: "stream", type: block?.type, name: block?.name, index: eventIndex });
|
|
19615
|
+
continue;
|
|
19616
|
+
}
|
|
19391
19617
|
if (passthrough && !pipelineCtx.supportsThinking && !sdkFeatures.thinkingPassthrough && (block?.type === "thinking" || block?.type === "redacted_thinking")) {
|
|
19392
19618
|
if (eventIndex !== undefined)
|
|
19393
19619
|
skipBlockIndices.add(eventIndex);
|
|
@@ -19492,6 +19718,10 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
19492
19718
|
`), "passthrough_tool_stream_stop");
|
|
19493
19719
|
streamClosed = true;
|
|
19494
19720
|
controller.close();
|
|
19721
|
+
if (earlyStopEnabled) {
|
|
19722
|
+
awaitingEarlyStopDrain = true;
|
|
19723
|
+
continue;
|
|
19724
|
+
}
|
|
19495
19725
|
break;
|
|
19496
19726
|
}
|
|
19497
19727
|
if (eventType === "content_block_delta") {
|
|
@@ -19763,7 +19993,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
19763
19993
|
} : classifyError(errMsg);
|
|
19764
19994
|
claudeLog("proxy.anthropic.error", { error: errMsg, classified: streamErr.type });
|
|
19765
19995
|
const sdkTerm = extractSdkTermination(errMsg);
|
|
19766
|
-
const canRecoverAsToolUse = (sdkTerm.reason === "max_turns" || sdkTerm.reason === "aborted" && sawDuplicateToolUse) && passthrough && capturedToolUses.length > 0 && messageStartEmitted;
|
|
19996
|
+
const canRecoverAsToolUse = (sdkTerm.reason === "max_turns" || sdkTerm.reason === "aborted" && (sawDuplicateToolUse || earlyStopFired)) && passthrough && capturedToolUses.length > 0 && messageStartEmitted;
|
|
19767
19997
|
if (canRecoverAsToolUse) {
|
|
19768
19998
|
diagnosticLog2.session(`${requestMeta.requestId} sdk_termination_recovered ${formatSdkTermination(sdkTerm, {
|
|
19769
19999
|
model,
|
package/dist/cli.js
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cherry Studio adapter.
|
|
3
|
+
*
|
|
4
|
+
* Cherry Studio (https://github.com/CherryHQ/cherry-studio) is a desktop chat
|
|
5
|
+
* client — not a coding agent. Pointed at Meridian it works for plain chat,
|
|
6
|
+
* but its web search failed (#481): the model reported it had "no WebSearch or
|
|
7
|
+
* WebFetch tool exposed". That's because Meridian blocks the SDK's built-in
|
|
8
|
+
* WebSearch/WebFetch globally — those are blocked for coding agents like
|
|
9
|
+
* OpenCode, which ship their own web-search equivalents (`websearch_web_search_exa`).
|
|
10
|
+
*
|
|
11
|
+
* Unlike a coding agent, Cherry Studio does NOT execute tools itself; it relies
|
|
12
|
+
* on Claude's own built-in web search. So this adapter:
|
|
13
|
+
* - unblocks the SDK's built-in WebSearch/WebFetch (verified to work on the
|
|
14
|
+
* Max/OAuth path — the SDK runs the search server-side and returns grounded
|
|
15
|
+
* results), and
|
|
16
|
+
* - runs in internal (non-passthrough) mode so the SDK actually executes the
|
|
17
|
+
* search instead of trying to hand it back to a client that can't run it.
|
|
18
|
+
*
|
|
19
|
+
* It exposes only the web tools — no filesystem MCP tools — since a chat client
|
|
20
|
+
* has no business reading or writing files on the proxy host.
|
|
21
|
+
*
|
|
22
|
+
* Detection: selected via `x-meridian-agent: cherry` (or `cherrystudio`) or the
|
|
23
|
+
* `MERIDIAN_DEFAULT_AGENT=cherry` env var. Cherry Studio doesn't send a
|
|
24
|
+
* Meridian-specific header, so a user running a dedicated Meridian for it should
|
|
25
|
+
* set the env default. (If a distinctive User-Agent is confirmed, add UA
|
|
26
|
+
* detection in detect.ts.)
|
|
27
|
+
*
|
|
28
|
+
* NOTE: agent-specific. See ARCHITECTURE.md "Agent-Specific Logic".
|
|
29
|
+
*/
|
|
30
|
+
import type { AgentAdapter } from "../adapter";
|
|
31
|
+
/** The SDK built-in web tools Cherry Studio wants Claude to run itself. */
|
|
32
|
+
export declare const CHERRY_WEB_TOOLS: readonly ["WebSearch", "WebFetch"];
|
|
33
|
+
/** Built-ins blocked for Cherry — everything OpenCode blocks EXCEPT the web tools. */
|
|
34
|
+
export declare const CHERRY_BLOCKED_BUILTIN_TOOLS: string[];
|
|
35
|
+
/** Incompatible tools for Cherry — CLAUDE_CODE_ONLY_TOOLS minus the web tools. */
|
|
36
|
+
export declare const CHERRY_INCOMPATIBLE_TOOLS: string[];
|
|
37
|
+
export declare const cherryAdapter: AgentAdapter;
|
|
38
|
+
//# sourceMappingURL=cherry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cherry.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/cherry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAI9C,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,oCAAqC,CAAA;AAIlE,sFAAsF;AACtF,eAAO,MAAM,4BAA4B,UAAmD,CAAA;AAE5F,kFAAkF;AAClF,eAAO,MAAM,yBAAyB,UAAoD,CAAA;AAE1F,eAAO,MAAM,aAAa,EAAE,YAiC3B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAkD9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,YAAY,CAgDtD"}
|
package/dist/proxy/messages.d.ts
CHANGED
|
@@ -81,6 +81,15 @@ export interface ToolCallInfo {
|
|
|
81
81
|
name: string;
|
|
82
82
|
/** Compact human-readable target (file path, command, pattern...), if any. */
|
|
83
83
|
target: string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* For mutating tools (edit/write/multiedit): a truncated summary of the
|
|
86
|
+
* content the call produced. On fresh replay the assistant's tool_use
|
|
87
|
+
* blocks are dropped, so without this the model knows THAT it edited a
|
|
88
|
+
* file but not WHAT it wrote — it then re-derives near-duplicate edits
|
|
89
|
+
* and confabulates a parallel editor when it doesn't recognize its own
|
|
90
|
+
* wording (#496 follow-up, stefanpartheym's transcript).
|
|
91
|
+
*/
|
|
92
|
+
contentSummary: string | undefined;
|
|
84
93
|
}
|
|
85
94
|
/**
|
|
86
95
|
* Index every assistant tool_use block in a conversation by id.
|
|
@@ -98,10 +107,12 @@ export declare function buildToolUseIndex(messages: Array<{
|
|
|
98
107
|
}>): Map<string, ToolCallInfo>;
|
|
99
108
|
/**
|
|
100
109
|
* Render a compact attribution label for a replayed tool result, e.g.
|
|
101
|
-
* `[write tmp/test2.txt]
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
110
|
+
* `[write tmp/test2.txt]`, `[bash echo hi]`, or — for mutating tools —
|
|
111
|
+
* `[edit a.yml → "# Ignore major bumps..."]` so the model can recognize its
|
|
112
|
+
* own prior work product on replay. Deliberately terse and bracket-formatted
|
|
113
|
+
* differently from the banned `[Tool Use: ...]` / `[Tool Result ...]` shapes
|
|
114
|
+
* (#111/#386) so the model reads it as context, not as tool-call syntax to
|
|
115
|
+
* imitate.
|
|
105
116
|
*/
|
|
106
117
|
export declare function describeToolCall(info: ToolCallInfo): string;
|
|
107
118
|
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/proxy/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,CAiBrD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAUtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAM7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,CAKzH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAU3D;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,aAAyC,CAAA;AAEtE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iCAAiC,CAC/C,CAAC,SAAS;IAAE,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,EAC3C,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAyCtB;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/proxy/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,CAiBrD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAUtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAM7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,CAKzH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAU3D;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,aAAyC,CAAA;AAEtE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iCAAiC,CAC/C,CAAC,SAAS;IAAE,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,EAC3C,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAyCtB;AAED,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAyCD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAC9C,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAyB3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAO3D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passthrough early-stop tracking.
|
|
3
|
+
*
|
|
4
|
+
* In passthrough mode the PreToolUse hook denies every client tool call
|
|
5
|
+
* ("forwarded to client — end your turn"), but the SDK then invokes the model
|
|
6
|
+
* one more time to digest the deny. That digest turn is discarded by the proxy
|
|
7
|
+
* yet fully billed — and on always-thinking models (Fable) it costs a whole
|
|
8
|
+
* thinking pass per tool step, roughly doubling per-step output spend and
|
|
9
|
+
* adding a full model round-trip of latency.
|
|
10
|
+
*
|
|
11
|
+
* The fix: the SDK emits each denied call's tool_result as a `user` message in
|
|
12
|
+
* the stream (verified against the real SDK) BEFORE it fires the digest turn's
|
|
13
|
+
* API request. So the proxy can watch the stream, and the moment every
|
|
14
|
+
* client-forwarded tool_use from the assistant turn has its deny persisted,
|
|
15
|
+
* abort the query — the digest turn never generates. Because the denies are
|
|
16
|
+
* already recorded in the SDK session history at that point, the session stays
|
|
17
|
+
* coherent and can be stored + resumed (unlike the #580 duplicate-abort case,
|
|
18
|
+
* which fires mid-hook before persistence).
|
|
19
|
+
*
|
|
20
|
+
* Pure module — no I/O, no imports from server.ts or session/.
|
|
21
|
+
*/
|
|
22
|
+
export interface EarlyStopTracker {
|
|
23
|
+
/** tool_use ids of client-forwarded calls awaiting a persisted deny result */
|
|
24
|
+
expected: Set<string>;
|
|
25
|
+
/** subset of `expected` whose tool_result has been observed in the stream */
|
|
26
|
+
resolved: Set<string>;
|
|
27
|
+
/** true once shouldEarlyStop has returned true — it fires at most once */
|
|
28
|
+
fired: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function createEarlyStopTracker(): EarlyStopTracker;
|
|
31
|
+
/**
|
|
32
|
+
* Is this content block a tool call that the proxy forwards to the client
|
|
33
|
+
* (as opposed to an internal tool the SDK executes itself)?
|
|
34
|
+
*
|
|
35
|
+
* Client tools appear either with the passthrough MCP prefix (mcp__oc__read)
|
|
36
|
+
* or as bare names (read) — the SDK strips the prefix in some event paths.
|
|
37
|
+
* Internal MCP tools (mcp__opencode__*) and ToolSearch are excluded.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isClientForwardedToolUse(block: unknown): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Record the client-forwarded tool_use ids from an assistant message's content.
|
|
42
|
+
*/
|
|
43
|
+
export declare function noteAssistantContent(tracker: EarlyStopTracker, content: unknown): void;
|
|
44
|
+
/**
|
|
45
|
+
* Record persisted tool_results from a user message's content. Only results
|
|
46
|
+
* matching an expected id count — unrelated results are ignored.
|
|
47
|
+
*/
|
|
48
|
+
export declare function noteUserContent(tracker: EarlyStopTracker, content: unknown): void;
|
|
49
|
+
/**
|
|
50
|
+
* True exactly once: when at least one client tool call was forwarded and
|
|
51
|
+
* every forwarded call's deny has been observed in the stream. At that point
|
|
52
|
+
* the digest turn hasn't generated yet — the caller should abort the query.
|
|
53
|
+
*/
|
|
54
|
+
export declare function shouldEarlyStop(tracker: EarlyStopTracker): boolean;
|
|
55
|
+
//# sourceMappingURL=passthroughEarlyStop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passthroughEarlyStop.d.ts","sourceRoot":"","sources":["../../src/proxy/passthroughEarlyStop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAUH,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,6EAA6E;IAC7E,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAA;CACf;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQhE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAOtF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAQjF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAQlE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkFeatures.d.ts","sourceRoot":"","sources":["../../src/proxy/sdkFeatures.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,gBAAgB,EAAE,OAAO,CAAA;IACzB,kFAAkF;IAClF,kBAAkB,EAAE,OAAO,CAAA;IAC3B,4DAA4D;IAC5D,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,CAAA;IACpC,wDAAwD;IACxD,MAAM,EAAE,OAAO,CAAA;IACf,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;IAC7C,4CAA4C;IAC5C,mBAAmB,EAAE,OAAO,CAAA;IAC5B,iFAAiF;IACjF,YAAY,EAAE,OAAO,CAAA;IACrB,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,QAAQ,EAAE,OAAO,CAAA;IACjB,uEAAuE;IACvE,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"sdkFeatures.d.ts","sourceRoot":"","sources":["../../src/proxy/sdkFeatures.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,gBAAgB,EAAE,OAAO,CAAA;IACzB,kFAAkF;IAClF,kBAAkB,EAAE,OAAO,CAAA;IAC3B,4DAA4D;IAC5D,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,CAAA;IACpC,wDAAwD;IACxD,MAAM,EAAE,OAAO,CAAA;IACf,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;IAC7C,4CAA4C;IAC5C,mBAAmB,EAAE,OAAO,CAAA;IAC5B,iFAAiF;IACjF,YAAY,EAAE,OAAO,CAAA;IACrB,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,QAAQ,EAAE,OAAO,CAAA;IACjB,uEAAuE;IACvE,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAA;AA4FpE;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAU1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,GAAG,SAAS,CAKhG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAOtE;AAKD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAgC5E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAInG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAI9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAGvD,YAAY,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAA;AAKpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAGvD,YAAY,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAA;AAKpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAoCnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAEpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAGzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AA2Q7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CA+pGhF;AAWD,wBAAgB,gCAAgC,IAAI,IAAI,CAavD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGhG"}
|
package/dist/proxy/tools.d.ts
CHANGED
|
@@ -19,6 +19,20 @@ export declare const BLOCKED_BUILTIN_TOOLS: string[];
|
|
|
19
19
|
* are blocked so Claude uses the agent's version instead of the SDK's.
|
|
20
20
|
*/
|
|
21
21
|
export declare const CLAUDE_CODE_ONLY_TOOLS: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Return the distinct native-server-tool `type`s present in a request's `tools`
|
|
24
|
+
* array, in first-seen order. Empty when there are none (the common case) or
|
|
25
|
+
* when `tools` isn't an array. Pure — no I/O.
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectServerTools(tools: unknown): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Build the actionable error returned when a request carries native server
|
|
30
|
+
* tools. It tells the user to route that specific call at the real Anthropic
|
|
31
|
+
* API (with their own key) rather than through Meridian — the plugin already
|
|
32
|
+
* supports a separate per-provider baseURL, so this is a config fix on their
|
|
33
|
+
* side, not something Meridian can execute on the Max subscription.
|
|
34
|
+
*/
|
|
35
|
+
export declare function serverToolErrorMessage(types: string[]): string;
|
|
22
36
|
/** MCP server name used by the calling agent */
|
|
23
37
|
export declare const MCP_SERVER_NAME = "opencode";
|
|
24
38
|
/** MCP tools that are allowed through the proxy's tool filter */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/proxy/tools.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,UAIjC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,UAuBlC,CAAA;AAED,gDAAgD;AAChD,eAAO,MAAM,eAAe,aAAa,CAAA;AAEzC,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,UAO7B,CAAA"}
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/proxy/tools.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,UAIjC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,UAuBlC,CAAA;AAeD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAU1D;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAS9D;AAED,gDAAgD;AAChD,eAAO,MAAM,eAAe,aAAa,CAAA;AAEzC,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,UAO7B,CAAA"}
|
|
@@ -56,6 +56,16 @@ export interface RequestContext {
|
|
|
56
56
|
supportsThinking: boolean;
|
|
57
57
|
shouldTrackFileChanges: boolean;
|
|
58
58
|
leaksCwdViaSystemReminder: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* The client is a pure chat client (no tool-execution loop) that runs the
|
|
61
|
+
* SDK in internal mode purely to reach Claude's own built-in tools (e.g.
|
|
62
|
+
* Cherry Studio using WebSearch). The SDK executes those tools itself, so the
|
|
63
|
+
* proxy must NOT surface the internal tool_use blocks — the client can't run
|
|
64
|
+
* them and would loop or choke — and should strip thinking blocks it can't
|
|
65
|
+
* render. Default false: normal internal-mode agents (Droid) keep current
|
|
66
|
+
* behaviour (their internal tools are mcp__-prefixed and already hidden).
|
|
67
|
+
*/
|
|
68
|
+
hidesInternalTools?: boolean;
|
|
59
69
|
prefersStreaming?: boolean;
|
|
60
70
|
extractFileChangesFromToolUse?: (toolName: string, toolInput: unknown) => FileChange[];
|
|
61
71
|
metadata: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/proxy/transform.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/proxy/transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Transform } from "../transform";
|
|
2
|
+
/**
|
|
3
|
+
* Cherry Studio transform — supplies the SDK tool config at request time.
|
|
4
|
+
*
|
|
5
|
+
* The runtime tool policy lives here (server.ts reads `pipelineCtx.*`, not the
|
|
6
|
+
* adapter methods). Cherry is a chat client that wants Claude's own built-in
|
|
7
|
+
* web search, so we:
|
|
8
|
+
* - allow only WebSearch/WebFetch (no filesystem MCP tools),
|
|
9
|
+
* - keep those web tools OUT of the disallowed lists, and
|
|
10
|
+
* - run non-passthrough so the SDK executes the search internally.
|
|
11
|
+
*
|
|
12
|
+
* See adapters/cherry.ts for the full rationale and #481.
|
|
13
|
+
*/
|
|
14
|
+
export declare const cherryTransforms: Transform[];
|
|
15
|
+
//# sourceMappingURL=cherry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cherry.d.ts","sourceRoot":"","sources":["../../../src/proxy/transforms/cherry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,cAAc,CAAA;AAO7D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,EAwBvC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/proxy/transforms/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/proxy/transforms/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAuB7C,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,SAAS,EAAE,CAE9E"}
|
package/dist/server.js
CHANGED
package/package.json
CHANGED