@salimassili/ai-costguard 1.2.0 → 2.0.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 (75) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/LICENSE +21 -0
  3. package/README.md +281 -103
  4. package/benchmarks/run.mjs +229 -0
  5. package/dist/cli.d.ts +50 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +178 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/core/CostGuard.d.ts +3 -4
  10. package/dist/core/CostGuard.d.ts.map +1 -1
  11. package/dist/core/CostGuard.js +1 -2
  12. package/dist/core/CostGuard.js.map +1 -1
  13. package/dist/core/GuardCore.d.ts +93 -13
  14. package/dist/core/GuardCore.d.ts.map +1 -1
  15. package/dist/core/GuardCore.js +372 -158
  16. package/dist/core/GuardCore.js.map +1 -1
  17. package/dist/core/GuardFree.d.ts +42 -18
  18. package/dist/core/GuardFree.d.ts.map +1 -1
  19. package/dist/core/GuardFree.js +95 -140
  20. package/dist/core/GuardFree.js.map +1 -1
  21. package/dist/core/GuardPro.d.ts +85 -5
  22. package/dist/core/GuardPro.d.ts.map +1 -1
  23. package/dist/core/GuardPro.js +216 -121
  24. package/dist/core/GuardPro.js.map +1 -1
  25. package/dist/core/event-log.d.ts +37 -0
  26. package/dist/core/event-log.d.ts.map +1 -0
  27. package/dist/core/event-log.js +49 -0
  28. package/dist/core/event-log.js.map +1 -0
  29. package/dist/core/events.d.ts +20 -0
  30. package/dist/core/events.d.ts.map +1 -0
  31. package/dist/core/events.js +46 -0
  32. package/dist/core/events.js.map +1 -0
  33. package/dist/core/similarity.d.ts +13 -0
  34. package/dist/core/similarity.d.ts.map +1 -0
  35. package/dist/core/similarity.js +51 -0
  36. package/dist/core/similarity.js.map +1 -0
  37. package/dist/core/tokenizer.d.ts +18 -0
  38. package/dist/core/tokenizer.d.ts.map +1 -0
  39. package/dist/core/tokenizer.js +137 -0
  40. package/dist/core/tokenizer.js.map +1 -0
  41. package/dist/core/types.d.ts +153 -5
  42. package/dist/core/types.d.ts.map +1 -1
  43. package/dist/core/types.js +0 -3
  44. package/dist/core/types.js.map +1 -1
  45. package/dist/core/webhooks.d.ts +15 -0
  46. package/dist/core/webhooks.d.ts.map +1 -0
  47. package/dist/core/webhooks.js +58 -0
  48. package/dist/core/webhooks.js.map +1 -0
  49. package/dist/dashboard.d.ts +73 -0
  50. package/dist/dashboard.d.ts.map +1 -0
  51. package/dist/dashboard.js +201 -0
  52. package/dist/dashboard.js.map +1 -0
  53. package/dist/index.d.ts +3 -4
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +1 -2
  56. package/dist/index.js.map +1 -1
  57. package/dist/pricing/index.d.ts +19 -2
  58. package/dist/pricing/index.d.ts.map +1 -1
  59. package/dist/pricing/index.js +93 -13
  60. package/dist/pricing/index.js.map +1 -1
  61. package/dist/pro.d.ts +3 -0
  62. package/dist/pro.d.ts.map +1 -0
  63. package/dist/pro.js +2 -0
  64. package/dist/pro.js.map +1 -0
  65. package/docs/BENCHMARKS.md +51 -0
  66. package/docs/DASHBOARD.md +61 -0
  67. package/docs/INTEGRATIONS.md +153 -0
  68. package/examples/integrations/anthropic-workflow-budget.mjs +36 -0
  69. package/examples/integrations/ci-budget-check.mjs +32 -0
  70. package/examples/integrations/crewai-budget-gate.mjs +31 -0
  71. package/examples/integrations/langchain-retry-storm.mjs +32 -0
  72. package/examples/integrations/mastra-agent.mjs +41 -0
  73. package/examples/integrations/openai-agent-loop.mjs +44 -0
  74. package/examples/integrations/vercel-ai-chatbot.mjs +29 -0
  75. package/package.json +35 -7
