@zanii/blackbox 0.20.0 → 0.21.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.
- package/dist/analysis/index.d.ts +1 -1
- package/dist/analysis/index.js +1 -1
- package/dist/analysis/learning.d.ts +59 -0
- package/dist/analysis/learning.js +139 -0
- package/dist/cost/index.js +5 -1
- package/dist/fleet/index.d.ts +24 -0
- package/dist/fleet/index.js +74 -1
- package/dist/fleet/insights.js +5 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +3 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/analysis/index.d.ts
CHANGED
|
@@ -103,4 +103,4 @@ export declare function verifyRegression(events: Ev[]): Finding[];
|
|
|
103
103
|
/** Stage 2 R4, judged at close: a run labelled (or claimed) a success that its own record contradicts:
|
|
104
104
|
* a check's last result failed, or the last tool call failed with nothing succeeding after it. */
|
|
105
105
|
export declare function falseSuccess(events: Ev[], now: number): Finding[];
|
|
106
|
-
export { type Lessons, lessons, POWER_KINDS, promptChanged, SELF_CHANGE_KINDS, selfChanges, systemPromptHash, } from "./learning.ts";
|
|
106
|
+
export { type Growth, growth, isoWeek, type Lessons, lessons, POWER_KINDS, promptChanged, SELF_CHANGE_KINDS, selfChanges, systemPromptHash, toolsHash, } from "./learning.ts";
|
package/dist/analysis/index.js
CHANGED
|
@@ -586,4 +586,4 @@ export function falseSuccess(events, now) {
|
|
|
586
586
|
: "The agent claimed it was done, but its last tool call failed and nothing succeeded after it.");
|
|
587
587
|
return [];
|
|
588
588
|
}
|
|
589
|
-
export { lessons, POWER_KINDS, promptChanged, SELF_CHANGE_KINDS, selfChanges, systemPromptHash, } from "./learning.js";
|
|
589
|
+
export { growth, isoWeek, lessons, POWER_KINDS, promptChanged, SELF_CHANGE_KINDS, selfChanges, systemPromptHash, toolsHash, } from "./learning.js";
|
|
@@ -52,3 +52,62 @@ export interface Lessons {
|
|
|
52
52
|
* own prompt. Codes and counts only, never content.
|
|
53
53
|
*/
|
|
54
54
|
export declare function lessons(summaries: readonly Summary[], label: string | null): Lessons;
|
|
55
|
+
/**
|
|
56
|
+
* spec/fleet.md §9: the fingerprint of a model request's tool definitions: `sha256:` + hex over the
|
|
57
|
+
* canonical JSON of the sorted list of each tool's canonical JSON (so their order doesn't matter;
|
|
58
|
+
* Anthropic's `cache_control` on a tool is left out, it moves without changing the tool), from
|
|
59
|
+
* `tools` (Anthropic, OpenAI, Gemini) or Bedrock's `toolConfig.tools`. Null when there are none.
|
|
60
|
+
*/
|
|
61
|
+
export declare function toolsHash(body: unknown): string | null;
|
|
62
|
+
/** The ISO week of a UTC timestamp: `2026-W41`. */
|
|
63
|
+
export declare function isoWeek(ts: string): string;
|
|
64
|
+
export interface Growth {
|
|
65
|
+
label: string | null;
|
|
66
|
+
sessions: number;
|
|
67
|
+
autonomy: Array<{
|
|
68
|
+
week: string;
|
|
69
|
+
sessions: number;
|
|
70
|
+
success: number;
|
|
71
|
+
failed: number;
|
|
72
|
+
autonomous: number;
|
|
73
|
+
autonomy_ppm: number;
|
|
74
|
+
failure_ppm: number;
|
|
75
|
+
}>;
|
|
76
|
+
versions: Array<{
|
|
77
|
+
id: string;
|
|
78
|
+
prompt: string | null;
|
|
79
|
+
tools: string | null;
|
|
80
|
+
model: string | null;
|
|
81
|
+
changed: string[];
|
|
82
|
+
sessions: number;
|
|
83
|
+
first_seen: string;
|
|
84
|
+
last_seen: string;
|
|
85
|
+
success_ppm: number;
|
|
86
|
+
spend_per_run_micro_usd: number;
|
|
87
|
+
human_steps: number;
|
|
88
|
+
declared: boolean;
|
|
89
|
+
}>;
|
|
90
|
+
versions_total: number;
|
|
91
|
+
learned: Array<{
|
|
92
|
+
session_id: string;
|
|
93
|
+
seq: number;
|
|
94
|
+
at: string;
|
|
95
|
+
kind: string;
|
|
96
|
+
approval_id: string | null;
|
|
97
|
+
approved: number;
|
|
98
|
+
corrected: number;
|
|
99
|
+
unknown: number;
|
|
100
|
+
checked: boolean;
|
|
101
|
+
}>;
|
|
102
|
+
hints: string[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* spec/fleet.md §9: how one agent (its label) grows, from its closed sessions' summaries, newest
|
|
106
|
+
* first. Autonomy per ISO week (a run done alone is a success with no human step, shown next to the
|
|
107
|
+
* failed runs, so an agent that stops asking and fails doesn't look better); its versions (the
|
|
108
|
+
* gateway's prompt and tools fingerprints and the model) with what changed and how each did; and
|
|
109
|
+
* the learned log, each self-change with the approvals it names checked against the window's.
|
|
110
|
+
*/
|
|
111
|
+
export declare function growth(summaries: readonly Summary[], label: string | null, options?: {
|
|
112
|
+
weeks?: number;
|
|
113
|
+
}): Growth;
|
|
@@ -189,3 +189,142 @@ export function lessons(summaries, label) {
|
|
|
189
189
|
brief,
|
|
190
190
|
};
|
|
191
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* spec/fleet.md §9: the fingerprint of a model request's tool definitions: `sha256:` + hex over the
|
|
194
|
+
* canonical JSON of the sorted list of each tool's canonical JSON (so their order doesn't matter;
|
|
195
|
+
* Anthropic's `cache_control` on a tool is left out, it moves without changing the tool), from
|
|
196
|
+
* `tools` (Anthropic, OpenAI, Gemini) or Bedrock's `toolConfig.tools`. Null when there are none.
|
|
197
|
+
*/
|
|
198
|
+
export function toolsHash(body) {
|
|
199
|
+
if (!isObj(body))
|
|
200
|
+
return null;
|
|
201
|
+
const list = Array.isArray(body.tools)
|
|
202
|
+
? body.tools
|
|
203
|
+
: isObj(body.toolConfig) && Array.isArray(body.toolConfig.tools)
|
|
204
|
+
? body.toolConfig.tools
|
|
205
|
+
: [];
|
|
206
|
+
if (!list.length)
|
|
207
|
+
return null;
|
|
208
|
+
const parts = list
|
|
209
|
+
.map((t) => canonical(isObj(t) ? Object.fromEntries(Object.entries(t).filter(([k]) => k !== "cache_control")) : t))
|
|
210
|
+
.sort();
|
|
211
|
+
return `sha256:${createHash("sha256").update(canonical(parts)).digest("hex")}`;
|
|
212
|
+
}
|
|
213
|
+
/** The ISO week of a UTC timestamp: `2026-W41`. */
|
|
214
|
+
export function isoWeek(ts) {
|
|
215
|
+
const d = new Date(Date.UTC(Number(ts.slice(0, 4)), Number(ts.slice(5, 7)) - 1, Number(ts.slice(8, 10))));
|
|
216
|
+
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7)); // the week's Thursday names its year
|
|
217
|
+
const year = d.getUTCFullYear();
|
|
218
|
+
const week = Math.floor((d.getTime() - Date.UTC(year, 0, 1)) / 86_400_000 / 7) + 1;
|
|
219
|
+
return `${year}-W${String(week).padStart(2, "0")}`;
|
|
220
|
+
}
|
|
221
|
+
const ppm = (n, d) => (d ? Math.floor((n * 1_000_000) / d) : 0);
|
|
222
|
+
const VERSIONS = 20;
|
|
223
|
+
const LEARNED = 50;
|
|
224
|
+
/**
|
|
225
|
+
* spec/fleet.md §9: how one agent (its label) grows, from its closed sessions' summaries, newest
|
|
226
|
+
* first. Autonomy per ISO week (a run done alone is a success with no human step, shown next to the
|
|
227
|
+
* failed runs, so an agent that stops asking and fails doesn't look better); its versions (the
|
|
228
|
+
* gateway's prompt and tools fingerprints and the model) with what changed and how each did; and
|
|
229
|
+
* the learned log, each self-change with the approvals it names checked against the window's.
|
|
230
|
+
*/
|
|
231
|
+
export function growth(summaries, label, options = {}) {
|
|
232
|
+
const weeks = options.weeks ?? 12;
|
|
233
|
+
const runs = summaries.filter((s) => s.closed && s.label === label);
|
|
234
|
+
const byWeek = new Map();
|
|
235
|
+
for (const s of runs) {
|
|
236
|
+
const week = isoWeek(s.started_at);
|
|
237
|
+
const w = byWeek.get(week) ?? {
|
|
238
|
+
week,
|
|
239
|
+
sessions: 0,
|
|
240
|
+
success: 0,
|
|
241
|
+
failed: 0,
|
|
242
|
+
autonomous: 0,
|
|
243
|
+
autonomy_ppm: 0,
|
|
244
|
+
failure_ppm: 0,
|
|
245
|
+
};
|
|
246
|
+
w.sessions++;
|
|
247
|
+
if (s.outcome === "success") {
|
|
248
|
+
w.success++;
|
|
249
|
+
if (!s.human_steps)
|
|
250
|
+
w.autonomous++;
|
|
251
|
+
}
|
|
252
|
+
else if (s.outcome === "failure" || s.outcome === "abandoned")
|
|
253
|
+
w.failed++;
|
|
254
|
+
byWeek.set(week, w);
|
|
255
|
+
}
|
|
256
|
+
const autonomy = [...byWeek.values()]
|
|
257
|
+
.sort((a, b) => (a.week < b.week ? -1 : 1))
|
|
258
|
+
.slice(-weeks)
|
|
259
|
+
.map((w) => ({
|
|
260
|
+
...w,
|
|
261
|
+
autonomy_ppm: ppm(w.autonomous, w.sessions),
|
|
262
|
+
failure_ppm: ppm(w.failed, w.sessions),
|
|
263
|
+
}));
|
|
264
|
+
const groups = new Map();
|
|
265
|
+
for (const s of runs)
|
|
266
|
+
if (s.version)
|
|
267
|
+
groups.set(s.version.id, [...(groups.get(s.version.id) ?? []), s]);
|
|
268
|
+
const all = [...groups.values()]
|
|
269
|
+
.map((ss) => {
|
|
270
|
+
const v = ss[0]?.version;
|
|
271
|
+
const starts = ss.map((s) => s.started_at).sort();
|
|
272
|
+
return {
|
|
273
|
+
id: v.id,
|
|
274
|
+
prompt: v.prompt,
|
|
275
|
+
tools: v.tools,
|
|
276
|
+
model: v.model,
|
|
277
|
+
changed: [],
|
|
278
|
+
sessions: ss.length,
|
|
279
|
+
first_seen: starts[0],
|
|
280
|
+
last_seen: starts[starts.length - 1],
|
|
281
|
+
success_ppm: ppm(ss.filter((s) => s.outcome === "success").length, ss.length),
|
|
282
|
+
spend_per_run_micro_usd: Math.floor(ss.reduce((n, s) => n + s.spend_micro_usd, 0) / ss.length),
|
|
283
|
+
human_steps: ss.reduce((n, s) => n + (s.human_steps ?? 0), 0),
|
|
284
|
+
declared: ss.some((s) => (s.self_changes?.length ?? 0) > 0),
|
|
285
|
+
};
|
|
286
|
+
})
|
|
287
|
+
.sort((a, b) => a.first_seen < b.first_seen ? -1 : a.first_seen > b.first_seen ? 1 : a.id < b.id ? -1 : 1);
|
|
288
|
+
for (let i = 1; i < all.length; i++) {
|
|
289
|
+
const [p, v] = [all[i - 1], all[i]];
|
|
290
|
+
v.changed = ["prompt", "tools", "model"].filter((k) => p[k] !== v[k]);
|
|
291
|
+
}
|
|
292
|
+
const decided = new Map();
|
|
293
|
+
for (const s of runs)
|
|
294
|
+
for (const [id, d] of Object.entries(s.approvals ?? {}))
|
|
295
|
+
decided.set(id, d);
|
|
296
|
+
const learned = [];
|
|
297
|
+
for (const s of runs)
|
|
298
|
+
for (const c of [...(s.self_changes ?? [])].reverse()) {
|
|
299
|
+
if (learned.length === LEARNED)
|
|
300
|
+
break;
|
|
301
|
+
const found = c.taught_by.map((id) => decided.get(id));
|
|
302
|
+
const approved = found.filter((d) => d === "approve").length;
|
|
303
|
+
const corrected = found.filter((d) => d === "reject").length;
|
|
304
|
+
const unknown = found.length - approved - corrected;
|
|
305
|
+
learned.push({
|
|
306
|
+
session_id: s.session_id,
|
|
307
|
+
seq: c.seq,
|
|
308
|
+
at: c.at,
|
|
309
|
+
kind: c.kind,
|
|
310
|
+
approval_id: c.approval_id,
|
|
311
|
+
approved,
|
|
312
|
+
corrected,
|
|
313
|
+
unknown,
|
|
314
|
+
checked: found.length > 0 && unknown === 0,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
const hints = [];
|
|
318
|
+
// a prompt that embeds the date or a request id is a new version every run
|
|
319
|
+
if (runs.length >= 10 && all.length * 2 > runs.length)
|
|
320
|
+
hints.push("many_versions");
|
|
321
|
+
return {
|
|
322
|
+
label,
|
|
323
|
+
sessions: runs.length,
|
|
324
|
+
autonomy,
|
|
325
|
+
versions: all.slice(-VERSIONS),
|
|
326
|
+
versions_total: all.length,
|
|
327
|
+
learned,
|
|
328
|
+
hints,
|
|
329
|
+
};
|
|
330
|
+
}
|
package/dist/cost/index.js
CHANGED
|
@@ -127,7 +127,11 @@ export function tokensOf(usage) {
|
|
|
127
127
|
cache_write: written,
|
|
128
128
|
}, { input_audio: audioIn, output_audio: audioOut });
|
|
129
129
|
}
|
|
130
|
-
|
|
130
|
+
// Anthropic's cache names are its own: they win over the Responses shape, since Anthropic also
|
|
131
|
+
// sends output_tokens_details (thinking_tokens) since Claude Sonnet 5
|
|
132
|
+
const anthropicCache = "cache_read_input_tokens" in usage || "cache_creation_input_tokens" in usage;
|
|
133
|
+
if (!anthropicCache &&
|
|
134
|
+
Object.keys(usage).some((k) => k.startsWith("input_tokens_details_") || k.startsWith("output_tokens_details_"))) {
|
|
131
135
|
const cached = n("input_tokens_details_cached_tokens");
|
|
132
136
|
const written = n("input_tokens_details_cache_write_tokens");
|
|
133
137
|
const audioIn = n("input_tokens_details_audio_tokens");
|
package/dist/fleet/index.d.ts
CHANGED
|
@@ -33,7 +33,31 @@ export interface Summary {
|
|
|
33
33
|
};
|
|
34
34
|
blocked_by: string | null;
|
|
35
35
|
near_misses: number;
|
|
36
|
+
/** spec/fleet.md §9: which version of the agent ran (only when it called a model) */
|
|
37
|
+
version?: {
|
|
38
|
+
id: string;
|
|
39
|
+
prompt: string | null;
|
|
40
|
+
tools: string | null;
|
|
41
|
+
model: string | null;
|
|
42
|
+
};
|
|
43
|
+
/** spec/fleet.md §9: the times a person stepped in (only when one did) */
|
|
44
|
+
human_steps?: number;
|
|
45
|
+
/** spec/fleet.md §9: the changes the agent reported to itself, the first 10 */
|
|
46
|
+
self_changes?: SelfChangeEntry[];
|
|
47
|
+
/** spec/fleet.md §9: approvals a person decided here, the first 50: id → approve | reject */
|
|
48
|
+
approvals?: Record<string, "approve" | "reject">;
|
|
49
|
+
}
|
|
50
|
+
export interface SelfChangeEntry {
|
|
51
|
+
seq: number;
|
|
52
|
+
at: string;
|
|
53
|
+
kind: string;
|
|
54
|
+
approval_id: string | null;
|
|
55
|
+
taught_by: string[];
|
|
36
56
|
}
|
|
57
|
+
/** An approval id: what a lesson may point at, and nothing else (spec/fleet.md §9). */
|
|
58
|
+
export declare const APPROVAL_ID: RegExp;
|
|
59
|
+
/** spec/fleet.md §9: the approval ids a self-change names as what taught it, at most 20. */
|
|
60
|
+
export declare function taughtBy(v: unknown): string[];
|
|
37
61
|
export declare function sessionSummary(lines: readonly string[], bodies: Bodies, prices: LoadedPrices): Summary;
|
|
38
62
|
/** The incident report (spec/fleet.md §2) in Markdown, in English or Arabic. */
|
|
39
63
|
export declare function incidentReport(lines: readonly string[], bodies: Bodies, prices: LoadedPrices, lang: "en" | "ar"): string;
|
package/dist/fleet/index.js
CHANGED
|
@@ -10,6 +10,45 @@ import { authorityTimeline } from "../authority/index.js";
|
|
|
10
10
|
import { formatAed, sessionCost, toAedFils } from "../cost/index.js";
|
|
11
11
|
import { callsOf } from "../reconcile/record.js";
|
|
12
12
|
import { canonical } from "../reconcile/shared.js";
|
|
13
|
+
/** An approval id: what a lesson may point at, and nothing else (spec/fleet.md §9). */
|
|
14
|
+
export const APPROVAL_ID = /^apr_[0-9a-f]{18}$/;
|
|
15
|
+
/** spec/fleet.md §9: the approval ids a self-change names as what taught it, at most 20. */
|
|
16
|
+
export function taughtBy(v) {
|
|
17
|
+
if (!Array.isArray(v))
|
|
18
|
+
return [];
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const x of v)
|
|
21
|
+
if (typeof x === "string" && APPROVAL_ID.test(x) && !out.includes(x) && out.length < 20)
|
|
22
|
+
out.push(x);
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
/** The agent's version: the first request's prompt and tools fingerprints, the first model. Only
|
|
26
|
+
* when the gateway fingerprinted that request: a version is evidence, never a guess. */
|
|
27
|
+
function versionOf(events) {
|
|
28
|
+
const req = events.find((e) => e.kind === "llm.request");
|
|
29
|
+
const str = (v) => (typeof v === "string" ? v : null);
|
|
30
|
+
const prompt = str(req?.meta.system_sha256);
|
|
31
|
+
const tools = str(req?.meta.tools_sha256);
|
|
32
|
+
if (prompt === null && tools === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
const model = str(events.find((e) => e.kind === "llm.response")?.meta.model);
|
|
35
|
+
const id = `ver_${createHash("sha256")
|
|
36
|
+
.update(canonical([prompt, tools, model]))
|
|
37
|
+
.digest("hex")
|
|
38
|
+
.slice(0, 12)}`;
|
|
39
|
+
return { id, prompt, tools, model };
|
|
40
|
+
}
|
|
41
|
+
/** A person stepping in: an approval they decided, a resume, an authority change, an `ask`. */
|
|
42
|
+
function isHumanStep(e) {
|
|
43
|
+
if (e.kind !== "control")
|
|
44
|
+
return false;
|
|
45
|
+
const m = e.meta;
|
|
46
|
+
if (m.action === "approval")
|
|
47
|
+
return (m.decision === "approve" || m.decision === "reject") && m.by !== "classifier";
|
|
48
|
+
if (m.action === "policy_check")
|
|
49
|
+
return m.decision === "ask";
|
|
50
|
+
return m.action === "resume" || m.action === "authority";
|
|
51
|
+
}
|
|
13
52
|
const sorted = (m) => Object.fromEntries(Object.keys(m)
|
|
14
53
|
.sort()
|
|
15
54
|
.map((k) => [k, m[k]]));
|
|
@@ -30,7 +69,22 @@ export function sessionSummary(lines, bodies, prices) {
|
|
|
30
69
|
let outcome = null;
|
|
31
70
|
let blockedBy = null;
|
|
32
71
|
let nearMisses = 0;
|
|
72
|
+
let humanSteps = 0;
|
|
73
|
+
const approvals = {};
|
|
74
|
+
let decided = 0;
|
|
33
75
|
for (const e of events) {
|
|
76
|
+
if (isHumanStep(e))
|
|
77
|
+
humanSteps++;
|
|
78
|
+
if (e.kind === "control" &&
|
|
79
|
+
e.meta.action === "approval" &&
|
|
80
|
+
(e.meta.decision === "approve" || e.meta.decision === "reject") &&
|
|
81
|
+
e.meta.by !== "classifier" &&
|
|
82
|
+
typeof e.meta.approval_id === "string" &&
|
|
83
|
+
!(e.meta.approval_id in approvals) &&
|
|
84
|
+
decided < 50) {
|
|
85
|
+
approvals[e.meta.approval_id] = e.meta.decision;
|
|
86
|
+
decided++;
|
|
87
|
+
}
|
|
34
88
|
if (e.kind === "tool.call" &&
|
|
35
89
|
e.meta.method === "tools/call" &&
|
|
36
90
|
typeof e.meta.tool === "string") {
|
|
@@ -59,8 +113,23 @@ export function sessionSummary(lines, bodies, prices) {
|
|
|
59
113
|
nearMisses++;
|
|
60
114
|
}
|
|
61
115
|
const claims = { satisfied: 0, failed: 0, unverified: 0 };
|
|
62
|
-
|
|
116
|
+
const evs = eventsOf(lines, bodies);
|
|
117
|
+
for (const c of landing(evs, lines, bodies).claims)
|
|
63
118
|
claims[c.verdict]++;
|
|
119
|
+
const selfChanges = evs
|
|
120
|
+
.filter((e) => e.kind === "sdk.event" && e.meta.type === "self_change")
|
|
121
|
+
.slice(0, 10)
|
|
122
|
+
.map((e) => {
|
|
123
|
+
const d = e.data ?? {};
|
|
124
|
+
return {
|
|
125
|
+
seq: e.seq,
|
|
126
|
+
at: e.ts,
|
|
127
|
+
kind: typeof d.kind === "string" && d.kind ? d.kind : "other",
|
|
128
|
+
approval_id: typeof d.approval_id === "string" ? d.approval_id : null,
|
|
129
|
+
taught_by: taughtBy(d.taught_by),
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
const version = versionOf(events);
|
|
64
133
|
const inControl = authorityTimeline(lines).at(-1)?.mode ?? "agent";
|
|
65
134
|
return {
|
|
66
135
|
session_id: first.session_id,
|
|
@@ -89,6 +158,10 @@ export function sessionSummary(lines, bodies, prices) {
|
|
|
89
158
|
claims,
|
|
90
159
|
blocked_by: blockedBy,
|
|
91
160
|
near_misses: nearMisses,
|
|
161
|
+
...(version ? { version } : {}),
|
|
162
|
+
...(humanSteps ? { human_steps: humanSteps } : {}),
|
|
163
|
+
...(selfChanges.length ? { self_changes: selfChanges } : {}),
|
|
164
|
+
...(decided ? { approvals } : {}),
|
|
92
165
|
};
|
|
93
166
|
}
|
|
94
167
|
const T = {
|
package/dist/fleet/insights.js
CHANGED
|
@@ -179,7 +179,11 @@ function value(v) {
|
|
|
179
179
|
return JSON.stringify(short);
|
|
180
180
|
}
|
|
181
181
|
const isMoment = (e) => {
|
|
182
|
-
const
|
|
182
|
+
const meta = e.meta;
|
|
183
|
+
const status = meta?.status;
|
|
184
|
+
// an allowed policy check (one per local tool call) is routine, not a moment
|
|
185
|
+
if (e.kind === "control" && meta?.action === "policy_check" && meta.decision === "allow")
|
|
186
|
+
return false;
|
|
183
187
|
return (e.kind === "finding" ||
|
|
184
188
|
e.kind === "control" ||
|
|
185
189
|
e.kind === "outcome" ||
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { A2A_STREAMING, type AgentCardReport, a2aMethod, a2aRequestMeta, a2aResp
|
|
|
2
2
|
export { causality, memoryXray } from "./agents/index.ts";
|
|
3
3
|
export { type DetectorOptions, detectors, fingerprint } from "./analysis/detectors.ts";
|
|
4
4
|
export { FAULTS, type Fault, faultOf } from "./analysis/faults.ts";
|
|
5
|
-
export { type Accuracy, type AnalyzeOptions, type AnswerClaims, analyze, answerClaims, answerCredential, answerRisk, answersOf, answerText, type ClaimEntry, type ClaimVerdict, type CriterionResult, canonicalNumber, checkAgainstPacks, checkFlightPlan, checkpointReplay, detectorAccuracy, dualWitness, Evidence, eventsOf, type Fact, type Finding as AnalysisFinding, factsIn, findingKey, type GroundedClaim, groundingFindings, groundingRequest, HOLD_TRIGGERS, identifiersIn, judgeFindings, judgeRequest, type Label as AccuracyLabel, type Landing, landing, lessons, loadReferencePacks, modelGroundingFindings, normaliseValue, OUTCOMES, type Outcome, type OutcomeRollup, packsFor, parseGroundingAnswer, parseJudgeAnswer, promptChanged, type ReferenceFact, type ReferencePack, type ReferenceVerdict, referenceContext, rollup, type Severity, schemaProblem, secretSent, selfChanges, systemPromptHash, toolDrifted, toolHallucinations, userDownvotes, verifyAnswerCredential, type WasteReason, type WasteReport, waste, wilsonLow, } from "./analysis/index.ts";
|
|
5
|
+
export { type Accuracy, type AnalyzeOptions, type AnswerClaims, analyze, answerClaims, answerCredential, answerRisk, answersOf, answerText, type ClaimEntry, type ClaimVerdict, type CriterionResult, canonicalNumber, checkAgainstPacks, checkFlightPlan, checkpointReplay, detectorAccuracy, dualWitness, Evidence, eventsOf, type Fact, type Finding as AnalysisFinding, factsIn, findingKey, type GroundedClaim, groundingFindings, groundingRequest, growth, HOLD_TRIGGERS, identifiersIn, isoWeek, judgeFindings, judgeRequest, type Label as AccuracyLabel, type Landing, landing, lessons, loadReferencePacks, modelGroundingFindings, normaliseValue, OUTCOMES, type Outcome, type OutcomeRollup, packsFor, parseGroundingAnswer, parseJudgeAnswer, promptChanged, type ReferenceFact, type ReferencePack, type ReferenceVerdict, referenceContext, rollup, type Severity, schemaProblem, secretSent, selfChanges, systemPromptHash, toolDrifted, toolHallucinations, toolsHash, userDownvotes, verifyAnswerCredential, type WasteReason, type WasteReport, waste, wilsonLow, } from "./analysis/index.ts";
|
|
6
6
|
export { injectionFindings, injectionRule } from "./analysis/injection.ts";
|
|
7
7
|
export { MITRE_ATLAS, OWASP_ASI, TAXONOMY, type Taxonomy, taxonomyOf, } from "./analysis/taxonomy.ts";
|
|
8
8
|
export { type ApprovalFinding, approvalConfirmation, approvalFindings, argsHash, verifyConfirmation, } from "./approvals/index.ts";
|
|
@@ -30,7 +30,7 @@ export { openSegments, type SealedSegment } from "./encryption/index.ts";
|
|
|
30
30
|
export { type EvidencePack, type EvidencePackOptions, evidencePack, renderEvidencePack, } from "./evidence/index.ts";
|
|
31
31
|
export { buildEquivocationProof, compareViews, cosignLedgerSth, verifyEquivocationProof, verifyLedgerCosignature, } from "./federation/index.ts";
|
|
32
32
|
export { buildOwnerAttestation, buildPayment, CURRENCIES, FTA_WALL_ID, financeFindings, formatMoney, ftaPayload, parseMoney, paymentsOf, screenCounterparty, screeningPayload, verifyOwnerAttestation, verifyOwnerBinding, } from "./finance/index.ts";
|
|
33
|
-
export { aggregateFindings, airworthiness, type Collision, collisions, didFromSeed, type FindingGroup, incidentReport, logbook, type Summary, sessionSummary, signatureOf, signatures, signCertificate, verifyCertificate, } from "./fleet/index.ts";
|
|
33
|
+
export { APPROVAL_ID, aggregateFindings, airworthiness, type Collision, collisions, didFromSeed, type FindingGroup, incidentReport, logbook, type Summary, sessionSummary, signatureOf, signatures, signCertificate, taughtBy, verifyCertificate, } from "./fleet/index.ts";
|
|
34
34
|
export { copilotContext, copilotPrompt, type Insights, insights, parseCopilotAnswer, } from "./fleet/insights.ts";
|
|
35
35
|
export { type AppealItem, type AppealPack, appealPack, decisionPayload, GOV_DECISION_KINDS, renderAppealPack, ruleConsistency, signSubjectClaim, subjectTag, verifyDecision, verifyFactors, verifySubjectClaim, } from "./gov/index.ts";
|
|
36
36
|
export { accessPayload, breakGlass, checkEpisodeTag, clinicianConfirmation, type EpisodeItem, episodeSeed, episodesPack, episodeTag, healthFindings, protocolTrail, recommendationHash, recommendationPayload, verifyCommitment, verifyHealthSignature, } from "./health/index.ts";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export { A2A_STREAMING, a2aMethod, a2aRequestMeta, a2aResponseMeta, a2aRestMetho
|
|
|
4
4
|
export { causality, memoryXray } from "./agents/index.js";
|
|
5
5
|
export { detectors, fingerprint } from "./analysis/detectors.js";
|
|
6
6
|
export { FAULTS, faultOf } from "./analysis/faults.js";
|
|
7
|
-
export { analyze, answerClaims, answerCredential, answerRisk, answersOf, answerText, canonicalNumber, checkAgainstPacks, checkFlightPlan, checkpointReplay, detectorAccuracy, dualWitness, Evidence, eventsOf, factsIn, findingKey, groundingFindings, groundingRequest, HOLD_TRIGGERS, identifiersIn, judgeFindings, judgeRequest, landing, lessons, loadReferencePacks, modelGroundingFindings, normaliseValue, OUTCOMES, packsFor, parseGroundingAnswer, parseJudgeAnswer, promptChanged, referenceContext, rollup, schemaProblem, secretSent, selfChanges, systemPromptHash, toolDrifted, toolHallucinations, userDownvotes, verifyAnswerCredential, waste, wilsonLow, } from "./analysis/index.js";
|
|
7
|
+
export { analyze, answerClaims, answerCredential, answerRisk, answersOf, answerText, canonicalNumber, checkAgainstPacks, checkFlightPlan, checkpointReplay, detectorAccuracy, dualWitness, Evidence, eventsOf, factsIn, findingKey, groundingFindings, groundingRequest, growth, HOLD_TRIGGERS, identifiersIn, isoWeek, judgeFindings, judgeRequest, landing, lessons, loadReferencePacks, modelGroundingFindings, normaliseValue, OUTCOMES, packsFor, parseGroundingAnswer, parseJudgeAnswer, promptChanged, referenceContext, rollup, schemaProblem, secretSent, selfChanges, systemPromptHash, toolDrifted, toolHallucinations, toolsHash, userDownvotes, verifyAnswerCredential, waste, wilsonLow, } from "./analysis/index.js";
|
|
8
8
|
export { injectionFindings, injectionRule } from "./analysis/injection.js";
|
|
9
9
|
export { MITRE_ATLAS, OWASP_ASI, TAXONOMY, taxonomyOf, } from "./analysis/taxonomy.js";
|
|
10
10
|
export { approvalConfirmation, approvalFindings, argsHash, verifyConfirmation, } from "./approvals/index.js";
|
|
@@ -32,7 +32,7 @@ export { openSegments } from "./encryption/index.js";
|
|
|
32
32
|
export { evidencePack, renderEvidencePack, } from "./evidence/index.js";
|
|
33
33
|
export { buildEquivocationProof, compareViews, cosignLedgerSth, verifyEquivocationProof, verifyLedgerCosignature, } from "./federation/index.js";
|
|
34
34
|
export { buildOwnerAttestation, buildPayment, CURRENCIES, FTA_WALL_ID, financeFindings, formatMoney, ftaPayload, parseMoney, paymentsOf, screenCounterparty, screeningPayload, verifyOwnerAttestation, verifyOwnerBinding, } from "./finance/index.js";
|
|
35
|
-
export { aggregateFindings, airworthiness, collisions, didFromSeed, incidentReport, logbook, sessionSummary, signatureOf, signatures, signCertificate, verifyCertificate, } from "./fleet/index.js";
|
|
35
|
+
export { APPROVAL_ID, aggregateFindings, airworthiness, collisions, didFromSeed, incidentReport, logbook, sessionSummary, signatureOf, signatures, signCertificate, taughtBy, verifyCertificate, } from "./fleet/index.js";
|
|
36
36
|
export { copilotContext, copilotPrompt, insights, parseCopilotAnswer, } from "./fleet/insights.js";
|
|
37
37
|
export { appealPack, decisionPayload, GOV_DECISION_KINDS, renderAppealPack, ruleConsistency, signSubjectClaim, subjectTag, verifyDecision, verifyFactors, verifySubjectClaim, } from "./gov/index.js";
|
|
38
38
|
export { accessPayload, breakGlass, checkEpisodeTag, clinicianConfirmation, episodeSeed, episodesPack, episodeTag, healthFindings, protocolTrail, recommendationHash, recommendationPayload, verifyCommitment, verifyHealthSignature, } from "./health/index.js";
|
package/dist/session/index.d.ts
CHANGED
|
@@ -388,6 +388,8 @@ export declare class BlackboxSession {
|
|
|
388
388
|
after?: string;
|
|
389
389
|
reason?: string;
|
|
390
390
|
approvalId?: string;
|
|
391
|
+
/** The approvals (ids) that taught it this, and nothing else: never content (fleet.md §9). */
|
|
392
|
+
taughtBy?: readonly string[];
|
|
391
393
|
}): void;
|
|
392
394
|
/** spec/findings.md §13.1: what in an answer (the latest, or the one at `seq`) would hold it,
|
|
393
395
|
* for an app that streams the answer by itself: `{seq, risks, hold}`. `hold` says whether the
|
package/dist/session/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { SELF_CHANGE_KINDS } from "../analysis/learning.js";
|
|
|
10
10
|
import { argsHash } from "../approvals/index.js";
|
|
11
11
|
import { attest, isReadOnly, parseCommand } from "../attest/index.js";
|
|
12
12
|
import { buildPayment, ftaPayload, screeningPayload, } from "../finance/index.js";
|
|
13
|
+
import { taughtBy } from "../fleet/index.js";
|
|
13
14
|
import { decisionPayload } from "../gov/index.js";
|
|
14
15
|
import { accessPayload, checkEpisodeTag, recommendationPayload, verifyHealthSignature, } from "../health/index.js";
|
|
15
16
|
import { memoryEntry } from "../memory/index.js";
|
|
@@ -624,6 +625,7 @@ export class BlackboxSession {
|
|
|
624
625
|
* pass its id), or it is SELF_CHANGE_UNAPPROVED. Never throws.
|
|
625
626
|
*/
|
|
626
627
|
selfChange(kind, options = {}) {
|
|
628
|
+
const taught = taughtBy(options.taughtBy);
|
|
627
629
|
const k = SELF_CHANGE_KINDS.includes(kind) ? kind : "other";
|
|
628
630
|
const sha = (text) => `sha256:${createHash("sha256").update(text).digest("hex")}`;
|
|
629
631
|
this.event("self_change", k, {
|
|
@@ -632,6 +634,7 @@ export class BlackboxSession {
|
|
|
632
634
|
...(options.after === undefined ? {} : { after_sha256: sha(options.after) }),
|
|
633
635
|
...(options.reason ? { reason: options.reason.slice(0, 500) } : {}),
|
|
634
636
|
...(options.approvalId ? { approval_id: options.approvalId.slice(0, 128) } : {}),
|
|
637
|
+
...(taught.length ? { taught_by: taught } : {}),
|
|
635
638
|
});
|
|
636
639
|
}
|
|
637
640
|
/** spec/findings.md §13.1: what in an answer (the latest, or the one at `seq`) would hold it,
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.21.0";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// The SDK version, on its own so the CLI can print it without loading the whole SDK.
|
|
2
|
-
export const VERSION = "0.
|
|
2
|
+
export const VERSION = "0.21.0";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zanii/blackbox",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.21.0",
|
|
5
5
|
"description": "The flight recorder for AI agents: sessions, a zero-loss spool, framework hooks, approvals, and offline verification of the gateway's hash-chained record.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"ai-agents",
|