@rynfar/meridian 1.62.5 → 1.62.7
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 +31 -1
- package/dist/{cli-dya07jbg.js → cli-21w6xm0d.js} +79 -81
- package/dist/{cli-je60fevk.js → cli-pc0mtjjv.js} +83 -1
- package/dist/{cli-d45dq9gf.js → cli-xfbhn15a.js} +31 -10
- package/dist/cli.js +6 -6
- package/dist/{profileCli-7f6yhakj.js → profileCli-39vshwdn.js} +1 -1
- package/dist/proxy/adapters/opencode.d.ts.map +1 -1
- package/dist/proxy/models.d.ts +20 -9
- package/dist/proxy/models.d.ts.map +1 -1
- package/dist/proxy/passthroughEarlyStop.d.ts +12 -3
- package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -1
- package/dist/proxy/query.d.ts +8 -0
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/setup.d.ts +43 -0
- package/dist/proxy/setup.d.ts.map +1 -1
- package/dist/server.js +3 -3
- package/dist/{setup-6c11e8d6.js → setup-0x573t61.js} +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,13 +104,43 @@ The Claude Agent SDK provides programmatic access to Claude. But your favorite c
|
|
|
104
104
|
| [Aider](https://github.com/paul-gauthier/aider) | ✅ Verified | Env vars — file editing, streaming; `--no-stream` broken (litellm bug) |
|
|
105
105
|
| [Open WebUI](https://github.com/open-webui/open-webui) | ✅ Verified | OpenAI-compatible endpoints — set base URL to `http://127.0.0.1:3456` |
|
|
106
106
|
| [Pi](https://github.com/mariozechner/pi-coding-agent) | ✅ Verified | models.json config (see [Agent Setup](docs/agents.md)) — full tool support via passthrough; detected via `x-meridian-agent: pi` header |
|
|
107
|
-
| [Prime Agent](https://www.npmjs.com/package/prime-agent) |
|
|
107
|
+
| [Prime Agent](https://www.npmjs.com/package/prime-agent) | ⚠️ Single-agent verified | Extension config (see [Agent Setup](docs/agents.md)) — reliable with one active agent. Concurrent RLM subagents receive distinct session keys, but are not yet production-safe; see [Prime Agent subagents](#prime-agent-subagents). The extension's `metadata.user_id` stamp is **required**, not optional. |
|
|
108
108
|
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | ✅ Verified | `ANTHROPIC_BASE_URL` — remote clients share a Max subscription over the network; client CWD preserved in system prompt |
|
|
109
109
|
| [Cherry Studio](https://github.com/CherryHQ/cherry-studio) | ✅ Verified | `cherry` adapter (see [Agent Setup](docs/agents.md)) — chat client with Claude's built-in web search via internal mode |
|
|
110
110
|
| Jcode | ✅ Verified | `/v1/chat/completions` + `x-jcode-session` header — dedicated `jcode` adapter keeps append-only history intact, so retained sessions resume on one SDK session (90.9% cache hit on turn 2 of a two-turn Opus session) |
|
|
111
111
|
| [Codex CLI](https://github.com/openai/codex) | ✅ Verified | `/v1/responses` (see [Agent Setup](docs/agents.md)) — Responses-API provider, passthrough tool execution; verified on 0.144 (plain + tool-driving turns) |
|
|
112
112
|
| [Continue](https://github.com/continuedev/continue) | 🔲 Untested | OpenAI-compatible endpoints should work — set `apiBase` to `http://127.0.0.1:3456` |
|
|
113
113
|
|
|
114
|
+
### Prime Agent subagents
|
|
115
|
+
|
|
116
|
+
Prime Agent is reliable through Meridian with one active agent. RLM children have
|
|
117
|
+
separate session identities and can execute successfully, but concurrent subagent
|
|
118
|
+
orchestration is not yet production-safe. Observed failure modes include overload
|
|
119
|
+
amplification, expensive cache churn after fresh-session replay, loss of child-task
|
|
120
|
+
context during recovery, undelivered tool envelopes, and incomplete parent-to-child
|
|
121
|
+
cancellation. Use a single active Prime Agent for unattended or usage-sensitive work
|
|
122
|
+
until coordinated fixes land in Prime Agent and Meridian.
|
|
123
|
+
|
|
124
|
+
Prime Agent can keep Opus on the root session while selecting Sol for an individual
|
|
125
|
+
child. A child inherits its parent's model unless the `rlm` call supplies an exact
|
|
126
|
+
`provider/model` selector returned by `rlm.find_models()`:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
sol_models = await rlm.find_models("sol")
|
|
130
|
+
print(sol_models) # choose an available exact selector for your authenticated providers
|
|
131
|
+
|
|
132
|
+
child = await rlm(
|
|
133
|
+
"Review this change and report your findings to the parent.",
|
|
134
|
+
name="sol-reviewer",
|
|
135
|
+
model="openai-codex/gpt-5.6-sol",
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The selector above requires an authenticated OpenAI Codex provider in Prime Agent;
|
|
140
|
+
Prime Inference may expose a different Sol selector. Explicit child model selection
|
|
141
|
+
reduces Claude Max pressure, but does not by itself fix the orchestration and
|
|
142
|
+
cancellation limitations above.
|
|
143
|
+
|
|
114
144
|
Tested an agent or built a plugin? [Open an issue](https://github.com/rynfar/meridian/issues) and we'll add it.
|
|
115
145
|
|
|
116
146
|
## FAQ
|
|
@@ -44,20 +44,23 @@ import {
|
|
|
44
44
|
isClosedControllerError,
|
|
45
45
|
mapModelToClaudeModel,
|
|
46
46
|
parseAuthorizationCodeInput,
|
|
47
|
+
recordExtendedContextRateLimited,
|
|
47
48
|
recordExtendedContextUnavailable,
|
|
48
49
|
resolveClaudeExecutableAsync,
|
|
49
50
|
resolvePassthrough,
|
|
50
51
|
resolveSdkModelDefaults,
|
|
51
52
|
stripExtendedContext,
|
|
52
53
|
subscriptionIncludesExtendedContext
|
|
53
|
-
} from "./cli-
|
|
54
|
+
} from "./cli-xfbhn15a.js";
|
|
54
55
|
import {
|
|
55
56
|
getSetting,
|
|
56
57
|
setSetting
|
|
57
58
|
} from "./cli-vj9cv18n.js";
|
|
58
59
|
import {
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
LRUMap,
|
|
61
|
+
checkPluginConfigured,
|
|
62
|
+
notePluginlessOpenCodeRequest
|
|
63
|
+
} from "./cli-pc0mtjjv.js";
|
|
61
64
|
import {
|
|
62
65
|
claudeLog,
|
|
63
66
|
createPlatformCredentialStore,
|
|
@@ -2282,7 +2285,13 @@ var init_opencode2 = __esm(() => {
|
|
|
2282
2285
|
openCodeAdapter = {
|
|
2283
2286
|
name: "opencode",
|
|
2284
2287
|
getSessionId(c) {
|
|
2285
|
-
|
|
2288
|
+
const base = c.req.header("x-opencode-session") ?? c.req.header("x-session-affinity");
|
|
2289
|
+
if (!base)
|
|
2290
|
+
return;
|
|
2291
|
+
if (c.req.header("x-opencode-agent-mode") !== "subagent")
|
|
2292
|
+
return base;
|
|
2293
|
+
const agent = c.req.header("x-opencode-agent-name")?.trim();
|
|
2294
|
+
return agent ? `${base}#${agent}` : base;
|
|
2286
2295
|
},
|
|
2287
2296
|
getAgentMode(c) {
|
|
2288
2297
|
return c.req.header("x-opencode-agent-mode");
|
|
@@ -11309,71 +11318,6 @@ function shouldAttemptRecovery(input) {
|
|
|
11309
11318
|
// src/proxy/server.ts
|
|
11310
11319
|
init_agentMatch();
|
|
11311
11320
|
|
|
11312
|
-
// src/utils/lruMap.ts
|
|
11313
|
-
class LRUMap {
|
|
11314
|
-
maxSize;
|
|
11315
|
-
onEvict;
|
|
11316
|
-
map = new Map;
|
|
11317
|
-
constructor(maxSize, onEvict) {
|
|
11318
|
-
this.maxSize = maxSize;
|
|
11319
|
-
this.onEvict = onEvict;
|
|
11320
|
-
}
|
|
11321
|
-
get size() {
|
|
11322
|
-
return this.map.size;
|
|
11323
|
-
}
|
|
11324
|
-
get(key) {
|
|
11325
|
-
const value = this.map.get(key);
|
|
11326
|
-
if (value === undefined)
|
|
11327
|
-
return;
|
|
11328
|
-
this.map.delete(key);
|
|
11329
|
-
this.map.set(key, value);
|
|
11330
|
-
return value;
|
|
11331
|
-
}
|
|
11332
|
-
set(key, value) {
|
|
11333
|
-
if (this.map.has(key)) {
|
|
11334
|
-
this.map.delete(key);
|
|
11335
|
-
} else if (this.map.size >= this.maxSize) {
|
|
11336
|
-
this.evictOldest();
|
|
11337
|
-
}
|
|
11338
|
-
this.map.set(key, value);
|
|
11339
|
-
return this;
|
|
11340
|
-
}
|
|
11341
|
-
has(key) {
|
|
11342
|
-
return this.map.has(key);
|
|
11343
|
-
}
|
|
11344
|
-
delete(key) {
|
|
11345
|
-
return this.map.delete(key);
|
|
11346
|
-
}
|
|
11347
|
-
clear() {
|
|
11348
|
-
this.map.clear();
|
|
11349
|
-
}
|
|
11350
|
-
entries() {
|
|
11351
|
-
return this.map.entries();
|
|
11352
|
-
}
|
|
11353
|
-
keys() {
|
|
11354
|
-
return this.map.keys();
|
|
11355
|
-
}
|
|
11356
|
-
values() {
|
|
11357
|
-
return this.map.values();
|
|
11358
|
-
}
|
|
11359
|
-
forEach(callbackfn) {
|
|
11360
|
-
this.map.forEach((value, key) => callbackfn(value, key, this));
|
|
11361
|
-
}
|
|
11362
|
-
[Symbol.iterator]() {
|
|
11363
|
-
return this.map[Symbol.iterator]();
|
|
11364
|
-
}
|
|
11365
|
-
evictOldest() {
|
|
11366
|
-
const oldestKey = this.map.keys().next().value;
|
|
11367
|
-
if (oldestKey === undefined)
|
|
11368
|
-
return;
|
|
11369
|
-
const oldestValue = this.map.get(oldestKey);
|
|
11370
|
-
if (oldestValue === undefined)
|
|
11371
|
-
return;
|
|
11372
|
-
this.map.delete(oldestKey);
|
|
11373
|
-
this.onEvict?.(oldestKey, oldestValue);
|
|
11374
|
-
}
|
|
11375
|
-
}
|
|
11376
|
-
|
|
11377
11321
|
// src/telemetry/index.ts
|
|
11378
11322
|
init_env();
|
|
11379
11323
|
import { join as join2 } from "node:path";
|
|
@@ -19415,12 +19359,15 @@ function stripConfigDir(env2) {
|
|
|
19415
19359
|
delete out.CLAUDE_CONFIG_DIR;
|
|
19416
19360
|
return out;
|
|
19417
19361
|
}
|
|
19418
|
-
function computePassthroughMaxTurns(hasDeferredTools, advisorModel) {
|
|
19362
|
+
function computePassthroughMaxTurns(hasDeferredTools, advisorModel, singleTurnHandoff) {
|
|
19419
19363
|
const deferredBump = hasDeferredTools ? 1 : 0;
|
|
19420
19364
|
const defaultBase = 3 + deferredBump;
|
|
19421
19365
|
const configured = envInt("PASSTHROUGH_MAX_TURNS", defaultBase);
|
|
19422
|
-
const
|
|
19366
|
+
const operatorPinned = env("PASSTHROUGH_MAX_TURNS") !== undefined && configured > 0;
|
|
19423
19367
|
const advisorBump = advisorModel ? 3 : 0;
|
|
19368
|
+
if (singleTurnHandoff && !operatorPinned)
|
|
19369
|
+
return 1;
|
|
19370
|
+
const base = configured > 0 ? configured : defaultBase;
|
|
19424
19371
|
return base + advisorBump;
|
|
19425
19372
|
}
|
|
19426
19373
|
function buildCwdNote(sdkCwd, clientCwd) {
|
|
@@ -19502,7 +19449,7 @@ function buildQueryOptions(ctx, abortController) {
|
|
|
19502
19449
|
prompt,
|
|
19503
19450
|
options: {
|
|
19504
19451
|
executable: "node",
|
|
19505
|
-
maxTurns: passthrough ? computePassthroughMaxTurns(hasDeferredTools, ctx.advisorModel) : 200,
|
|
19452
|
+
maxTurns: passthrough ? computePassthroughMaxTurns(hasDeferredTools, ctx.advisorModel, ctx.earlyStop !== false && !hasDeferredTools && !ctx.advisorModel && !outputFormat) : 200,
|
|
19506
19453
|
cwd: workingDirectory,
|
|
19507
19454
|
model,
|
|
19508
19455
|
pathToClaudeCodeExecutable: claudeExecutable,
|
|
@@ -21056,8 +21003,8 @@ function createProxyServer(config = {}) {
|
|
|
21056
21003
|
proxyLogSilent = finalConfig.silent;
|
|
21057
21004
|
const serverVersion = finalConfig.version ?? "unknown";
|
|
21058
21005
|
restoreActiveProfile(finalConfig.profiles);
|
|
21059
|
-
const sessionDiscoveredTools = new
|
|
21060
|
-
const sessionToolCache = new
|
|
21006
|
+
const sessionDiscoveredTools = new LRUMap(getMaxSessionsLimit());
|
|
21007
|
+
const sessionToolCache = new LRUMap(getMaxSessionsLimit());
|
|
21061
21008
|
const sessionMcpCache = new LRUMap(getMaxSessionsLimit());
|
|
21062
21009
|
const RESUME_REFUSAL_MAX_RETRIES = 3;
|
|
21063
21010
|
const RESUME_REFUSAL_RETRY_DELAY_MS = parseInt(process.env.MERIDIAN_BUSY_RETRY_DELAY_MS ?? "500", 10);
|
|
@@ -21362,7 +21309,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21362
21309
|
const isSubagentRequest = declaredAgentMode === "subagent" || requestSource?.startsWith("subagent-") === true;
|
|
21363
21310
|
const agentMode = isSubagentRequest ? "subagent" : declaredAgentMode;
|
|
21364
21311
|
const requestedModel = typeof body.model === "string" ? body.model : "sonnet";
|
|
21365
|
-
let model = mapModelToClaudeModel(requestedModel, authStatus?.subscriptionType, agentMode);
|
|
21312
|
+
let model = mapModelToClaudeModel(requestedModel, authStatus?.subscriptionType, agentMode, profile.id);
|
|
21366
21313
|
const envOverrides = explicitModelPin(requestedModel);
|
|
21367
21314
|
const cwdResolution = resolveSdkWorkingDirectory({
|
|
21368
21315
|
envOverride: process.env.MERIDIAN_WORKDIR ?? process.env.CLAUDE_PROXY_WORKDIR,
|
|
@@ -21445,6 +21392,20 @@ data: ${JSON.stringify(lastError)}
|
|
|
21445
21392
|
const taskBudget = Number.isFinite(parsedBudget) ? { total: parsedBudget } : body.task_budget ? { total: body.task_budget.total ?? body.task_budget } : undefined;
|
|
21446
21393
|
const betas = betaFilter.forwarded;
|
|
21447
21394
|
const agentSessionId = adapter.getSessionId(c, body);
|
|
21395
|
+
const pluginlessWarning = notePluginlessOpenCodeRequest({
|
|
21396
|
+
userAgent: c.req.header("user-agent"),
|
|
21397
|
+
agentModeHeader: c.req.header("x-opencode-agent-mode"),
|
|
21398
|
+
sessionId: agentSessionId
|
|
21399
|
+
});
|
|
21400
|
+
if (pluginlessWarning) {
|
|
21401
|
+
plog(`[PROXY] ${requestMeta.requestId} ${pluginlessWarning}`);
|
|
21402
|
+
diagnosticLog2.log({
|
|
21403
|
+
level: "warn",
|
|
21404
|
+
category: "session",
|
|
21405
|
+
message: `${requestMeta.requestId} ${pluginlessWarning}`,
|
|
21406
|
+
requestId: requestMeta.requestId
|
|
21407
|
+
});
|
|
21408
|
+
}
|
|
21448
21409
|
const profileSessionId = profile.id !== "default" && agentSessionId ? `${profile.id}:${agentSessionId}` : agentSessionId;
|
|
21449
21410
|
const commitSessionTurn = () => {
|
|
21450
21411
|
if (profileSessionId)
|
|
@@ -21871,6 +21832,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21871
21832
|
cleanEnv: profileEnv,
|
|
21872
21833
|
envOverrides,
|
|
21873
21834
|
hasDeferredTools,
|
|
21835
|
+
earlyStop: earlyStopEnabled,
|
|
21874
21836
|
resumeSessionId,
|
|
21875
21837
|
isUndo,
|
|
21876
21838
|
resumeSessionAtUuid: undoRollbackUuid ?? passthroughToolCallAssistantUuid,
|
|
@@ -21959,6 +21921,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21959
21921
|
cleanEnv: profileEnv,
|
|
21960
21922
|
envOverrides,
|
|
21961
21923
|
hasDeferredTools,
|
|
21924
|
+
earlyStop: earlyStopEnabled,
|
|
21962
21925
|
resumeSessionId: undefined,
|
|
21963
21926
|
isUndo: false,
|
|
21964
21927
|
resumeSessionAtUuid: undefined,
|
|
@@ -21992,7 +21955,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
21992
21955
|
if (isExtraUsageRequiredError(errMsg) && hasExtendedContext(model)) {
|
|
21993
21956
|
const from = model;
|
|
21994
21957
|
model = stripExtendedContext(model);
|
|
21995
|
-
recordExtendedContextUnavailable();
|
|
21958
|
+
recordExtendedContextUnavailable(profile.id);
|
|
21996
21959
|
claudeLog("upstream.context_fallback", {
|
|
21997
21960
|
mode: "non_stream",
|
|
21998
21961
|
from,
|
|
@@ -22028,6 +21991,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
22028
21991
|
cleanEnv: profileEnv,
|
|
22029
21992
|
envOverrides,
|
|
22030
21993
|
hasDeferredTools,
|
|
21994
|
+
earlyStop: earlyStopEnabled,
|
|
22031
21995
|
resumeSessionId: undefined,
|
|
22032
21996
|
isUndo: false,
|
|
22033
21997
|
resumeSessionAtUuid: undefined,
|
|
@@ -22071,6 +22035,7 @@ data: ${JSON.stringify(lastError)}
|
|
|
22071
22035
|
if (hasExtendedContext(model)) {
|
|
22072
22036
|
const from = model;
|
|
22073
22037
|
model = stripExtendedContext(model);
|
|
22038
|
+
recordExtendedContextRateLimited(profile.id, priorityCooldownUntil(profile.id, Date.now()));
|
|
22074
22039
|
claudeLog("upstream.context_fallback", {
|
|
22075
22040
|
mode: "non_stream",
|
|
22076
22041
|
from,
|
|
@@ -22244,6 +22209,17 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
22244
22209
|
reason: sdkTerm.reason,
|
|
22245
22210
|
captured: capturedToolUses.length
|
|
22246
22211
|
});
|
|
22212
|
+
if (lastUsage)
|
|
22213
|
+
logUsage(requestMeta.requestId, lastUsage);
|
|
22214
|
+
} else if (passthrough && sdkTerm.reason === "max_turns" && contentBlocks.length > 0) {
|
|
22215
|
+
lastStopReason = "max_tokens";
|
|
22216
|
+
claudeLog("passthrough.capped_turn_truncated", {
|
|
22217
|
+
mode: "non_stream",
|
|
22218
|
+
blocks: contentBlocks.length
|
|
22219
|
+
});
|
|
22220
|
+
plog(`[PROXY] ${requestMeta.requestId} capped turn produced no forwardable tool call — reporting as truncated`);
|
|
22221
|
+
if (lastUsage)
|
|
22222
|
+
logUsage(requestMeta.requestId, lastUsage);
|
|
22247
22223
|
} else {
|
|
22248
22224
|
claudeLog("upstream.failed", {
|
|
22249
22225
|
mode: "non_stream",
|
|
@@ -22524,6 +22500,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22524
22500
|
cleanEnv: profileEnv,
|
|
22525
22501
|
envOverrides,
|
|
22526
22502
|
hasDeferredTools,
|
|
22503
|
+
earlyStop: earlyStopEnabled,
|
|
22527
22504
|
resumeSessionId,
|
|
22528
22505
|
isUndo,
|
|
22529
22506
|
resumeSessionAtUuid: undoRollbackUuid ?? passthroughToolCallAssistantUuid,
|
|
@@ -22611,6 +22588,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22611
22588
|
cleanEnv: profileEnv,
|
|
22612
22589
|
envOverrides,
|
|
22613
22590
|
hasDeferredTools,
|
|
22591
|
+
earlyStop: earlyStopEnabled,
|
|
22614
22592
|
resumeSessionId: undefined,
|
|
22615
22593
|
isUndo: false,
|
|
22616
22594
|
resumeSessionAtUuid: undefined,
|
|
@@ -22644,7 +22622,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22644
22622
|
if (isExtraUsageRequiredError(errMsg) && hasExtendedContext(model)) {
|
|
22645
22623
|
const from = model;
|
|
22646
22624
|
model = stripExtendedContext(model);
|
|
22647
|
-
recordExtendedContextUnavailable();
|
|
22625
|
+
recordExtendedContextUnavailable(profile.id);
|
|
22648
22626
|
claudeLog("upstream.context_fallback", {
|
|
22649
22627
|
mode: "stream",
|
|
22650
22628
|
from,
|
|
@@ -22680,6 +22658,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22680
22658
|
cleanEnv: profileEnv,
|
|
22681
22659
|
envOverrides,
|
|
22682
22660
|
hasDeferredTools,
|
|
22661
|
+
earlyStop: earlyStopEnabled,
|
|
22683
22662
|
resumeSessionId: undefined,
|
|
22684
22663
|
isUndo: false,
|
|
22685
22664
|
resumeSessionAtUuid: undefined,
|
|
@@ -22723,6 +22702,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
|
|
|
22723
22702
|
if (hasExtendedContext(model)) {
|
|
22724
22703
|
const from = model;
|
|
22725
22704
|
model = stripExtendedContext(model);
|
|
22705
|
+
recordExtendedContextRateLimited(profile.id, priorityCooldownUntil(profile.id, Date.now()));
|
|
22726
22706
|
claudeLog("upstream.context_fallback", {
|
|
22727
22707
|
mode: "stream",
|
|
22728
22708
|
from,
|
|
@@ -23168,6 +23148,7 @@ data: ${JSON.stringify({
|
|
|
23168
23148
|
cleanEnv: profileEnv,
|
|
23169
23149
|
envOverrides,
|
|
23170
23150
|
hasDeferredTools,
|
|
23151
|
+
earlyStop: earlyStopEnabled,
|
|
23171
23152
|
resumeSessionId: currentSessionId || resumeSessionId,
|
|
23172
23153
|
isUndo: false,
|
|
23173
23154
|
resumeSessionAtUuid: nextPassthroughToolCallAssistantUuid,
|
|
@@ -23426,10 +23407,6 @@ data: {"type":"message_stop"}
|
|
|
23426
23407
|
claudeLog("passthrough.client_abort_settled", { action: disposition.action });
|
|
23427
23408
|
return;
|
|
23428
23409
|
}
|
|
23429
|
-
if (passthrough && streamedToolUseIds.size > 0 && !sawCanonicalResult) {
|
|
23430
|
-
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23431
|
-
claudeLog("passthrough.noncanonical_session_evicted", { mode: "stream", reason: "drain_error" });
|
|
23432
|
-
}
|
|
23433
23410
|
const stderrOutput = stderrLines.join(`
|
|
23434
23411
|
`).trim();
|
|
23435
23412
|
if (stderrOutput && error instanceof Error && !error.message.includes(stderrOutput)) {
|
|
@@ -23459,6 +23436,11 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
23459
23436
|
capturedToolUses: capturedToolUses.length,
|
|
23460
23437
|
abortIsOurs: sawDuplicateToolUse
|
|
23461
23438
|
}) && messageStartEmitted;
|
|
23439
|
+
const recoverableCheckpoint = canRecoverAsToolUse && sdkTerm.reason === "max_turns" && Boolean(currentSessionId) && Boolean(nextPassthroughToolCallAssistantUuid) && Boolean(nextPassthroughToolCallIds?.length) && earlyStopFired && !isIndependentSession && !sawDuplicateToolUse;
|
|
23440
|
+
if (passthrough && streamedToolUseIds.size > 0 && !sawCanonicalResult && !recoverableCheckpoint) {
|
|
23441
|
+
evictSession(profileSessionId, profileScopedCwd, body.messages || []);
|
|
23442
|
+
claudeLog("passthrough.noncanonical_session_evicted", { mode: "stream", reason: "drain_error" });
|
|
23443
|
+
}
|
|
23462
23444
|
if (canRecoverAsToolUse) {
|
|
23463
23445
|
diagnosticLog2.session(`${requestMeta.requestId} sdk_termination_recovered ${formatSdkTermination(sdkTerm, {
|
|
23464
23446
|
model,
|
|
@@ -23510,6 +23492,17 @@ data: {"type":"message_stop"}
|
|
|
23510
23492
|
|
|
23511
23493
|
`), "recover_message_stop");
|
|
23512
23494
|
recordEnvelopeViolations(checkUndeliveredToolUses(capturedToolUses, streamedToolUseIds));
|
|
23495
|
+
if (recoverableCheckpoint) {
|
|
23496
|
+
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, nextPassthroughToolCallAssistantUuid, nextPassthroughToolCallIds);
|
|
23497
|
+
commitSessionTurn();
|
|
23498
|
+
claudeLog("passthrough.checkpoint_persisted", {
|
|
23499
|
+
mode: "stream",
|
|
23500
|
+
reason: "single_turn_boundary",
|
|
23501
|
+
toolCalls: nextPassthroughToolCallIds.length
|
|
23502
|
+
});
|
|
23503
|
+
}
|
|
23504
|
+
if (lastUsage)
|
|
23505
|
+
logUsage(requestMeta.requestId, lastUsage);
|
|
23513
23506
|
const recoverTotalMs = Date.now() - requestStartAt;
|
|
23514
23507
|
const recoverQueueWaitMs = totalQueueWaitMs(requestMeta);
|
|
23515
23508
|
telemetryStore2.record({
|
|
@@ -23540,6 +23533,11 @@ data: {"type":"message_stop"}
|
|
|
23540
23533
|
contentBlocks: eventsForwarded + unseenToolUses.length,
|
|
23541
23534
|
textEvents: textEventsForwarded,
|
|
23542
23535
|
error: null,
|
|
23536
|
+
inputTokens: lastUsage?.input_tokens,
|
|
23537
|
+
outputTokens: lastUsage?.output_tokens,
|
|
23538
|
+
cacheReadInputTokens: lastUsage?.cache_read_input_tokens,
|
|
23539
|
+
cacheCreationInputTokens: lastUsage?.cache_creation_input_tokens,
|
|
23540
|
+
cacheHitRate: computeCacheHitRate(lastUsage),
|
|
23543
23541
|
...envelopeViolations.length > 0 ? { envelopeViolations: [...envelopeViolations] } : {}
|
|
23544
23542
|
});
|
|
23545
23543
|
if (!streamClosed) {
|
|
@@ -5,6 +5,72 @@ import { dirname, join } from "path";
|
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { applyEdits, modify, parse as parseJsonc } from "jsonc-parser";
|
|
7
7
|
|
|
8
|
+
// src/utils/lruMap.ts
|
|
9
|
+
class LRUMap {
|
|
10
|
+
maxSize;
|
|
11
|
+
onEvict;
|
|
12
|
+
map = new Map;
|
|
13
|
+
constructor(maxSize, onEvict) {
|
|
14
|
+
this.maxSize = maxSize;
|
|
15
|
+
this.onEvict = onEvict;
|
|
16
|
+
}
|
|
17
|
+
get size() {
|
|
18
|
+
return this.map.size;
|
|
19
|
+
}
|
|
20
|
+
get(key) {
|
|
21
|
+
const value = this.map.get(key);
|
|
22
|
+
if (value === undefined)
|
|
23
|
+
return;
|
|
24
|
+
this.map.delete(key);
|
|
25
|
+
this.map.set(key, value);
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
set(key, value) {
|
|
29
|
+
if (this.map.has(key)) {
|
|
30
|
+
this.map.delete(key);
|
|
31
|
+
} else if (this.map.size >= this.maxSize) {
|
|
32
|
+
this.evictOldest();
|
|
33
|
+
}
|
|
34
|
+
this.map.set(key, value);
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
has(key) {
|
|
38
|
+
return this.map.has(key);
|
|
39
|
+
}
|
|
40
|
+
delete(key) {
|
|
41
|
+
return this.map.delete(key);
|
|
42
|
+
}
|
|
43
|
+
clear() {
|
|
44
|
+
this.map.clear();
|
|
45
|
+
}
|
|
46
|
+
entries() {
|
|
47
|
+
return this.map.entries();
|
|
48
|
+
}
|
|
49
|
+
keys() {
|
|
50
|
+
return this.map.keys();
|
|
51
|
+
}
|
|
52
|
+
values() {
|
|
53
|
+
return this.map.values();
|
|
54
|
+
}
|
|
55
|
+
forEach(callbackfn) {
|
|
56
|
+
this.map.forEach((value, key) => callbackfn(value, key, this));
|
|
57
|
+
}
|
|
58
|
+
[Symbol.iterator]() {
|
|
59
|
+
return this.map[Symbol.iterator]();
|
|
60
|
+
}
|
|
61
|
+
evictOldest() {
|
|
62
|
+
const oldestKey = this.map.keys().next().value;
|
|
63
|
+
if (oldestKey === undefined)
|
|
64
|
+
return;
|
|
65
|
+
const oldestValue = this.map.get(oldestKey);
|
|
66
|
+
if (oldestValue === undefined)
|
|
67
|
+
return;
|
|
68
|
+
this.map.delete(oldestKey);
|
|
69
|
+
this.onEvict?.(oldestKey, oldestValue);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/proxy/setup.ts
|
|
8
74
|
class UnparseableConfigError extends Error {
|
|
9
75
|
configPath;
|
|
10
76
|
constructor(configPath) {
|
|
@@ -55,6 +121,22 @@ function checkPluginConfigured(configPath) {
|
|
|
55
121
|
const plugins = Array.isArray(config.plugin) ? config.plugin : [];
|
|
56
122
|
return plugins.some((p) => typeof p === "string" && isMeridianEntry(p));
|
|
57
123
|
}
|
|
124
|
+
var pluginlessWarned = new LRUMap(256);
|
|
125
|
+
function clearPluginlessWarnings() {
|
|
126
|
+
pluginlessWarned.clear();
|
|
127
|
+
}
|
|
128
|
+
function notePluginlessOpenCodeRequest(input) {
|
|
129
|
+
if (!input.userAgent?.toLowerCase().startsWith("opencode/"))
|
|
130
|
+
return;
|
|
131
|
+
if (input.agentModeHeader)
|
|
132
|
+
return;
|
|
133
|
+
const key = input.sessionId || "(keyless)";
|
|
134
|
+
if (pluginlessWarned.get(key))
|
|
135
|
+
return;
|
|
136
|
+
pluginlessWarned.set(key, true);
|
|
137
|
+
const shortId = input.sessionId ? `${input.sessionId.slice(0, 12)}…` : "(no session header)";
|
|
138
|
+
return `OpenCode request without the Meridian plugin's agent headers (session ${shortId}). ` + `OpenCode runs its internal title/summary agents under your session id, so Meridian ` + `cannot tell them apart from your conversation: the first turn of each session can fail ` + `with a 400 or replay against a cold cache. Fix: meridian setup (or update the plugin).`;
|
|
139
|
+
}
|
|
58
140
|
function runSetup(pluginPath, configPath) {
|
|
59
141
|
const path = configPath ?? findOpencodeConfigPath();
|
|
60
142
|
const dir = dirname(path);
|
|
@@ -82,4 +164,4 @@ function runSetup(pluginPath, configPath) {
|
|
|
82
164
|
return { configPath: path, pluginPath, alreadyConfigured, removedStale, created: false };
|
|
83
165
|
}
|
|
84
166
|
|
|
85
|
-
export { UnparseableConfigError, findOpencodeConfigPath, findPluginPath, checkPluginConfigured, runSetup };
|
|
167
|
+
export { LRUMap, UnparseableConfigError, findOpencodeConfigPath, findPluginPath, checkPluginConfigured, clearPluginlessWarnings, notePluginlessOpenCodeRequest, runSetup };
|
|
@@ -92,7 +92,7 @@ function supports1mContext(model) {
|
|
|
92
92
|
return false;
|
|
93
93
|
return true;
|
|
94
94
|
}
|
|
95
|
-
function mapModelToClaudeModel(model, subscriptionType, agentMode) {
|
|
95
|
+
function mapModelToClaudeModel(model, subscriptionType, agentMode, profileId) {
|
|
96
96
|
if (model.includes("haiku"))
|
|
97
97
|
return "haiku";
|
|
98
98
|
const use1m = supports1mContext(model);
|
|
@@ -105,7 +105,7 @@ function mapModelToClaudeModel(model, subscriptionType, agentMode) {
|
|
|
105
105
|
if (fableOverrideRaw && fableOverride !== "fable[1m]") {
|
|
106
106
|
warnUnrecognizedTierOverride("FABLE_MODEL", fableOverrideRaw, "fable");
|
|
107
107
|
}
|
|
108
|
-
if (use1m && !isSubagent && !isExtendedContextKnownUnavailable())
|
|
108
|
+
if (use1m && !isSubagent && !isExtendedContextKnownUnavailable(profileId))
|
|
109
109
|
return "fable[1m]";
|
|
110
110
|
return "fable";
|
|
111
111
|
}
|
|
@@ -117,25 +117,46 @@ function mapModelToClaudeModel(model, subscriptionType, agentMode) {
|
|
|
117
117
|
if (opusOverrideRaw && opusOverride !== "opus[1m]") {
|
|
118
118
|
warnUnrecognizedTierOverride("OPUS_MODEL", opusOverrideRaw, "opus");
|
|
119
119
|
}
|
|
120
|
-
if (use1m && !isSubagent && !isExtendedContextKnownUnavailable())
|
|
120
|
+
if (use1m && !isSubagent && !isExtendedContextKnownUnavailable(profileId))
|
|
121
121
|
return "opus[1m]";
|
|
122
122
|
return "opus";
|
|
123
123
|
}
|
|
124
124
|
const sonnetOverride = process.env.MERIDIAN_SONNET_MODEL ?? process.env.CLAUDE_PROXY_SONNET_MODEL;
|
|
125
125
|
if (sonnetOverride === "sonnet[1m]") {
|
|
126
|
-
if (!use1m || isSubagent || isExtendedContextKnownUnavailable())
|
|
126
|
+
if (!use1m || isSubagent || isExtendedContextKnownUnavailable(profileId))
|
|
127
127
|
return "sonnet";
|
|
128
128
|
return "sonnet[1m]";
|
|
129
129
|
}
|
|
130
130
|
return "sonnet";
|
|
131
131
|
}
|
|
132
132
|
var EXTRA_USAGE_RETRY_MS = 60 * 60 * 1000;
|
|
133
|
-
var
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
var DEFAULT_BENCH_KEY = "__default__";
|
|
134
|
+
var extendedContextBenchedUntil = new Map;
|
|
135
|
+
function benchExtendedContext(profileId, until) {
|
|
136
|
+
if (until <= Date.now())
|
|
137
|
+
return;
|
|
138
|
+
const key = profileId || DEFAULT_BENCH_KEY;
|
|
139
|
+
const existing = extendedContextBenchedUntil.get(key);
|
|
140
|
+
if (existing !== undefined && existing >= until)
|
|
141
|
+
return;
|
|
142
|
+
extendedContextBenchedUntil.set(key, until);
|
|
143
|
+
}
|
|
144
|
+
function recordExtendedContextUnavailable(profileId) {
|
|
145
|
+
benchExtendedContext(profileId, Date.now() + EXTRA_USAGE_RETRY_MS);
|
|
146
|
+
}
|
|
147
|
+
function recordExtendedContextRateLimited(profileId, until) {
|
|
148
|
+
benchExtendedContext(profileId, until);
|
|
136
149
|
}
|
|
137
|
-
function isExtendedContextKnownUnavailable() {
|
|
138
|
-
|
|
150
|
+
function isExtendedContextKnownUnavailable(profileId) {
|
|
151
|
+
const key = profileId || DEFAULT_BENCH_KEY;
|
|
152
|
+
const until = extendedContextBenchedUntil.get(key);
|
|
153
|
+
if (until === undefined)
|
|
154
|
+
return false;
|
|
155
|
+
if (until <= Date.now()) {
|
|
156
|
+
extendedContextBenchedUntil.delete(key);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
139
160
|
}
|
|
140
161
|
function stripExtendedContext(model) {
|
|
141
162
|
if (model === "opus[1m]")
|
|
@@ -855,4 +876,4 @@ Examples:
|
|
|
855
876
|
meridian profile list # Show all profiles`);
|
|
856
877
|
}
|
|
857
878
|
|
|
858
|
-
export { env, envBool, resolvePassthrough, envInt, init_env, CANONICAL_SONNET_MODEL, resolveSdkModelDefaults, explicitModelPin, mapModelToClaudeModel, recordExtendedContextUnavailable, stripExtendedContext, hasExtendedContext, subscriptionIncludesExtendedContext, getAuthCacheInfo, getClaudeAuthStatusAsync, getResolvedClaudeExecutableInfo, resolveClaudeExecutableAsync, isClosedControllerError, OAUTH_TOKEN_URL, OAUTH_CLIENT_ID, OAUTH_REDIRECT_URI, buildAuthLoginEnv, createManualOAuthSession, parseAuthorizationCodeInput, profileAdd, profileAddOauthToken, profileList, dirsToRemoveOnProfileRemove, profileRemove, profileSwitch, profileLogin, profileHelp };
|
|
879
|
+
export { env, envBool, resolvePassthrough, envInt, init_env, CANONICAL_SONNET_MODEL, resolveSdkModelDefaults, explicitModelPin, mapModelToClaudeModel, recordExtendedContextUnavailable, recordExtendedContextRateLimited, stripExtendedContext, hasExtendedContext, subscriptionIncludesExtendedContext, getAuthCacheInfo, getClaudeAuthStatusAsync, getResolvedClaudeExecutableInfo, resolveClaudeExecutableAsync, isClosedControllerError, OAUTH_TOKEN_URL, OAUTH_CLIENT_ID, OAUTH_REDIRECT_URI, buildAuthLoginEnv, createManualOAuthSession, parseAuthorizationCodeInput, profileAdd, profileAddOauthToken, profileList, dirsToRemoveOnProfileRemove, profileRemove, profileSwitch, profileLogin, profileHelp };
|
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startProxyServer
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-21w6xm0d.js";
|
|
5
5
|
import"./cli-m0p2bc8v.js";
|
|
6
6
|
import"./cli-sry5aqdj.js";
|
|
7
7
|
import"./cli-xmweegb1.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveClaudeExecutableAsync
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-xfbhn15a.js";
|
|
11
11
|
import"./cli-vj9cv18n.js";
|
|
12
|
-
import"./cli-
|
|
12
|
+
import"./cli-pc0mtjjv.js";
|
|
13
13
|
import"./cli-khhjyk04.js";
|
|
14
14
|
import {
|
|
15
15
|
__require
|
|
@@ -55,7 +55,7 @@ See https://github.com/rynfar/meridian for full documentation.`);
|
|
|
55
55
|
process.exit(0);
|
|
56
56
|
}
|
|
57
57
|
if (args[0] === "profile") {
|
|
58
|
-
const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-
|
|
58
|
+
const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-39vshwdn.js");
|
|
59
59
|
const subcommand = args[1];
|
|
60
60
|
const profileId = args[2];
|
|
61
61
|
const headless = args.includes("--headless");
|
|
@@ -80,7 +80,7 @@ if (args[0] === "profile") {
|
|
|
80
80
|
process.exit(0);
|
|
81
81
|
}
|
|
82
82
|
if (args[0] === "setup") {
|
|
83
|
-
const { findPluginPath, runSetup, UnparseableConfigError } = await import("./setup-
|
|
83
|
+
const { findPluginPath, runSetup, UnparseableConfigError } = await import("./setup-0x573t61.js");
|
|
84
84
|
const pluginPath = findPluginPath(import.meta.url);
|
|
85
85
|
let result;
|
|
86
86
|
try {
|
|
@@ -146,7 +146,7 @@ async function runCli(start = startProxyServer, runAuthCheck = async () => {
|
|
|
146
146
|
return execFile(claudePath, ["auth", "status"], { timeout: 5000 });
|
|
147
147
|
}) {
|
|
148
148
|
try {
|
|
149
|
-
const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-
|
|
149
|
+
const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-0x573t61.js");
|
|
150
150
|
const configPath = findOpencodeConfigPath();
|
|
151
151
|
const { existsSync } = await import("fs");
|
|
152
152
|
if (existsSync(configPath) && !checkPluginConfigured(configPath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAS9C,eAAO,MAAM,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAS9C,eAAO,MAAM,eAAe,EAAE,YAoK7B,CAAA;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
|
package/dist/proxy/models.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export interface ClaudeAuthStatus {
|
|
|
54
54
|
}
|
|
55
55
|
/** Clear the per-variable warn-once tracking — for testing only. */
|
|
56
56
|
export declare function resetWarnedTierOverrides(): void;
|
|
57
|
-
export declare function mapModelToClaudeModel(model: string, subscriptionType?: string | null, agentMode?: string | null): ClaudeModel;
|
|
57
|
+
export declare function mapModelToClaudeModel(model: string, subscriptionType?: string | null, agentMode?: string | null, profileId?: string): ClaudeModel;
|
|
58
58
|
/**
|
|
59
59
|
* Record that Extra Usage is not enabled on this subscription.
|
|
60
60
|
* For the next hour, mapModelToClaudeModel will return the base model
|
|
@@ -62,15 +62,26 @@ export declare function mapModelToClaudeModel(model: string, subscriptionType?:
|
|
|
62
62
|
* the next request probes [1m] once; if Extra Usage was enabled in the
|
|
63
63
|
* meantime it succeeds and the flag is never set again.
|
|
64
64
|
*/
|
|
65
|
-
export declare function recordExtendedContextUnavailable(): void;
|
|
65
|
+
export declare function recordExtendedContextUnavailable(profileId?: string): void;
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
* Record that a [1m] request was rate-limited, benching it until `until`.
|
|
68
|
+
*
|
|
69
|
+
* Callers derive `until` from the account's own observed reset rather than a
|
|
70
|
+
* constant. Stripping [1m] on a rate limit while recording nothing is what
|
|
71
|
+
* makes the next request map straight back to [1m]: the conversation then
|
|
72
|
+
* flaps between two models and pays a cold prompt cache in BOTH directions,
|
|
73
|
+
* which routinely costs more than the rate limit it was routing around (#862).
|
|
74
|
+
*/
|
|
75
|
+
export declare function recordExtendedContextRateLimited(profileId: string | undefined, until: number): void;
|
|
76
|
+
/**
|
|
77
|
+
* Returns true while this profile's [1m] access is benched. Expired marks are
|
|
78
|
+
* dropped on read, so the next request probes [1m] once — and if the window
|
|
79
|
+
* has genuinely reset, it simply succeeds.
|
|
80
|
+
*/
|
|
81
|
+
export declare function isExtendedContextKnownUnavailable(profileId?: string): boolean;
|
|
82
|
+
/** Clear extended-context benches — for testing only. Clears every profile
|
|
83
|
+
* when no id is given. */
|
|
84
|
+
export declare function resetExtendedContextUnavailable(profileId?: string): void;
|
|
74
85
|
/**
|
|
75
86
|
* Strip the [1m] suffix from a model, returning the base variant.
|
|
76
87
|
* Used for fallback when the 1M context window is rate-limited.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/proxy/models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsBH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,CAAA;AAEzG;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,mBAAmB,CAAA;AACrD,eAAO,MAAM,oBAAoB,kBAAkB,CAAA;AACnD,eAAO,MAAM,sBAAsB,oBAAoB,CAAA;AACvD,eAAO,MAAM,qBAAqB,qBAAqB,CAAA;AAEvD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAM3F;AACD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAuCD,oEAAoE;AACpE,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAkBD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/proxy/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,9 +13,18 @@
|
|
|
13
13
|
* checkpoint, but they are NOT a durability acknowledgement: a live PTY E2E
|
|
14
14
|
* observed the assistant and deny in the iterator while neither existed in the
|
|
15
15
|
* session JSONL after an immediate abort. The proxy therefore freezes the
|
|
16
|
-
* assistant UUID/tool IDs at deny settlement
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* assistant UUID/tool IDs at deny settlement and stores the checkpoint only
|
|
17
|
+
* after the SDK's canonical terminal result commits the transcript.
|
|
18
|
+
*
|
|
19
|
+
* What stops the digest turn is the maxTurns cap in query.ts, not this module:
|
|
20
|
+
* capped at 1, the SDK reaches the tool-use boundary and then declines to start
|
|
21
|
+
* another turn, so the digest never generates AND the terminal result still
|
|
22
|
+
* arrives (as `error_max_turns`) to commit the transcript. That is the
|
|
23
|
+
* combination an immediate abort could not give — it skipped the commit.
|
|
24
|
+
*
|
|
25
|
+
* This module still drains rather than aborts, because the cap is lifted for
|
|
26
|
+
* deferred tools, advisors, structured output, and the kill switch. In those
|
|
27
|
+
* configurations the digest turn does generate and is discarded here.
|
|
19
28
|
*
|
|
20
29
|
* Pure module — no I/O, no imports from server.ts or session/.
|
|
21
30
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passthroughEarlyStop.d.ts","sourceRoot":"","sources":["../../src/proxy/passthroughEarlyStop.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"passthroughEarlyStop.d.ts","sourceRoot":"","sources":["../../src/proxy/passthroughEarlyStop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAUH,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,6EAA6E;IAC7E,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB;yEACqE;IACrE,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,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;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAatF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAQjF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAM5E;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EACtD,WAAW,EAAE,SAAS,MAAM,EAAE,GAC7B,OAAO,CAuCT;AAED,8EAA8E;AAC9E,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAE1F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAMlE;AAED,qEAAqE;AACrE,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtB;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,oBAAoB,EAAE,OAAO,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,mBAAmB,EAAE,OAAO,CAAA;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,oEAAoE;IACpE,WAAW,EAAE,OAAO,CAAA;CACrB,GAAG,sBAAsB,CAMzB"}
|
package/dist/proxy/query.d.ts
CHANGED
|
@@ -39,6 +39,14 @@ export interface QueryContext {
|
|
|
39
39
|
envOverrides?: Record<string, string | undefined>;
|
|
40
40
|
/** Whether any passthrough tools use deferred loading */
|
|
41
41
|
hasDeferredTools: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether passthrough early stop is active (MERIDIAN_PASSTHROUGH_EARLY_STOP
|
|
44
|
+
* != "0"). Gates the single-turn maxTurns cap: the cap is only safe when the
|
|
45
|
+
* checkpoint machinery is running to capture and store the tool boundary.
|
|
46
|
+
* Defaults to on — omitting it must not silently reintroduce the billed
|
|
47
|
+
* digest turn.
|
|
48
|
+
*/
|
|
49
|
+
earlyStop?: boolean;
|
|
42
50
|
/** SDK session ID for resume (if continuing a session) */
|
|
43
51
|
resumeSessionId?: string;
|
|
44
52
|
/** Whether this is an undo operation */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/proxy/query.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/proxy/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAkBA,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;AAoDnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAGpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAIzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AA0W7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAkBA,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;AAoDnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAGpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAIzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AA0W7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAylKhF;AAWD,wBAAgB,gCAAgC,IAAI,IAAI,CAavD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAqHhG"}
|
package/dist/proxy/setup.d.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* - `meridian setup` — writes the plugin entry
|
|
7
7
|
* - `meridian` startup — warns if plugin is missing
|
|
8
8
|
* - `GET /health` — reports plugin status
|
|
9
|
+
* - every request — warns when an OpenCode client sends no plugin
|
|
10
|
+
* headers (see notePluginlessOpenCodeRequest)
|
|
9
11
|
*/
|
|
10
12
|
/**
|
|
11
13
|
* Thrown when an existing OpenCode config can't be parsed (even tolerantly).
|
|
@@ -32,6 +34,47 @@ export declare function findPluginPath(fromUrl: string): string;
|
|
|
32
34
|
* plugin is missing.
|
|
33
35
|
*/
|
|
34
36
|
export declare function checkPluginConfigured(configPath?: string): boolean;
|
|
37
|
+
/** Reset the warned-session memory. Used by tests. */
|
|
38
|
+
export declare function clearPluginlessWarnings(): void;
|
|
39
|
+
/**
|
|
40
|
+
* NOTE: OpenCode-specific. Warn when an OpenCode client reaches the proxy
|
|
41
|
+
* without the plugin's agent headers, once per session.
|
|
42
|
+
*
|
|
43
|
+
* This exists because the exposure it reports cannot be fixed from inside
|
|
44
|
+
* Meridian. OpenCode 1.18.11 sends `x-session-affinity` natively, so a
|
|
45
|
+
* plugin-less client is fully keyed and never reaches the fingerprint fallback
|
|
46
|
+
* — and its internal `title` / `summary` / `compaction` agents run under the
|
|
47
|
+
* SAME session id as the user's chat. One real key, two unrelated
|
|
48
|
+
* conversations. Live, both attempts of a plugin-less run returned HTTP 400
|
|
49
|
+
* `session_turn_conflict` on the user's first turn after an ~8s wait.
|
|
50
|
+
*
|
|
51
|
+
* The fix for that collision scopes the session key by agent, which it reads
|
|
52
|
+
* from the plugin's `x-opencode-agent-mode`. A client that sends none cannot be
|
|
53
|
+
* scoped, and inferring the agent from request shape was tried and reverted:
|
|
54
|
+
* "tool-less, one message" is equally the first turn of an ordinary tool-less
|
|
55
|
+
* chat, and keying that apart broke resume for it.
|
|
56
|
+
*
|
|
57
|
+
* So the remaining job is to stop the exposure being silent. The startup
|
|
58
|
+
* warning in `bin/cli.ts` does not cover it — that one is gated on an OpenCode
|
|
59
|
+
* config FILE existing, deliberately, so Meridian stays quiet for the many
|
|
60
|
+
* clients that are not OpenCode. Run the documented
|
|
61
|
+
* `ANTHROPIC_BASE_URL=… opencode` with no config file and nothing warns.
|
|
62
|
+
*
|
|
63
|
+
* Keyed on the `opencode/` User-Agent rather than the resolved adapter:
|
|
64
|
+
* `MERIDIAN_DEFAULT_AGENT` defaults to opencode, so unrelated clients land on
|
|
65
|
+
* that adapter, and telling a Pi user to configure an OpenCode plugin is worse
|
|
66
|
+
* than saying nothing. The User-Agent has no such ambiguity.
|
|
67
|
+
*
|
|
68
|
+
* Returns the message to log, or undefined when there is nothing to say.
|
|
69
|
+
* Stateful but I/O-free — the caller owns the logging.
|
|
70
|
+
*/
|
|
71
|
+
export declare function notePluginlessOpenCodeRequest(input: {
|
|
72
|
+
userAgent: string | undefined;
|
|
73
|
+
/** The plugin's `x-opencode-agent-mode` header, if it sent one. */
|
|
74
|
+
agentModeHeader: string | undefined;
|
|
75
|
+
/** Client session id — used only to warn once per conversation. */
|
|
76
|
+
sessionId: string | undefined;
|
|
77
|
+
}): string | undefined;
|
|
35
78
|
export interface SetupResult {
|
|
36
79
|
configPath: string;
|
|
37
80
|
pluginPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/proxy/setup.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/proxy/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aACnB,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAI/C;AAoBD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAW/C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtD;AAkBD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlE;AAaD,sDAAsD;AACtD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,mEAAmE;IACnE,eAAe,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,mEAAmE;IACnE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,GAAG,MAAM,GAAG,SAAS,CAkBrB;AAMD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,CAsC7E"}
|
package/dist/server.js
CHANGED
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
runObserveHook,
|
|
12
12
|
runTransformHook,
|
|
13
13
|
startProxyServer
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-21w6xm0d.js";
|
|
15
15
|
import"./cli-m0p2bc8v.js";
|
|
16
16
|
import"./cli-sry5aqdj.js";
|
|
17
17
|
import"./cli-xmweegb1.js";
|
|
18
|
-
import"./cli-
|
|
18
|
+
import"./cli-xfbhn15a.js";
|
|
19
19
|
import"./cli-vj9cv18n.js";
|
|
20
|
-
import"./cli-
|
|
20
|
+
import"./cli-pc0mtjjv.js";
|
|
21
21
|
import"./cli-khhjyk04.js";
|
|
22
22
|
import"./cli-p9swy5t3.js";
|
|
23
23
|
export {
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UnparseableConfigError,
|
|
3
3
|
checkPluginConfigured,
|
|
4
|
+
clearPluginlessWarnings,
|
|
4
5
|
findOpencodeConfigPath,
|
|
5
6
|
findPluginPath,
|
|
7
|
+
notePluginlessOpenCodeRequest,
|
|
6
8
|
runSetup
|
|
7
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-pc0mtjjv.js";
|
|
8
10
|
import"./cli-p9swy5t3.js";
|
|
9
11
|
export {
|
|
10
12
|
runSetup,
|
|
13
|
+
notePluginlessOpenCodeRequest,
|
|
11
14
|
findPluginPath,
|
|
12
15
|
findOpencodeConfigPath,
|
|
16
|
+
clearPluginlessWarnings,
|
|
13
17
|
checkPluginConfigured,
|
|
14
18
|
UnparseableConfigError
|
|
15
19
|
};
|
package/package.json
CHANGED