@@ -0,0 +1,201 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { createServer } from 'node:http';
3
+ const DEFAULT_EVENT_LOG_PATH = '.ai-costguard/events.jsonl';
4
+ const DEFAULT_DASHBOARD_HOST = '127.0.0.1';
5
+ const DEFAULT_DASHBOARD_PORT = 4318;
6
+ /**
7
+ * Returns the default local event log path.
8
+ */
9
+ export function getDefaultEventLogPath() {
10
+ return DEFAULT_EVENT_LOG_PATH;
11
+ }
12
+ /**
13
+ * Reads dashboard events from a local JSONL event log.
14
+ */
15
+ export function readDashboardEvents(eventLogPath = DEFAULT_EVENT_LOG_PATH) {
16
+ if (!existsSync(eventLogPath))
17
+ return [];
18
+ const lines = readFileSync(eventLogPath, 'utf8')
19
+ .split(/\r?\n/u)
20
+ .map((line) => line.trim())
21
+ .filter(Boolean);
22
+ const events = [];
23
+ for (const line of lines) {
24
+ const event = parseDashboardEvent(line);
25
+ if (event)
26
+ events.push(event);
27
+ }
28
+ return events;
29
+ }
30
+ /**
31
+ * Builds dashboard metrics from a local event log.
32
+ */
33
+ export function summarizeDashboard(options = {}) {
34
+ const eventLogPath = options.eventLogPath ?? DEFAULT_EVENT_LOG_PATH;
35
+ const recentLimit = Math.max(1, Math.trunc(options.recentLimit ?? 25));
36
+ const events = readDashboardEvents(eventLogPath);
37
+ const allowed = events.filter((event) => event.type === 'allow');
38
+ const blocked = events.filter((event) => event.type === 'block');
39
+ const costEvents = events.filter((event) => event.type === 'cost');
40
+ const estimatedSpendUsd = sum(allowed.map((event) => event.estimatedCost));
41
+ const estimatedSavingsUsd = sum(blocked.map((event) => event.estimatedCost));
42
+ const attemptedSpendUsd = costEvents.length
43
+ ? sum(costEvents.map((event) => event.estimatedCost))
44
+ : estimatedSpendUsd + estimatedSavingsUsd;
45
+ const actualSpendUsd = sum(events.map((event) => event.actualCost ?? 0));
46
+ const budgetUsd = options.budgetUsd;
47
+ return {
48
+ eventLogPath,
49
+ generatedAt: new Date().toISOString(),
50
+ budgetUsd,
51
+ budgetUsedPercent: budgetUsd && budgetUsd > 0 ? round((estimatedSpendUsd / budgetUsd) * 100, 2) : undefined,
52
+ requestsAllowed: allowed.length,
53
+ requestsBlocked: blocked.length,
54
+ estimatedSpendUsd: roundMoney(estimatedSpendUsd),
55
+ estimatedSavingsUsd: roundMoney(estimatedSavingsUsd),
56
+ attemptedSpendUsd: roundMoney(attemptedSpendUsd),
57
+ actualSpendUsd: roundMoney(actualSpendUsd),
58
+ loopDetections: blocked.filter((event) => event.code === 'LOOP_DETECTED').length,
59
+ retryDetections: blocked.filter((event) => event.code === 'RETRY_STORM_DETECTED').length,
60
+ recentEvents: events.slice(-recentLimit).reverse(),
61
+ };
62
+ }
63
+ /**
64
+ * Formats a dashboard summary for terminal output.
65
+ */
66
+ export function formatDashboardSummary(summary) {
67
+ const budgetLine = summary.budgetUsd === undefined
68
+ ? `Budget used: $${summary.estimatedSpendUsd.toFixed(6)} estimated`
69
+ : `Budget used: ${summary.budgetUsedPercent?.toFixed(2) ?? '0.00'}% ($${summary.estimatedSpendUsd.toFixed(6)} / $${summary.budgetUsd.toFixed(6)})`;
70
+ return [
71
+ 'AI CostGuard local dashboard',
72
+ `Event log: ${summary.eventLogPath}`,
73
+ budgetLine,
74
+ `Requests allowed: ${summary.requestsAllowed}`,
75
+ `Requests blocked: ${summary.requestsBlocked}`,
76
+ `Estimated spend: $${summary.estimatedSpendUsd.toFixed(6)}`,
77
+ `Estimated savings: $${summary.estimatedSavingsUsd.toFixed(6)}`,
78
+ `Attempted spend: $${summary.attemptedSpendUsd.toFixed(6)}`,
79
+ `Actual spend: $${summary.actualSpendUsd.toFixed(6)}`,
80
+ `Loop detections: ${summary.loopDetections}`,
81
+ `Retry detections: ${summary.retryDetections}`,
82
+ `Recent events: ${summary.recentEvents.length}`,
83
+ '',
84
+ ].join('\n');
85
+ }
86
+ /**
87
+ * Starts a local-only HTTP dashboard server.
88
+ */
89
+ export function startDashboardServer(options = {}) {
90
+ const host = options.host ?? DEFAULT_DASHBOARD_HOST;
91
+ const port = options.port ?? DEFAULT_DASHBOARD_PORT;
92
+ const server = createServer((request, response) => {
93
+ const summary = summarizeDashboard(options);
94
+ if (request.url?.startsWith('/events.json')) {
95
+ response.writeHead(200, { 'content-type': 'application/json; charset=utf-8' });
96
+ response.end(JSON.stringify(summary, null, 2));
97
+ return;
98
+ }
99
+ response.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
100
+ response.end(renderDashboardHtml(summary));
101
+ });
102
+ return new Promise((resolve, reject) => {
103
+ server.once('error', reject);
104
+ server.listen(port, host, () => {
105
+ server.off('error', reject);
106
+ const address = server.address();
107
+ const actualPort = typeof address === 'object' && address ? address.port : port;
108
+ resolve({ server, url: `http://${host}:${actualPort}` });
109
+ });
110
+ });
111
+ }
112
+ function renderDashboardHtml(summary) {
113
+ const recentRows = summary.recentEvents
114
+ .map((event) => `<tr>
115
+ <td>${escapeHtml(event.timestamp)}</td>
116
+ <td>${escapeHtml(event.type)}</td>
117
+ <td>${escapeHtml(event.code ?? '')}</td>
118
+ <td>${escapeHtml(event.model)}</td>
119
+ <td>${escapeHtml(event.scopeKey)}</td>
120
+ <td>$${event.estimatedCost.toFixed(6)}</td>
121
+ </tr>`)
122
+ .join('');
123
+ return `<!doctype html>
124
+ <html lang="en">
125
+ <head>
126
+ <meta charset="utf-8">
127
+ <meta name="viewport" content="width=device-width, initial-scale=1">
128
+ <title>AI CostGuard Local Dashboard</title>
129
+ <style>
130
+ body { margin: 0; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #101418; color: #eef2f4; }
131
+ main { max-width: 1120px; margin: 0 auto; padding: 32px 20px; }
132
+ h1 { margin: 0 0 8px; font-size: 32px; }
133
+ p { color: #a8b3bd; }
134
+ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin: 24px 0; }
135
+ .metric { border: 1px solid #2d363e; border-radius: 8px; padding: 16px; background: #161c22; }
136
+ .label { color: #8d99a5; font-size: 13px; }
137
+ .value { margin-top: 8px; font-size: 24px; font-weight: 700; }
138
+ table { width: 100%; border-collapse: collapse; margin-top: 20px; background: #161c22; }
139
+ th, td { border-bottom: 1px solid #2d363e; padding: 10px; text-align: left; font-size: 14px; }
140
+ th { color: #a8b3bd; }
141
+ code { color: #90cdf4; }
142
+ </style>
143
+ </head>
144
+ <body>
145
+ <main>
146
+ <h1>AI CostGuard Local Dashboard</h1>
147
+ <p>Local-only view generated from <code>${escapeHtml(summary.eventLogPath)}</code>. Refresh the page for updates.</p>
148
+ <section class="grid">
149
+ ${metric('Budget used', summary.budgetUsedPercent === undefined ? `$${summary.estimatedSpendUsd.toFixed(6)}` : `${summary.budgetUsedPercent.toFixed(2)}%`)}
150
+ ${metric('Requests allowed', String(summary.requestsAllowed))}
151
+ ${metric('Requests blocked', String(summary.requestsBlocked))}
152
+ ${metric('Estimated spend', `$${summary.estimatedSpendUsd.toFixed(6)}`)}
153
+ ${metric('Estimated savings', `$${summary.estimatedSavingsUsd.toFixed(6)}`)}
154
+ ${metric('Loop detections', String(summary.loopDetections))}
155
+ ${metric('Retry detections', String(summary.retryDetections))}
156
+ ${metric('Actual spend', `$${summary.actualSpendUsd.toFixed(6)}`)}
157
+ </section>
158
+ <h2>Recent Guard Events</h2>
159
+ <table>
160
+ <thead><tr><th>Time</th><th>Type</th><th>Code</th><th>Model</th><th>Scope</th><th>Estimated Cost</th></tr></thead>
161
+ <tbody>${recentRows || '<tr><td colspan="6">No events yet.</td></tr>'}</tbody>
162
+ </table>
163
+ </main>
164
+ </body>
165
+ </html>`;
166
+ }
167
+ function metric(label, value) {
168
+ return `<div class="metric"><div class="label">${escapeHtml(label)}</div><div class="value">${escapeHtml(value)}</div></div>`;
169
+ }
170
+ function parseDashboardEvent(line) {
171
+ try {
172
+ const value = JSON.parse(line);
173
+ if (value.version !== 1 || !value.timestamp || !value.type || !value.model || !value.scopeKey)
174
+ return undefined;
175
+ if (typeof value.estimatedCost !== 'number' || typeof value.tokens !== 'number')
176
+ return undefined;
177
+ return value;
178
+ }
179
+ catch {
180
+ return undefined;
181
+ }
182
+ }
183
+ function sum(values) {
184
+ return values.reduce((total, value) => total + value, 0);
185
+ }
186
+ function roundMoney(value) {
187
+ return round(value, 6);
188
+ }
189
+ function round(value, digits) {
190
+ const factor = 10 ** digits;
191
+ return Math.round(value * factor) / factor;
192
+ }
193
+ function escapeHtml(value) {
194
+ return value
195
+ .replaceAll('&', '&amp;')
196
+ .replaceAll('<', '&lt;')
197
+ .replaceAll('>', '&gt;')
198
+ .replaceAll('"', '&quot;')
199
+ .replaceAll("'", '&#39;');
200
+ }
201
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,YAAY,EAAe,MAAM,WAAW,CAAC;AAGtD,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AAC5D,MAAM,sBAAsB,GAAG,WAAW,CAAC;AAC3C,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAoDpC;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAY,GAAG,sBAAsB;IACvE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,EAAE,CAAC;IAEzC,MAAM,KAAK,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC;SAC7C,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,KAAK;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAA4B,EAAE;IAC/D,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,sBAAsB,CAAC;IACpE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACnE,MAAM,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IAC3E,MAAM,mBAAmB,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7E,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM;QACzC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACrD,CAAC,CAAC,iBAAiB,GAAG,mBAAmB,CAAC;IAC5C,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAEpC,OAAO;QACL,YAAY;QACZ,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,SAAS;QACT,iBAAiB,EAAE,SAAS,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,GAAG,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QAC3G,eAAe,EAAE,OAAO,CAAC,MAAM;QAC/B,eAAe,EAAE,OAAO,CAAC,MAAM;QAC/B,iBAAiB,EAAE,UAAU,CAAC,iBAAiB,CAAC;QAChD,mBAAmB,EAAE,UAAU,CAAC,mBAAmB,CAAC;QACpD,iBAAiB,EAAE,UAAU,CAAC,iBAAiB,CAAC;QAChD,cAAc,EAAE,UAAU,CAAC,cAAc,CAAC;QAC1C,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,MAAM;QAChF,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC,MAAM;QACxF,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE;KACnD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAyB;IAC9D,MAAM,UAAU,GACd,OAAO,CAAC,SAAS,KAAK,SAAS;QAC7B,CAAC,CAAC,iBAAiB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;QACnE,CAAC,CAAC,gBAAgB,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,MAAM,OAAO,OAAO,CAAC,iBAAiB,CAAC,OAAO,CACrG,CAAC,CACF,OAAO,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAE9C,OAAO;QACL,8BAA8B;QAC9B,cAAc,OAAO,CAAC,YAAY,EAAE;QACpC,UAAU;QACV,qBAAqB,OAAO,CAAC,eAAe,EAAE;QAC9C,qBAAqB,OAAO,CAAC,eAAe,EAAE;QAC9C,qBAAqB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QAC3D,uBAAuB,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QAC/D,qBAAqB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QAC3D,kBAAkB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QACrD,oBAAoB,OAAO,CAAC,cAAc,EAAE;QAC5C,qBAAqB,OAAO,CAAC,eAAe,EAAE;QAC9C,kBAAkB,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE;QAC/C,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAA4B,EAAE;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,sBAAsB,CAAC;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,sBAAsB,CAAC;IACpD,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;QAChD,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAE5C,IAAI,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC5C,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,iCAAiC,EAAE,CAAC,CAAC;YAC/E,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACxE,QAAQ,CAAC,GAAG,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAChF,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,IAAI,IAAI,UAAU,EAAE,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAyB;IACpD,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY;SACpC,GAAG,CACF,CAAC,KAAK,EAAE,EAAE,CAAC;cACH,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;cAC3B,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;cACtB,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;cAC5B,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC;cACvB,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;eACzB,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;YACjC,CACP;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,OAAO;;;;;;;;;;;;;;;;;;;;;;;;8CAwBqC,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC;;QAEtE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;QACxJ,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,CAAC,iBAAiB,EAAE,IAAI,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,MAAM,CAAC,mBAAmB,EAAE,IAAI,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACzD,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC3D,MAAM,CAAC,cAAc,EAAE,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;;;;;eAKxD,UAAU,IAAI,8CAA8C;;;;QAInE,CAAC;AACT,CAAC;AAED,SAAS,MAAM,CAAC,KAAa,EAAE,KAAa;IAC1C,OAAO,0CAA0C,UAAU,CAAC,KAAK,CAAC,4BAA4B,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC;AAChI,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QAC1D,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAC;QAChH,IAAI,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QAClG,OAAO,KAAuB,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,MAAyB;IACpC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,MAAc;IAC1C,MAAM,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- export { guard, GuardError, middleware } from './core/GuardFree.js';
2
- export { GuardPro, validateLicense, getProGuard } from './core/GuardPro.js';
3
- export type { GuardProConfig } from './core/GuardPro.js';
1
+ export { guard, guardFunction, GuardError, middleware } from './core/GuardFree.js';
2
+ export type { GuardedClient, GuardEventControls } from './core/GuardFree.js';
4
3
  export { getPricing, registerPricing, listPricing } from './pricing/index.js';
