opengauge 0.1.5 → 0.2.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.
Files changed (57) hide show
  1. package/README.md +42 -0
  2. package/bin/opengauge.js +81 -14
  3. package/dist/cli/stats.d.ts +17 -0
  4. package/dist/cli/stats.d.ts.map +1 -0
  5. package/dist/cli/stats.js +286 -0
  6. package/dist/cli/stats.js.map +1 -0
  7. package/dist/core/circuit-breaker/index.d.ts +50 -0
  8. package/dist/core/circuit-breaker/index.d.ts.map +1 -0
  9. package/dist/core/circuit-breaker/index.js +168 -0
  10. package/dist/core/circuit-breaker/index.js.map +1 -0
  11. package/dist/core/cost/index.d.ts +41 -0
  12. package/dist/core/cost/index.d.ts.map +1 -0
  13. package/dist/core/cost/index.js +111 -0
  14. package/dist/core/cost/index.js.map +1 -0
  15. package/dist/core/index.d.ts +19 -0
  16. package/dist/core/index.d.ts.map +1 -0
  17. package/dist/core/index.js +43 -0
  18. package/dist/core/index.js.map +1 -0
  19. package/dist/core/insights/index.d.ts +56 -0
  20. package/dist/core/insights/index.d.ts.map +1 -0
  21. package/dist/core/insights/index.js +239 -0
  22. package/dist/core/insights/index.js.map +1 -0
  23. package/dist/db/schema.d.ts.map +1 -1
  24. package/dist/db/schema.js +87 -0
  25. package/dist/db/schema.js.map +1 -1
  26. package/dist/db/session-queries.d.ts +145 -0
  27. package/dist/db/session-queries.d.ts.map +1 -0
  28. package/dist/db/session-queries.js +301 -0
  29. package/dist/db/session-queries.js.map +1 -0
  30. package/dist/plugins/openclaw/config.d.ts +24 -0
  31. package/dist/plugins/openclaw/config.d.ts.map +1 -0
  32. package/dist/plugins/openclaw/config.js +84 -0
  33. package/dist/plugins/openclaw/config.js.map +1 -0
  34. package/dist/plugins/openclaw/index.d.ts +39 -0
  35. package/dist/plugins/openclaw/index.d.ts.map +1 -0
  36. package/dist/plugins/openclaw/index.js +124 -0
  37. package/dist/plugins/openclaw/index.js.map +1 -0
  38. package/dist/plugins/openclaw/wrapped-provider.d.ts +67 -0
  39. package/dist/plugins/openclaw/wrapped-provider.d.ts.map +1 -0
  40. package/dist/plugins/openclaw/wrapped-provider.js +324 -0
  41. package/dist/plugins/openclaw/wrapped-provider.js.map +1 -0
  42. package/dist/proxy/providers.d.ts +26 -0
  43. package/dist/proxy/providers.d.ts.map +1 -0
  44. package/dist/proxy/providers.js +101 -0
  45. package/dist/proxy/providers.js.map +1 -0
  46. package/dist/proxy/server.d.ts +18 -0
  47. package/dist/proxy/server.d.ts.map +1 -0
  48. package/dist/proxy/server.js +291 -0
  49. package/dist/proxy/server.js.map +1 -0
  50. package/dist/proxy/session-manager.d.ts +36 -0
  51. package/dist/proxy/session-manager.d.ts.map +1 -0
  52. package/dist/proxy/session-manager.js +117 -0
  53. package/dist/proxy/session-manager.js.map +1 -0
  54. package/dist/server/routes/index.d.ts.map +1 -1
  55. package/dist/server/routes/index.js +4 -2
  56. package/dist/server/routes/index.js.map +1 -1
  57. package/package.json +3 -1
package/README.md CHANGED
@@ -76,6 +76,48 @@ npm start # Run CLI entry locally
76
76
  npm pack --dry-run # Preview npm package contents
