@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 +48 -7
- package/dist/agent-tracker.d.ts +82 -0
- package/dist/agent-tracker.d.ts.map +1 -0
- package/dist/agent-tracker.js +281 -0
- package/dist/agent-tracker.js.map +1 -0
- package/dist/standalone-proxy.d.ts +18 -0
- package/dist/standalone-proxy.d.ts.map +1 -1
- package/dist/standalone-proxy.js +317 -40
- package/dist/standalone-proxy.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +13 -0
- package/dist/telemetry.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,24 +3,26 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@relayplane/proxy)
|
|
4
4
|
[](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
|
-
**
|
|
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
|
|
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
|
|
13
|
-
- 📈 Local dashboard
|
|
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
|
|
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;
|
|
1
|
+
{"version":3,"file":"standalone-proxy.d.ts","sourceRoot":"","sources":["../src/standalone-proxy.ts"],"names":[],"mappings":"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"}
|