@rynfar/meridian 1.31.1 → 1.34.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 +43 -2
- package/dist/{cli-7hathpbb.js → cli-1qv75efv.js} +110 -27
- package/dist/cli.js +1 -1
- package/dist/proxy/adapters/detect.d.ts.map +1 -1
- package/dist/proxy/adapters/forgecode.d.ts +28 -0
- package/dist/proxy/adapters/forgecode.d.ts.map +1 -0
- package/dist/proxy/openai.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/tokenUsage.d.ts +47 -0
- package/dist/proxy/tokenUsage.d.ts.map +1 -0
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
Meridian bridges the Claude Code SDK to the standard Anthropic API. No OAuth interception. No binary patches. No hacks. Just pure, documented SDK calls. Any tool that speaks the Anthropic or OpenAI protocol — OpenCode, Crush, Cline, Aider, Pi, Droid, Open WebUI — connects to Meridian and gets Claude, with session management, streaming, and prompt caching handled natively by the SDK.
|
|
15
|
+
Meridian bridges the Claude Code SDK to the standard Anthropic API. No OAuth interception. No binary patches. No hacks. Just pure, documented SDK calls. Any tool that speaks the Anthropic or OpenAI protocol — OpenCode, ForgeCode, Crush, Cline, Aider, Pi, Droid, Open WebUI — connects to Meridian and gets Claude, with session management, streaming, and prompt caching handled natively by the SDK.
|
|
16
16
|
|
|
17
17
|
> [!NOTE]
|
|
18
18
|
> ### How Meridian works with Anthropic
|
|
@@ -273,6 +273,45 @@ Point any OpenAI-compatible tool at `http://127.0.0.1:3456` with any API key val
|
|
|
273
273
|
|
|
274
274
|
> **Note:** Multi-turn conversations work by packing prior turns into the system prompt. Each request is a fresh SDK session — OpenAI clients replay full history themselves and don't use Meridian's session resumption.
|
|
275
275
|
|
|
276
|
+
### ForgeCode
|
|
277
|
+
|
|
278
|
+
Add a custom provider to `~/forge/.forge.toml`:
|
|
279
|
+
|
|
280
|
+
```toml
|
|
281
|
+
[[providers]]
|
|
282
|
+
id = "meridian"
|
|
283
|
+
url = "http://127.0.0.1:3456/v1/messages"
|
|
284
|
+
models = "http://127.0.0.1:3456/v1/models"
|
|
285
|
+
api_key_vars = "MERIDIAN_API_KEY"
|
|
286
|
+
response_type = "Anthropic"
|
|
287
|
+
auth_methods = ["api_key"]
|
|
288
|
+
|
|
289
|
+
[session]
|
|
290
|
+
provider_id = "meridian"
|
|
291
|
+
model_id = "claude-opus-4-6"
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Set the API key env var (any value — Meridian authenticates through the SDK, not API keys):
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
export MERIDIAN_API_KEY=unused
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Then log in and select the model:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
forge provider login meridian # enter any value when prompted
|
|
304
|
+
forge config set provider meridian --model claude-opus-4-6
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Start Meridian with the ForgeCode adapter:
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
MERIDIAN_DEFAULT_AGENT=forgecode meridian
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
ForgeCode uses reqwest's default User-Agent, so automatic detection isn't possible. The `MERIDIAN_DEFAULT_AGENT` env var tells Meridian to use the ForgeCode adapter for all unrecognized requests. If you run other agents alongside ForgeCode, use the `x-meridian-agent: forgecode` header instead (add `[providers.headers]` to your `.forge.toml`).
|
|
314
|
+
|
|
276
315
|
### Pi
|
|
277
316
|
|
|
278
317
|
Pi uses the `@mariozechner/pi-ai` library which supports a configurable `baseUrl` on the model. Add a provider-level override in `~/.pi/agent/models.json`:
|
|
@@ -305,6 +344,7 @@ export ANTHROPIC_BASE_URL=http://127.0.0.1:3456
|
|
|
305
344
|
| Agent | Status | Notes |
|
|
306
345
|
|-------|--------|-------|
|
|
307
346
|
| [OpenCode](https://github.com/anomalyco/opencode) | ✅ Verified | Requires `meridian setup` — full tool support, session resume, streaming, subagents |
|
|
347
|
+
| [ForgeCode](https://forgecode.dev) | ✅ Verified | Provider config (see above) — passthrough tool execution, session resume, streaming |
|
|
308
348
|
| [Droid (Factory AI)](https://factory.ai/product/ide) | ✅ Verified | BYOK config (see above) — full tool support, session resume, streaming |
|
|
309
349
|
| [Crush](https://github.com/charmbracelet/crush) | ✅ Verified | Provider config (see above) — full tool support, session resume, headless `crush run` |
|
|
310
350
|
| [Cline](https://github.com/cline/cline) | ✅ Verified | Config (see above) — full tool support, file read/write/edit, bash, session resume |
|
|
@@ -324,6 +364,7 @@ src/proxy/
|
|
|
324
364
|
├── adapters/
|
|
325
365
|
│ ├── detect.ts ← Agent detection from request headers
|
|
326
366
|
│ ├── opencode.ts ← OpenCode adapter
|
|
367
|
+
│ ├── forgecode.ts ← ForgeCode adapter
|
|
327
368
|
│ ├── crush.ts ← Crush adapter
|
|
328
369
|
│ ├── droid.ts ← Droid adapter
|
|
329
370
|
│ ├── pi.ts ← Pi adapter
|
|
@@ -394,7 +435,7 @@ Implement the `AgentAdapter` interface in `src/proxy/adapters/`. See [`adapters/
|
|
|
394
435
|
| `MERIDIAN_TELEMETRY_SIZE` | `CLAUDE_PROXY_TELEMETRY_SIZE` | `1000` | Telemetry ring buffer size |
|
|
395
436
|
| `MERIDIAN_NO_FILE_CHANGES` | `CLAUDE_PROXY_NO_FILE_CHANGES` | unset | Disable "Files changed" summary in responses |
|
|
396
437
|
| `MERIDIAN_SONNET_MODEL` | `CLAUDE_PROXY_SONNET_MODEL` | `sonnet` | Sonnet context tier: `sonnet` (200k, default) or `sonnet[1m]` (1M, requires Extra Usage†) |
|
|
397
|
-
| `MERIDIAN_DEFAULT_AGENT` | — | `opencode` | Default adapter for unrecognized agents: `opencode`, `pi`, `crush`, `droid`, `passthrough`. Requires restart. |
|
|
438
|
+
| `MERIDIAN_DEFAULT_AGENT` | — | `opencode` | Default adapter for unrecognized agents: `opencode`, `forgecode`, `pi`, `crush`, `droid`, `passthrough`. Requires restart. |
|
|
398
439
|
| `MERIDIAN_PROFILES` | — | unset | JSON array of profile configs (overrides disk discovery). See [Multi-Profile Support](#multi-profile-support). |
|
|
399
440
|
| `MERIDIAN_DEFAULT_PROFILE` | — | *(first profile)* | Default profile ID when no header is sent |
|
|
400
441
|
|
|
@@ -7413,7 +7413,6 @@ function translateAnthropicSseEvent(event, completionId, model, created) {
|
|
|
7413
7413
|
return null;
|
|
7414
7414
|
}
|
|
7415
7415
|
function buildModelList(isMaxSubscription, now = Math.floor(Date.now() / 1000)) {
|
|
7416
|
-
const extendedContext = isMaxSubscription ? 1e6 : 200000;
|
|
7417
7416
|
return [
|
|
7418
7417
|
{
|
|
7419
7418
|
id: "claude-sonnet-4-6",
|
|
@@ -7421,7 +7420,7 @@ function buildModelList(isMaxSubscription, now = Math.floor(Date.now() / 1000))
|
|
|
7421
7420
|
created: now,
|
|
7422
7421
|
owned_by: "anthropic",
|
|
7423
7422
|
display_name: "Claude Sonnet 4.6",
|
|
7424
|
-
context_window:
|
|
7423
|
+
context_window: 200000
|
|
7425
7424
|
},
|
|
7426
7425
|
{
|
|
7427
7426
|
id: "claude-opus-4-6",
|
|
@@ -7429,7 +7428,7 @@ function buildModelList(isMaxSubscription, now = Math.floor(Date.now() / 1000))
|
|
|
7429
7428
|
created: now,
|
|
7430
7429
|
owned_by: "anthropic",
|
|
7431
7430
|
display_name: "Claude Opus 4.6",
|
|
7432
|
-
context_window:
|
|
7431
|
+
context_window: isMaxSubscription ? 1e6 : 200000
|
|
7433
7432
|
},
|
|
7434
7433
|
{
|
|
7435
7434
|
id: "claude-haiku-4-5-20251001",
|
|
@@ -8132,13 +8131,85 @@ var piAdapter = {
|
|
|
8132
8131
|
}
|
|
8133
8132
|
};
|
|
8134
8133
|
|
|
8134
|
+
// src/proxy/adapters/forgecode.ts
|
|
8135
|
+
var FORGECODE_MCP_SERVER_NAME = "forgecode";
|
|
8136
|
+
var FORGECODE_ALLOWED_MCP_TOOLS = [
|
|
8137
|
+
`mcp__${FORGECODE_MCP_SERVER_NAME}__read`,
|
|
8138
|
+
`mcp__${FORGECODE_MCP_SERVER_NAME}__write`,
|
|
8139
|
+
`mcp__${FORGECODE_MCP_SERVER_NAME}__edit`,
|
|
8140
|
+
`mcp__${FORGECODE_MCP_SERVER_NAME}__bash`,
|
|
8141
|
+
`mcp__${FORGECODE_MCP_SERVER_NAME}__glob`,
|
|
8142
|
+
`mcp__${FORGECODE_MCP_SERVER_NAME}__grep`
|
|
8143
|
+
];
|
|
8144
|
+
function extractForgeCodeCwd(body) {
|
|
8145
|
+
let systemText = "";
|
|
8146
|
+
if (typeof body.system === "string") {
|
|
8147
|
+
systemText = body.system;
|
|
8148
|
+
} else if (Array.isArray(body.system)) {
|
|
8149
|
+
systemText = body.system.filter((b) => b.type === "text" && b.text).map((b) => b.text).join(`
|
|
8150
|
+
`);
|
|
8151
|
+
}
|
|
8152
|
+
if (!systemText)
|
|
8153
|
+
return;
|
|
8154
|
+
const match2 = systemText.match(/<current_working_directory>\s*([^<]+?)\s*<\/current_working_directory>/i);
|
|
8155
|
+
return match2?.[1]?.trim() || undefined;
|
|
8156
|
+
}
|
|
8157
|
+
var forgeCodeAdapter = {
|
|
8158
|
+
name: "forgecode",
|
|
8159
|
+
getSessionId(_c) {
|
|
8160
|
+
return;
|
|
8161
|
+
},
|
|
8162
|
+
extractWorkingDirectory(body) {
|
|
8163
|
+
return extractForgeCodeCwd(body);
|
|
8164
|
+
},
|
|
8165
|
+
normalizeContent(content) {
|
|
8166
|
+
return normalizeContent(content);
|
|
8167
|
+
},
|
|
8168
|
+
getBlockedBuiltinTools() {
|
|
8169
|
+
return BLOCKED_BUILTIN_TOOLS;
|
|
8170
|
+
},
|
|
8171
|
+
getAgentIncompatibleTools() {
|
|
8172
|
+
return CLAUDE_CODE_ONLY_TOOLS;
|
|
8173
|
+
},
|
|
8174
|
+
getMcpServerName() {
|
|
8175
|
+
return FORGECODE_MCP_SERVER_NAME;
|
|
8176
|
+
},
|
|
8177
|
+
getAllowedMcpTools() {
|
|
8178
|
+
return FORGECODE_ALLOWED_MCP_TOOLS;
|
|
8179
|
+
},
|
|
8180
|
+
buildSdkAgents(_body, _mcpToolNames) {
|
|
8181
|
+
return {};
|
|
8182
|
+
},
|
|
8183
|
+
buildSdkHooks(_body, _sdkAgents) {
|
|
8184
|
+
return;
|
|
8185
|
+
},
|
|
8186
|
+
buildSystemContextAddendum(_body, _sdkAgents) {
|
|
8187
|
+
return "";
|
|
8188
|
+
},
|
|
8189
|
+
extractFileChangesFromToolUse(toolName, toolInput) {
|
|
8190
|
+
const input = toolInput;
|
|
8191
|
+
const filePath = input?.file_path ?? input?.filePath ?? input?.path;
|
|
8192
|
+
if (toolName === "write" && filePath) {
|
|
8193
|
+
return [{ operation: "wrote", path: String(filePath) }];
|
|
8194
|
+
}
|
|
8195
|
+
if ((toolName === "patch" || toolName === "multi_patch") && filePath) {
|
|
8196
|
+
return [{ operation: "edited", path: String(filePath) }];
|
|
8197
|
+
}
|
|
8198
|
+
if (toolName === "shell" && input?.command) {
|
|
8199
|
+
return extractFileChangesFromBash(String(input.command));
|
|
8200
|
+
}
|
|
8201
|
+
return [];
|
|
8202
|
+
}
|
|
8203
|
+
};
|
|
8204
|
+
|
|
8135
8205
|
// src/proxy/adapters/detect.ts
|
|
8136
8206
|
var ADAPTER_MAP = {
|
|
8137
8207
|
opencode: openCodeAdapter,
|
|
8138
8208
|
droid: droidAdapter,
|
|
8139
8209
|
crush: crushAdapter,
|
|
8140
8210
|
passthrough: passthroughAdapter,
|
|
8141
|
-
pi: piAdapter
|
|
8211
|
+
pi: piAdapter,
|
|
8212
|
+
forgecode: forgeCodeAdapter
|
|
8142
8213
|
};
|
|
8143
8214
|
var envDefault = process.env.MERIDIAN_DEFAULT_AGENT || "";
|
|
8144
8215
|
if (envDefault && !ADAPTER_MAP[envDefault]) {
|
|
@@ -14028,6 +14099,33 @@ function formatAnomalyAlerts(requestId, anomalies) {
|
|
|
14028
14099
|
});
|
|
14029
14100
|
}
|
|
14030
14101
|
|
|
14102
|
+
// src/proxy/tokenUsage.ts
|
|
14103
|
+
function computeCacheHitRate(usage) {
|
|
14104
|
+
if (!usage)
|
|
14105
|
+
return;
|
|
14106
|
+
const read = usage.cache_read_input_tokens ?? 0;
|
|
14107
|
+
const creation = usage.cache_creation_input_tokens ?? 0;
|
|
14108
|
+
const uncached = usage.input_tokens ?? 0;
|
|
14109
|
+
const total = uncached + read + creation;
|
|
14110
|
+
if (total === 0)
|
|
14111
|
+
return;
|
|
14112
|
+
return read / total;
|
|
14113
|
+
}
|
|
14114
|
+
function formatTokenCount(n) {
|
|
14115
|
+
return n > 1000 ? `${Math.round(n / 1000)}k` : String(n);
|
|
14116
|
+
}
|
|
14117
|
+
function formatUsageSummary(usage) {
|
|
14118
|
+
const parts = [
|
|
14119
|
+
`input=${formatTokenCount(usage.input_tokens ?? 0)}`,
|
|
14120
|
+
`output=${formatTokenCount(usage.output_tokens ?? 0)}`,
|
|
14121
|
+
...usage.cache_read_input_tokens ? [`cache_read=${formatTokenCount(usage.cache_read_input_tokens)}`] : [],
|
|
14122
|
+
...usage.cache_creation_input_tokens ? [`cache_write=${formatTokenCount(usage.cache_creation_input_tokens)}`] : []
|
|
14123
|
+
];
|
|
14124
|
+
const rate = computeCacheHitRate(usage);
|
|
14125
|
+
const cacheTag = rate !== undefined ? ` cache=${Math.round(rate * 100)}%` : "";
|
|
14126
|
+
return `${parts.join(" ")}${cacheTag}`;
|
|
14127
|
+
}
|
|
14128
|
+
|
|
14031
14129
|
// src/proxy/session/lineage.ts
|
|
14032
14130
|
import { createHash as createHash2 } from "crypto";
|
|
14033
14131
|
var MIN_SUFFIX_FOR_COMPACTION = 2;
|
|
@@ -14706,29 +14804,7 @@ function buildFreshPrompt(messages, stripCacheControl) {
|
|
|
14706
14804
|
`) || "";
|
|
14707
14805
|
}
|
|
14708
14806
|
function logUsage(requestId, usage) {
|
|
14709
|
-
|
|
14710
|
-
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
14711
|
-
const totalInput = usage.input_tokens ?? 0;
|
|
14712
|
-
const cacheRate = totalInput > 0 ? Math.round(cacheRead / totalInput * 100) : 0;
|
|
14713
|
-
const cacheTag = totalInput > 0 ? ` cache=${cacheRate}%` : "";
|
|
14714
|
-
const parts = [
|
|
14715
|
-
`input=${fmt2(usage.input_tokens ?? 0)}`,
|
|
14716
|
-
`output=${fmt2(usage.output_tokens ?? 0)}`,
|
|
14717
|
-
...usage.cache_read_input_tokens ? [`cache_read=${fmt2(usage.cache_read_input_tokens)}`] : [],
|
|
14718
|
-
...usage.cache_creation_input_tokens ? [`cache_write=${fmt2(usage.cache_creation_input_tokens)}`] : []
|
|
14719
|
-
];
|
|
14720
|
-
console.error(`[PROXY] ${requestId} usage: ${parts.join(" ")}${cacheTag}`);
|
|
14721
|
-
}
|
|
14722
|
-
function computeCacheHitRate(usage) {
|
|
14723
|
-
if (!usage)
|
|
14724
|
-
return;
|
|
14725
|
-
const read = usage.cache_read_input_tokens ?? 0;
|
|
14726
|
-
const creation = usage.cache_creation_input_tokens ?? 0;
|
|
14727
|
-
const uncached = usage.input_tokens ?? 0;
|
|
14728
|
-
const total = uncached + read + creation;
|
|
14729
|
-
if (total === 0)
|
|
14730
|
-
return;
|
|
14731
|
-
return read / total;
|
|
14807
|
+
console.error(`[PROXY] ${requestId} usage: ${formatUsageSummary(usage)}`);
|
|
14732
14808
|
}
|
|
14733
14809
|
function checkTokenHealth(requestId, sdkSessionId, usage, turnNumber, isResume, isPassthrough) {
|
|
14734
14810
|
if (!usage || !sdkSessionId)
|
|
@@ -14881,6 +14957,13 @@ function createProxyServer(config = {}) {
|
|
|
14881
14957
|
console.error(`[PROXY] ${requestMeta.requestId} ignoring malformed x-opencode-thinking header: ${e instanceof Error ? e.message : String(e)}`);
|
|
14882
14958
|
}
|
|
14883
14959
|
}
|
|
14960
|
+
const thinkingBetaStripped = betaFilter.stripped.some((b) => b.startsWith("interleaved-thinking"));
|
|
14961
|
+
if (thinkingBetaStripped) {
|
|
14962
|
+
thinking = { type: "disabled" };
|
|
14963
|
+
if (betaFilter.stripped.length > 0) {
|
|
14964
|
+
console.error(`[PROXY] ${requestMeta.requestId} thinking disabled (thinking beta stripped by ${getBetaPolicyFromEnv()} policy)`);
|
|
14965
|
+
}
|
|
14966
|
+
}
|
|
14884
14967
|
const parsedBudget = taskBudgetHeader ? Number.parseInt(taskBudgetHeader, 10) : NaN;
|
|
14885
14968
|
const taskBudget = Number.isFinite(parsedBudget) ? { total: parsedBudget } : body.task_budget ? { total: body.task_budget.total ?? body.task_budget } : undefined;
|
|
14886
14969
|
const betas = betaFilter.forwarded;
|
package/dist/cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAuC9C;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,YAAY,CA+BtD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForgeCode agent adapter.
|
|
3
|
+
*
|
|
4
|
+
* Provides ForgeCode-specific behavior for session tracking, working directory
|
|
5
|
+
* extraction, content normalization, and tool configuration.
|
|
6
|
+
*
|
|
7
|
+
* ForgeCode (forgecode.dev) is a Rust-based terminal coding agent by Antinomy
|
|
8
|
+
* that makes standard Anthropic Messages API calls. When using a custom provider
|
|
9
|
+
* URL (pointing at Meridian), ForgeCode operates in passthrough mode with its
|
|
10
|
+
* own tool execution loop.
|
|
11
|
+
*
|
|
12
|
+
* Key characteristics:
|
|
13
|
+
* - User-Agent: reqwest default (no distinctive prefix) — use x-meridian-agent or env var
|
|
14
|
+
* - No session header: relies on fingerprint-based session cache
|
|
15
|
+
* - CWD in system prompt: <current_working_directory>/path</current_working_directory>
|
|
16
|
+
* - Snake_case tools: read, write, patch, multi_patch, shell, fs_search, etc.
|
|
17
|
+
* - Always streams (stream: true by default)
|
|
18
|
+
* - Manages its own tool execution loop: passthrough mode is appropriate
|
|
19
|
+
* - Subagent routing handled client-side via Task tool — invisible to proxy
|
|
20
|
+
*
|
|
21
|
+
* Detection: ForgeCode uses reqwest's default User-Agent, so automatic detection
|
|
22
|
+
* is unreliable. Use one of:
|
|
23
|
+
* - x-meridian-agent: forgecode header (per-request)
|
|
24
|
+
* - MERIDIAN_DEFAULT_AGENT=forgecode env var (global default)
|
|
25
|
+
*/
|
|
26
|
+
import type { AgentAdapter } from "../adapter";
|
|
27
|
+
export declare const forgeCodeAdapter: AgentAdapter;
|
|
28
|
+
//# sourceMappingURL=forgecode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgecode.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/forgecode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAwC9C,eAAO,MAAM,gBAAgB,EAAE,YA6F9B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/proxy/openai.ts"],"names":[],"mappings":"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
|
|
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;
|
|
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;AAwBvD,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;AAkJ7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAqwDhF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiEhG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token usage formatting and cache-hit-rate calculations.
|
|
3
|
+
*
|
|
4
|
+
* Pure functions shared between stderr request logging and telemetry storage.
|
|
5
|
+
* Extracting these out of server.ts guarantees a single source of truth for
|
|
6
|
+
* the cache-hit-rate formula — stderr logs and the telemetry dashboard now
|
|
7
|
+
* agree.
|
|
8
|
+
*
|
|
9
|
+
* Previously `logUsage` computed `cache_read / input_tokens`, but the SDK
|
|
10
|
+
* reports `input_tokens` as *only* the non-cached portion, so the ratio blew
|
|
11
|
+
* past 100% (e.g. `cache=2600000%`) whenever a cache hit actually happened.
|
|
12
|
+
* `computeCacheHitRate` already had the correct formula; this module moves
|
|
13
|
+
* `logUsage` onto the same helper.
|
|
14
|
+
*
|
|
15
|
+
* This module is pure — no I/O, no imports from server.ts or session/.
|
|
16
|
+
*/
|
|
17
|
+
import type { TokenUsage } from "./session/lineage";
|
|
18
|
+
/**
|
|
19
|
+
* Compute the fraction of input tokens served from cache for a single turn.
|
|
20
|
+
*
|
|
21
|
+
* The SDK's `input_tokens` field reports only the non-cached portion, so the
|
|
22
|
+
* true total input size is `input_tokens + cache_read_input_tokens +
|
|
23
|
+
* cache_creation_input_tokens`. Returns a value in [0, 1], or `undefined` if
|
|
24
|
+
* there is no input to measure against.
|
|
25
|
+
*/
|
|
26
|
+
export declare function computeCacheHitRate(usage: TokenUsage | undefined): number | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Format an integer token count for compact display.
|
|
29
|
+
*
|
|
30
|
+
* - values ≤ 1000 → exact integer (e.g. `"847"`)
|
|
31
|
+
* - values > 1000 → rounded to nearest thousand with "k" suffix (e.g. `"71k"`)
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatTokenCount(n: number): string;
|
|
34
|
+
/**
|
|
35
|
+
* Build the single-line stderr summary for a request's token usage.
|
|
36
|
+
*
|
|
37
|
+
* Example outputs:
|
|
38
|
+
* "input=3 output=416 cache_read=71k cache_write=2k cache=97%"
|
|
39
|
+
* "input=10 output=8 cache_write=59k cache=0%"
|
|
40
|
+
* "input=1000 output=50" (no caching activity)
|
|
41
|
+
*
|
|
42
|
+
* The `cache=XX%` tag is emitted whenever `computeCacheHitRate` returns a
|
|
43
|
+
* defined value. The tag is suppressed only when there is literally no input
|
|
44
|
+
* data to compute a ratio from (neither uncached nor cached).
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatUsageSummary(usage: TokenUsage): string;
|
|
47
|
+
//# sourceMappingURL=tokenUsage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenUsage.d.ts","sourceRoot":"","sources":["../../src/proxy/tokenUsage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAQrF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAU5D"}
|
package/dist/server.js
CHANGED
package/package.json
CHANGED