77
77
  ```
78
78
 
79
+ ## Competitors and positioning
80
+
81
+ OpenGauge sits between chat UIs and full LLM observability suites.
82
+
83
+ ### PromptOps / Observability tools
84
+
85
+ Examples: PromptLayer, Helicone, Langfuse, Humanloop, Arize Phoenix
86
+
87
+ - Great at: traces, eval pipelines, team dashboards, observability depth.
88
+ - OpenGauge advantage: local-first workflow, in-chat prompt improvement, duplicate-risk + token-efficiency feedback in one loop.
89
+
90
+ ### Multi-model chat interfaces
91
+
92
+ Examples: LibreChat, Open WebUI, Chatbot UI, AnythingLLM
93
+
94
+ - Great at: broad chat UX and plugin ecosystems.
95
+ - OpenGauge advantage: prompt quality optimization is first-class (Improve + analytics), not only chat.
96
+
97
+ ### IDE coding assistants
98
+
99
+ Examples: Continue and other IDE-native AI assistants
100
+
101
+ - Great at: deep coding workflows inside editors.
102
+ - OpenGauge advantage: model-agnostic PromptOps for any user (product, ops, research, support), not just coding.
103
+
104
+ ### Cloud model platforms
105
+
106
+ Examples: Azure AI Studio, Vertex AI, Bedrock consoles
107
+
108
+ - Great at: enterprise governance and managed cloud workflows.
109
+ - OpenGauge advantage: fast setup, no cloud lock-in, supports local Ollama and cloud providers together.
110
+
111
+ ### Why choose OpenGauge
112
+
113
+ - Improve prompts before send (optional Auto Improve mode)
114
+ - Measure quality, duplicates, and token efficiency after send
115
+ - Keep data local with SQLite and run quickly with `npx opengauge`
116
+
117
+ Positioning line:
118
+
119
+ > OpenGauge is PromptOps in the loop: improve prompt quality before send, measure impact after send, and reduce token waste continuously.
120
+
79
121
  ## License
80
122
 
81
123
  MIT
package/bin/opengauge.js CHANGED
@@ -1,18 +1,69 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * OpenGauge CLI — starts the server and opens the browser
4
+ * OpenGauge CLI
5
5
  *
6
- * Usage:
7
- * npx opengauge
8
- * npx opengauge --port 8080
9
- * npx opengauge --no-open
6
+ * Commands:
7
+ * npx opengauge Start the chat UI server
8
+ * npx opengauge stats Show analytics dashboard
9
+ * npx opengauge watch Start proxy watch mode
10
+ * npx opengauge --help Show help
10
11
  */
11
12
 
12
- const { createServer } = require('../dist/server/index');
13
-
14
13
  async function main() {
15
14
  const args = process.argv.slice(2);
15
+ const command = args[0];
16
+
17
+ // ---- stats command ----
18
+ if (command === 'stats') {
19
+ const { runStats } = require('../dist/cli/stats');
20
+ await runStats(args.slice(1));
21
+ return;
22
+ }
23
+
24
+ // ---- watch command ----
25
+ if (command === 'watch') {
26
+ const { startWatchProxy } = require('../dist/proxy/server');
27
+ let port = 4000;
28
+ let optimize = false;
29
+ let aggressiveness = 'conservative';
30
+
31
+ for (let i = 1; i < args.length; i++) {
32
+ if (args[i] === '--port' && args[i + 1]) {
33
+ port = parseInt(args[i + 1], 10);
34
+ i++;
35
+ }
36
+ if (args[i] === '--optimize') optimize = true;
37
+ if (args[i] && args[i].startsWith('--aggressiveness=')) {
38
+ aggressiveness = args[i].split('=')[1];
39
+ }
40
+ if (args[i] === '--help' || args[i] === '-h') {
41
+ console.log(`
42
+ OpenGauge Watch — Local proxy for observing LLM API traffic
43
+
44
+ Usage:
45
+ npx opengauge watch [options]
46
+
47
+ Options:
48
+ --port <number> Port to run on (default: 4000)
49
+ --optimize Enable prompt optimization
50
+ --aggressiveness=<level> conservative | medium | aggressive (default: conservative)
51
+ --help, -h Show this help message
52
+
53
+ Examples:
54
+ ANTHROPIC_BASE_URL=http://localhost:4000 claude
55
+ OPENAI_BASE_URL=http://localhost:4000/v1 your-tool
56
+ `);
57
+ process.exit(0);
58
+ }
59
+ }
60
+
61
+ startWatchProxy({ port, optimize, aggressiveness });
62
+ return;
63
+ }
64
+
65
+ // ---- Default: start chat UI server ----
66
+ const { createServer } = require('../dist/server/index');
16
67
 
17
68
  let port = 3000;
18
69
  let shouldOpen = true;
@@ -27,29 +78,45 @@ async function main() {
27
78
  }
28
79
  if (args[i] === '--help' || args[i] === '-h') {
29
80
  console.log(`