5
4
  export type { ModelPricing } from './pricing/index.js';
6
- export type { GuardConfig } from './core/types.js';
5
+ export type { GuardConfig, GuardErrorCode, GuardEvent, GuardEventHandler, GuardEventName, GuardScope, GuardState, GuardWebhookConfig, RequestContext, } from './core/types.js';
7
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EACV,WAAW,EACX,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,cAAc,GACf,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export { guard, GuardError, middleware } from './core/GuardFree.js';
2
- export { GuardPro, validateLicense, getProGuard } from './core/GuardPro.js';
1
+ export { guard, guardFunction, GuardError, middleware } from './core/GuardFree.js';
3
2
  export { getPricing, registerPricing, listPricing } from './pricing/index.js';
4
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1,11 +1,28 @@
1
+ /**
2
+ * Pricing entry expressed in USD per 1,000 tokens.
3
+ */
1
4
  export interface ModelPricing {
5
+ /** Model name or model family prefix. */
2
6
  model: string;
7
+ /** USD price per 1,000 input tokens. */
3
8
  inputPer1kTokens: number;
9
+ /** USD price per 1,000 output tokens. */
4
10
  outputPer1kTokens: number;
11
+ /** Date this pricing entry was last checked, formatted as YYYY-MM-DD. */
5
12
  lastUpdated: string;
13
+ /** Human-readable source for the pricing entry. */
6
14
  source: string;
7
15
  }
