@rynfar/meridian 1.38.0 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -3
- package/dist/{cli-bfgya0hb.js → cli-jbdchsr4.js} +430 -135
- package/dist/cli.js +1 -1
- package/dist/proxy/adapter.d.ts +28 -2
- package/dist/proxy/adapter.d.ts.map +1 -1
- package/dist/proxy/adapters/claudecode.d.ts +21 -0
- package/dist/proxy/adapters/claudecode.d.ts.map +1 -0
- package/dist/proxy/adapters/detect.d.ts +3 -2
- package/dist/proxy/adapters/detect.d.ts.map +1 -1
- package/dist/proxy/adapters/pi.d.ts.map +1 -1
- package/dist/proxy/agentDefs.d.ts +2 -0
- package/dist/proxy/agentDefs.d.ts.map +1 -1
- package/dist/proxy/agentMatch.d.ts +11 -1
- package/dist/proxy/agentMatch.d.ts.map +1 -1
- package/dist/proxy/messages.d.ts +11 -0
- package/dist/proxy/messages.d.ts.map +1 -1
- package/dist/proxy/models.d.ts +25 -0
- package/dist/proxy/models.d.ts.map +1 -1
- package/dist/proxy/openai.d.ts.map +1 -1
- package/dist/proxy/passthroughTools.d.ts +18 -0
- package/dist/proxy/passthroughTools.d.ts.map +1 -1
- package/dist/proxy/query.d.ts +19 -1
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts +10 -1
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +4 -2
|
@@ -7888,6 +7888,184 @@ function stripMcpPrefix(toolName) {
|
|
|
7888
7888
|
}
|
|
7889
7889
|
return toolName;
|
|
7890
7890
|
}
|
|
7891
|
+
function toCamelCase(s) {
|
|
7892
|
+
return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
7893
|
+
}
|
|
7894
|
+
function toSnakeCase(s) {
|
|
7895
|
+
return s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
7896
|
+
}
|
|
7897
|
+
function normalizeToolInput(input, clientSchema) {
|
|
7898
|
+
if (!input || !clientSchema?.properties)
|
|
7899
|
+
return input;
|
|
7900
|
+
const schemaKeys = new Set(Object.keys(clientSchema.properties));
|
|
7901
|
+
const required = new Set(clientSchema.required ?? []);
|
|
7902
|
+
const missingRequired = [...required].filter((k) => input[k] === undefined);
|
|
7903
|
+
if (missingRequired.length === 0)
|
|
7904
|
+
return input;
|
|
7905
|
+
const normalized = { ...input };
|
|
7906
|
+
for (const key of Object.keys(normalized)) {
|
|
7907
|
+
if (schemaKeys.has(key))
|
|
7908
|
+
continue;
|
|
7909
|
+
const camel = toCamelCase(key);
|
|
7910
|
+
if (camel !== key && schemaKeys.has(camel) && normalized[camel] === undefined) {
|
|
7911
|
+
normalized[camel] = normalized[key];
|
|
7912
|
+
delete normalized[key];
|
|
7913
|
+
continue;
|
|
7914
|
+
}
|
|
7915
|
+
const snake = toSnakeCase(key);
|
|
7916
|
+
if (snake !== key && schemaKeys.has(snake) && normalized[snake] === undefined) {
|
|
7917
|
+
normalized[snake] = normalized[key];
|
|
7918
|
+
delete normalized[key];
|
|
7919
|
+
}
|
|
7920
|
+
}
|
|
7921
|
+
return normalized;
|
|
7922
|
+
}
|
|
7923
|
+
|
|
7924
|
+
// src/proxy/agentDefs.ts
|
|
7925
|
+
var FALLBACK_AGENT_NAME = "general";
|
|
7926
|
+
var DEFAULT_AGENT_TYPES = {
|
|
7927
|
+
build: "The default agent. Executes tools based on configured permissions.",
|
|
7928
|
+
plan: "Plan mode. Disallows all edit tools.",
|
|
7929
|
+
explore: "Contextual grep for codebases. Answers 'Where is X?', 'Which file has Y?'.",
|
|
7930
|
+
general: "General-purpose agent for researching complex questions and executing multi-step tasks."
|
|
7931
|
+
};
|
|
7932
|
+
function parseAgentDescriptions(taskDescription) {
|
|
7933
|
+
const agents = new Map;
|
|
7934
|
+
const agentSection = taskDescription.match(/Available agent types.*?:\n((?:- [\w][\w-]*:.*\n?)+)/s);
|
|
7935
|
+
if (!agentSection)
|
|
7936
|
+
return agents;
|
|
7937
|
+
const entries = agentSection[1].matchAll(/^- ([\w][\w-]*):\s*(.+)/gm);
|
|
7938
|
+
for (const match2 of entries) {
|
|
7939
|
+
agents.set(match2[1], match2[2].trim());
|
|
7940
|
+
}
|
|
7941
|
+
return agents;
|
|
7942
|
+
}
|
|
7943
|
+
function buildAgentDefinitions(taskDescription, mcpToolNames) {
|
|
7944
|
+
const descriptions = parseAgentDescriptions(taskDescription);
|
|
7945
|
+
const agents = {};
|
|
7946
|
+
for (const [name, description] of descriptions) {
|
|
7947
|
+
agents[name] = {
|
|
7948
|
+
description,
|
|
7949
|
+
prompt: buildAgentPrompt(name, description),
|
|
7950
|
+
model: "inherit",
|
|
7951
|
+
...mcpToolNames?.length ? { tools: [...mcpToolNames] } : {}
|
|
7952
|
+
};
|
|
7953
|
+
}
|
|
7954
|
+
if (descriptions.size > 0) {
|
|
7955
|
+
ensureDefaultAgents(agents, mcpToolNames);
|
|
7956
|
+
addCaseVariants(agents);
|
|
7957
|
+
}
|
|
7958
|
+
return agents;
|
|
7959
|
+
}
|
|
7960
|
+
function ensureDefaultAgents(agents, mcpToolNames) {
|
|
7961
|
+
for (const [name, description] of Object.entries(DEFAULT_AGENT_TYPES)) {
|
|
7962
|
+
if (!agents[name]) {
|
|
7963
|
+
agents[name] = {
|
|
7964
|
+
description,
|
|
7965
|
+
prompt: buildAgentPrompt(name, description),
|
|
7966
|
+
model: "inherit",
|
|
7967
|
+
...mcpToolNames?.length ? { tools: [...mcpToolNames] } : {}
|
|
7968
|
+
};
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7971
|
+
}
|
|
7972
|
+
function addCaseVariants(agents) {
|
|
7973
|
+
const baseNames = Object.keys(agents);
|
|
7974
|
+
for (const name of baseNames) {
|
|
7975
|
+
const def = agents[name];
|
|
7976
|
+
const titleCase = name.replace(/(^|-)(\w)/g, (_m, sep, ch) => sep + ch.toUpperCase());
|
|
7977
|
+
if (titleCase !== name && !agents[titleCase]) {
|
|
7978
|
+
agents[titleCase] = def;
|
|
7979
|
+
}
|
|
7980
|
+
}
|
|
7981
|
+
const ALIASES = {
|
|
7982
|
+
"general-purpose": "general",
|
|
7983
|
+
"General-Purpose": "general"
|
|
7984
|
+
};
|
|
7985
|
+
for (const [alias, target] of Object.entries(ALIASES)) {
|
|
7986
|
+
if (!agents[alias] && agents[target]) {
|
|
7987
|
+
agents[alias] = agents[target];
|
|
7988
|
+
}
|
|
7989
|
+
}
|
|
7990
|
+
}
|
|
7991
|
+
function buildAgentPrompt(name, description) {
|
|
7992
|
+
return `You are the "${name}" agent. ${description}
|
|
7993
|
+
|
|
7994
|
+
Focus on your specific role and complete the task thoroughly. Return a clear, concise result.`;
|
|
7995
|
+
}
|
|
7996
|
+
|
|
7997
|
+
// src/proxy/agentMatch.ts
|
|
7998
|
+
var KNOWN_ALIASES = {
|
|
7999
|
+
"general-purpose": "general",
|
|
8000
|
+
default: "general",
|
|
8001
|
+
"code-reviewer": "oracle",
|
|
8002
|
+
reviewer: "oracle",
|
|
8003
|
+
"code-review": "oracle",
|
|
8004
|
+
review: "oracle",
|
|
8005
|
+
consultation: "oracle",
|
|
8006
|
+
analyzer: "oracle",
|
|
8007
|
+
debugger: "oracle",
|
|
8008
|
+
search: "explore",
|
|
8009
|
+
grep: "explore",
|
|
8010
|
+
find: "explore",
|
|
8011
|
+
"codebase-search": "explore",
|
|
8012
|
+
research: "librarian",
|
|
8013
|
+
docs: "librarian",
|
|
8014
|
+
documentation: "librarian",
|
|
8015
|
+
lookup: "librarian",
|
|
8016
|
+
reference: "librarian",
|
|
8017
|
+
consult: "oracle",
|
|
8018
|
+
architect: "oracle",
|
|
8019
|
+
"image-analyzer": "multimodal-looker",
|
|
8020
|
+
image: "multimodal-looker",
|
|
8021
|
+
pdf: "multimodal-looker",
|
|
8022
|
+
visual: "multimodal-looker",
|
|
8023
|
+
planner: "plan",
|
|
8024
|
+
planning: "plan",
|
|
8025
|
+
builder: "build",
|
|
8026
|
+
coder: "build",
|
|
8027
|
+
developer: "build",
|
|
8028
|
+
writer: "build",
|
|
8029
|
+
executor: "build"
|
|
8030
|
+
};
|
|
8031
|
+
var STRIP_SUFFIXES = ["-agent", "-tool", "-worker", "-task", " agent", " tool"];
|
|
8032
|
+
function resolveAgentAlias(input) {
|
|
8033
|
+
const lowered = input.toLowerCase();
|
|
8034
|
+
return KNOWN_ALIASES[lowered] ?? lowered;
|
|
8035
|
+
}
|
|
8036
|
+
function fuzzyMatchAgentName(input, validAgents) {
|
|
8037
|
+
if (!input)
|
|
8038
|
+
return input;
|
|
8039
|
+
if (validAgents.length === 0)
|
|
8040
|
+
return input.toLowerCase();
|
|
8041
|
+
const lowered = input.toLowerCase();
|
|
8042
|
+
const exact = validAgents.find((a) => a.toLowerCase() === lowered);
|
|
8043
|
+
if (exact)
|
|
8044
|
+
return exact;
|
|
8045
|
+
const alias = KNOWN_ALIASES[lowered];
|
|
8046
|
+
if (alias && validAgents.includes(alias))
|
|
8047
|
+
return alias;
|
|
8048
|
+
const prefixMatch = validAgents.find((a) => a.toLowerCase().startsWith(lowered));
|
|
8049
|
+
if (prefixMatch)
|
|
8050
|
+
return prefixMatch;
|
|
8051
|
+
const substringMatch = validAgents.find((a) => a.toLowerCase().includes(lowered));
|
|
8052
|
+
if (substringMatch)
|
|
8053
|
+
return substringMatch;
|
|
8054
|
+
for (const suffix of STRIP_SUFFIXES) {
|
|
8055
|
+
if (lowered.endsWith(suffix)) {
|
|
8056
|
+
const stripped = lowered.slice(0, -suffix.length);
|
|
8057
|
+
const strippedMatch = validAgents.find((a) => a.toLowerCase() === stripped);
|
|
8058
|
+
if (strippedMatch)
|
|
8059
|
+
return strippedMatch;
|
|
8060
|
+
}
|
|
8061
|
+
}
|
|
8062
|
+
const reverseMatch = validAgents.find((a) => lowered.includes(a.toLowerCase()));
|
|
8063
|
+
if (reverseMatch)
|
|
8064
|
+
return reverseMatch;
|
|
8065
|
+
if (validAgents.includes(FALLBACK_AGENT_NAME))
|
|
8066
|
+
return FALLBACK_AGENT_NAME;
|
|
8067
|
+
return lowered;
|
|
8068
|
+
}
|
|
7891
8069
|
|
|
7892
8070
|
// src/utils/lruMap.ts
|
|
7893
8071
|
class LRUMap {
|
|
@@ -8797,6 +8975,16 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
8797
8975
|
import { join as join2, dirname as dirname2 } from "path";
|
|
8798
8976
|
import { promisify } from "util";
|
|
8799
8977
|
var exec = promisify(execCallback);
|
|
8978
|
+
var CANONICAL_OPUS_MODEL = "claude-opus-4-7";
|
|
8979
|
+
var CANONICAL_SONNET_MODEL = "claude-sonnet-4-6";
|
|
8980
|
+
var CANONICAL_HAIKU_MODEL = "claude-haiku-4-5";
|
|
8981
|
+
function resolveSdkModelDefaults() {
|
|
8982
|
+
return {
|
|
8983
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: process.env.MERIDIAN_DEFAULT_OPUS_MODEL ?? CANONICAL_OPUS_MODEL,
|
|
8984
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: process.env.MERIDIAN_DEFAULT_SONNET_MODEL ?? CANONICAL_SONNET_MODEL,
|
|
8985
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: process.env.MERIDIAN_DEFAULT_HAIKU_MODEL ?? CANONICAL_HAIKU_MODEL
|
|
8986
|
+
};
|
|
8987
|
+
}
|
|
8800
8988
|
var AUTH_STATUS_CACHE_TTL_MS = 60000;
|
|
8801
8989
|
var AUTH_STATUS_FAILURE_TTL_MS = 5000;
|
|
8802
8990
|
var cachedAuthStatus = null;
|
|
@@ -8933,16 +9121,14 @@ async function resolveClaudeExecutableAsync() {
|
|
|
8933
9121
|
return cachedClaudePathPromise;
|
|
8934
9122
|
cachedClaudePathPromise = (async () => {
|
|
8935
9123
|
const runningUnderBun = typeof process.versions.bun !== "undefined";
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
} catch {}
|
|
8945
|
-
}
|
|
9124
|
+
try {
|
|
9125
|
+
const pkgPath = fileURLToPath2(import.meta.resolve("@anthropic-ai/claude-code/package.json"));
|
|
9126
|
+
const bundledBinary = join2(dirname2(pkgPath), "bin", "claude.exe");
|
|
9127
|
+
if (existsSync2(bundledBinary)) {
|
|
9128
|
+
cachedClaudePath = bundledBinary;
|
|
9129
|
+
return bundledBinary;
|
|
9130
|
+
}
|
|
9131
|
+
} catch {}
|
|
8946
9132
|
try {
|
|
8947
9133
|
const { stdout } = await exec("which claude");
|
|
8948
9134
|
const claudePath = stdout.trim();
|
|
@@ -8951,7 +9137,7 @@ async function resolveClaudeExecutableAsync() {
|
|
|
8951
9137
|
return claudePath;
|
|
8952
9138
|
}
|
|
8953
9139
|
} catch {}
|
|
8954
|
-
if (
|
|
9140
|
+
if (runningUnderBun) {
|
|
8955
9141
|
try {
|
|
8956
9142
|
const sdkPath = fileURLToPath2(import.meta.resolve("@anthropic-ai/claude-agent-sdk"));
|
|
8957
9143
|
const sdkCliJs = join2(dirname2(sdkPath), "cli.js");
|
|
@@ -9164,7 +9350,15 @@ function buildModelList(isMaxSubscription, now = Math.floor(Date.now() / 1000))
|
|
|
9164
9350
|
context_window: isMaxSubscription ? 1e6 : 200000
|
|
9165
9351
|
},
|
|
9166
9352
|
{
|
|
9167
|
-
id: "claude-
|
|
9353
|
+
id: "claude-opus-4-7",
|
|
9354
|
+
object: "model",
|
|
9355
|
+
created: now,
|
|
9356
|
+
owned_by: "anthropic",
|
|
9357
|
+
display_name: "Claude Opus 4.7",
|
|
9358
|
+
context_window: isMaxSubscription ? 1e6 : 200000
|
|
9359
|
+
},
|
|
9360
|
+
{
|
|
9361
|
+
id: "claude-haiku-4-5",
|
|
9168
9362
|
object: "model",
|
|
9169
9363
|
created: now,
|
|
9170
9364
|
owned_by: "anthropic",
|
|
@@ -9204,6 +9398,27 @@ function normalizeContent(content) {
|
|
|
9204
9398
|
}
|
|
9205
9399
|
return String(content);
|
|
9206
9400
|
}
|
|
9401
|
+
function extractAdvisorModel(tools) {
|
|
9402
|
+
if (!Array.isArray(tools))
|
|
9403
|
+
return;
|
|
9404
|
+
for (const tool of tools) {
|
|
9405
|
+
if (!tool || typeof tool !== "object")
|
|
9406
|
+
continue;
|
|
9407
|
+
const candidate = tool;
|
|
9408
|
+
if (typeof candidate.type === "string" && candidate.type.startsWith("advisor_") && typeof candidate.model === "string" && candidate.model.length > 0) {
|
|
9409
|
+
return candidate.model;
|
|
9410
|
+
}
|
|
9411
|
+
}
|
|
9412
|
+
return;
|
|
9413
|
+
}
|
|
9414
|
+
function stripAdvisorTools(tools) {
|
|
9415
|
+
return tools.filter((tool) => {
|
|
9416
|
+
if (!tool || typeof tool !== "object")
|
|
9417
|
+
return true;
|
|
9418
|
+
const candidate = tool;
|
|
9419
|
+
return !(typeof candidate.type === "string" && candidate.type.startsWith("advisor_"));
|
|
9420
|
+
});
|
|
9421
|
+
}
|
|
9207
9422
|
function getLastUserMessage(messages) {
|
|
9208
9423
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
9209
9424
|
if (messages[i]?.role === "user")
|
|
@@ -9440,104 +9655,6 @@ var ALLOWED_MCP_TOOLS = [
|
|
|
9440
9655
|
`mcp__${MCP_SERVER_NAME}__grep`
|
|
9441
9656
|
];
|
|
9442
9657
|
|
|
9443
|
-
// src/proxy/agentDefs.ts
|
|
9444
|
-
function parseAgentDescriptions(taskDescription) {
|
|
9445
|
-
const agents = new Map;
|
|
9446
|
-
const agentSection = taskDescription.match(/Available agent types.*?:\n((?:- [\w][\w-]*:.*\n?)+)/s);
|
|
9447
|
-
if (!agentSection)
|
|
9448
|
-
return agents;
|
|
9449
|
-
const entries = agentSection[1].matchAll(/^- ([\w][\w-]*):\s*(.+)/gm);
|
|
9450
|
-
for (const match2 of entries) {
|
|
9451
|
-
agents.set(match2[1], match2[2].trim());
|
|
9452
|
-
}
|
|
9453
|
-
return agents;
|
|
9454
|
-
}
|
|
9455
|
-
function buildAgentDefinitions(taskDescription, mcpToolNames) {
|
|
9456
|
-
const descriptions = parseAgentDescriptions(taskDescription);
|
|
9457
|
-
const agents = {};
|
|
9458
|
-
for (const [name, description] of descriptions) {
|
|
9459
|
-
agents[name] = {
|
|
9460
|
-
description,
|
|
9461
|
-
prompt: buildAgentPrompt(name, description),
|
|
9462
|
-
model: "inherit",
|
|
9463
|
-
...mcpToolNames?.length ? { tools: [...mcpToolNames] } : {}
|
|
9464
|
-
};
|
|
9465
|
-
}
|
|
9466
|
-
return agents;
|
|
9467
|
-
}
|
|
9468
|
-
function buildAgentPrompt(name, description) {
|
|
9469
|
-
return `You are the "${name}" agent. ${description}
|
|
9470
|
-
|
|
9471
|
-
Focus on your specific role and complete the task thoroughly. Return a clear, concise result.`;
|
|
9472
|
-
}
|
|
9473
|
-
|
|
9474
|
-
// src/proxy/agentMatch.ts
|
|
9475
|
-
var KNOWN_ALIASES = {
|
|
9476
|
-
"general-purpose": "general",
|
|
9477
|
-
default: "general",
|
|
9478
|
-
"code-reviewer": "oracle",
|
|
9479
|
-
reviewer: "oracle",
|
|
9480
|
-
"code-review": "oracle",
|
|
9481
|
-
review: "oracle",
|
|
9482
|
-
consultation: "oracle",
|
|
9483
|
-
analyzer: "oracle",
|
|
9484
|
-
debugger: "oracle",
|
|
9485
|
-
search: "explore",
|
|
9486
|
-
grep: "explore",
|
|
9487
|
-
find: "explore",
|
|
9488
|
-
"codebase-search": "explore",
|
|
9489
|
-
research: "librarian",
|
|
9490
|
-
docs: "librarian",
|
|
9491
|
-
documentation: "librarian",
|
|
9492
|
-
lookup: "librarian",
|
|
9493
|
-
reference: "librarian",
|
|
9494
|
-
consult: "oracle",
|
|
9495
|
-
architect: "oracle",
|
|
9496
|
-
"image-analyzer": "multimodal-looker",
|
|
9497
|
-
image: "multimodal-looker",
|
|
9498
|
-
pdf: "multimodal-looker",
|
|
9499
|
-
visual: "multimodal-looker",
|
|
9500
|
-
planner: "plan",
|
|
9501
|
-
planning: "plan",
|
|
9502
|
-
builder: "build",
|
|
9503
|
-
coder: "build",
|
|
9504
|
-
developer: "build",
|
|
9505
|
-
writer: "build",
|
|
9506
|
-
executor: "build"
|
|
9507
|
-
};
|
|
9508
|
-
var STRIP_SUFFIXES = ["-agent", "-tool", "-worker", "-task", " agent", " tool"];
|
|
9509
|
-
function fuzzyMatchAgentName(input, validAgents) {
|
|
9510
|
-
if (!input)
|
|
9511
|
-
return input;
|
|
9512
|
-
if (validAgents.length === 0)
|
|
9513
|
-
return input.toLowerCase();
|
|
9514
|
-
const lowered = input.toLowerCase();
|
|
9515
|
-
const exact = validAgents.find((a) => a.toLowerCase() === lowered);
|
|
9516
|
-
if (exact)
|
|
9517
|
-
return exact;
|
|
9518
|
-
const alias = KNOWN_ALIASES[lowered];
|
|
9519
|
-
if (alias && validAgents.includes(alias))
|
|
9520
|
-
return alias;
|
|
9521
|
-
const prefixMatch = validAgents.find((a) => a.toLowerCase().startsWith(lowered));
|
|
9522
|
-
if (prefixMatch)
|
|
9523
|
-
return prefixMatch;
|
|
9524
|
-
const substringMatch = validAgents.find((a) => a.toLowerCase().includes(lowered));
|
|
9525
|
-
if (substringMatch)
|
|
9526
|
-
return substringMatch;
|
|
9527
|
-
for (const suffix of STRIP_SUFFIXES) {
|
|
9528
|
-
if (lowered.endsWith(suffix)) {
|
|
9529
|
-
const stripped = lowered.slice(0, -suffix.length);
|
|
9530
|
-
const strippedMatch = validAgents.find((a) => a.toLowerCase() === stripped);
|
|
9531
|
-
if (strippedMatch)
|
|
9532
|
-
return strippedMatch;
|
|
9533
|
-
}
|
|
9534
|
-
}
|
|
9535
|
-
const reverseMatch = validAgents.find((a) => lowered.includes(a.toLowerCase()));
|
|
9536
|
-
if (reverseMatch)
|
|
9537
|
-
return reverseMatch;
|
|
9538
|
-
return lowered;
|
|
9539
|
-
}
|
|
9540
|
-
|
|
9541
9658
|
// src/proxy/transforms/opencode.ts
|
|
9542
9659
|
var openCodeTransforms = [
|
|
9543
9660
|
{
|
|
@@ -10082,6 +10199,9 @@ var piAdapter = {
|
|
|
10082
10199
|
extractWorkingDirectory(body) {
|
|
10083
10200
|
return extractPiCwd(body);
|
|
10084
10201
|
},
|
|
10202
|
+
extractClientWorkingDirectory(body) {
|
|
10203
|
+
return extractPiCwd(body);
|
|
10204
|
+
},
|
|
10085
10205
|
normalizeContent(content) {
|
|
10086
10206
|
return normalizeContent(content);
|
|
10087
10207
|
},
|
|
@@ -10234,6 +10354,79 @@ var forgeCodeAdapter = {
|
|
|
10234
10354
|
}
|
|
10235
10355
|
};
|
|
10236
10356
|
|
|
10357
|
+
// src/proxy/adapters/claudecode.ts
|
|
10358
|
+
function extractClaudeCodeClientCwd(body) {
|
|
10359
|
+
let systemText = "";
|
|
10360
|
+
if (typeof body.system === "string") {
|
|
10361
|
+
systemText = body.system;
|
|
10362
|
+
} else if (Array.isArray(body.system)) {
|
|
10363
|
+
systemText = body.system.filter((b) => b.type === "text" && b.text).map((b) => b.text).join(`
|
|
10364
|
+
`);
|
|
10365
|
+
}
|
|
10366
|
+
if (!systemText)
|
|
10367
|
+
return;
|
|
10368
|
+
const match2 = systemText.match(/Primary working directory:\s*([^\n<]+)/i);
|
|
10369
|
+
return match2?.[1]?.trim() || undefined;
|
|
10370
|
+
}
|
|
10371
|
+
var claudeCodeAdapter = {
|
|
10372
|
+
name: "claude-code",
|
|
10373
|
+
getSessionId(_c) {
|
|
10374
|
+
return;
|
|
10375
|
+
},
|
|
10376
|
+
extractWorkingDirectory(_body) {
|
|
10377
|
+
return;
|
|
10378
|
+
},
|
|
10379
|
+
extractClientWorkingDirectory(body) {
|
|
10380
|
+
return extractClaudeCodeClientCwd(body);
|
|
10381
|
+
},
|
|
10382
|
+
normalizeContent(content) {
|
|
10383
|
+
return normalizeContent(content);
|
|
10384
|
+
},
|
|
10385
|
+
getBlockedBuiltinTools() {
|
|
10386
|
+
return BLOCKED_BUILTIN_TOOLS;
|
|
10387
|
+
},
|
|
10388
|
+
getAgentIncompatibleTools() {
|
|
10389
|
+
return CLAUDE_CODE_ONLY_TOOLS;
|
|
10390
|
+
},
|
|
10391
|
+
getMcpServerName() {
|
|
10392
|
+
return MCP_SERVER_NAME;
|
|
10393
|
+
},
|
|
10394
|
+
getAllowedMcpTools() {
|
|
10395
|
+
return ALLOWED_MCP_TOOLS;
|
|
10396
|
+
},
|
|
10397
|
+
getCoreToolNames() {
|
|
10398
|
+
return ["Read", "Write", "Edit", "Bash", "Glob", "Grep"];
|
|
10399
|
+
},
|
|
10400
|
+
usesPassthrough() {
|
|
10401
|
+
const envVal = process.env.MERIDIAN_PASSTHROUGH ?? process.env.CLAUDE_PROXY_PASSTHROUGH;
|
|
10402
|
+
if (envVal === "0" || envVal === "false" || envVal === "no") {
|
|
10403
|
+
return false;
|
|
10404
|
+
}
|
|
10405
|
+
return true;
|
|
10406
|
+
},
|
|
10407
|
+
supportsThinking() {
|
|
10408
|
+
return true;
|
|
10409
|
+
},
|
|
10410
|
+
shouldTrackFileChanges() {
|
|
10411
|
+
return false;
|
|
10412
|
+
},
|
|
10413
|
+
extractFileChangesFromToolUse(toolName, toolInput) {
|
|
10414
|
+
const input = toolInput;
|
|
10415
|
+
const filePath = input?.file_path ?? input?.filePath ?? input?.path;
|
|
10416
|
+
const lowerName = toolName.toLowerCase();
|
|
10417
|
+
if (lowerName === "write" && filePath) {
|
|
10418
|
+
return [{ operation: "wrote", path: String(filePath) }];
|
|
10419
|
+
}
|
|
10420
|
+
if ((lowerName === "edit" || lowerName === "multiedit") && filePath) {
|
|
10421
|
+
return [{ operation: "edited", path: String(filePath) }];
|
|
10422
|
+
}
|
|
10423
|
+
if (lowerName === "bash" && input?.command) {
|
|
10424
|
+
return extractFileChangesFromBash(String(input.command));
|
|
10425
|
+
}
|
|
10426
|
+
return [];
|
|
10427
|
+
}
|
|
10428
|
+
};
|
|
10429
|
+
|
|
10237
10430
|
// src/proxy/adapters/detect.ts
|
|
10238
10431
|
var ADAPTER_MAP = {
|
|
10239
10432
|
opencode: openCodeAdapter,
|
|
@@ -10241,7 +10434,9 @@ var ADAPTER_MAP = {
|
|
|
10241
10434
|
crush: crushAdapter,
|
|
10242
10435
|
passthrough: passthroughAdapter,
|
|
10243
10436
|
pi: piAdapter,
|
|
10244
|
-
forgecode: forgeCodeAdapter
|
|
10437
|
+
forgecode: forgeCodeAdapter,
|
|
10438
|
+
"claude-code": claudeCodeAdapter,
|
|
10439
|
+
claudecode: claudeCodeAdapter
|
|
10245
10440
|
};
|
|
10246
10441
|
var envDefault = process.env.MERIDIAN_DEFAULT_AGENT || "";
|
|
10247
10442
|
if (envDefault && !ADAPTER_MAP[envDefault]) {
|
|
@@ -10272,6 +10467,9 @@ function detectAdapter(c) {
|
|
|
10272
10467
|
if (userAgent.startsWith("Charm-Crush/")) {
|
|
10273
10468
|
return crushAdapter;
|
|
10274
10469
|
}
|
|
10470
|
+
if (userAgent.startsWith("claude-cli/")) {
|
|
10471
|
+
return claudeCodeAdapter;
|
|
10472
|
+
}
|
|
10275
10473
|
if (isLiteLLMRequest(c)) {
|
|
10276
10474
|
return passthroughAdapter;
|
|
10277
10475
|
}
|
|
@@ -15974,16 +16172,35 @@ function createOpencodeMcpServer() {
|
|
|
15974
16172
|
}
|
|
15975
16173
|
|
|
15976
16174
|
// src/proxy/query.ts
|
|
15977
|
-
function
|
|
16175
|
+
function computePassthroughMaxTurns(resumeSessionId, hasDeferredTools, advisorModel) {
|
|
16176
|
+
const hasResume = !!resumeSessionId;
|
|
16177
|
+
const base = hasResume && hasDeferredTools ? 4 : hasResume || hasDeferredTools ? 3 : 2;
|
|
16178
|
+
const advisorBump = advisorModel ? 3 : 0;
|
|
16179
|
+
return base + advisorBump;
|
|
16180
|
+
}
|
|
16181
|
+
function buildCwdNote(sdkCwd, clientCwd) {
|
|
16182
|
+
if (!clientCwd || clientCwd === sdkCwd)
|
|
16183
|
+
return "";
|
|
16184
|
+
return `
|
|
16185
|
+
|
|
16186
|
+
<env>
|
|
16187
|
+
` + `Working directory: ${clientCwd}
|
|
16188
|
+
` + `</env>
|
|
16189
|
+
` + `<meridian-note>
|
|
16190
|
+
` + `You are reached through a proxy. The subprocess running you resides at ` + `"${sdkCwd}" on the proxy host, but that is not the user's working directory. ` + `Always treat "${clientCwd}" as the working directory when referring to files or paths.
|
|
16191
|
+
` + `</meridian-note>`;
|
|
16192
|
+
}
|
|
16193
|
+
function resolveSystemPrompt(systemContext, passthrough, settingSources, codeSystemPrompt, clientSystemPrompt, cwdNote) {
|
|
15978
16194
|
const hasSettings = settingSources != null && settingSources.length > 0;
|
|
15979
16195
|
const usePreset = codeSystemPrompt ?? (hasSettings || !passthrough && !!systemContext);
|
|
15980
16196
|
const includeClient = clientSystemPrompt ?? true;
|
|
15981
16197
|
const clientContext = includeClient ? systemContext : undefined;
|
|
16198
|
+
const append = [clientContext, cwdNote].filter(Boolean).join("") || undefined;
|
|
15982
16199
|
if (usePreset) {
|
|
15983
|
-
return
|
|
16200
|
+
return append ? { systemPrompt: { type: "preset", preset: "claude_code", append } } : { systemPrompt: { type: "preset", preset: "claude_code" } };
|
|
15984
16201
|
}
|
|
15985
|
-
if (
|
|
15986
|
-
return { systemPrompt:
|
|
16202
|
+
if (append)
|
|
16203
|
+
return { systemPrompt: append };
|
|
15987
16204
|
return {};
|
|
15988
16205
|
}
|
|
15989
16206
|
function buildQueryOptions(ctx) {
|
|
@@ -15991,6 +16208,7 @@ function buildQueryOptions(ctx) {
|
|
|
15991
16208
|
prompt,
|
|
15992
16209
|
model,
|
|
15993
16210
|
workingDirectory,
|
|
16211
|
+
clientWorkingDirectory,
|
|
15994
16212
|
systemContext,
|
|
15995
16213
|
claudeExecutable,
|
|
15996
16214
|
passthrough,
|
|
@@ -16023,19 +16241,20 @@ function buildQueryOptions(ctx) {
|
|
|
16023
16241
|
sdkDebug,
|
|
16024
16242
|
additionalDirectories
|
|
16025
16243
|
} = ctx;
|
|
16244
|
+
const cwdNote = buildCwdNote(workingDirectory, clientWorkingDirectory);
|
|
16026
16245
|
const allBlockedTools = [...blockedTools, ...incompatibleTools];
|
|
16027
16246
|
return {
|
|
16028
16247
|
prompt,
|
|
16029
16248
|
options: {
|
|
16030
16249
|
executable: "node",
|
|
16031
|
-
maxTurns: passthrough ? resumeSessionId
|
|
16250
|
+
maxTurns: passthrough ? computePassthroughMaxTurns(resumeSessionId, hasDeferredTools, ctx.advisorModel) : 200,
|
|
16032
16251
|
cwd: workingDirectory,
|
|
16033
16252
|
model,
|
|
16034
16253
|
pathToClaudeCodeExecutable: claudeExecutable,
|
|
16035
16254
|
...stream2 ? { includePartialMessages: true } : {},
|
|
16036
16255
|
permissionMode: "bypassPermissions",
|
|
16037
16256
|
allowDangerouslySkipPermissions: true,
|
|
16038
|
-
...resolveSystemPrompt(systemContext, passthrough, settingSources, codeSystemPrompt, clientSystemPrompt),
|
|
16257
|
+
...resolveSystemPrompt(systemContext, passthrough, settingSources, codeSystemPrompt, clientSystemPrompt, cwdNote),
|
|
16039
16258
|
...passthrough ? {
|
|
16040
16259
|
disallowedTools: [...allBlockedTools],
|
|
16041
16260
|
...passthroughMcp ? {
|
|
@@ -16074,7 +16293,8 @@ function buildQueryOptions(ctx) {
|
|
|
16074
16293
|
...maxBudgetUsd && maxBudgetUsd > 0 ? { maxBudgetUsd } : {},
|
|
16075
16294
|
...fallbackModel ? { fallbackModel } : {},
|
|
16076
16295
|
...sdkDebug ? { debug: true } : {},
|
|
16077
|
-
...additionalDirectories && additionalDirectories.length > 0 ? { additionalDirectories } : {}
|
|
16296
|
+
...additionalDirectories && additionalDirectories.length > 0 ? { additionalDirectories } : {},
|
|
16297
|
+
...ctx.advisorModel ? { advisorModel: ctx.advisorModel } : {}
|
|
16078
16298
|
}
|
|
16079
16299
|
};
|
|
16080
16300
|
}
|
|
@@ -16414,6 +16634,10 @@ function sanitizeTextContent(text, opts = {}) {
|
|
|
16414
16634
|
|
|
16415
16635
|
// src/proxy/session/lineage.ts
|
|
16416
16636
|
import { createHash as createHash2 } from "crypto";
|
|
16637
|
+
function normalizeContextUsage(usage) {
|
|
16638
|
+
const lastIteration = usage.iterations?.at(-1);
|
|
16639
|
+
return lastIteration ?? usage;
|
|
16640
|
+
}
|
|
16417
16641
|
var MIN_SUFFIX_FOR_COMPACTION = 2;
|
|
16418
16642
|
function computeLineageHash(messages) {
|
|
16419
16643
|
if (!messages || messages.length === 0)
|
|
@@ -17201,6 +17425,7 @@ function createProxyServer(config = {}) {
|
|
|
17201
17425
|
const requestSource = c.req.header("x-meridian-source")?.slice(0, 64) || undefined;
|
|
17202
17426
|
let model = mapModelToClaudeModel(body.model || "sonnet", authStatus?.subscriptionType, agentMode);
|
|
17203
17427
|
const workingDirectory = (process.env.MERIDIAN_WORKDIR ?? process.env.CLAUDE_PROXY_WORKDIR) || adapter.extractWorkingDirectory(body) || process.cwd();
|
|
17428
|
+
const clientWorkingDirectory = adapter.extractClientWorkingDirectory?.(body) || workingDirectory;
|
|
17204
17429
|
const {
|
|
17205
17430
|
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS,
|
|
17206
17431
|
ANTHROPIC_API_KEY: _dropApiKey,
|
|
@@ -17208,7 +17433,8 @@ function createProxyServer(config = {}) {
|
|
|
17208
17433
|
ANTHROPIC_AUTH_TOKEN: _dropAuthToken,
|
|
17209
17434
|
...cleanEnv
|
|
17210
17435
|
} = process.env;
|
|
17211
|
-
const
|
|
17436
|
+
const sdkModelDefaults = resolveSdkModelDefaults();
|
|
17437
|
+
const profileEnv = { ...sdkModelDefaults, ...cleanEnv, ...profile.env };
|
|
17212
17438
|
let systemContext = "";
|
|
17213
17439
|
if (body.system) {
|
|
17214
17440
|
if (typeof body.system === "string") {
|
|
@@ -17269,7 +17495,7 @@ function createProxyServer(config = {}) {
|
|
|
17269
17495
|
const betas = betaFilter.forwarded;
|
|
17270
17496
|
const agentSessionId = adapter.getSessionId(c);
|
|
17271
17497
|
const profileSessionId = profile.id !== "default" && agentSessionId ? `${profile.id}:${agentSessionId}` : agentSessionId;
|
|
17272
|
-
const profileScopedCwd = profile.id !== "default" ? `${
|
|
17498
|
+
const profileScopedCwd = profile.id !== "default" ? `${clientWorkingDirectory}::profile=${profile.id}` : clientWorkingDirectory;
|
|
17273
17499
|
const isIndependentSession = requestSource?.startsWith("fork-") || requestSource?.startsWith("subagent-") || false;
|
|
17274
17500
|
let lineageResult = isIndependentSession ? { type: "diverged" } : lookupSession(profileSessionId, body.messages || [], profileScopedCwd);
|
|
17275
17501
|
if (lineageResult.type === "undo" && adapter.name === "opencode" && !agentSessionId) {
|
|
@@ -17383,6 +17609,10 @@ function createProxyServer(config = {}) {
|
|
|
17383
17609
|
const fileChanges = [];
|
|
17384
17610
|
let passthroughMcp;
|
|
17385
17611
|
let requestTools = Array.isArray(body.tools) ? body.tools : [];
|
|
17612
|
+
const advisorModel = extractAdvisorModel(requestTools);
|
|
17613
|
+
if (advisorModel) {
|
|
17614
|
+
requestTools = stripAdvisorTools(requestTools);
|
|
17615
|
+
}
|
|
17386
17616
|
if (passthrough && requestTools.length === 0 && profileSessionId) {
|
|
17387
17617
|
const cached = sessionToolCache.get(profileSessionId);
|
|
17388
17618
|
if (cached && cached.length > 0) {
|
|
@@ -17428,10 +17658,15 @@ function createProxyServer(config = {}) {
|
|
|
17428
17658
|
if (hasDeferredTools && coreSet && !coreSet.has(toolName.toLowerCase())) {
|
|
17429
17659
|
discoveredTools.add(toolName);
|
|
17430
17660
|
}
|
|
17661
|
+
const clientTool = requestTools.find((t) => t.name === toolName);
|
|
17662
|
+
let toolInput = normalizeToolInput(input.tool_input, clientTool?.input_schema);
|
|
17663
|
+
if (toolName.toLowerCase() === "task" && toolInput?.subagent_type && typeof toolInput.subagent_type === "string") {
|
|
17664
|
+
toolInput = { ...toolInput, subagent_type: resolveAgentAlias(toolInput.subagent_type) };
|
|
17665
|
+
}
|
|
17431
17666
|
capturedToolUses.push({
|
|
17432
17667
|
id: input.tool_use_id,
|
|
17433
17668
|
name: toolName,
|
|
17434
|
-
input:
|
|
17669
|
+
input: toolInput
|
|
17435
17670
|
});
|
|
17436
17671
|
return {
|
|
17437
17672
|
decision: "block",
|
|
@@ -17459,6 +17694,7 @@ function createProxyServer(config = {}) {
|
|
|
17459
17694
|
sdkUuidMap.push(null);
|
|
17460
17695
|
claudeLog("upstream.start", { mode: "non_stream", model });
|
|
17461
17696
|
let lastUsage;
|
|
17697
|
+
let lastStopReason;
|
|
17462
17698
|
try {
|
|
17463
17699
|
if (!claudeExecutable) {
|
|
17464
17700
|
claudeExecutable = await resolveClaudeExecutableAsync();
|
|
@@ -17475,6 +17711,7 @@ function createProxyServer(config = {}) {
|
|
|
17475
17711
|
prompt: makePrompt(),
|
|
17476
17712
|
model,
|
|
17477
17713
|
workingDirectory,
|
|
17714
|
+
clientWorkingDirectory,
|
|
17478
17715
|
systemContext,
|
|
17479
17716
|
claudeExecutable,
|
|
17480
17717
|
passthrough,
|
|
@@ -17505,7 +17742,8 @@ function createProxyServer(config = {}) {
|
|
|
17505
17742
|
maxBudgetUsd: sdkFeatures.maxBudgetUsd,
|
|
17506
17743
|
fallbackModel: sdkFeatures.fallbackModel,
|
|
17507
17744
|
sdkDebug: sdkFeatures.sdkDebug,
|
|
17508
|
-
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined
|
|
17745
|
+
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined,
|
|
17746
|
+
advisorModel
|
|
17509
17747
|
}))) {
|
|
17510
17748
|
if (event.type === "assistant" && !event.error) {
|
|
17511
17749
|
didYieldContent = true;
|
|
@@ -17532,6 +17770,7 @@ function createProxyServer(config = {}) {
|
|
|
17532
17770
|
prompt: buildFreshPrompt(allMessages, sanitizeOpts),
|
|
17533
17771
|
model,
|
|
17534
17772
|
workingDirectory,
|
|
17773
|
+
clientWorkingDirectory,
|
|
17535
17774
|
systemContext,
|
|
17536
17775
|
claudeExecutable,
|
|
17537
17776
|
passthrough,
|
|
@@ -17562,7 +17801,8 @@ function createProxyServer(config = {}) {
|
|
|
17562
17801
|
maxBudgetUsd: sdkFeatures.maxBudgetUsd,
|
|
17563
17802
|
fallbackModel: sdkFeatures.fallbackModel,
|
|
17564
17803
|
sdkDebug: sdkFeatures.sdkDebug,
|
|
17565
|
-
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined
|
|
17804
|
+
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined,
|
|
17805
|
+
advisorModel
|
|
17566
17806
|
}));
|
|
17567
17807
|
return;
|
|
17568
17808
|
}
|
|
@@ -17660,6 +17900,9 @@ function createProxyServer(config = {}) {
|
|
|
17660
17900
|
const msgUsage = message.message.usage;
|
|
17661
17901
|
if (msgUsage)
|
|
17662
17902
|
lastUsage = { ...lastUsage, ...msgUsage };
|
|
17903
|
+
if (typeof message.message.stop_reason === "string") {
|
|
17904
|
+
lastStopReason = message.message.stop_reason;
|
|
17905
|
+
}
|
|
17663
17906
|
}
|
|
17664
17907
|
}
|
|
17665
17908
|
claudeLog("upstream.completed", {
|
|
@@ -17697,19 +17940,27 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17697
17940
|
throw error;
|
|
17698
17941
|
}
|
|
17699
17942
|
if (passthrough && capturedToolUses.length > 0) {
|
|
17700
|
-
|
|
17701
|
-
|
|
17702
|
-
|
|
17703
|
-
|
|
17704
|
-
|
|
17705
|
-
|
|
17706
|
-
|
|
17707
|
-
});
|
|
17943
|
+
const capturedById = new Map(capturedToolUses.map((tu) => [tu.id, tu]));
|
|
17944
|
+
for (const block of contentBlocks) {
|
|
17945
|
+
if (block.type === "tool_use" && capturedById.has(block.id)) {
|
|
17946
|
+
const captured = capturedById.get(block.id);
|
|
17947
|
+
block.name = captured.name;
|
|
17948
|
+
block.input = captured.input;
|
|
17949
|
+
capturedById.delete(block.id);
|
|
17708
17950
|
}
|
|
17709
17951
|
}
|
|
17952
|
+
for (const tu of capturedById.values()) {
|
|
17953
|
+
contentBlocks.push({
|
|
17954
|
+
type: "tool_use",
|
|
17955
|
+
id: tu.id,
|
|
17956
|
+
name: tu.name,
|
|
17957
|
+
input: tu.input
|
|
17958
|
+
});
|
|
17959
|
+
}
|
|
17710
17960
|
}
|
|
17711
17961
|
const hasToolUse = contentBlocks.some((b) => b.type === "tool_use");
|
|
17712
|
-
const
|
|
17962
|
+
const heuristicStopReason = hasToolUse ? "tool_use" : "end_turn";
|
|
17963
|
+
const stopReason = lastStopReason && lastStopReason !== "end_turn" && lastStopReason !== "tool_use" ? lastStopReason : heuristicStopReason;
|
|
17713
17964
|
if (trackFileChanges) {
|
|
17714
17965
|
if (passthrough && stopReason === "end_turn" && pipelineCtx.extractFileChangesFromToolUse) {
|
|
17715
17966
|
const passthroughChanges = extractFileChangesFromMessages(body.messages || [], pipelineCtx.extractFileChangesFromToolUse);
|
|
@@ -17851,6 +18102,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17851
18102
|
prompt: makePrompt(),
|
|
17852
18103
|
model,
|
|
17853
18104
|
workingDirectory,
|
|
18105
|
+
clientWorkingDirectory,
|
|
17854
18106
|
systemContext,
|
|
17855
18107
|
claudeExecutable,
|
|
17856
18108
|
passthrough,
|
|
@@ -17881,7 +18133,8 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17881
18133
|
maxBudgetUsd: sdkFeatures.maxBudgetUsd,
|
|
17882
18134
|
fallbackModel: sdkFeatures.fallbackModel,
|
|
17883
18135
|
sdkDebug: sdkFeatures.sdkDebug,
|
|
17884
|
-
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined
|
|
18136
|
+
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined,
|
|
18137
|
+
advisorModel
|
|
17885
18138
|
}))) {
|
|
17886
18139
|
if (event.type === "stream_event") {
|
|
17887
18140
|
didYieldClientEvent = true;
|
|
@@ -17908,6 +18161,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17908
18161
|
prompt: buildFreshPrompt(allMessages, sanitizeOpts),
|
|
17909
18162
|
model,
|
|
17910
18163
|
workingDirectory,
|
|
18164
|
+
clientWorkingDirectory,
|
|
17911
18165
|
systemContext,
|
|
17912
18166
|
claudeExecutable,
|
|
17913
18167
|
passthrough,
|
|
@@ -17938,7 +18192,8 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17938
18192
|
maxBudgetUsd: sdkFeatures.maxBudgetUsd,
|
|
17939
18193
|
fallbackModel: sdkFeatures.fallbackModel,
|
|
17940
18194
|
sdkDebug: sdkFeatures.sdkDebug,
|
|
17941
|
-
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined
|
|
18195
|
+
additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined,
|
|
18196
|
+
advisorModel
|
|
17942
18197
|
}));
|
|
17943
18198
|
return;
|
|
17944
18199
|
}
|
|
@@ -18018,6 +18273,8 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
18018
18273
|
}
|
|
18019
18274
|
}, 15000);
|
|
18020
18275
|
const skipBlockIndices = new Set;
|
|
18276
|
+
const taskToolBlockIndices = new Set;
|
|
18277
|
+
const taskToolJsonBuffer = new Map;
|
|
18021
18278
|
const streamedToolUseIds = new Set;
|
|
18022
18279
|
let nextClientBlockIndex = 0;
|
|
18023
18280
|
const sdkToClientIndex = new Map;
|
|
@@ -18098,6 +18355,9 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
18098
18355
|
} else if (passthrough && block.id) {
|
|
18099
18356
|
streamedToolUseIds.add(block.id);
|
|
18100
18357
|
}
|
|
18358
|
+
if (passthrough && eventIndex !== undefined && block.name.toLowerCase() === "task") {
|
|
18359
|
+
taskToolBlockIndices.add(eventIndex);
|
|
18360
|
+
}
|
|
18101
18361
|
}
|
|
18102
18362
|
if (eventIndex !== undefined) {
|
|
18103
18363
|
sdkToClientIndex.set(eventIndex, nextClientBlockIndex++);
|
|
@@ -18118,6 +18378,39 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
18118
18378
|
continue;
|
|
18119
18379
|
}
|
|
18120
18380
|
}
|
|
18381
|
+
if (passthrough && eventIndex !== undefined && taskToolBlockIndices.has(eventIndex)) {
|
|
18382
|
+
if (eventType === "content_block_delta") {
|
|
18383
|
+
const delta = event.delta;
|
|
18384
|
+
if (delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
|
|
18385
|
+
const prev = taskToolJsonBuffer.get(eventIndex) ?? "";
|
|
18386
|
+
taskToolJsonBuffer.set(eventIndex, prev + delta.partial_json);
|
|
18387
|
+
continue;
|
|
18388
|
+
}
|
|
18389
|
+
}
|
|
18390
|
+
if (eventType === "content_block_stop") {
|
|
18391
|
+
const buffered = taskToolJsonBuffer.get(eventIndex);
|
|
18392
|
+
if (buffered) {
|
|
18393
|
+
let fixed = buffered;
|
|
18394
|
+
try {
|
|
18395
|
+
const parsed = JSON.parse(buffered);
|
|
18396
|
+
if (typeof parsed.subagent_type === "string") {
|
|
18397
|
+
parsed.subagent_type = resolveAgentAlias(parsed.subagent_type);
|
|
18398
|
+
}
|
|
18399
|
+
fixed = JSON.stringify(parsed);
|
|
18400
|
+
} catch {}
|
|
18401
|
+
const clientIdx = sdkToClientIndex.get(eventIndex) ?? eventIndex;
|
|
18402
|
+
safeEnqueue(encoder.encode(`event: content_block_delta
|
|
18403
|
+
data: ${JSON.stringify({
|
|
18404
|
+
type: "content_block_delta",
|
|
18405
|
+
index: clientIdx,
|
|
18406
|
+
delta: { type: "input_json_delta", partial_json: fixed }
|
|
18407
|
+
})}
|
|
18408
|
+
|
|
18409
|
+
`), "task_tool_fixed_delta");
|
|
18410
|
+
taskToolJsonBuffer.delete(eventIndex);
|
|
18411
|
+
}
|
|
18412
|
+
}
|
|
18413
|
+
}
|
|
18121
18414
|
const payload = encoder.encode(`event: ${eventType}
|
|
18122
18415
|
data: ${JSON.stringify(event)}
|
|
18123
18416
|
|
|
@@ -18701,7 +18994,7 @@ data: ${JSON.stringify({
|
|
|
18701
18994
|
if (!session.contextUsage) {
|
|
18702
18995
|
return c.json({ error: "No usage data available for this session" }, 404);
|
|
18703
18996
|
}
|
|
18704
|
-
return c.json({ session_id: claudeSessionId, context_usage: session.contextUsage });
|
|
18997
|
+
return c.json({ session_id: claudeSessionId, context_usage: normalizeContextUsage(session.contextUsage) });
|
|
18705
18998
|
});
|
|
18706
18999
|
app.get("/v1/sessions/recover", (c) => {
|
|
18707
19000
|
const sessions = listStoredSessions();
|
|
@@ -18777,6 +19070,8 @@ async function startProxyServer(config = {}) {
|
|
|
18777
19070
|
if (!finalConfig.silent) {
|
|
18778
19071
|
console.log(`Meridian running at http://${finalConfig.host}:${info.port}`);
|
|
18779
19072
|
console.log(`Telemetry dashboard: http://${finalConfig.host}:${info.port}/telemetry`);
|
|
19073
|
+
const pins = resolveSdkModelDefaults();
|
|
19074
|
+
console.log(`Model pins: opus=${pins.ANTHROPIC_DEFAULT_OPUS_MODEL} sonnet=${pins.ANTHROPIC_DEFAULT_SONNET_MODEL} haiku=${pins.ANTHROPIC_DEFAULT_HAIKU_MODEL}`);
|
|
18780
19075
|
console.log(`
|
|
18781
19076
|
Point any Anthropic-compatible tool at this endpoint:`);
|
|
18782
19077
|
console.log(` ANTHROPIC_API_KEY=x ANTHROPIC_BASE_URL=http://${finalConfig.host}:${info.port}`);
|