@agentguard-run/spend 0.1.7 → 0.1.8
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/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/serve.d.ts +10 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +334 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA8BH,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyClF"}
|
package/dist/cli/main.js
CHANGED
|
@@ -55,6 +55,7 @@ commands:
|
|
|
55
55
|
init Scaffold a project (policy.yaml + quickstart + .gitignore).
|
|
56
56
|
doctor Check installation health and configuration.
|
|
57
57
|
explain Decode a signed receipt with cap math + signature breakdown.
|
|
58
|
+
serve Open a local dashboard at http://localhost:8787.
|
|
58
59
|
--version Show the installed SDK version.
|
|
59
60
|
--help Show this help.
|
|
60
61
|
|
|
@@ -99,6 +100,10 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
99
100
|
const { runExplain } = await Promise.resolve().then(() => __importStar(require('./explain')));
|
|
100
101
|
return runExplain(rest);
|
|
101
102
|
}
|
|
103
|
+
if (command === 'serve') {
|
|
104
|
+
const { runServe } = await Promise.resolve().then(() => __importStar(require('./serve')));
|
|
105
|
+
return runServe(rest);
|
|
106
|
+
}
|
|
102
107
|
process.stderr.write(`agentguard: unknown command '${command}'\n\n`);
|
|
103
108
|
process.stderr.write(HELP);
|
|
104
109
|
return 2;
|
package/dist/cli/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BH,oBAyCC;AArED,oCAAoD;AAEpD,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBZ,CAAC;AAEK,KAAK,UAAU,IAAI,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,cAAc,gCAAwB,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE3B,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,OAAO,EAAE,GAAG,wDAAa,QAAQ,GAAC,CAAC;QAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,EAAE,SAAS,EAAE,GAAG,wDAAa,UAAU,GAAC,CAAC;QAC/C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,OAAO,EAAE,GAAG,wDAAa,QAAQ,GAAC,CAAC;QAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,EAAE,SAAS,EAAE,GAAG,wDAAa,UAAU,GAAC,CAAC;QAC/C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,EAAE,UAAU,EAAE,GAAG,wDAAa,WAAW,GAAC,CAAC;QACjD,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,QAAQ,EAAE,GAAG,wDAAa,SAAS,GAAC,CAAC;QAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,OAAO,OAAO,CAAC,CAAC;IACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,8CAA8C;AAC9C,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,CAAC,IAAI,CACT,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAC5B,CAAC,GAAG,EAAE,EAAE;QACN,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentguard serve` — local dashboard at localhost:8787 (configurable).
|
|
3
|
+
*
|
|
4
|
+
* Aggregates per-tenant decision logs under ~/.agentguard/<tenant>/decisions.ndjson
|
|
5
|
+
* + ~/.agentguard/demo/decisions.ndjson and serves a single-page dashboard.
|
|
6
|
+
*
|
|
7
|
+
* No outbound network calls. Pure Node stdlib HTTP server.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runServe(argv: string[]): Promise<number>;
|
|
10
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/cli/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiLH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA8G9D"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `agentguard serve` — local dashboard at localhost:8787 (configurable).
|
|
4
|
+
*
|
|
5
|
+
* Aggregates per-tenant decision logs under ~/.agentguard/<tenant>/decisions.ndjson
|
|
6
|
+
* + ~/.agentguard/demo/decisions.ndjson and serves a single-page dashboard.
|
|
7
|
+
*
|
|
8
|
+
* No outbound network calls. Pure Node stdlib HTTP server.
|
|
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.runServe = runServe;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const http = __importStar(require("http"));
|
|
47
|
+
const os = __importStar(require("os"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const index_1 = require("../index");
|
|
50
|
+
const decision_log_1 = require("../decision-log");
|
|
51
|
+
const colors_1 = require("./colors");
|
|
52
|
+
const AGENTGUARD_HOME = path.join(os.homedir(), '.agentguard');
|
|
53
|
+
function scanLogFiles() {
|
|
54
|
+
if (!fs.existsSync(AGENTGUARD_HOME))
|
|
55
|
+
return [];
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const entry of fs.readdirSync(AGENTGUARD_HOME, { withFileTypes: true })) {
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
const candidate = path.join(AGENTGUARD_HOME, entry.name, 'decisions.ndjson');
|
|
60
|
+
if (fs.existsSync(candidate))
|
|
61
|
+
out.push(candidate);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return out.sort();
|
|
65
|
+
}
|
|
66
|
+
function loadAllDecisions() {
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const logPath of scanLogFiles()) {
|
|
69
|
+
const tenant = path.basename(path.dirname(logPath));
|
|
70
|
+
try {
|
|
71
|
+
const content = fs.readFileSync(logPath, 'utf-8');
|
|
72
|
+
for (const line of content.split('\n')) {
|
|
73
|
+
if (!line.trim())
|
|
74
|
+
continue;
|
|
75
|
+
try {
|
|
76
|
+
const d = JSON.parse(line);
|
|
77
|
+
d._tenant = tenant;
|
|
78
|
+
out.push(d);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// skip malformed line
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// skip unreadable file
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
function computeStats(decisions) {
|
|
92
|
+
const totalCalls = decisions.length;
|
|
93
|
+
const blockedCount = decisions.filter((d) => d.decision?.action === 'block').length;
|
|
94
|
+
const downgradeCount = decisions.filter((d) => d.decision?.action === 'downgrade').length;
|
|
95
|
+
const allowCount = totalCalls - blockedCount - downgradeCount;
|
|
96
|
+
const spentCents = decisions
|
|
97
|
+
.filter((d) => ['allow', 'downgrade'].includes(d.decision?.action))
|
|
98
|
+
.reduce((sum, d) => sum + (d.decision.projectedCents || 0), 0);
|
|
99
|
+
const savedCents = decisions
|
|
100
|
+
.filter((d) => d.decision?.action === 'block')
|
|
101
|
+
.reduce((sum, d) => sum + (d.decision.projectedCents || 0), 0);
|
|
102
|
+
const byAgent = {};
|
|
103
|
+
const byProvider = {};
|
|
104
|
+
for (const d of decisions) {
|
|
105
|
+
if (!['allow', 'downgrade'].includes(d.decision?.action))
|
|
106
|
+
continue;
|
|
107
|
+
const scopeKey = d.decision?.triggeredScopeKey || '';
|
|
108
|
+
let agentId = 'unknown';
|
|
109
|
+
for (const part of scopeKey.split('|')) {
|
|
110
|
+
if (part.startsWith('agentId=')) {
|
|
111
|
+
agentId = part.slice(8);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
byAgent[agentId] = (byAgent[agentId] || 0) + (d.decision.projectedCents || 0);
|
|
116
|
+
const prov = d.decision.provider || 'unknown';
|
|
117
|
+
byProvider[prov] = (byProvider[prov] || 0) + (d.decision.projectedCents || 0);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
totals: {
|
|
121
|
+
spent_cents: spentCents,
|
|
122
|
+
saved_cents: savedCents,
|
|
123
|
+
calls: totalCalls,
|
|
124
|
+
blocked: blockedCount,
|
|
125
|
+
downgraded: downgradeCount,
|
|
126
|
+
allowed: allowCount,
|
|
127
|
+
},
|
|
128
|
+
by_agent: Object.entries(byAgent).map(([k, v]) => ({ agent: k, spent_cents: v })).sort((a, b) => b.spent_cents - a.spent_cents),
|
|
129
|
+
by_provider: Object.entries(byProvider).map(([k, v]) => ({ provider: k, spent_cents: v })).sort((a, b) => b.spent_cents - a.spent_cents),
|
|
130
|
+
recent: decisions.slice(-50).reverse(),
|
|
131
|
+
version: index_1.AGENTGUARD_SPEND_VERSION,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Dashboard HTML — IDENTICAL to the Python version so users see the same UI
|
|
135
|
+
// whether they ran `pip install agentguard-spend` or `npm install -g`.
|
|
136
|
+
const DASHBOARD_HTML = `<!doctype html>
|
|
137
|
+
<html lang="en"><head><meta charset="utf-8" />
|
|
138
|
+
<title>AgentGuard Spend · Local Dashboard</title>
|
|
139
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
140
|
+
<style>
|
|
141
|
+
:root { --bg:#07101E; --surface:#0C1828; --surface-2:#0F1F35; --border:rgba(42,188,180,0.18); --border-dim:rgba(255,255,255,0.08); --teal:#2abcb4; --teal-glow:rgba(42,188,180,0.15); --text:#FFF; --text-2:#DCE8F0; --muted:#8AA0B3; --green:#4ade80; --amber:#F1C40F; --red:#FF6B6B; --code:#E6F0F5; }
|
|
142
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
143
|
+
html, body { background: var(--bg); color: var(--text-2); font-family: 'DM Sans', -apple-system, system-ui, sans-serif; font-size: 15px; min-height: 100vh; -webkit-font-smoothing: antialiased; }
|
|
144
|
+
a { color: var(--teal); text-decoration: none; } a:hover { text-decoration: underline; }
|
|
145
|
+
code, .mono { font-family: 'JetBrains Mono', monospace; font-size: 13px; }
|
|
146
|
+
.topbar { display: flex; align-items: center; justify-content: space-between; padding: 16px 32px; border-bottom: 1px solid var(--border-dim); background: rgba(7,16,30,0.92); backdrop-filter: blur(10px); position: sticky; top: 0; z-index: 50; }
|
|
147
|
+
.brand { display: inline-flex; align-items: center; gap: 12px; }
|
|
148
|
+
.brand .hex { width: 22px; height: 22px; background: var(--teal); color: var(--bg); display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; border-radius: 4px; }
|
|
149
|
+
.brand .name { font-family: 'Cormorant Garamond', Georgia, serif; font-size: 22px; color: var(--text); }
|
|
150
|
+
.brand .name .accent { color: var(--teal); }
|
|
151
|
+
.brand .tag { margin-left: 8px; font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; color: var(--teal); padding: 3px 8px; border: 1px solid var(--border); border-radius: 3px; }
|
|
152
|
+
.refresh-btn { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--teal); background: transparent; border: 1px solid var(--teal); border-radius: 4px; padding: 7px 14px; cursor: pointer; }
|
|
153
|
+
.refresh-btn:hover { background: var(--teal-glow); }
|
|
154
|
+
.shell { padding: 32px; max-width: 1280px; margin: 0 auto; }
|
|
155
|
+
.stats-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 28px; }
|
|
156
|
+
@media (max-width: 800px) { .stats-row { grid-template-columns: repeat(2, 1fr); } }
|
|
157
|
+
.stat-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 18px 20px; }
|
|
158
|
+
.stat-card .label { font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
|
|
159
|
+
.stat-card .value { font-size: 28px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
|
|
160
|
+
.stat-card.green .value { color: var(--green); }
|
|
161
|
+
.stat-card.red .value { color: var(--red); }
|
|
162
|
+
.stat-card.amber .value { color: var(--amber); }
|
|
163
|
+
.stat-card .sub { color: var(--muted); font-size: 12px; margin-top: 4px; }
|
|
164
|
+
.section { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 24px 26px; margin-bottom: 24px; }
|
|
165
|
+
.section h2 { font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.15em; text-transform: uppercase; color: var(--teal); margin-bottom: 16px; }
|
|
166
|
+
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
|
|
167
|
+
@media (max-width: 800px) { .two-col { grid-template-columns: 1fr; } }
|
|
168
|
+
.bar-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border-dim); font-size: 13.5px; }
|
|
169
|
+
.bar-row:last-child { border-bottom: none; }
|
|
170
|
+
.bar-row .name { width: 35%; color: var(--text); }
|
|
171
|
+
.bar-row .bar { flex: 1; height: 10px; background: var(--surface-2); border-radius: 2px; overflow: hidden; }
|
|
172
|
+
.bar-row .bar-fill { height: 100%; background: var(--teal); transition: width 0.4s; }
|
|
173
|
+
.bar-row .amount { width: 80px; text-align: right; color: var(--green); font-weight: 700; font-family: 'JetBrains Mono', monospace; font-size: 13px; }
|
|
174
|
+
table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
175
|
+
th { text-align: left; padding: 10px 12px; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--border); }
|
|
176
|
+
td { padding: 12px; border-bottom: 1px solid var(--border-dim); vertical-align: top; }
|
|
177
|
+
td.action-block { color: var(--red); font-weight: 700; }
|
|
178
|
+
td.action-downgrade { color: var(--amber); font-weight: 700; }
|
|
179
|
+
td.action-allow { color: var(--green); }
|
|
180
|
+
td.action-shadow { color: var(--muted); }
|
|
181
|
+
td .mono { color: var(--code); }
|
|
182
|
+
.pill { display: inline-block; padding: 2px 8px; border-radius: 3px; font-family: 'JetBrains Mono', monospace; font-size: 11px; background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border-dim); }
|
|
183
|
+
.empty { text-align: center; padding: 56px 20px; color: var(--muted); font-size: 14px; }
|
|
184
|
+
.empty code { display: block; margin-top: 8px; font-size: 14px; color: var(--teal); }
|
|
185
|
+
.live-indicator { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--green); margin-right: 6px; animation: pulse 2s ease-in-out infinite; }
|
|
186
|
+
@keyframes pulse { 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(74,222,128,0.4); } 50% { opacity: 0.7; box-shadow: 0 0 0 6px rgba(74,222,128,0); } }
|
|
187
|
+
</style></head><body>
|
|
188
|
+
<div class="topbar">
|
|
189
|
+
<div class="brand"><span class="hex">⬡</span><span class="name">Agent<span class="accent">Guard</span></span><span class="tag">Spend · Local Dashboard</span></div>
|
|
190
|
+
<div><span class="mono" style="color: var(--muted); margin-right: 16px;"><span class="live-indicator"></span>v__VERSION__ · localhost:__PORT__</span><button class="refresh-btn" onclick="loadStats()">Refresh</button></div>
|
|
191
|
+
</div>
|
|
192
|
+
<div class="shell">
|
|
193
|
+
<div class="stats-row">
|
|
194
|
+
<div class="stat-card green"><div class="label">Spent (all-time)</div><div class="value" id="spent">$0.00</div><div class="sub" id="spent-sub">across <span id="call-count">0</span> calls</div></div>
|
|
195
|
+
<div class="stat-card red"><div class="label">Saved by blocks</div><div class="value" id="saved">+$0.00</div><div class="sub"><span id="blocked-count">0</span> calls blocked</div></div>
|
|
196
|
+
<div class="stat-card amber"><div class="label">Downgraded</div><div class="value" id="downgraded">0</div><div class="sub">calls routed to cheaper model</div></div>
|
|
197
|
+
<div class="stat-card"><div class="label">Allowed</div><div class="value" id="allowed">0</div><div class="sub">policy-checked & passed</div></div>
|
|
198
|
+
</div>
|
|
199
|
+
<div class="two-col">
|
|
200
|
+
<div class="section"><h2>Spend by Agent</h2><div id="by-agent"></div></div>
|
|
201
|
+
<div class="section"><h2>Spend by Provider</h2><div id="by-provider"></div></div>
|
|
202
|
+
</div>
|
|
203
|
+
<div class="section">
|
|
204
|
+
<h2>Recent Decisions</h2>
|
|
205
|
+
<table><thead><tr><th style="width:80px">Action</th><th>Agent</th><th>Provider · Model</th><th style="width:120px;text-align:right">Amount</th><th style="width:120px">Receipt</th></tr></thead><tbody id="recent-rows"></tbody></table>
|
|
206
|
+
</div>
|
|
207
|
+
<div style="text-align: center; color: var(--muted); font-size: 12px; margin-top: 32px;">Local-only. No outbound network calls. Reads from <code class="mono">~/.agentguard/*/decisions.ndjson</code>.<br/>Source: <a href="https://agentguard.run">agentguard.run</a> · <a href="https://www.npmjs.com/package/@agentguard-run/spend">npm</a> · <a href="https://pypi.org/project/agentguard-spend/">pypi</a></div>
|
|
208
|
+
</div>
|
|
209
|
+
<script>
|
|
210
|
+
function formatCents(cents) { const sign = cents < 0 ? '-' : ''; const abs = Math.abs(Math.round(cents)); const dollars = Math.floor(abs / 100); const remainder = abs % 100; return sign + '$' + dollars.toLocaleString() + '.' + String(remainder).padStart(2, '0'); }
|
|
211
|
+
function renderBars(containerId, items, key) { const el = document.getElementById(containerId); if (!items.length) { el.innerHTML = '<div style="color:var(--muted);font-size:13px;padding:8px 0">no data yet</div>'; return; } const max = Math.max(...items.map(i => i.spent_cents)) || 1; el.innerHTML = items.slice(0, 8).map(i => '<div class="bar-row"><span class="name">' + i[key] + '</span><span class="bar"><span class="bar-fill" style="width:' + (i.spent_cents/max*100).toFixed(1) + '%"></span></span><span class="amount">' + formatCents(i.spent_cents) + '</span></div>').join(''); }
|
|
212
|
+
function renderRecent(items) { const tbody = document.getElementById('recent-rows'); if (!items.length) { tbody.innerHTML = '<tr><td colspan="5"><div class="empty">no decisions yet.<br>run <code>agentguard demo</code> to see a real signed receipt here.</div></td></tr>'; return; } tbody.innerHTML = items.map(d => { const dec = d.decision; const scope = dec.triggeredScopeKey || ''; const agentMatch = scope.match(/agentId=([^|]+)/); const agent = agentMatch ? agentMatch[1] : '<span style="color:var(--muted)">—</span>'; const action = dec.action || 'allow'; return '<tr><td class="action-' + action + '">' + action.toUpperCase() + '</td><td class="mono">' + agent + '</td><td><span class="pill">' + (dec.provider || '?') + '</span> ' + (dec.modelRequested || '') + '</td><td style="text-align:right" class="mono">' + formatCents(dec.projectedCents || 0) + '</td><td class="mono"><a href="#" onclick="return verifyReceipt(\\'' + d.entryHash + '\\')">' + d.entryHash.slice(0, 12) + '...</a></td></tr>'; }).join(''); }
|
|
213
|
+
async function verifyReceipt(hash) { try { const r = await fetch('/api/verify/' + hash); const d = await r.json(); alert(d.ok ? '✓ verified: signature valid, hash matches, chain intact' : '✗ verification failed: ' + (d.reason || 'unknown')); } catch (e) { alert('verify error: ' + e); } return false; }
|
|
214
|
+
async function loadStats() { try { const r = await fetch('/api/stats'); const s = await r.json(); document.getElementById('spent').textContent = formatCents(s.totals.spent_cents); document.getElementById('saved').textContent = '+' + formatCents(s.totals.saved_cents); document.getElementById('downgraded').textContent = s.totals.downgraded; document.getElementById('allowed').textContent = s.totals.allowed; document.getElementById('call-count').textContent = s.totals.calls; document.getElementById('blocked-count').textContent = s.totals.blocked; renderBars('by-agent', s.by_agent, 'agent'); renderBars('by-provider', s.by_provider, 'provider'); renderRecent(s.recent); } catch (e) { console.error('load failed:', e); } }
|
|
215
|
+
loadStats();
|
|
216
|
+
setInterval(loadStats, 5000);
|
|
217
|
+
</script></body></html>
|
|
218
|
+
`;
|
|
219
|
+
async function runServe(argv) {
|
|
220
|
+
let port = 8787;
|
|
221
|
+
let host = '127.0.0.1';
|
|
222
|
+
let noOpen = false;
|
|
223
|
+
for (let i = 0; i < argv.length; i++) {
|
|
224
|
+
const a = argv[i];
|
|
225
|
+
if (a === '--port')
|
|
226
|
+
port = parseInt(argv[++i] ?? '8787', 10);
|
|
227
|
+
else if (a === '--host')
|
|
228
|
+
host = argv[++i] ?? '127.0.0.1';
|
|
229
|
+
else if (a === '--no-open')
|
|
230
|
+
noOpen = true;
|
|
231
|
+
else if (a === '--help' || a === '-h') {
|
|
232
|
+
console.log('agentguard serve [--port 8787] [--host 127.0.0.1] [--no-open]');
|
|
233
|
+
return 0;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
console.log('');
|
|
237
|
+
console.log(' ' + (0, colors_1.banner)(index_1.AGENTGUARD_SPEND_VERSION));
|
|
238
|
+
console.log('');
|
|
239
|
+
console.log(' ' + (0, colors_1.cyanBold)('agentguard serve') + (0, colors_1.dim)(' · local dashboard'));
|
|
240
|
+
console.log('');
|
|
241
|
+
const logFiles = scanLogFiles();
|
|
242
|
+
if (logFiles.length === 0) {
|
|
243
|
+
console.log(` ${(0, colors_1.dim)('no decision logs found yet at ~/.agentguard/*/decisions.ndjson')}`);
|
|
244
|
+
console.log(` ${(0, colors_1.dim)('run')} ${(0, colors_1.greenBold)('agentguard demo')} ${(0, colors_1.dim)('to produce one, then refresh.')}`);
|
|
245
|
+
console.log('');
|
|
246
|
+
}
|
|
247
|
+
const server = http.createServer(async (req, res) => {
|
|
248
|
+
const url = (req.url || '/').split('?')[0];
|
|
249
|
+
const sendJSON = (status, payload) => {
|
|
250
|
+
const body = JSON.stringify(payload);
|
|
251
|
+
res.writeHead(status, {
|
|
252
|
+
'Content-Type': 'application/json',
|
|
253
|
+
'Content-Length': Buffer.byteLength(body).toString(),
|
|
254
|
+
'Cache-Control': 'no-store',
|
|
255
|
+
});
|
|
256
|
+
res.end(body);
|
|
257
|
+
};
|
|
258
|
+
const sendHTML = (html) => {
|
|
259
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });
|
|
260
|
+
res.end(html);
|
|
261
|
+
};
|
|
262
|
+
if (url === '/' || url === '/index.html') {
|
|
263
|
+
sendHTML(DASHBOARD_HTML.replace('__VERSION__', index_1.AGENTGUARD_SPEND_VERSION).replace('__PORT__', String(port)));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (url === '/api/stats') {
|
|
267
|
+
sendJSON(200, computeStats(loadAllDecisions()));
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (url.startsWith('/api/verify/')) {
|
|
271
|
+
const entryHash = url.split('/').pop();
|
|
272
|
+
const decisions = loadAllDecisions();
|
|
273
|
+
const match = decisions.find((d) => d.entryHash === entryHash);
|
|
274
|
+
if (!match) {
|
|
275
|
+
sendJSON(404, { ok: false, reason: 'receipt not found' });
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const publicKeyHex = match.publicKeyHex;
|
|
280
|
+
if (!publicKeyHex) {
|
|
281
|
+
sendJSON(400, { ok: false, reason: 'no public key in stored receipt' });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const publicKey = Uint8Array.from(Buffer.from(publicKeyHex, 'hex'));
|
|
285
|
+
const entry = {
|
|
286
|
+
sequence: match.sequence,
|
|
287
|
+
entryHash: match.entryHash,
|
|
288
|
+
previousHash: match.previousHash,
|
|
289
|
+
signature: match.signature,
|
|
290
|
+
signerFingerprint: match.signerFingerprint,
|
|
291
|
+
decision: match.decision,
|
|
292
|
+
};
|
|
293
|
+
const ok = await (0, decision_log_1.verifyEntry)(entry, publicKey);
|
|
294
|
+
sendJSON(200, { ok: Boolean(ok) });
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
sendJSON(500, { ok: false, reason: String(e?.message || e) });
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
sendJSON(404, { error: 'not found' });
|
|
302
|
+
});
|
|
303
|
+
const url = `http://${host}:${port}`;
|
|
304
|
+
server.listen(port, host, () => {
|
|
305
|
+
console.log(` ${(0, colors_1.green)('→')} dashboard: ${(0, colors_1.greenBold)(url)}`);
|
|
306
|
+
console.log(` ${(0, colors_1.dim)(' reading: ~/.agentguard/*/decisions.ndjson')}`);
|
|
307
|
+
console.log(` ${(0, colors_1.dim)(' press Ctrl+C to stop')}`);
|
|
308
|
+
console.log('');
|
|
309
|
+
if (!noOpen) {
|
|
310
|
+
setTimeout(() => {
|
|
311
|
+
try {
|
|
312
|
+
const { exec } = require('child_process');
|
|
313
|
+
const cmd = process.platform === 'darwin'
|
|
314
|
+
? `open "${url}"`
|
|
315
|
+
: process.platform === 'win32'
|
|
316
|
+
? `start "" "${url}"`
|
|
317
|
+
: `xdg-open "${url}"`;
|
|
318
|
+
exec(cmd);
|
|
319
|
+
}
|
|
320
|
+
catch { /* best-effort */ }
|
|
321
|
+
}, 400);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
process.on('SIGINT', () => {
|
|
325
|
+
console.log('');
|
|
326
|
+
console.log(` ${(0, colors_1.green)('✓')} dashboard stopped`);
|
|
327
|
+
console.log('');
|
|
328
|
+
server.close();
|
|
329
|
+
process.exit(0);
|
|
330
|
+
});
|
|
331
|
+
// Keep alive
|
|
332
|
+
return new Promise(() => { });
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/cli/serve.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export { canonicalJson, sha256Hex, computeEntryHash, computeSignerFingerprint, s
|
|
|
12
12
|
export { InMemorySpendStore } from './store-memory';
|
|
13
13
|
export { SpendGuard, withSpendGuard, AgentGuardBlockedError, type SpendGuardConfig, type OpenAIBindingOptions, } from './spend-guard';
|
|
14
14
|
export { DEFAULT_LOCALE, SUPPORTED_LOCALES, TRANSLATIONS, type SupportedLocale, resolveLocale, t, formatBlockedTrace, type BlockedTraceArgs, } from './i18n';
|
|
15
|
-
export declare const AGENTGUARD_SPEND_VERSION = "0.1.
|
|
15
|
+
export declare const AGENTGUARD_SPEND_VERSION = "0.1.8";
|
|
16
16
|
/** Patent marking. 35 U.S.C. § 287 constructive notice. */
|
|
17
17
|
export declare const PATENT_NOTICE: string;
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ Object.defineProperty(exports, "TRANSLATIONS", { enumerable: true, get: function
|
|
|
46
46
|
Object.defineProperty(exports, "resolveLocale", { enumerable: true, get: function () { return i18n_1.resolveLocale; } });
|
|
47
47
|
Object.defineProperty(exports, "t", { enumerable: true, get: function () { return i18n_1.t; } });
|
|
48
48
|
Object.defineProperty(exports, "formatBlockedTrace", { enumerable: true, get: function () { return i18n_1.formatBlockedTrace; } });
|
|
49
|
-
exports.AGENTGUARD_SPEND_VERSION = '0.1.
|
|
49
|
+
exports.AGENTGUARD_SPEND_VERSION = '0.1.8';
|
|
50
50
|
/** Patent marking. 35 U.S.C. § 287 constructive notice. */
|
|
51
51
|
exports.PATENT_NOTICE = 'Protected by U.S. patent-pending technology ' +
|
|
52
52
|
'(App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626; ' +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentguard-run/spend",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Local-runtime spend caps and capability-gated model routing for AI agents. Prompts, API keys, and signing keys stay inside the customer runtime. Zero data plane involvement.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|