8
- export declare function getPricing(model: string, overrides?: ModelPricing[]): ModelPricing | undefined;
9
- export declare function registerPricing(entries: ModelPricing[]): void;
16
+ /**
17
+ * Returns pricing for a model from overrides, runtime entries, or built-in entries.
18
+ */
19
+ export declare function getPricing(model: string, overrides?: readonly ModelPricing[]): ModelPricing | undefined;
20
+ /**
21
+ * Registers or replaces runtime pricing entries by model name.
22
+ */
23
+ export declare function registerPricing(entries: readonly ModelPricing[]): void;
24
+ /**
25
+ * Lists built-in and runtime pricing entries, deduplicated by normalized model name.
26
+ */
10
27
  export declare function listPricing(): ModelPricing[];
11
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pricing/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAwDD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,YAAY,EAAO,GAAG,YAAY,GAAG,SAAS,CAkBlG;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAI7D;AAED,wBAAgB,WAAW,IAAI,YAAY,EAAE,CAY5C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pricing/index.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;CAChB;AA0GD;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,SAAS,YAAY,EAAO,GAAG,YAAY,GAAG,SAAS,CAuB3G;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAMtE;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,YAAY,EAAE,CAe5C"}
@@ -1,60 +1,114 @@
1
- /* MAINTENANCE: update BUILTIN_PRICING when model prices change.
2
- Check: https://openai.com/pricing and https://www.anthropic.com/pricing
3
- Update the lastUpdated field on every change. */
1
+ const STALE_PRICING_DAYS = 30;
4
2
  const BUILTIN_PRICING = [
3
+ {
4
+ model: 'gpt-5.5',
5
+ inputPer1kTokens: 0.005,
6
+ outputPer1kTokens: 0.03,
7
+ lastUpdated: '2026-06-07',
8
+ source: 'https://developers.openai.com/api/docs/pricing',
9
+ },
10
+ {
11
+ model: 'gpt-5.4',
12
+ inputPer1kTokens: 0.0025,
13
+ outputPer1kTokens: 0.015,
14
+ lastUpdated: '2026-06-07',
15
+ source: 'https://developers.openai.com/api/docs/pricing',
16
+ },
17
+ {
18
+ model: 'gpt-5.4-mini',
19
+ inputPer1kTokens: 0.00075,
20
+ outputPer1kTokens: 0.0045,
21
+ lastUpdated: '2026-06-07',
22
+ source: 'https://developers.openai.com/api/docs/pricing',
23
+ },
24
+ {
25
+ model: 'gpt-5.4-nano',
26
+ inputPer1kTokens: 0.0002,
27
+ outputPer1kTokens: 0.00125,
28
+ lastUpdated: '2026-06-07',
29
+ source: 'https://developers.openai.com/api/docs/pricing',
30
+ },
5
31
  {
6
32
  model: 'gpt-4',
7
33
  inputPer1kTokens: 0.03,
8
34
  outputPer1kTokens: 0.06,
9
35
  lastUpdated: '2026-05-21',
10
- source: 'https://openai.com/pricing'
36
+ source: 'https://openai.com/pricing',
11
37
  },
12
38
  {
13
39
  model: 'gpt-4o',
14
40
  inputPer1kTokens: 0.005,
15
41
  outputPer1kTokens: 0.015,
16
42
  lastUpdated: '2026-05-21',
17
- source: 'https://openai.com/pricing'
43
+ source: 'https://openai.com/pricing',
18
44
  },
19
45
  {
20
46
  model: 'gpt-4o-mini',
21
47
  inputPer1kTokens: 0.00015,
22
48
  outputPer1kTokens: 0.0006,
23
49
  lastUpdated: '2026-05-21',
24
- source: 'https://openai.com/pricing'
50
+ source: 'https://openai.com/pricing',
25
51
  },
26
52
  {
27
53
  model: 'gpt-3.5-turbo',
28
54
  inputPer1kTokens: 0.0005,
29
55
  outputPer1kTokens: 0.0015,
30
56
  lastUpdated: '2026-05-21',
31
- source: 'https://openai.com/pricing'
57
+ source: 'https://openai.com/pricing',
58
+ },
59
+ {
60
+ model: 'claude-opus-4.8',
61
+ inputPer1kTokens: 0.005,
62
+ outputPer1kTokens: 0.025,
63
+ lastUpdated: '2026-06-07',
64
+ source: 'https://claude.com/platform/api',
65
+ },
66
+ {
67
+ model: 'claude-sonnet-4.6',
68
+ inputPer1kTokens: 0.003,
69
+ outputPer1kTokens: 0.015,
70
+ lastUpdated: '2026-06-07',
71
+ source: 'https://claude.com/platform/api',
72
+ },
73
+ {
74
+ model: 'claude-haiku-4.5',
75
+ inputPer1kTokens: 0.001,
76
+ outputPer1kTokens: 0.005,
77
+ lastUpdated: '2026-06-07',
78
+ source: 'https://claude.com/platform/api',
32
79
  },
33
80
  {
34
81
  model: 'claude-3-opus',
35
82
  inputPer1kTokens: 0.015,
36
83
  outputPer1kTokens: 0.075,
37
84
  lastUpdated: '2026-05-21',
38
- source: 'https://www.anthropic.com/pricing'
85
+ source: 'https://www.anthropic.com/pricing',
39
86
  },
40
87
  {
41
88
  model: 'claude-3-sonnet',
42
89
  inputPer1kTokens: 0.003,
43
90
  outputPer1kTokens: 0.015,
44
91
  lastUpdated: '2026-05-21',
45
- source: 'https://www.anthropic.com/pricing'
92
+ source: 'https://www.anthropic.com/pricing',
46
93
  },
47
94
  {
48
95
  model: 'claude-3-haiku',
49
96
  inputPer1kTokens: 0.00025,
50
97
  outputPer1kTokens: 0.00125,
51
98
  lastUpdated: '2026-05-21',
52
- source: 'https://www.anthropic.com/pricing'
53
- }
99
+ source: 'https://www.anthropic.com/pricing',
100
+ },
54
101
  ];