30
- OpenGauge — Token-efficient LLM chat interface
81
+ OpenGauge — PromptOps observability platform
31
82
 
32
83
  Usage:
33
- npx opengauge [options]
84
+ npx opengauge [command] [options]
34
85
 
35
- Options:
86
+ Commands:
87
+ (default) Start the chat UI server
88
+ stats Show analytics dashboard
89
+ watch Start proxy watch mode for IDE agents
90
+
91
+ Options (chat server):
36
92
  --port <number> Port to run on (default: 3000)
37
93
  --no-open Don't open browser automatically
38
94
  --help, -h Show this help message
39
95
 
96
+ Stats options:
97
+ --period=<N>d|h|w|m Time period (e.g. 7d, 24h, 4w)
98
+ --model=<name> Filter by model
99
+ --source=<name> Filter by source (chat, openclaw, proxy)
100
+ --alerts Show active alerts only
101
+ --json Machine-readable JSON output
102
+ --compare Show optimization comparison
103
+
104
+ Watch options:
105
+ --port <number> Proxy port (default: 4000)
106
+ --optimize Enable prompt optimization
107
+ --aggressiveness=<l> conservative | medium | aggressive
108
+
40
109
  Config:
41
110
  ~/.opengauge/config.yml Provider configuration
42
111
  ~/.opengauge/opengauge.db SQLite database
43
-
44
- Homepage: https://github.com/opengauge/opengauge
45
112
  `);
46
113
  process.exit(0);
47
114
  }
48
115
  }
49
116
 
50
117
  console.log(`
