@rynfar/meridian 1.37.4 → 1.37.6
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 +94 -2
- package/dist/{cli-g6ndy8jh.js → cli-z5r7ptsm.js} +192 -123
- package/dist/cli.js +1 -1
- package/dist/proxy/openai.d.ts +29 -1
- package/dist/proxy/openai.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/cache.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -49,6 +49,95 @@ ANTHROPIC_API_KEY=x ANTHROPIC_BASE_URL=http://127.0.0.1:3456 opencode
|
|
|
49
49
|
|
|
50
50
|
The API key value is a placeholder — Meridian authenticates through the Claude Code SDK, not API keys. Most Anthropic-compatible tools require this field to be set, but any value works.
|
|
51
51
|
|
|
52
|
+
### NixOS / Nix Flake
|
|
53
|
+
|
|
54
|
+
Meridian provides a Nix flake for declarative installation.
|
|
55
|
+
|
|
56
|
+
**Add to your flake inputs:**
|
|
57
|
+
|
|
58
|
+
```nix
|
|
59
|
+
{
|
|
60
|
+
inputs.meridian.url = "github:rynfar/meridian";
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Install the package** (via overlay or directly):
|
|
65
|
+
|
|
66
|
+
```nix
|
|
67
|
+
# Option A: overlay
|
|
68
|
+
nixpkgs.overlays = [ meridian.overlays.default ];
|
|
69
|
+
environment.systemPackages = [ pkgs.meridian ];
|
|
70
|
+
|
|
71
|
+
# Option B: direct reference
|
|
72
|
+
environment.systemPackages = [ meridian.packages.${system}.meridian ];
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**OpenCode plugin** -- the plugin file is included at `${pkgs.meridian}/lib/meridian/plugin/meridian.ts`. Since this path lives in the Nix store, you need to make it available to OpenCode:
|
|
76
|
+
|
|
77
|
+
If you generate your OpenCode config from Nix (e.g. via Home Manager), interpolate the path directly:
|
|
78
|
+
|
|
79
|
+
```nix
|
|
80
|
+
# home-manager example
|
|
81
|
+
xdg.configFile."opencode/opencode.json".text = builtins.toJSON {
|
|
82
|
+
plugin = [ "${pkgs.meridian}/lib/meridian/plugin/meridian.ts" ];
|
|
83
|
+
};
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If you don't manage your OpenCode config through Nix, symlink the plugin to a stable path and reference that instead:
|
|
87
|
+
|
|
88
|
+
```nix
|
|
89
|
+
# configuration.nix or home-manager
|
|
90
|
+
environment.etc."meridian/plugin/meridian.ts".source =
|
|
91
|
+
"${pkgs.meridian}/lib/meridian/plugin/meridian.ts";
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Then in `~/.config/opencode/opencode.json`:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{ "plugin": ["/etc/meridian/plugin/meridian.ts"] }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> **Important:** Do not use `meridian setup` on NixOS. It writes an absolute Nix store path (e.g. `/nix/store/...-meridian-1.x.x/lib/...`) into your OpenCode config, which will break on the next `nixos-rebuild switch` or `home-manager switch` when the store path changes. Use one of the approaches above instead.
|
|
101
|
+
|
|
102
|
+
**Home Manager service** -- run Meridian as a user systemd service:
|
|
103
|
+
|
|
104
|
+
```nix
|
|
105
|
+
# flake.nix
|
|
106
|
+
{
|
|
107
|
+
inputs.meridian.url = "github:rynfar/meridian";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# home-manager config
|
|
111
|
+
{
|
|
112
|
+
imports = [ meridian.homeManagerModules.default ];
|
|
113
|
+
|
|
114
|
+
services.meridian = {
|
|
115
|
+
enable = true;
|
|
116
|
+
settings = {
|
|
117
|
+
port = 3456;
|
|
118
|
+
host = "127.0.0.1";
|
|
119
|
+
# passthrough = true;
|
|
120
|
+
# defaultAgent = "opencode";
|
|
121
|
+
# sonnetModel = "sonnet";
|
|
122
|
+
};
|
|
123
|
+
# Extra env vars not covered by settings
|
|
124
|
+
# environment = {
|
|
125
|
+
# MERIDIAN_MAX_CONCURRENT = "20";
|
|
126
|
+
# };
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The service starts automatically on login. Manage it with `systemctl --user {start,stop,restart,status} meridian`.
|
|
132
|
+
|
|
133
|
+
The plugin path is also available as `config.services.meridian.opencode.pluginPath` for use in your OpenCode config:
|
|
134
|
+
|
|
135
|
+
```nix
|
|
136
|
+
xdg.configFile."opencode/opencode.json".text = builtins.toJSON {
|
|
137
|
+
plugin = [ config.services.meridian.opencode.pluginPath ];
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
52
141
|
## Why Meridian?
|
|
53
142
|
|
|
54
143
|
The Claude Code SDK provides programmatic access to Claude. But your favorite coding tools expect an Anthropic API endpoint. Meridian bridges that gap — it runs locally, accepts standard API requests, and routes them through the SDK. Claude Code does the heavy lifting; Meridian translates the output.
|
|
@@ -60,14 +149,14 @@ The Claude Code SDK provides programmatic access to Claude. But your favorite co
|
|
|
60
149
|
## Features
|
|
61
150
|
|
|
62
151
|
- **Standard Anthropic API** — drop-in compatible with any tool that supports a custom `base_url`
|
|
63
|
-
- **OpenAI-compatible API** — `/v1/chat/completions` and `/v1/models` for tools that only speak the OpenAI protocol (Open WebUI, Continue, etc.) — no LiteLLM needed
|
|
152
|
+
- **OpenAI-compatible API** — `/v1/chat/completions` and `/v1/models` for tools that only speak the OpenAI protocol (Open WebUI, Continue, etc.) — no LiteLLM needed, including `image_url` support for data URLs
|
|
64
153
|
- **Session management** — conversations persist across requests, survive compaction and undo, resume after proxy restarts
|
|
65
154
|
- **Streaming** — full SSE streaming with MCP tool filtering
|
|
66
155
|
- **Concurrent sessions** — run parent and subagent requests in parallel
|
|
67
156
|
- **Subagent model selection** — primary agents get 1M context; subagents get 200k, preserving rate-limit budget
|
|
68
157
|
- **Auto token refresh** — expired OAuth tokens are refreshed automatically; requests continue without interruption
|
|
69
158
|
- **Passthrough mode** — forward tool calls to the client instead of executing internally
|
|
70
|
-
- **Multimodal** — images, documents,
|
|
159
|
+
- **Multimodal** — images, documents, file attachments, and multimodal tool results pass through to Claude
|
|
71
160
|
- **Multi-profile** — switch between Claude accounts instantly, no restart needed
|
|
72
161
|
- **Telemetry dashboard** — real-time performance metrics at `/telemetry`, including token usage and prompt cache efficiency ([`MONITORING.md`](MONITORING.md))
|
|
73
162
|
- **Telemetry persistence** — opt-in SQLite storage for telemetry data that survives proxy restarts, with configurable retention
|
|
@@ -320,6 +409,9 @@ Meridian speaks the OpenAI protocol natively — no LiteLLM or translation proxy
|
|
|
320
409
|
|
|
321
410
|
**`POST /v1/chat/completions`** — accepts OpenAI chat format, returns OpenAI completion format (streaming and non-streaming)
|
|
322
411
|
|
|
412
|
+
- `image_url` parts are supported when provided as **data URLs** (`data:image/...;base64,...`)
|
|
413
|
+
- multimodal tool flows where a tool returns `tool_result.content = [text, image]` are preserved through the structured multimodal path instead of being flattened to text
|
|
414
|
+
|
|
323
415
|
**`GET /v1/models`** — returns available Claude models in OpenAI format
|
|
324
416
|
|
|
325
417
|
Point any OpenAI-compatible tool at `http://127.0.0.1:3456` with any API key value:
|
|
@@ -8904,7 +8904,67 @@ function isClosedControllerError(error) {
|
|
|
8904
8904
|
function extractOpenAiContent(content) {
|
|
8905
8905
|
if (typeof content === "string")
|
|
8906
8906
|
return content;
|
|
8907
|
-
return content.
|
|
8907
|
+
return content.map((p) => {
|
|
8908
|
+
if (p.type === "text" && typeof p.text === "string")
|
|
8909
|
+
return p.text;
|
|
8910
|
+
if (p.type === "image_url")
|
|
8911
|
+
return "[Image attached]";
|
|
8912
|
+
return "";
|
|
8913
|
+
}).filter(Boolean).join("");
|
|
8914
|
+
}
|
|
8915
|
+
function parseDataUrlImage(url) {
|
|
8916
|
+
const match2 = /^data:(image\/[a-zA-Z0-9.+-]+);base64,(.+)$/s.exec(url);
|
|
8917
|
+
if (!match2)
|
|
8918
|
+
return null;
|
|
8919
|
+
const mediaType = match2[1];
|
|
8920
|
+
const data = match2[2];
|
|
8921
|
+
if (!mediaType || !data)
|
|
8922
|
+
return null;
|
|
8923
|
+
return {
|
|
8924
|
+
type: "image",
|
|
8925
|
+
source: {
|
|
8926
|
+
type: "base64",
|
|
8927
|
+
media_type: mediaType,
|
|
8928
|
+
data
|
|
8929
|
+
}
|
|
8930
|
+
};
|
|
8931
|
+
}
|
|
8932
|
+
function translateOpenAiContentToAnthropic(content) {
|
|
8933
|
+
if (typeof content === "string")
|
|
8934
|
+
return content;
|
|
8935
|
+
const parts = [];
|
|
8936
|
+
for (const part of content) {
|
|
8937
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
8938
|
+
parts.push({ type: "text", text: part.text });
|
|
8939
|
+
continue;
|
|
8940
|
+
}
|
|
8941
|
+
if (part.type === "image_url") {
|
|
8942
|
+
const url = part.image_url?.url;
|
|
8943
|
+
if (typeof url === "string") {
|
|
8944
|
+
const parsed = parseDataUrlImage(url);
|
|
8945
|
+
if (parsed) {
|
|
8946
|
+
parts.push(parsed);
|
|
8947
|
+
continue;
|
|
8948
|
+
}
|
|
8949
|
+
}
|
|
8950
|
+
parts.push({ type: "text", text: "[Unsupported image_url omitted: only data URLs are currently supported]" });
|
|
8951
|
+
}
|
|
8952
|
+
}
|
|
8953
|
+
if (parts.length === 1 && parts[0]?.type === "text") {
|
|
8954
|
+
return parts[0].text;
|
|
8955
|
+
}
|
|
8956
|
+
return parts;
|
|
8957
|
+
}
|
|
8958
|
+
function summarizeAnthropicContent(content) {
|
|
8959
|
+
if (typeof content === "string")
|
|
8960
|
+
return content;
|
|
8961
|
+
return content.map((part) => {
|
|
8962
|
+
if (part.type === "text")
|
|
8963
|
+
return part.text;
|
|
8964
|
+
if (part.type === "image")
|
|
8965
|
+
return "[Image attached]";
|
|
8966
|
+
return "";
|
|
8967
|
+
}).filter(Boolean).join("");
|
|
8908
8968
|
}
|
|
8909
8969
|
function translateOpenAiToAnthropic(body) {
|
|
8910
8970
|
const messages = body.messages ?? [];
|
|
@@ -8920,7 +8980,7 @@ function translateOpenAiToAnthropic(body) {
|
|
|
8920
8980
|
} else {
|
|
8921
8981
|
turns.push({
|
|
8922
8982
|
role: msg.role === "assistant" ? "assistant" : "user",
|
|
8923
|
-
content:
|
|
8983
|
+
content: translateOpenAiContentToAnthropic(msg.content ?? "")
|
|
8924
8984
|
});
|
|
8925
8985
|
}
|
|
8926
8986
|
}
|
|
@@ -8928,7 +8988,7 @@ function translateOpenAiToAnthropic(body) {
|
|
|
8928
8988
|
`);
|
|
8929
8989
|
let messagesToSend = turns;
|
|
8930
8990
|
if (turns.length > 1) {
|
|
8931
|
-
const history = turns.slice(0, -1).map((m) => `${m.role}: ${m.content}`).join(`
|
|
8991
|
+
const history = turns.slice(0, -1).map((m) => `${m.role}: ${summarizeAnthropicContent(m.content)}`).join(`
|
|
8932
8992
|
`);
|
|
8933
8993
|
const historyBlock = `<conversation_history>
|
|
8934
8994
|
${history}
|
|
@@ -9407,7 +9467,7 @@ function fuzzyMatchAgentName(input, validAgents) {
|
|
|
9407
9467
|
var openCodeAdapter = {
|
|
9408
9468
|
name: "opencode",
|
|
9409
9469
|
getSessionId(c) {
|
|
9410
|
-
return c.req.header("x-opencode-session");
|
|
9470
|
+
return c.req.header("x-opencode-session") ?? c.req.header("x-session-affinity");
|
|
9411
9471
|
},
|
|
9412
9472
|
extractWorkingDirectory(body) {
|
|
9413
9473
|
return extractClientCwd(body);
|
|
@@ -16384,7 +16444,7 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
|
|
|
16384
16444
|
if (sessionId)
|
|
16385
16445
|
sessionCache.set(sessionId, state);
|
|
16386
16446
|
const fp = getConversationFingerprint(messages, workingDirectory);
|
|
16387
|
-
if (fp)
|
|
16447
|
+
if (fp && !sessionId)
|
|
16388
16448
|
fingerprintCache.set(fp, state);
|
|
16389
16449
|
const key = sessionId || fp;
|
|
16390
16450
|
if (key) {
|
|
@@ -16395,41 +16455,114 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
|
|
|
16395
16455
|
// src/proxy/server.ts
|
|
16396
16456
|
var exec3 = promisify3(execCallback2);
|
|
16397
16457
|
var claudeExecutable = "";
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16458
|
+
var MULTIMODAL_TYPES = new Set(["image", "document", "file"]);
|
|
16459
|
+
function hasMultimodalContent(content) {
|
|
16460
|
+
if (!Array.isArray(content))
|
|
16461
|
+
return false;
|
|
16462
|
+
return content.some((block) => {
|
|
16463
|
+
if (!block || typeof block !== "object")
|
|
16464
|
+
return false;
|
|
16465
|
+
if (MULTIMODAL_TYPES.has(block.type))
|
|
16466
|
+
return true;
|
|
16467
|
+
if (block.type === "tool_result")
|
|
16468
|
+
return hasMultimodalContent(block.content);
|
|
16469
|
+
return false;
|
|
16470
|
+
});
|
|
16471
|
+
}
|
|
16472
|
+
function stripCacheControlDeep(content) {
|
|
16473
|
+
if (!Array.isArray(content))
|
|
16474
|
+
return content;
|
|
16475
|
+
return content.map((block) => {
|
|
16476
|
+
if (!block || typeof block !== "object")
|
|
16477
|
+
return block;
|
|
16478
|
+
const { cache_control, ...rest } = block;
|
|
16479
|
+
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
16480
|
+
return {
|
|
16481
|
+
...rest,
|
|
16482
|
+
content: stripCacheControlDeep(block.content)
|
|
16483
|
+
};
|
|
16484
|
+
}
|
|
16485
|
+
return rest;
|
|
16486
|
+
});
|
|
16487
|
+
}
|
|
16488
|
+
function normalizeStructuredUserContent(content) {
|
|
16489
|
+
if (!Array.isArray(content))
|
|
16490
|
+
return content;
|
|
16491
|
+
const normalized = [];
|
|
16492
|
+
for (const block of content) {
|
|
16493
|
+
if (!block || typeof block !== "object")
|
|
16494
|
+
continue;
|
|
16495
|
+
if (block.type === "tool_result" && Array.isArray(block.content) && hasMultimodalContent(block.content)) {
|
|
16496
|
+
normalized.push(...normalizeStructuredUserContent(block.content));
|
|
16497
|
+
continue;
|
|
16498
|
+
}
|
|
16499
|
+
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
16500
|
+
normalized.push({
|
|
16501
|
+
...block,
|
|
16502
|
+
content: normalizeStructuredUserContent(block.content)
|
|
16503
|
+
});
|
|
16504
|
+
continue;
|
|
16505
|
+
}
|
|
16506
|
+
normalized.push(block);
|
|
16507
|
+
}
|
|
16508
|
+
return normalized;
|
|
16509
|
+
}
|
|
16510
|
+
function flattenAssistantContent(content) {
|
|
16511
|
+
if (typeof content === "string")
|
|
16512
|
+
return content;
|
|
16513
|
+
if (!Array.isArray(content))
|
|
16514
|
+
return String(content ?? "");
|
|
16515
|
+
return content.map((b) => b?.type === "text" && b.text ? b.text : "").filter(Boolean).join(`
|
|
16516
|
+
`);
|
|
16517
|
+
}
|
|
16518
|
+
function flattenUserContent(content, sanitizeOpts = {}) {
|
|
16519
|
+
if (typeof content === "string")
|
|
16520
|
+
return sanitizeTextContent(content, sanitizeOpts);
|
|
16521
|
+
if (!Array.isArray(content))
|
|
16522
|
+
return String(content ?? "");
|
|
16523
|
+
return content.map((b) => {
|
|
16524
|
+
if (b?.type === "text" && b.text)
|
|
16525
|
+
return sanitizeTextContent(b.text, sanitizeOpts);
|
|
16526
|
+
if (b?.type === "tool_result") {
|
|
16527
|
+
const inner = b.content;
|
|
16528
|
+
if (typeof inner === "string")
|
|
16529
|
+
return inner;
|
|
16530
|
+
if (Array.isArray(inner)) {
|
|
16531
|
+
return inner.map((ib) => ib?.type === "text" && ib.text ? ib.text : "").filter(Boolean).join(`
|
|
16532
|
+
`);
|
|
16533
|
+
}
|
|
16534
|
+
return "";
|
|
16535
|
+
}
|
|
16536
|
+
if (b?.type === "image")
|
|
16537
|
+
return "[Image attached]";
|
|
16538
|
+
if (b?.type === "document")
|
|
16539
|
+
return "[Document attached]";
|
|
16540
|
+
if (b?.type === "file")
|
|
16541
|
+
return "[File attached]";
|
|
16542
|
+
return "";
|
|
16543
|
+
}).filter(Boolean).join(`
|
|
16544
|
+
`);
|
|
16545
|
+
}
|
|
16546
|
+
function buildFreshPrompt(messages, sanitizeOpts = {}) {
|
|
16547
|
+
const hasMultimodal = messages.some((m) => hasMultimodalContent(m.content));
|
|
16401
16548
|
if (hasMultimodal) {
|
|
16402
16549
|
const structured = [];
|
|
16403
16550
|
for (const m of messages) {
|
|
16404
16551
|
if (m.role === "user") {
|
|
16405
16552
|
structured.push({
|
|
16406
16553
|
type: "user",
|
|
16407
|
-
message: { role: "user", content:
|
|
16554
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
16408
16555
|
parent_tool_use_id: null
|
|
16409
16556
|
});
|
|
16410
16557
|
} else {
|
|
16411
|
-
|
|
16412
|
-
if (
|
|
16413
|
-
|
|
16414
|
-
|
|
16415
|
-
|
|
16416
|
-
|
|
16417
|
-
|
|
16418
|
-
if (b.type === "tool_use")
|
|
16419
|
-
return `[Tool Use: ${b.name}(${JSON.stringify(b.input)})]`;
|
|
16420
|
-
if (b.type === "tool_result")
|
|
16421
|
-
return `[Tool Result: ${typeof b.content === "string" ? b.content : JSON.stringify(b.content)}]`;
|
|
16422
|
-
return "";
|
|
16423
|
-
}).filter(Boolean).join(`
|
|
16424
|
-
`);
|
|
16425
|
-
} else {
|
|
16426
|
-
text = `[Assistant: ${String(m.content)}]`;
|
|
16558
|
+
const assistantText = flattenAssistantContent(m.content);
|
|
16559
|
+
if (assistantText) {
|
|
16560
|
+
structured.push({
|
|
16561
|
+
type: "user",
|
|
16562
|
+
message: { role: "user", content: `[Assistant: ${assistantText}]` },
|
|
16563
|
+
parent_tool_use_id: null
|
|
16564
|
+
});
|
|
16427
16565
|
}
|
|
16428
|
-
structured.push({
|
|
16429
|
-
type: "user",
|
|
16430
|
-
message: { role: "user", content: text },
|
|
16431
|
-
parent_tool_use_id: null
|
|
16432
|
-
});
|
|
16433
16566
|
}
|
|
16434
16567
|
}
|
|
16435
16568
|
return async function* () {
|
|
@@ -16439,31 +16572,9 @@ function buildFreshPrompt(messages, stripCacheControl, sanitizeOpts = {}) {
|
|
|
16439
16572
|
}
|
|
16440
16573
|
return messages.map((m) => {
|
|
16441
16574
|
const role = m.role === "assistant" ? "Assistant" : "Human";
|
|
16442
|
-
|
|
16443
|
-
|
|
16444
|
-
|
|
16445
|
-
} else if (Array.isArray(m.content)) {
|
|
16446
|
-
content = m.content.map((block) => {
|
|
16447
|
-
if (block.type === "text" && block.text)
|
|
16448
|
-
return sanitizeTextContent(block.text, sanitizeOpts);
|
|
16449
|
-
if (block.type === "tool_use")
|
|
16450
|
-
return `[Tool Use: ${block.name}(${JSON.stringify(block.input)})]`;
|
|
16451
|
-
if (block.type === "tool_result")
|
|
16452
|
-
return `[Tool Result for ${block.tool_use_id}: ${typeof block.content === "string" ? block.content : JSON.stringify(block.content)}]`;
|
|
16453
|
-
if (block.type === "image")
|
|
16454
|
-
return "[Image attached]";
|
|
16455
|
-
if (block.type === "document")
|
|
16456
|
-
return "[Document attached]";
|
|
16457
|
-
if (block.type === "file")
|
|
16458
|
-
return "[File attached]";
|
|
16459
|
-
return "";
|
|
16460
|
-
}).filter(Boolean).join(`
|
|
16461
|
-
`);
|
|
16462
|
-
} else {
|
|
16463
|
-
content = String(m.content);
|
|
16464
|
-
}
|
|
16465
|
-
return `${role}: ${content}`;
|
|
16466
|
-
}).join(`
|
|
16575
|
+
const content = m.role === "assistant" ? flattenAssistantContent(m.content) : flattenUserContent(m.content, sanitizeOpts);
|
|
16576
|
+
return content ? `${role}: ${content}` : "";
|
|
16577
|
+
}).filter(Boolean).join(`
|
|
16467
16578
|
|
|
16468
16579
|
`) || "";
|
|
16469
16580
|
}
|
|
@@ -16567,17 +16678,7 @@ function createProxyServer(config = {}) {
|
|
|
16567
16678
|
return withClaudeLogContext({ requestId: requestMeta.requestId, endpoint: requestMeta.endpoint }, async () => {
|
|
16568
16679
|
const adapter = detectAdapter(c);
|
|
16569
16680
|
try {
|
|
16570
|
-
let
|
|
16571
|
-
if (!Array.isArray(content))
|
|
16572
|
-
return content;
|
|
16573
|
-
return content.map((block) => {
|
|
16574
|
-
if (block.cache_control) {
|
|
16575
|
-
const { cache_control, ...rest } = block;
|
|
16576
|
-
return rest;
|
|
16577
|
-
}
|
|
16578
|
-
return block;
|
|
16579
|
-
});
|
|
16580
|
-
}, makePrompt = function() {
|
|
16681
|
+
let makePrompt = function() {
|
|
16581
16682
|
if (structuredMessages) {
|
|
16582
16683
|
const msgs = structuredMessages;
|
|
16583
16684
|
return async function* () {
|
|
@@ -16594,6 +16695,7 @@ function createProxyServer(config = {}) {
|
|
|
16594
16695
|
const profile = resolveProfile(finalConfig.profiles, finalConfig.defaultProfile, c.req.header("x-meridian-profile") || undefined);
|
|
16595
16696
|
const authStatus = await getClaudeAuthStatusAsync(profile.id !== "default" ? profile.id : undefined, Object.keys(profile.env).length > 0 ? profile.env : undefined);
|
|
16596
16697
|
const agentMode = c.req.header("x-opencode-agent-mode") ?? null;
|
|
16698
|
+
const requestSource = c.req.header("x-meridian-source")?.slice(0, 64) || undefined;
|
|
16597
16699
|
let model = mapModelToClaudeModel(body.model || "sonnet", authStatus?.subscriptionType, agentMode);
|
|
16598
16700
|
const adapterStreamPref = adapter.prefersStreaming?.(body);
|
|
16599
16701
|
const stream2 = adapterStreamPref !== undefined ? adapterStreamPref : body.stream ?? false;
|
|
@@ -16653,7 +16755,11 @@ function createProxyServer(config = {}) {
|
|
|
16653
16755
|
const agentSessionId = adapter.getSessionId(c);
|
|
16654
16756
|
const profileSessionId = profile.id !== "default" && agentSessionId ? `${profile.id}:${agentSessionId}` : agentSessionId;
|
|
16655
16757
|
const profileScopedCwd = profile.id !== "default" ? `${workingDirectory}::profile=${profile.id}` : workingDirectory;
|
|
16656
|
-
const
|
|
16758
|
+
const isIndependentSession = requestSource?.startsWith("fork-") || requestSource?.startsWith("subagent-") || false;
|
|
16759
|
+
let lineageResult = isIndependentSession ? { type: "diverged" } : lookupSession(profileSessionId, body.messages || [], profileScopedCwd);
|
|
16760
|
+
if (lineageResult.type === "undo" && adapter.name === "opencode" && !agentSessionId) {
|
|
16761
|
+
lineageResult = { type: "diverged" };
|
|
16762
|
+
}
|
|
16657
16763
|
const isResume = lineageResult.type === "continuation" || lineageResult.type === "compaction";
|
|
16658
16764
|
const isUndo = lineageResult.type === "undo";
|
|
16659
16765
|
const cachedSession = lineageResult.type !== "diverged" ? lineageResult.session : undefined;
|
|
@@ -16666,10 +16772,10 @@ function createProxyServer(config = {}) {
|
|
|
16666
16772
|
const lineageType = lineageResult.type === "diverged" && !cachedSession ? "new" : lineageResult.type;
|
|
16667
16773
|
const msgCount = Array.isArray(body.messages) ? body.messages.length : 0;
|
|
16668
16774
|
const toolCount = body.tools?.length ?? 0;
|
|
16669
|
-
const requestLogLine = `${requestMeta.requestId} adapter=${adapter.name} model=${model} stream=${stream2} tools=${toolCount} lineage=${lineageType} session=${resumeSessionId?.slice(0, 8) || "new"}${isUndo && undoRollbackUuid ? ` rollback=${undoRollbackUuid.slice(0, 8)}` : ""}${agentMode ? ` agent=${agentMode}` : ""} active=${activeSessions}/${MAX_CONCURRENT_SESSIONS} msgCount=${msgCount}`;
|
|
16775
|
+
const requestLogLine = `${requestMeta.requestId} adapter=${adapter.name}${requestSource ? ` source=${requestSource}` : ""} model=${model} stream=${stream2} tools=${toolCount} lineage=${lineageType} session=${resumeSessionId?.slice(0, 8) || "new"}${isUndo && undoRollbackUuid ? ` rollback=${undoRollbackUuid.slice(0, 8)}` : ""}${agentMode ? ` agent=${agentMode}` : ""} active=${activeSessions}/${MAX_CONCURRENT_SESSIONS} msgCount=${msgCount}`;
|
|
16670
16776
|
console.error(`[PROXY] ${requestLogLine} msgs=${msgSummary}`);
|
|
16671
16777
|
diagnosticLog2.session(`${requestLogLine}`, requestMeta.requestId);
|
|
16672
|
-
if (lineageResult.type === "diverged" && profileSessionId) {
|
|
16778
|
+
if (lineageResult.type === "diverged" && profileSessionId && !isIndependentSession) {
|
|
16673
16779
|
const recovery = lookupSessionRecovery(profileSessionId);
|
|
16674
16780
|
if (recovery) {
|
|
16675
16781
|
const prevId = recovery.previousClaudeSessionId || recovery.claudeSessionId;
|
|
@@ -16712,8 +16818,7 @@ function createProxyServer(config = {}) {
|
|
|
16712
16818
|
} else {
|
|
16713
16819
|
messagesToConvert = allMessages;
|
|
16714
16820
|
}
|
|
16715
|
-
const
|
|
16716
|
-
const hasMultimodal = messagesToConvert?.some((m) => Array.isArray(m.content) && m.content.some((b) => MULTIMODAL_TYPES.has(b.type)));
|
|
16821
|
+
const hasMultimodal = messagesToConvert?.some((m) => hasMultimodalContent(m.content));
|
|
16717
16822
|
let structuredMessages;
|
|
16718
16823
|
let textPrompt;
|
|
16719
16824
|
if (hasMultimodal) {
|
|
@@ -16723,7 +16828,7 @@ function createProxyServer(config = {}) {
|
|
|
16723
16828
|
if (m.role === "user") {
|
|
16724
16829
|
structuredMessages.push({
|
|
16725
16830
|
type: "user",
|
|
16726
|
-
message: { role: "user", content:
|
|
16831
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
16727
16832
|
parent_tool_use_id: null
|
|
16728
16833
|
});
|
|
16729
16834
|
}
|
|
@@ -16733,63 +16838,27 @@ function createProxyServer(config = {}) {
|
|
|
16733
16838
|
if (m.role === "user") {
|
|
16734
16839
|
structuredMessages.push({
|
|
16735
16840
|
type: "user",
|
|
16736
|
-
message: { role: "user", content:
|
|
16841
|
+
message: { role: "user", content: normalizeStructuredUserContent(stripCacheControlDeep(m.content)) },
|
|
16737
16842
|
parent_tool_use_id: null
|
|
16738
16843
|
});
|
|
16739
16844
|
} else {
|
|
16740
|
-
|
|
16741
|
-
if (
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
if (b.type === "tool_use")
|
|
16748
|
-
return `[Tool Use: ${b.name}(${JSON.stringify(b.input)})]`;
|
|
16749
|
-
if (b.type === "tool_result")
|
|
16750
|
-
return `[Tool Result: ${typeof b.content === "string" ? b.content : JSON.stringify(b.content)}]`;
|
|
16751
|
-
return "";
|
|
16752
|
-
}).filter(Boolean).join(`
|
|
16753
|
-
`);
|
|
16754
|
-
} else {
|
|
16755
|
-
text = `[Assistant: ${String(m.content)}]`;
|
|
16845
|
+
const assistantText = flattenAssistantContent(m.content);
|
|
16846
|
+
if (assistantText) {
|
|
16847
|
+
structuredMessages.push({
|
|
16848
|
+
type: "user",
|
|
16849
|
+
message: { role: "user", content: `[Assistant: ${assistantText}]` },
|
|
16850
|
+
parent_tool_use_id: null
|
|
16851
|
+
});
|
|
16756
16852
|
}
|
|
16757
|
-
structuredMessages.push({
|
|
16758
|
-
type: "user",
|
|
16759
|
-
message: { role: "user", content: text },
|
|
16760
|
-
parent_tool_use_id: null
|
|
16761
|
-
});
|
|
16762
16853
|
}
|
|
16763
16854
|
}
|
|
16764
16855
|
}
|
|
16765
16856
|
} else {
|
|
16766
16857
|
textPrompt = messagesToConvert?.map((m) => {
|
|
16767
16858
|
const role = m.role === "assistant" ? "Assistant" : "Human";
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
} else if (Array.isArray(m.content)) {
|
|
16772
|
-
content = m.content.map((block) => {
|
|
16773
|
-
if (block.type === "text" && block.text)
|
|
16774
|
-
return sanitizeTextContent(block.text, sanitizeOpts);
|
|
16775
|
-
if (block.type === "tool_use")
|
|
16776
|
-
return `[Tool Use: ${block.name}(${JSON.stringify(block.input)})]`;
|
|
16777
|
-
if (block.type === "tool_result")
|
|
16778
|
-
return `[Tool Result for ${block.tool_use_id}: ${typeof block.content === "string" ? block.content : JSON.stringify(block.content)}]`;
|
|
16779
|
-
if (block.type === "image")
|
|
16780
|
-
return "[Image attached]";
|
|
16781
|
-
if (block.type === "document")
|
|
16782
|
-
return "[Document attached]";
|
|
16783
|
-
if (block.type === "file")
|
|
16784
|
-
return "[File attached]";
|
|
16785
|
-
return "";
|
|
16786
|
-
}).filter(Boolean).join(`
|
|
16787
|
-
`);
|
|
16788
|
-
} else {
|
|
16789
|
-
content = String(m.content);
|
|
16790
|
-
}
|
|
16791
|
-
return `${role}: ${content}`;
|
|
16792
|
-
}).join(`
|
|
16859
|
+
const content = m.role === "assistant" ? flattenAssistantContent(m.content) : flattenUserContent(m.content, sanitizeOpts);
|
|
16860
|
+
return content ? `${role}: ${content}` : "";
|
|
16861
|
+
}).filter(Boolean).join(`
|
|
16793
16862
|
|
|
16794
16863
|
`) || "";
|
|
16795
16864
|
}
|
|
@@ -16943,7 +17012,7 @@ function createProxyServer(config = {}) {
|
|
|
16943
17012
|
for (let i = 0;i < allMessages.length; i++)
|
|
16944
17013
|
sdkUuidMap.push(null);
|
|
16945
17014
|
yield* query(buildQueryOptions({
|
|
16946
|
-
prompt: buildFreshPrompt(allMessages,
|
|
17015
|
+
prompt: buildFreshPrompt(allMessages, sanitizeOpts),
|
|
16947
17016
|
model,
|
|
16948
17017
|
workingDirectory,
|
|
16949
17018
|
systemContext,
|
|
@@ -17186,7 +17255,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17186
17255
|
cacheCreationInputTokens: lastUsage?.cache_creation_input_tokens,
|
|
17187
17256
|
cacheHitRate: computeCacheHitRate(lastUsage)
|
|
17188
17257
|
});
|
|
17189
|
-
if (currentSessionId) {
|
|
17258
|
+
if (currentSessionId && !isIndependentSession) {
|
|
17190
17259
|
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage);
|
|
17191
17260
|
}
|
|
17192
17261
|
const responseSessionId = currentSessionId || resumeSessionId || `session_${Date.now()}`;
|
|
@@ -17312,7 +17381,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
17312
17381
|
for (let i = 0;i < allMessages.length; i++)
|
|
17313
17382
|
sdkUuidMap.push(null);
|
|
17314
17383
|
yield* query(buildQueryOptions({
|
|
17315
|
-
prompt: buildFreshPrompt(allMessages,
|
|
17384
|
+
prompt: buildFreshPrompt(allMessages, sanitizeOpts),
|
|
17316
17385
|
model,
|
|
17317
17386
|
workingDirectory,
|
|
17318
17387
|
systemContext,
|
|
@@ -17570,7 +17639,7 @@ data: ${JSON.stringify({ type: "message_stop" })}
|
|
|
17570
17639
|
const allNames = [...sessionDiscoveredTools.get(sessId)];
|
|
17571
17640
|
console.error(`[PROXY] ${requestMeta.requestId} discovered=${discoveredTools.size} (${newNames}) session_total=${allNames.length}`);
|
|
17572
17641
|
}
|
|
17573
|
-
if (currentSessionId) {
|
|
17642
|
+
if (currentSessionId && !isIndependentSession) {
|
|
17574
17643
|
storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage);
|
|
17575
17644
|
}
|
|
17576
17645
|
if (!streamClosed) {
|
package/dist/cli.js
CHANGED
package/dist/proxy/openai.d.ts
CHANGED
|
@@ -16,9 +16,22 @@
|
|
|
16
16
|
* and don't benefit from Meridian's session resumption.
|
|
17
17
|
*/
|
|
18
18
|
export type OpenAiRole = "system" | "user" | "assistant";
|
|
19
|
+
export interface OpenAiTextPart {
|
|
20
|
+
type: "text";
|
|
21
|
+
text?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface OpenAiImageUrlPart {
|
|
24
|
+
type: "image_url";
|
|
25
|
+
image_url?: {
|
|
26
|
+
url?: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
19
29
|
export interface OpenAiContentPart {
|
|
20
30
|
type: string;
|
|
21
31
|
text?: string;
|
|
32
|
+
image_url?: {
|
|
33
|
+
url?: string;
|
|
34
|
+
};
|
|
22
35
|
}
|
|
23
36
|
export interface OpenAiMessage {
|
|
24
37
|
role: OpenAiRole;
|
|
@@ -33,9 +46,22 @@ export interface OpenAiChatRequest {
|
|
|
33
46
|
temperature?: number;
|
|
34
47
|
top_p?: number;
|
|
35
48
|
}
|
|
49
|
+
export interface AnthropicTextBlock {
|
|
50
|
+
type: "text";
|
|
51
|
+
text: string;
|
|
52
|
+
}
|
|
53
|
+
export interface AnthropicImageBlock {
|
|
54
|
+
type: "image";
|
|
55
|
+
source: {
|
|
56
|
+
type: "base64";
|
|
57
|
+
media_type: string;
|
|
58
|
+
data: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export type AnthropicInputContentBlock = AnthropicTextBlock | AnthropicImageBlock;
|
|
36
62
|
export interface AnthropicMessage {
|
|
37
63
|
role: "user" | "assistant";
|
|
38
|
-
content: string;
|
|
64
|
+
content: string | AnthropicInputContentBlock[];
|
|
39
65
|
}
|
|
40
66
|
export interface AnthropicRequestBody {
|
|
41
67
|
model: string;
|
|
@@ -103,6 +129,8 @@ export interface OpenAiModel {
|
|
|
103
129
|
/**
|
|
104
130
|
* Normalise an OpenAI message content field to a plain string.
|
|
105
131
|
* Handles both string content and structured content arrays.
|
|
132
|
+
* Non-text blocks are summarized so history packing does not silently erase
|
|
133
|
+
* multimodal context.
|
|
106
134
|
*/
|
|
107
135
|
export declare function extractOpenAiContent(content: string | OpenAiContentPart[]): string;
|
|
108
136
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/proxy/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAA;AAExD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/proxy/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AA0BvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EAEnB,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;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AA0BvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EAEnB,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;AA8N7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAy5DhF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiEhG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,WAAW,CAAA;AAMlB,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAqCD;kGACkG;AAClG,wBAAgB,iBAAiB,SAYhC;AAED;iFACiF;AACjF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAC/C,IAAI,CAoBN;AAUD;;uDAEuD;AACvD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,gBAAgB,CAAC,EAAE,MAAM,GACxB,aAAa,CAuDf;AAED;;uFAEuF;AACvF,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CA2BtF;AAED;;;yFAGyF;AACzF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,EACnD,eAAe,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,EACzB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EACtC,YAAY,CAAC,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,WAAW,CAAA;AAMlB,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAqCD;kGACkG;AAClG,wBAAgB,iBAAiB,SAYhC;AAED;iFACiF;AACjF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAC/C,IAAI,CAoBN;AAUD;;uDAEuD;AACvD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,gBAAgB,CAAC,EAAE,MAAM,GACxB,aAAa,CAuDf;AAED;;uFAEuF;AACvF,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CA2BtF;AAED;;;yFAGyF;AACzF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,EACnD,eAAe,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,EACzB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,EACtC,YAAY,CAAC,EAAE,UAAU,QAoC1B"}
|
package/dist/server.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynfar/meridian",
|
|
3
|
-
"version": "1.37.
|
|
3
|
+
"version": "1.37.6",
|
|
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",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"postbuild": "node --check dist/cli.js && node --check dist/server.js && test -f dist/proxy/server.d.ts",
|
|
26
26
|
"prepublishOnly": "bun run build",
|
|
27
27
|
"test": "bun test --path-ignore-patterns '**/*session-store*' --path-ignore-patterns '**/*proxy-async-ops*' --path-ignore-patterns '**/*proxy-extra-usage-fallback*' --path-ignore-patterns '**/*models-auth-status*' --path-ignore-patterns '**/*proxy-context-usage-store*' --path-ignore-patterns '**/*proxy-passthrough-thinking*' --path-ignore-patterns '**/*profile-switch-integration*' --path-ignore-patterns '**/*session-recovery*' --path-ignore-patterns '**/*models.test*' --path-ignore-patterns '**/*proxy-health-degraded*' --path-ignore-patterns '**/*proxy-subagent-model-selection*' && bun test src/__tests__/profile-switch-integration.test.ts && bun test src/__tests__/proxy-extra-usage-fallback.test.ts && bun test src/__tests__/proxy-async-ops.test.ts && bun test src/__tests__/proxy-session-store.test.ts && bun test src/__tests__/session-store-pruning.test.ts && bun test src/__tests__/proxy-session-store-locking.test.ts && bun test src/__tests__/proxy-context-usage-store.test.ts && bun test src/__tests__/models-auth-status.test.ts && bun test src/__tests__/proxy-passthrough-thinking.test.ts && bun test src/__tests__/proxy-session-recovery.test.ts && bun test src/__tests__/models.test.ts && bun test src/__tests__/proxy-health-degraded.test.ts && bun test src/__tests__/proxy-subagent-model-selection.test.ts",
|
|
28
|
+
"nix:lock": "bun2nix -o bun.nix",
|
|
28
29
|
"typecheck": "tsc --noEmit",
|
|
29
30
|
"proxy:direct": "bun run ./bin/cli.ts"
|
|
30
31
|
},
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"@hono/node-server": "^1.19.11",
|
|
37
38
|
"@types/bun": "^1.3.11",
|
|
38
39
|
"@types/node": "^22.0.0",
|
|
40
|
+
"bun2nix": "^2.0.8",
|
|
39
41
|
"glob": "^13.0.0",
|
|
40
42
|
"hono": "^4.11.4",
|
|
41
43
|
"typescript": "^5.8.2"
|