55
102
  const runtimePricing = new Map();
103
+ const staleWarnings = new Set();
104
+ /**
105
+ * Returns pricing for a model from overrides, runtime entries, or built-in entries.
106
+ */
56
107
  export function getPricing(model, overrides = []) {
57
108
  const normalizedModel = normalizeModel(model);
109
+ warnIfAnyStale(overrides);
110
+ warnIfAnyStale(runtimePricing.values());
111
+ warnIfAnyStale(BUILTIN_PRICING);
58
112
  const overrideExact = findExact(normalizedModel, overrides);
59
113
  if (overrideExact)
60
114
  return overrideExact;
@@ -72,11 +126,18 @@ export function getPricing(model, overrides = []) {
72
126
  return builtinExact;
73
127
  return findFuzzy(normalizedModel, BUILTIN_PRICING);
74
128
  }
129
+ /**
130
+ * Registers or replaces runtime pricing entries by model name.
131
+ */
75
132
  export function registerPricing(entries) {
133
+ warnIfAnyStale(entries);
76
134
  for (const entry of entries) {
77
135
  runtimePricing.set(normalizeModel(entry.model), entry);
78
136
  }
79
137
  }
138
+ /**
139
+ * Lists built-in and runtime pricing entries, deduplicated by normalized model name.
140
+ */
80
141
  export function listPricing() {
81
142
  const merged = new Map();
82
143
  for (const entry of BUILTIN_PRICING) {
@@ -85,7 +146,9 @@ export function listPricing() {
85
146
  for (const entry of runtimePricing.values()) {
86
147
  merged.set(normalizeModel(entry.model), entry);
87
148
  }
88
- return Array.from(merged.values());
149
+ const entries = Array.from(merged.values());
150
+ warnIfAnyStale(entries);
151
+ return entries;
89
152
  }
90
153
  function findExact(model, entries) {
91
154
  return entries.find((entry) => normalizeModel(entry.model) === model);
@@ -94,10 +157,27 @@ function findFuzzy(model, entries) {
94
157
  const sortedEntries = [...entries].sort((a, b) => b.model.length - a.model.length);
95
158
  return sortedEntries.find((entry) => {
96
159
  const entryModel = normalizeModel(entry.model);
97
- return model.includes(entryModel) || entryModel.includes(model);
160
+ return model.startsWith(`${entryModel}-`) || model.startsWith(`${entryModel}:`);
98
161
  });
99
162
  }
100
163
  function normalizeModel(model) {
101
164
  return model.trim().toLowerCase();
102
165
  }
166
+ function warnIfAnyStale(entries) {
167
+ for (const entry of entries) {
168
+ warnIfStale(entry);
169
+ }
170
+ }
171
+ function warnIfStale(entry) {
172
+ const lastUpdatedMs = Date.parse(`${entry.lastUpdated}T00:00:00.000Z`);
173
+ if (!Number.isFinite(lastUpdatedMs))
174
+ return;
175
+ const ageDays = (Date.now() - lastUpdatedMs) / 86_400_000;
176
+ const warningKey = `${normalizeModel(entry.model)}:${entry.lastUpdated}`;
177
+ if (ageDays > STALE_PRICING_DAYS && !staleWarnings.has(warningKey)) {
178
+ staleWarnings.add(warningKey);
179
+ console.warn(`[AI CostGuard] Pricing for "${entry.model}" is older than ${STALE_PRICING_DAYS} days. ` +
180
+ `Last checked ${entry.lastUpdated}; verify ${entry.source}.`);
181
+ }
182
+ }
103
183
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pricing/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pricing/index.ts"],"names":[],"mappings":"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"}
package/dist/pro.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { GuardPro, getProGuard, validateLicense } from './core/GuardPro.js';
2
+ export type { GuardProConfig, GuardProRedisClient } from './core/GuardPro.js';
3
+ //# sourceMappingURL=pro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pro.d.ts","sourceRoot":"","sources":["../src/pro.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/pro.js ADDED
@@ -0,0 +1,2 @@
1
+ export { GuardPro, getProGuard, validateLicense } from './core/GuardPro.js';
2
+ //# sourceMappingURL=pro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pro.js","sourceRoot":"","sources":["../src/pro.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,51 @@
1
+ # Benchmarks
2
+
3
+ Benchmarks are local measurements, not universal guarantees. Hardware, Node version, model request shape, history size, and enabled behavior checks all matter.
4
+
5
+ Run:
6
+
7
+ ```bash
8
+ npm run build
9
+ npm run benchmark
10
+ ```
11
+
12
+ For shorter sanity runs:
13
+
14
+ ```bash
15
+ node benchmarks/run.mjs --iterations 500
16
+ ```
17
+
18
+ The benchmark script measures:
19
+
20
+ - Runtime overhead per guarded function call
21
+ - Approximate heap delta after guarded calls
22
+ - Benign false-positive scenario for repeated "again" prompts
23
+ - Loop detection block step for repeated prompts
24
+ - Cost-estimation sample boundaries
25
+
26
+ ## Current Local Result
27
+
28
+ Current local run:
29
+
30
+ - Date: `2026-06-08T13:03:42.459Z`
31
+ - Node: `v24.14.1`
32
+ - Platform: `win32`
33
+ - Iterations: `5000`
34
+ - Direct mocked async call: `0.000310 ms/call`
35
+ - Guarded mocked async call: `0.021001 ms/call`
36
+ - Added overhead: `0.020691 ms/call`
37
+ - Benign repeated "again" prompts blocked: `0`
38
+ - Repeated loop prompt blocked at step: `3`
39
+ - GC exposed for memory run: `false`
40
+
41
+ Do not quote benchmark numbers without the Node version, platform, iteration count, and date.
42
+
43
+ Generated benchmark output is intentionally not published in the npm package. Re-run the benchmark on your target runtime before using numbers in public claims.
44
+
45
+ ## Interpreting Results
46
+
47
+ - `runtimeOverhead.addedPerCallMs` is the local overhead added by the guard wrapper in the benchmark request shape.
48
+ - `memoryOverhead.heapDeltaBytes` is noisy unless Node runs with `--expose-gc`.
49
+ - `falsePositiveScenarios.blocked` should remain `0` for the included benign repeated "again" prompts.
50
+ - `loopDetectionBehavior.blockedAtStep` should show when a repeated loop is stopped.
51
+ - `costEstimationBoundaries` reports this package's dependency-free estimator, not exact provider tokenizer output.
@@ -0,0 +1,61 @@
1
+ # Local Dashboard
2
+
3
+ AI CostGuard includes a local-only dashboard command. It does not create an account, send telemetry, or run a cloud backend.
4
+
5
+ The dashboard reads a JSONL event log written by guarded clients:
6
+
7
+ ```ts
8
+ import { guard } from '@salimassili/ai-costguard';
9
+
10
+ const openai = guard(client, {
11
+ budget: 5,
12
+ eventLogPath: '.ai-costguard/events.jsonl',
13
+ eventLogPrompt: 'none',
14
+ });
15
+ ```
16
+
17
+ Start the dashboard:
18
+
19
+ ```bash
20
+ ai-costguard dashboard --events .ai-costguard/events.jsonl --budget 5
21
+ ```
22
+
23
+ For scoped packages or one-off runs:
24
+
25
+ ```bash
26
+ npx @salimassili/ai-costguard dashboard --events .ai-costguard/events.jsonl --budget 5
27
+ ```
28
+
29
+ If the package is installed locally, this also works:
30
+
31
+ ```bash
32
+ npx ai-costguard dashboard --events .ai-costguard/events.jsonl --budget 5
33
+ ```
34
+
35
+ ## What It Shows
36
+
37
+ - Budget used
38
+ - Requests allowed
39
+ - Requests blocked
40
+ - Estimated spend
41
+ - Estimated savings
42
+ - Attempted spend
43
+ - Actual spend when provider usage is available
44
+ - Loop detections
45
+ - Retry detections
46
+ - Recent guard events
47
+
48
+ ## Non-Interactive Summary
49
+
50
+ Use `--once` for CI, smoke tests, or terminal summaries:
51
+
52
+ ```bash
53
+ ai-costguard dashboard --events .ai-costguard/events.jsonl --budget 5 --once
54
+ ai-costguard dashboard --events .ai-costguard/events.jsonl --budget 5 --once --json
55
+ ```
56
+
57
+ ## Privacy Notes
58
+
59
+ `eventLogPrompt` defaults to `none`, so prompt text is not written to disk. Set `eventLogPrompt: 'preview'` only for local debugging where prompt previews are acceptable.
60
+
61
+ The dashboard is a local development view, not a billing ledger. Use provider billing exports for financial reconciliation.