51
- ⚡ OpenGauge v0.1.0
52
- Token-efficient LLM chat interface
118
+ ⚡ OpenGauge v0.2.0
119
+ PromptOps observability platform
53
120
  `);
54
121
 
55
122
  await createServer(port);
@@ -0,0 +1,17 @@
1
+ /**
2
+ * opengauge stats — Terminal analytics dashboard
3
+ *
4
+ * Reads the SQLite database and renders analytics to the terminal.
5
+ * Supports filtering by period, model, source, and output format.
6
+ */
7
+ export interface StatsOptions {
8
+ period?: string;
9
+ model?: string;
10
+ source?: string;
11
+ alerts?: boolean;
12
+ json?: boolean;
13
+ compare?: boolean;
14
+ }
15
+ export declare function parseStatsArgs(args: string[]): StatsOptions;
16
+ export declare function runStats(args: string[]): Promise<void>;
17
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/cli/stats.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAW3D;AAmCD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiL5D"}
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ /**
3
+ * opengauge stats — Terminal analytics dashboard
4
+ *
5
+ * Reads the SQLite database and renders analytics to the terminal.
6
+ * Supports filtering by period, model, source, and output format.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.parseStatsArgs = parseStatsArgs;
13
+ exports.runStats = runStats;
14
+ const chalk_1 = __importDefault(require("chalk"));
15
+ const cli_table3_1 = __importDefault(require("cli-table3"));
16
+ const db_1 = require("../db");
17
+ const session_queries_1 = require("../db/session-queries");
18
+ const queries_1 = require("../db/queries");
19
+ function parseStatsArgs(args) {
20
+ const opts = {};
21
+ for (const arg of args) {
22
+ if (arg.startsWith('--period='))
23
+ opts.period = arg.split('=')[1];
24
+ else if (arg.startsWith('--model='))
25
+ opts.model = arg.split('=')[1];
26
+ else if (arg.startsWith('--source='))
27
+ opts.source = arg.split('=')[1];
28
+ else if (arg === '--alerts')
29
+ opts.alerts = true;
30
+ else if (arg === '--json')
31
+ opts.json = true;
32
+ else if (arg === '--compare')
33
+ opts.compare = true;
34
+ }
35
+ return opts;
36
+ }
37
+ function parsePeriod(period) {
38
+ if (!period)
39
+ return undefined;
40
+ const match = period.match(/^(\d+)(h|d|w|m)$/);
41
+ if (!match)
42
+ return undefined;
43
+ const val = parseInt(match[1], 10);
44
+ const unit = match[2];
45
+ const ms = { h: 3600000, d: 86400000, w: 604800000, m: 2592000000 };
46
+ return Date.now() - val * (ms[unit] || 86400000);
47
+ }
48
+ function formatCost(usd) {
49
+ if (usd < 0.01)
50
+ return `$${usd.toFixed(6)}`;
51
+ if (usd < 1)
52
+ return `$${usd.toFixed(4)}`;
53
+ return `$${usd.toFixed(2)}`;
54
+ }
55
+ function formatTokens(n) {
56
+ if (n >= 1_000_000)
57
+ return `${(n / 1_000_000).toFixed(1)}M`;
58
+ if (n >= 1_000)
59
+ return `${(n / 1_000).toFixed(1)}K`;
60
+ return String(n);
61
+ }
62
+ function formatDuration(startMs, endMs) {
63
+ const duration = (endMs || Date.now()) - startMs;
64
+ const mins = Math.floor(duration / 60000);
65
+ if (mins < 60)
66
+ return `${mins}m`;
67
+ const hours = Math.floor(mins / 60);
68
+ if (hours < 24)
69
+ return `${hours}h ${mins % 60}m`;
70
+ return `${Math.floor(hours / 24)}d ${hours % 24}h`;
71
+ }
72
+ // ---- Main stats command ----
73
+ async function runStats(args) {
74
+ const opts = parseStatsArgs(args);
75
+ const db = (0, db_1.getDb)();
76
+ const sq = new session_queries_1.SessionQueries(db);
77
+ const since = parsePeriod(opts.period);
78
+ if (opts.json) {
79
+ return runStatsJson(sq, opts, since);
80
+ }
81
+ if (opts.alerts) {
82
+ return renderAlerts(sq, since);
83
+ }
84
+ if (opts.compare) {
85
+ return renderComparison(sq, since);
86
+ }
87
+ // ---- Header ----
88
+ console.log();
89
+ console.log(chalk_1.default.bold.cyan(' OpenGauge Stats'));
90
+ console.log(chalk_1.default.dim(` ${opts.period ? `Last ${opts.period}` : 'All time'}${opts.source ? ` · source: ${opts.source}` : ''}${opts.model ? ` · model: ${opts.model}` : ''}`));
91
+ console.log();
92
+ // ---- Total Spend ----
93
+ const summary = sq.getSpendSummary(since, opts.source);
94
+ const spendTable = new cli_table3_1.default({
95
+ head: ['Metric', 'Value'].map(h => chalk_1.default.bold(h)),
96
+ style: { head: [], border: [] },
97
+ });
98
+ spendTable.push(['Total Spend', chalk_1.default.yellow(formatCost(summary.total_cost_usd))], ['Tokens In', formatTokens(summary.total_tokens_in)], ['Tokens Out', formatTokens(summary.total_tokens_out)], ['Tokens Saved', chalk_1.default.green(formatTokens(summary.total_tokens_saved))], ['Cost Saved', chalk_1.default.green(formatCost(summary.total_cost_saved_usd))], ['Sessions', String(summary.session_count)], ['API Calls', String(summary.interaction_count)]);
99
+ console.log(chalk_1.default.bold(' Total Spend'));
100
+ console.log(spendTable.toString());
101
+ console.log();
102
+ // ---- Spend by Source ----
103
+ const sources = ['chat', 'openclaw', 'proxy', 'log_ingest'];
104
+ const sourceRows = [];
105
+ for (const src of sources) {
106
+ const s = sq.getSpendSummary(since, src);
107
+ if (s.session_count > 0) {
108
+ sourceRows.push([src, formatCost(s.total_cost_usd), String(s.session_count), String(s.interaction_count)]);
109
+ }
110
+ }
111
+ if (sourceRows.length > 0) {
112
+ const sourceTable = new cli_table3_1.default({
113
+ head: ['Source', 'Spend', 'Sessions', 'Calls'].map(h => chalk_1.default.bold(h)),
114
+ style: { head: [], border: [] },
115
+ });
116
+ sourceTable.push(...sourceRows);
117
+ console.log(chalk_1.default.bold(' Spend by Source'));
118
+ console.log(sourceTable.toString());
119
+ console.log();
120
+ }
121
+ // ---- Model Distribution ----
122
+ const models = sq.getModelUsage(since);
123
+ if (models.length > 0) {
124
+ const modelTable = new cli_table3_1.default({
125
+ head: ['Provider', 'Model', 'Spend', 'Tokens In', 'Tokens Out', 'Sessions'].map(h => chalk_1.default.bold(h)),
126
+ style: { head: [], border: [] },
127
+ });
128
+ for (const m of models.slice(0, 10)) {
129
+ modelTable.push([
130
+ m.provider, m.model,
131
+ chalk_1.default.yellow(formatCost(m.total_cost_usd)),
132
+ formatTokens(m.total_tokens_in),
133
+ formatTokens(m.total_tokens_out),
134
+ String(m.session_count),
135
+ ]);
136
+ }
137
+ console.log(chalk_1.default.bold(' Model Distribution'));
138
+ console.log(modelTable.toString());
139
+ console.log();
140
+ }
141
+ // ---- Daily Spend Trend ----
142
+ const daily = sq.getDailySpend(opts.period ? parseInt(opts.period) || 7 : 7);
143
+ if (daily.length > 0) {
144
+ const dailyTable = new cli_table3_1.default({
145
+ head: ['Date', 'Spend', 'Tokens', 'Sessions'].map(h => chalk_1.default.bold(h)),
146
+ style: { head: [], border: [] },
147
+ });
148
+ for (const d of daily.slice(0, 14)) {
149
+ dailyTable.push([
150
+ d.day,
151
+ chalk_1.default.yellow(formatCost(d.cost_usd)),
152
+ formatTokens(d.tokens_in + d.tokens_out),
153
+ String(d.sessions),
154
+ ]);
155
+ }
156
+ console.log(chalk_1.default.bold(' Daily Spend'));
157
+ console.log(dailyTable.toString());
158
+ console.log();
159
+ }
160
+ // ---- Top Sessions by Cost ----
161
+ const topSessions = sq.getTopSessionsByCost(5, since);
162
+ if (topSessions.length > 0) {
163
+ const sessionTable = new cli_table3_1.default({
164
+ head: ['Source', 'Model', 'Cost', 'Calls', 'Duration'].map(h => chalk_1.default.bold(h)),
165
+ style: { head: [], border: [] },
166
+ });
167
+ for (const s of topSessions) {
168
+ sessionTable.push([
169
+ s.source,
170
+ s.model,
171
+ chalk_1.default.yellow(formatCost(s.total_cost_usd)),
172
+ String(s.interaction_count),
173
+ formatDuration(s.started_at, s.ended_at),
174
+ ]);
175
+ }
176
+ console.log(chalk_1.default.bold(' Top Sessions by Cost'));
177
+ console.log(sessionTable.toString());
178
+ console.log();
179
+ }
180
+ // ---- Circuit Breaker Activity ----
181
+ const alertSummary = sq.getAlertSummary(since);
182
+ if (alertSummary.length > 0) {
183
+ const alertTable = new cli_table3_1.default({
184
+ head: ['Type', 'Severity', 'Count'].map(h => chalk_1.default.bold(h)),
185
+ style: { head: [], border: [] },
186
+ });
187
+ for (const a of alertSummary) {
188
+ const severityColor = a.severity === 'critical' ? chalk_1.default.red : a.severity === 'warning' ? chalk_1.default.yellow : chalk_1.default.dim;
189
+ alertTable.push([a.alert_type, severityColor(a.severity), String(a.count)]);
190
+ }
191
+ console.log(chalk_1.default.bold(' Circuit Breaker Activity'));
192
+ console.log(alertTable.toString());
193
+ console.log();
194
+ }
195
+ // ---- Active Alerts ----
196
+ const activeAlerts = sq.queryAlerts({ dismissed: false, limit: 5, since });
197
+ if (activeAlerts.length > 0) {
198
+ console.log(chalk_1.default.bold(' Active Alerts'));
199
+ for (const alert of activeAlerts) {
200
+ const icon = alert.severity === 'critical' ? chalk_1.default.red('!!') : alert.severity === 'warning' ? chalk_1.default.yellow('!!') : chalk_1.default.dim('i');
201
+ console.log(` ${icon} [${alert.alert_type}] ${alert.message}`);
202
+ }
203
+ console.log();
204
+ }
205
+ // ---- Also include legacy chat UI stats ----
206
+ try {
207
+ const legacyQueries = new queries_1.Queries(db);
208
+ const legacyUsage = legacyQueries.getAggregatedTokenUsage();
209
+ if (legacyUsage.length > 0) {
210
+ const legacyTable = new cli_table3_1.default({
211
+ head: ['Provider', 'Model', 'Tokens In', 'Tokens Out', 'Saved', 'Requests'].map(h => chalk_1.default.bold(h)),
212
+ style: { head: [], border: [] },
213
+ });
214
+ for (const u of legacyUsage) {
215
+ legacyTable.push([
216
+ u.provider, u.model,
217
+ formatTokens(u.total_tokens_in),
218
+ formatTokens(u.total_tokens_out),
219
+ chalk_1.default.green(formatTokens(u.total_tokens_saved)),
220
+ String(u.request_count),
221
+ ]);
222
+ }
223
+ console.log(chalk_1.default.bold(' Chat UI Usage (legacy)'));
224
+ console.log(legacyTable.toString());
225
+ console.log();
226
+ }
227
+ }
228
+ catch {
229
+ // Legacy tables may not exist
230
+ }
231
+ }
232
+ // ---- JSON output ----
233
+ function runStatsJson(sq, opts, since) {
234
+ const output = {
235
+ summary: sq.getSpendSummary(since, opts.source),
236
+ models: sq.getModelUsage(since),
237
+ daily: sq.getDailySpend(7),
238
+ topSessions: sq.getTopSessionsByCost(5, since),
239
+ alerts: sq.queryAlerts({ dismissed: false, limit: 20, since }),
240
+ alertSummary: sq.getAlertSummary(since),
241
+ };
242
+ console.log(JSON.stringify(output, null, 2));
243
+ }
244
+ // ---- Alerts view ----
245
+ function renderAlerts(sq, since) {
246
+ const alerts = sq.queryAlerts({ dismissed: false, since, limit: 50 });
247
+ console.log();
248
+ console.log(chalk_1.default.bold.cyan(' OpenGauge Alerts'));
249
+ console.log();
250
+ if (alerts.length === 0) {
251
+ console.log(chalk_1.default.green(' No active alerts.'));
252
+ console.log();
253
+ return;
254
+ }
255
+ for (const alert of alerts) {
256
+ const icon = alert.severity === 'critical' ? chalk_1.default.red.bold('CRITICAL')
257
+ : alert.severity === 'warning' ? chalk_1.default.yellow.bold('WARNING')
258
+ : chalk_1.default.dim('INFO');
259
+ const time = new Date(alert.created_at).toLocaleString();
260
+ console.log(` ${icon} ${chalk_1.default.bold(alert.alert_type)}`);
261
+ console.log(` ${alert.message}`);
262
+ console.log(chalk_1.default.dim(` ${time} session: ${alert.session_id.slice(0, 8)}...`));
263
+ console.log();
264
+ }
265
+ }
266
+ // ---- Comparison view (A/B optimization) ----
267
+ function renderComparison(sq, since) {
268
+ const summary = sq.getSpendSummary(since);
269
+ console.log();
270
+ console.log(chalk_1.default.bold.cyan(' OpenGauge Optimization Comparison'));
271
+ console.log();
272
+ if (summary.interaction_count === 0) {
273
+ console.log(chalk_1.default.dim(' No data available.'));
274
+ console.log();
275
+ return;
276
+ }
277
+ const actualSpend = summary.total_cost_usd;
278
+ const savedAmount = summary.total_cost_saved_usd;
279
+ const optimizedSpend = actualSpend - savedAmount;
280
+ const savingsPercent = actualSpend > 0 ? (savedAmount / actualSpend) * 100 : 0;
281
+ console.log(` ${chalk_1.default.bold('API calls observed:')} ${summary.interaction_count}`);
282
+ console.log(` ${chalk_1.default.bold('Actual spend:')} ${chalk_1.default.yellow(formatCost(actualSpend))}`);
283
+ console.log(` ${chalk_1.default.bold('Optimized spend:')} ${chalk_1.default.green(formatCost(optimizedSpend))} ${chalk_1.default.green(`(saved ${formatCost(savedAmount)} / ${savingsPercent.toFixed(1)}%)`)}`);
284
+ console.log();
285
+ }
286
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/cli/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @opengauge/core — Circuit Breaker
3
+ *
4
+ * Detects runaway loops in LLM agent interactions using trigram Jaccard similarity.
5
+ * Pure functions — takes an array of recent interactions and returns a verdict.
6
+ * No DB dependency at call time.
7
+ */
8
+ export interface Interaction {
9
+ role: 'user' | 'assistant' | 'system';
10
+ content: string;
11
+ timestamp?: number;
12
+ }
13
+ export type Verdict = 'ok' | 'warning' | 'trip';
14
+ export interface CircuitBreakerResult {
15
+ verdict: Verdict;
16
+ reason: string;
17
+ /** Highest pairwise similarity found among recent interactions */
18
+ peakSimilarity: number;
19
+ /** Number of near-duplicate pairs detected */
20
+ duplicatePairCount: number;
21
+ /** Cluster size of the largest group of similar messages */
22
+ largestClusterSize: number;
23
+ }
24
+ export interface CircuitBreakerConfig {
25
+ /** Similarity threshold to consider two messages near-duplicates (0-1). Default: 0.85 */
26
+ similarityThreshold?: number;
27
+ /** Number of duplicate pairs that triggers a warning. Default: 3 */
28
+ warningPairCount?: number;
29
+ /** Number of duplicate pairs that trips the breaker. Default: 6 */
30
+ tripPairCount?: number;
31
+ /** Minimum cluster size to trip. Default: 4 */
32
+ tripClusterSize?: number;
33
+ /** Only consider messages within this time window (ms). 0 = no limit. Default: 0 */
34
+ timeWindowMs?: number;
35
+ /** Only analyze assistant messages (typical for runaway agent detection). Default: false */
36
+ assistantOnly?: boolean;
37
+ }
38
+ /**
39
+ * Jaccard similarity between two trigram sets: |A ∩ B| / |A ∪ B|
40
+ */
41
+ declare function trigramJaccard(a: string, b: string): number;
42
+ /**
43
+ * Check a sequence of recent interactions for runaway loop patterns.
44
+ *
45
+ * Pure function — no side effects, no DB access.
46
+ * Pass in the most recent N interactions (e.g. last 20-50 messages from an agent session).
47
+ */
48
+ export declare function checkRunawayLoop(recentInteractions: Interaction[], config?: CircuitBreakerConfig): CircuitBreakerResult;
49
+ export { trigramJaccard };
50
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/circuit-breaker/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,cAAc,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA2BD;;GAEG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAepD;AAkDD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,kBAAkB,EAAE,WAAW,EAAE,EACjC,MAAM,CAAC,EAAE,oBAAoB,GAC5B,oBAAoB,CA4EtB;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}