@relayplane/proxy 1.7.1 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,24 +3,26 @@
3
3
  [![npm](https://img.shields.io/npm/v/@relayplane/proxy)](https://www.npmjs.com/package/@relayplane/proxy)
4
4
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/RelayPlane/proxy/blob/main/LICENSE)
5
5
 
6
- An open-source LLM proxy that sits between your AI agents and providers. Tracks every request, shows where the money goes, and offers configurable task-aware routing — all running locally.
6
+ An open-source LLM proxy that sits between your AI agents and providers. Tracks every request, shows where the money goes, and offers configurable task-aware routing — all running **locally, for free**.
7
7
 
8
- **Key features:**
8
+ **Free, open-source proxy features:**
9
9
  - 📊 Per-request cost tracking across 11+ providers
10
- - 💰 **Cache-aware cost tracking** — accurately tracks Anthropic prompt caching with cache read savings, creation costs, and true per-request costs including cached tokens
10
+ - 💰 **Cache-aware cost tracking** — accurately tracks Anthropic prompt caching with cache read savings, creation costs, and true per-request costs
11
11
  - 🔀 Configurable task-aware routing (complexity-based, cascade, model overrides)
12
- - 🛡️ Circuit breaker architecture — if the proxy fails, your agent doesn't notice
13
- - 📈 Local dashboard with cost breakdown, savings analysis, and provider health
12
+ - 🛡️ Circuit breaker — if the proxy fails, your agent doesn't notice
13
+ - 📈 **Local dashboard** at `localhost:4100` — cost breakdown, savings analysis, provider health
14
14
  - 💵 **Budget enforcement** — daily/hourly/per-request spend limits with block, warn, downgrade, or alert actions
15
15
  - 🔍 **Anomaly detection** — catches runaway agent loops, cost spikes, and token explosions in real time
16
16
  - 🔔 **Cost alerts** — threshold alerts at configurable percentages, webhook delivery, alert history
17
17
  - ⬇️ **Auto-downgrade** — automatically switches to cheaper models when budget thresholds are hit
18
- - 📦 **Aggressive cache** — exact-match and aggressive response caching with gzipped disk persistence
19
- - 🧠 **Osmosis mesh** — opt-in collective learning layer that shares anonymized routing signals across users
18
+ - 📦 **Aggressive cache** — exact-match response caching with gzipped disk persistence
19
+ - 🧠 **Osmosis mesh** — opt-in collective learning layer that shares anonymized routing signals across users (free, opt-in)
20
20
  - 🔧 **systemd/launchd service** — `relayplane service install` for always-on operation with auto-restart
21
21
  - 🏥 **Health watchdog** — `/health` endpoint with uptime tracking and active probing
22
22
  - 🛡️ **Config resilience** — atomic writes, automatic backup/restore, credential separation
23
23
 
24
+ > **Cloud dashboard available separately** — see [Cloud Dashboard & Pro Features](#cloud-dashboard--pro-features) below. Your prompts always stay local.
25
+
24
26
  ## Quick Start
25
27
 
26
28
  ```bash
@@ -296,6 +298,15 @@ When enabled, the proxy sends anonymized metadata to `api.relayplane.com`:
296
298
 
297
299
  **Never collected:** prompts, responses, file paths, or anything that could identify you or your project. Your prompts go directly to LLM providers, never through RelayPlane servers.
298
300
 
301
+ > **Cloud dashboard setup:** To see your data at [relayplane.com/dashboard](https://relayplane.com/dashboard), run `relayplane login` then `relayplane telemetry on`. This is the explicit opt-in — you're choosing to send anonymous metadata to power the cloud dashboard. You can disable anytime.
302
+
303
+ When the proxy connects and telemetry is enabled, it will confirm:
304
+ ```
305
+ [RelayPlane] Cloud dashboard connected — telemetry enabled.
306
+ Your prompts stay local. Only anonymous metadata (model, tokens, cost) is sent.
307
+ Disable anytime: relayplane telemetry off
308
+ ```
309
+
299
310
  ### Audit mode
300
311
 
301
312
  Audit mode buffers telemetry events in memory so you can inspect exactly what would be sent before it goes anywhere. Useful for compliance review.
@@ -555,6 +566,36 @@ relayplane [command] [options]
555
566
  | `--audit` | — | Show telemetry payloads before sending |
556
567
  | `-v, --verbose` | — | Verbose logging |
557
568
 
569
+ ## Cloud Dashboard & Pro Features
570
+
571
+ The proxy is fully functional without a cloud account. All features above are **local and free**.
572
+
573
+ For teams that want persistent cloud analytics, email digests, and shared routing intelligence, [relayplane.com](https://relayplane.com) offers:
574
+
575
+ | Feature | Plan |
576
+ |---------|------|
577
+ | Cloud dashboard — run history, cost trends, analytics | Starter ($9/mo) |
578
+ | Policy engine — budget rules, model allowlists, approval gates | Starter |
579
+ | Weekly cost digest emails | Starter |
580
+ | Routing recommendations from collective intelligence | Starter |
581
+ | 90-day history, data export | Pro ($29/mo) |
582
+ | Cloud anomaly alerts (email, webhook) | Pro |
583
+ | Team access & shared dashboards | Max ($99/mo) |
584
+ | Governance & compliance rules | Max |
585
+
586
+ **[View pricing →](https://relayplane.com/pricing)**
587
+
588
+ ### Connecting to Cloud
589
+
590
+ ```bash
591
+ relayplane login # authenticate with your cloud account
592
+ relayplane telemetry on # opt in to send anonymous metadata (model, tokens, cost, latency)
593
+ ```
594
+
595
+ > **Privacy-first:** Enabling cloud telemetry sends only anonymous metadata — model name, token counts, cost, latency. Your prompts, inputs, and outputs **never leave your machine**. You can disable anytime: `relayplane telemetry off`.
596
+
597
+ ---
598
+
558
599
  ## Your Keys Stay Yours
559
600
 
560
601
  RelayPlane requires your own provider API keys. Your prompts go directly to LLM providers — never through RelayPlane servers. All proxy execution is local. Telemetry (anonymous metadata only) is opt-in.
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Per-Agent Cost Tracking
3
+ *
4
+ * Fingerprints agents by hashing the first 500 chars of their system prompt
5
+ * (SHA-256, first 12 hex chars). Maintains an agent registry at ~/.relayplane/agents.json.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export interface AgentRegistryEntry {
10
+ name: string;
11
+ fingerprint: string;
12
+ firstSeen: string;
13
+ lastSeen: string;
14
+ systemPromptPreview: string;
15
+ totalRequests: number;
16
+ totalCost: number;
17
+ }
18
+ export interface AgentRegistry {
19
+ [fingerprint: string]: AgentRegistryEntry;
20
+ }
21
+ /**
22
+ * Compute agent fingerprint from system prompt content.
23
+ * Uses first 500 chars → SHA-256 → first 12 hex chars.
24
+ */
25
+ export declare function computeFingerprint(systemPrompt: string): string;
26
+ /**
27
+ * Extract system message text from a messages array.
28
+ * Returns empty string if no system message found.
29
+ */
30
+ export declare function extractSystemPrompt(messages: Array<{
31
+ role?: string;
32
+ content?: unknown;
33
+ }>): string;
34
+ /**
35
+ * Extract system prompt from an Anthropic-style request body
36
+ * where system is a top-level field rather than in messages.
37
+ */
38
+ export declare function extractSystemPromptFromBody(body: Record<string, unknown>): string;
39
+ /**
40
+ * Load agent registry from disk.
41
+ */
42
+ export declare function loadAgentRegistry(): void;
43
+ /**
44
+ * Flush agent registry to disk immediately.
45
+ */
46
+ export declare function flushAgentRegistry(): void;
47
+ /**
48
+ * Record a request for an agent. Creates registry entry if new.
49
+ * Returns the fingerprint and resolved agentId.
50
+ */
51
+ export declare function trackAgent(systemPrompt: string, costUsd: number, explicitAgentId?: string): {
52
+ fingerprint: string;
53
+ agentId: string | undefined;
54
+ };
55
+ /**
56
+ * Update cost for an agent after response is received.
57
+ */
58
+ export declare function updateAgentCost(fingerprint: string, costUsd: number): void;
59
+ /**
60
+ * Rename an agent in the registry.
61
+ */
62
+ export declare function renameAgent(fingerprint: string, newName: string): boolean;
63
+ /**
64
+ * Get the full agent registry.
65
+ */
66
+ export declare function getAgentRegistry(): AgentRegistry;
67
+ /**
68
+ * Get agent registry with cost summaries from request history.
69
+ */
70
+ export declare function getAgentSummaries(requestHistory: Array<{
71
+ agentFingerprint?: string;
72
+ costUsd: number;
73
+ timestamp: string;
74
+ }>): Array<AgentRegistryEntry & {
75
+ costFromHistory: number;
76
+ requestsFromHistory: number;
77
+ }>;
78
+ /**
79
+ * Reset registry (for testing).
80
+ */
81
+ export declare function _resetForTesting(): void;
82
+ //# sourceMappingURL=agent-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tracker.d.ts","sourceRoot":"","sources":["../src/agent-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAAC;CAC3C;AAUD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,MAAM,CAgBjG;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAajF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAiBxC;AAcD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,MAAM,GACvB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAiCtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAM1E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAMzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,KAAK,CAAC;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,GACvF,KAAK,CAAC,kBAAkB,GAAG;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CtF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC"}
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ /**
3
+ * Per-Agent Cost Tracking
4
+ *
5
+ * Fingerprints agents by hashing the first 500 chars of their system prompt
6
+ * (SHA-256, first 12 hex chars). Maintains an agent registry at ~/.relayplane/agents.json.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.computeFingerprint = computeFingerprint;
45
+ exports.extractSystemPrompt = extractSystemPrompt;
46
+ exports.extractSystemPromptFromBody = extractSystemPromptFromBody;
47
+ exports.loadAgentRegistry = loadAgentRegistry;
48
+ exports.flushAgentRegistry = flushAgentRegistry;
49
+ exports.trackAgent = trackAgent;
50
+ exports.updateAgentCost = updateAgentCost;
51
+ exports.renameAgent = renameAgent;
52
+ exports.getAgentRegistry = getAgentRegistry;
53
+ exports.getAgentSummaries = getAgentSummaries;
54
+ exports._resetForTesting = _resetForTesting;
55
+ const crypto = __importStar(require("node:crypto"));
56
+ const fs = __importStar(require("node:fs"));
57
+ const path = __importStar(require("node:path"));
58
+ const os = __importStar(require("node:os"));
59
+ const REGISTRY_DIR = path.join(os.homedir(), '.relayplane');
60
+ const REGISTRY_FILE = path.join(REGISTRY_DIR, 'agents.json');
61
+ let agentRegistry = {};
62
+ let nextAgentNumber = 1;
63
+ let registryDirty = false;
64
+ let flushTimer = null;
65
+ /**
66
+ * Compute agent fingerprint from system prompt content.
67
+ * Uses first 500 chars → SHA-256 → first 12 hex chars.
68
+ */
69
+ function computeFingerprint(systemPrompt) {
70
+ const input = systemPrompt.slice(0, 500);
71
+ const hash = crypto.createHash('sha256').update(input).digest('hex');
72
+ return hash.slice(0, 12);
73
+ }
74
+ /**
75
+ * Extract system message text from a messages array.
76
+ * Returns empty string if no system message found.
77
+ */
78
+ function extractSystemPrompt(messages) {
79
+ if (!messages || !Array.isArray(messages))
80
+ return '';
81
+ for (const msg of messages) {
82
+ if (msg.role === 'system') {
83
+ if (typeof msg.content === 'string')
84
+ return msg.content;
85
+ if (Array.isArray(msg.content)) {
86
+ return msg.content
87
+ .map((part) => {
88
+ const p = part;
89
+ return p.type === 'text' ? (p.text ?? '') : '';
90
+ })
91
+ .join('');
92
+ }
93
+ }
94
+ }
95
+ return '';
96
+ }
97
+ /**
98
+ * Extract system prompt from an Anthropic-style request body
99
+ * where system is a top-level field rather than in messages.
100
+ */
101
+ function extractSystemPromptFromBody(body) {
102
+ // Check top-level 'system' field (Anthropic native format)
103
+ if (typeof body.system === 'string')
104
+ return body.system;
105
+ if (Array.isArray(body.system)) {
106
+ return body.system
107
+ .map(p => p.type === 'text' ? (p.text ?? '') : (typeof p === 'string' ? p : ''))
108
+ .join('');
109
+ }
110
+ // Check messages array (OpenAI format)
111
+ if (Array.isArray(body.messages)) {
112
+ return extractSystemPrompt(body.messages);
113
+ }
114
+ return '';
115
+ }
116
+ /**
117
+ * Load agent registry from disk.
118
+ */
119
+ function loadAgentRegistry() {
120
+ try {
121
+ if (fs.existsSync(REGISTRY_FILE)) {
122
+ const data = fs.readFileSync(REGISTRY_FILE, 'utf-8');
123
+ agentRegistry = JSON.parse(data);
124
+ // Compute next agent number from existing names
125
+ for (const entry of Object.values(agentRegistry)) {
126
+ const match = entry.name.match(/^Agent (\d+)$/);
127
+ if (match) {
128
+ const num = parseInt(match[1], 10);
129
+ if (num >= nextAgentNumber)
130
+ nextAgentNumber = num + 1;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ catch {
136
+ agentRegistry = {};
137
+ }
138
+ }
139
+ /**
140
+ * Save agent registry to disk (debounced).
141
+ */
142
+ function scheduleFlush() {
143
+ registryDirty = true;
144
+ if (flushTimer)
145
+ return;
146
+ flushTimer = setTimeout(() => {
147
+ flushTimer = null;
148
+ flushAgentRegistry();
149
+ }, 5000);
150
+ }
151
+ /**
152
+ * Flush agent registry to disk immediately.
153
+ */
154
+ function flushAgentRegistry() {
155
+ if (!registryDirty)
156
+ return;
157
+ try {
158
+ fs.mkdirSync(REGISTRY_DIR, { recursive: true });
159
+ fs.writeFileSync(REGISTRY_FILE, JSON.stringify(agentRegistry, null, 2), 'utf-8');
160
+ registryDirty = false;
161
+ }
162
+ catch {
163
+ // Silent failure — don't break the proxy
164
+ }
165
+ }
166
+ /**
167
+ * Record a request for an agent. Creates registry entry if new.
168
+ * Returns the fingerprint and resolved agentId.
169
+ */
170
+ function trackAgent(systemPrompt, costUsd, explicitAgentId) {
171
+ if (!systemPrompt) {
172
+ return { fingerprint: 'unknown', agentId: explicitAgentId };
173
+ }
174
+ const fingerprint = computeFingerprint(systemPrompt);
175
+ const now = new Date().toISOString();
176
+ if (!agentRegistry[fingerprint]) {
177
+ agentRegistry[fingerprint] = {
178
+ name: `Agent ${nextAgentNumber++}`,
179
+ fingerprint,
180
+ firstSeen: now,
181
+ lastSeen: now,
182
+ systemPromptPreview: systemPrompt.slice(0, 80),
183
+ totalRequests: 0,
184
+ totalCost: 0,
185
+ };
186
+ }
187
+ const entry = agentRegistry[fingerprint];
188
+ entry.lastSeen = now;
189
+ entry.totalRequests++;
190
+ entry.totalCost += costUsd;
191
+ // If explicit agentId provided, use it as the name (first time only, don't override user renames)
192
+ if (explicitAgentId && entry.name.startsWith('Agent ')) {
193
+ entry.name = explicitAgentId;
194
+ }
195
+ scheduleFlush();
196
+ return { fingerprint, agentId: explicitAgentId };
197
+ }
198
+ /**
199
+ * Update cost for an agent after response is received.
200
+ */
201
+ function updateAgentCost(fingerprint, costUsd) {
202
+ const entry = agentRegistry[fingerprint];
203
+ if (entry) {
204
+ entry.totalCost += costUsd;
205
+ scheduleFlush();
206
+ }
207
+ }
208
+ /**
209
+ * Rename an agent in the registry.
210
+ */
211
+ function renameAgent(fingerprint, newName) {
212
+ const entry = agentRegistry[fingerprint];
213
+ if (!entry)
214
+ return false;
215
+ entry.name = newName;
216
+ scheduleFlush();
217
+ return true;
218
+ }
219
+ /**
220
+ * Get the full agent registry.
221
+ */
222
+ function getAgentRegistry() {
223
+ return agentRegistry;
224
+ }
225
+ /**
226
+ * Get agent registry with cost summaries from request history.
227
+ */
228
+ function getAgentSummaries(requestHistory) {
229
+ // Aggregate from history
230
+ const historyStats = new Map();
231
+ for (const r of requestHistory) {
232
+ const fp = r.agentFingerprint ?? 'unknown';
233
+ const existing = historyStats.get(fp) ?? { cost: 0, requests: 0, lastActive: '' };
234
+ existing.cost += r.costUsd;
235
+ existing.requests++;
236
+ if (r.timestamp > existing.lastActive)
237
+ existing.lastActive = r.timestamp;
238
+ historyStats.set(fp, existing);
239
+ }
240
+ const results = [];
241
+ // Include all registered agents
242
+ for (const [fp, entry] of Object.entries(agentRegistry)) {
243
+ const hs = historyStats.get(fp) ?? { cost: 0, requests: 0, lastActive: '' };
244
+ results.push({
245
+ ...entry,
246
+ costFromHistory: hs.cost,
247
+ requestsFromHistory: hs.requests,
248
+ });
249
+ historyStats.delete(fp);
250
+ }
251
+ // Include unregistered fingerprints from history
252
+ for (const [fp, hs] of historyStats) {
253
+ if (fp === 'unknown')
254
+ continue;
255
+ results.push({
256
+ name: fp,
257
+ fingerprint: fp,
258
+ firstSeen: hs.lastActive,
259
+ lastSeen: hs.lastActive,
260
+ systemPromptPreview: '',
261
+ totalRequests: hs.requests,
262
+ totalCost: hs.cost,
263
+ costFromHistory: hs.cost,
264
+ requestsFromHistory: hs.requests,
265
+ });
266
+ }
267
+ return results;
268
+ }
269
+ /**
270
+ * Reset registry (for testing).
271
+ */
272
+ function _resetForTesting() {
273
+ agentRegistry = {};
274
+ nextAgentNumber = 1;
275
+ registryDirty = false;
276
+ if (flushTimer) {
277
+ clearTimeout(flushTimer);
278
+ flushTimer = null;
279
+ }
280
+ }
281
+ //# sourceMappingURL=agent-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tracker.js","sourceRoot":"","sources":["../src/agent-tracker.ts"],"names":[],"mappings":"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"}
@@ -92,6 +92,24 @@ export interface ProxyConfig {
92
92
  */
93
93
  anthropicAuth?: 'passthrough' | 'env' | 'auto';
94
94
  }
95
+ /** Rolling request history for telemetry endpoints (max 10000 entries) */
96
+ export interface RequestContentData {
97
+ systemPrompt?: string;
98
+ userMessage?: string;
99
+ responsePreview?: string;
100
+ fullResponse?: string;
101
+ }
102
+ /**
103
+ * Extract request content for logging. Handles Anthropic and OpenAI formats.
104
+ */
105
+ export declare function extractRequestContent(body: Record<string, unknown>, isAnthropic: boolean): {
106
+ systemPrompt?: string;
107
+ userMessage?: string;
108
+ };
109
+ /**
110
+ * Extract assistant response text from response payload.
111
+ */
112
+ export declare function extractResponseText(responseData: Record<string, unknown>, isAnthropic: boolean): string;
95
113
  export declare function parseModelSuffix(model: string): ParsedModel;
96
114
  export declare function classifyComplexity(messages: Array<{
97
115
  role?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"standalone-proxy.d.ts","sourceRoot":"","sources":["../src/standalone-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAOlC,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAY,MAAM,kBAAkB,CAAC;AAE3E,KAAK,QAAQ,GAAG,YAAY,GACxB,YAAY,GACZ,UAAU,GACV,MAAM,GACN,SAAS,GACT,UAAU,GACV,WAAW,GACX,YAAY,CAAC;AAMjB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAiD5C,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,gBAAuB,CAAC;AAuBxD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CA6C9D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAc/E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGrD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAQ/E,CAAC;AAiDF;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAWjD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvD;AAkBD,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjD,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;CAC9B;AAcD,UAAU,aAAa;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC;IAChD,cAAc,EAAE,MAAM,CAAC;CACxB;AAmBD,KAAK,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AA6EpD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;CAChD;AA2ZD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAe3D;AAuDD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,UAAU,CAuCpG;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,OAAO,CAIlG;AAwmDD;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CA6yD/E"}
1
+ {"version":3,"file":"standalone-proxy.d.ts","sourceRoot":"","sources":["../src/standalone-proxy.ts"],"names":[],"mappings":"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"}