ambitry 0.1.3 → 0.1.5
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/parse.js +7 -2
- package/dist/viewer.js +28 -9
- package/package.json +1 -1
package/dist/parse.js
CHANGED
|
@@ -94,7 +94,11 @@ export class ResponseParser {
|
|
|
94
94
|
this.outputTokens = e.message?.usage?.output_tokens ?? this.outputTokens;
|
|
95
95
|
break;
|
|
96
96
|
case 'content_block_start':
|
|
97
|
-
|
|
97
|
+
// server_tool_use covers Anthropic's own tools (web search, code
|
|
98
|
+
// execution). They are calls the agent made and belong in the audit
|
|
99
|
+
// log; matching only tool_use leaves them invisible to both the trace
|
|
100
|
+
// and the policy.
|
|
101
|
+
if (e.content_block?.type === 'tool_use' || e.content_block?.type === 'server_tool_use') {
|
|
98
102
|
this.partial.set(e.index, { name: e.content_block.name, json: '' });
|
|
99
103
|
}
|
|
100
104
|
break;
|
|
@@ -176,7 +180,8 @@ export class ResponseParser {
|
|
|
176
180
|
this.outputTokens = json.usage?.output_tokens ?? null;
|
|
177
181
|
const content = json.content ?? [];
|
|
178
182
|
for (let i = 0; i < content.length; i++) {
|
|
179
|
-
|
|
183
|
+
const type = content[i]?.type;
|
|
184
|
+
if (type === 'tool_use' || type === 'server_tool_use') {
|
|
180
185
|
this.done.push({ name: content[i].name, input: content[i].input ?? {}, index: i });
|
|
181
186
|
}
|
|
182
187
|
}
|
package/dist/viewer.js
CHANGED
|
@@ -103,13 +103,20 @@ function toolCells(t) {
|
|
|
103
103
|
}).join('');
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
function meter(label, spent, cap) {
|
|
106
|
+
function meter(label, spent, cap, unpriced) {
|
|
107
107
|
const pct = cap ? Math.min(100, (spent / cap) * 100) : 0;
|
|
108
|
+
// An unpriced model contributes nothing to the total, so the figure is a
|
|
109
|
+
// floor rather than the spend. Saying so beats implying a precise zero.
|
|
110
|
+
const note = unpriced
|
|
111
|
+
? unpriced + ' request' + (unpriced === 1 ? '' : 's') + ' unpriced'
|
|
112
|
+
: (cap ? null : 'no cap set');
|
|
108
113
|
const bar = cap
|
|
109
114
|
? '<div class="bar' + (pct > 80 ? ' hot' : '') + '"><i style="width:' + pct + '%"></i></div>'
|
|
110
|
-
: '
|
|
111
|
-
return '<div class="card"><div class="k">' + label + '</div><div class="v">' +
|
|
112
|
-
(
|
|
115
|
+
: '';
|
|
116
|
+
return '<div class="card"><div class="k">' + label + '</div><div class="v">' +
|
|
117
|
+
(unpriced ? '≥ ' : '') + money(spent) +
|
|
118
|
+
(cap ? ' <span class="muted" style="font-size:13px">/ ' + money(cap) + '</span>' : '') + '</div>' +
|
|
119
|
+
bar + (note ? '<div class="k" style="margin-top:8px">' + note + '</div>' : '') + '</div>';
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
async function refresh() {
|
|
@@ -143,15 +150,27 @@ async function refresh() {
|
|
|
143
150
|
// Counts denied tool calls as well as rejected requests. Tool denial
|
|
144
151
|
// returns 200 with the call stripped, so counting status codes alone
|
|
145
152
|
// reports zero blocks while enforcement is visibly working.
|
|
146
|
-
const
|
|
147
|
-
|
|
153
|
+
const byPolicy = traces.reduce((n, t) => n + (t.denied_count || 0), 0);
|
|
154
|
+
const stopped = traces.filter(t => t.status === 403).length;
|
|
155
|
+
const blocked = byPolicy + stopped;
|
|
156
|
+
// Naming the cause matters: a kill-switch stop is not a policy denial, and
|
|
157
|
+
// labelling everything "by policy" contradicts the card beside it that
|
|
158
|
+
// says the proxy is only logging.
|
|
159
|
+
const cause = byPolicy && stopped ? 'policy and kill switch'
|
|
160
|
+
: byPolicy ? 'tool calls denied'
|
|
161
|
+
: stopped ? 'requests stopped'
|
|
162
|
+
: 'nothing blocked';
|
|
163
|
+
|
|
164
|
+
// A request whose model has no published rate contributes nothing to spend.
|
|
165
|
+
const unpriced = traces.filter(t => t.cost_usd === null && t.status === 200).length;
|
|
166
|
+
|
|
148
167
|
$('cards').innerHTML =
|
|
149
|
-
meter('Spend · last hour', status.spend.lastHour, status.limits.perHourUsd) +
|
|
150
|
-
meter('Spend · last day', status.spend.lastDay, status.limits.perDayUsd) +
|
|
168
|
+
meter('Spend · last hour', status.spend.lastHour, status.limits.perHourUsd, unpriced) +
|
|
169
|
+
meter('Spend · last day', status.spend.lastDay, status.limits.perDayUsd, unpriced) +
|
|
151
170
|
'<div class="card"><div class="k">Requests</div><div class="v">' + traces.length + '</div>' +
|
|
152
171
|
'<div class="k" style="margin-top:8px">' + (status.enforcing ? 'policy enforcing' : 'logging only') + '</div></div>' +
|
|
153
172
|
'<div class="card"><div class="k">Blocked</div><div class="v">' + blocked + '</div>' +
|
|
154
|
-
'<div class="k" style="margin-top:8px">
|
|
173
|
+
'<div class="k" style="margin-top:8px">' + cause + '</div></div>';
|
|
155
174
|
|
|
156
175
|
if (!traces.length) {
|
|
157
176
|
$('list').innerHTML = '<div class="empty">No traffic yet. Point your SDK at ' +
|