@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 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, { name: block.name, target });
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
- return info.target ? `[${info.name} ${info.target}]` : `[${info.name}]`;
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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startProxyServer
4
- } from "./cli-1v1narm9.js";
4
+ } from "./cli-vhrprwj4.js";
5
5
  import"./cli-cx463q74.js";
6
6
  import"./cli-sry5aqdj.js";
7
7
  import"./cli-4rqtm83g.js";
@@ -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;AA8C9C;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,YAAY,CAgDtD"}
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"}
@@ -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]` or `[bash echo hi]`. Deliberately terse and
102
- * bracket-formatted differently from the banned `[Tool Use: ...]` /
103
- * `[Tool Result ...]` shapes (#111/#386) so the model reads it as context,
104
- * not as tool-call syntax to imitate.
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;CAC3B;AAKD;;;;;;;;;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,CAqB3B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAE3D"}
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;AAqFpE;;;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
+ {"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;AAkCnG,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,CAkiGhF;AAWD,wBAAgB,gCAAgC,IAAI,IAAI,CAavD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGhG"}
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"}
@@ -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":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAGnE;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAGnB,SAAS,CAAC,CAAC,GAAG,EAAE,cAAc,GAAG,cAAc,CAAA;IAC/C,UAAU,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,eAAe,CAAA;IAClD,WAAW,CAAC,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAGzC,SAAS,CAAC,CAAC,GAAG,EAAE,cAAc,GAAG,cAAc,CAAA;IAC/C,SAAS,CAAC,CAAC,GAAG,EAAE,cAAc,GAAG,cAAc,CAAA;IAC/C,YAAY,CAAC,CAAC,GAAG,EAAE,iBAAiB,GAAG,iBAAiB,CAAA;IACxD,OAAO,CAAC,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAAA;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;IAClB,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IAGzB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,GAAG,EAAE,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;IAGxB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9B,QAAQ,CAAC,EAAE,GAAG,CAAA;IACd,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAA;IAChC,gBAAgB,EAAE,OAAO,CAAA;IACzB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,yBAAyB,EAAE,OAAO,CAAA;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,6BAA6B,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,KAAK,UAAU,EAAE,CAAA;IAGtF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,GAAG,EAAE,CAAA;IACd,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC9B;AAGD,MAAM,WAAW,cAAc;IAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AACpF,MAAM,WAAW,cAAc;IAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AACpF,MAAM,WAAW,iBAAiB;IAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AACvF,MAAM,WAAW,YAAY;IAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AAElF,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,cAAc,GAAG,SAAS,CAAA;AAE/G,8DAA8D;AAC9D,MAAM,MAAM,WAAW,GAAG,aAAa,CAAA;AAEvC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,CAAC,EACN,WAAW,EAAE,MAAM,GAClB,CAAC,CAiBH;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,CAAC,EACN,WAAW,EAAE,MAAM,GAClB,IAAI,CAeN;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,iBAAiB,EAAE,SAAS,SAAS,EAAE,EACvC,gBAAgB,EAAE,SAAS,SAAS,EAAE,GACrC,SAAS,EAAE,CAEb;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,GAAG,CAAA;IACT,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,GAAG,EAAE,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,gBAAgB,EAAE,MAAM,CAAA;CACzB,GAAG,cAAc,CAqBjB"}
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;AAqB7C,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,SAAS,EAAE,CAE9E"}
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
@@ -11,7 +11,7 @@ import {
11
11
  runObserveHook,
12
12
  runTransformHook,
13
13
  startProxyServer
14
- } from "./cli-1v1narm9.js";
14
+ } from "./cli-vhrprwj4.js";
15
15
  import"./cli-cx463q74.js";
16
16
  import"./cli-sry5aqdj.js";
17
17
  import"./cli-4rqtm83g.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rynfar/meridian",
3
- "version": "1.47.0",
3
+ "version": "1.48.1",
4
4
  "description": "Local Anthropic API powered by your Claude Max subscription. One subscription, every agent.",
5
5
  "type": "module",
6
6
  "main": "./dist/server.js",