@zanii/blackbox 0.21.2 → 0.23.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 (95) hide show
  1. package/README.md +1 -0
  2. package/dist/actions/index.d.ts +29 -0
  3. package/dist/actions/index.js +114 -0
  4. package/dist/admission/index.d.ts +30 -0
  5. package/dist/admission/index.js +106 -0
  6. package/dist/analysis/accepted.d.ts +26 -0
  7. package/dist/analysis/accepted.js +61 -0
  8. package/dist/analysis/detectors.js +12 -9
  9. package/dist/analysis/faults.js +71 -0
  10. package/dist/analysis/grounding.js +5 -9
  11. package/dist/analysis/guard.d.ts +72 -0
  12. package/dist/analysis/guard.js +240 -0
  13. package/dist/analysis/hallucination.js +2 -2
  14. package/dist/analysis/index.d.ts +21 -1
  15. package/dist/analysis/index.js +101 -19
  16. package/dist/analysis/injection.d.ts +2 -1
  17. package/dist/analysis/injection.js +16 -16
  18. package/dist/analysis/landing.js +60 -14
  19. package/dist/analysis/plan-checks.d.ts +55 -0
  20. package/dist/analysis/plan-checks.js +748 -0
  21. package/dist/analysis/taxonomy.js +1 -0
  22. package/dist/analysis/waste.js +2 -3
  23. package/dist/approvals/index.d.ts +12 -3
  24. package/dist/approvals/index.js +36 -10
  25. package/dist/authority/index.js +3 -3
  26. package/dist/aviation/index.d.ts +422 -0
  27. package/dist/aviation/index.js +1014 -0
  28. package/dist/aviation/qrh.d.ts +4 -0
  29. package/dist/aviation/qrh.js +171 -0
  30. package/dist/budgets/index.d.ts +63 -0
  31. package/dist/budgets/index.js +161 -0
  32. package/dist/cli.js +199 -24
  33. package/dist/compliance/index.d.ts +2 -0
  34. package/dist/compliance/index.js +26 -2
  35. package/dist/cost/batch.d.ts +26 -0
  36. package/dist/cost/batch.js +173 -0
  37. package/dist/cost/index.d.ts +21 -0
  38. package/dist/cost/index.js +115 -30
  39. package/dist/cv/index.js +1 -1
  40. package/dist/duty/index.js +2 -1
  41. package/dist/evals/index.d.ts +233 -0
  42. package/dist/evals/index.js +488 -0
  43. package/dist/evidence/index.d.ts +9 -0
  44. package/dist/evidence/index.js +50 -0
  45. package/dist/federation/index.d.ts +9 -0
  46. package/dist/federation/index.js +8 -1
  47. package/dist/finance/index.js +3 -4
  48. package/dist/fleet/index.d.ts +25 -0
  49. package/dist/fleet/index.js +57 -17
  50. package/dist/fleet/insights.js +4 -1
  51. package/dist/health/index.js +2 -2
  52. package/dist/hooks/ai-sdk.d.ts +17 -19
  53. package/dist/hooks/ai-sdk.js +13 -7
  54. package/dist/hooks/index.d.ts +1 -0
  55. package/dist/hooks/index.js +1 -0
  56. package/dist/hooks/mastra.d.ts +26 -0
  57. package/dist/hooks/mastra.js +63 -0
  58. package/dist/index.d.ts +24 -9
  59. package/dist/index.js +25 -9
  60. package/dist/mcp-requests/index.d.ts +26 -0
  61. package/dist/mcp-requests/index.js +154 -0
  62. package/dist/mcp-server/index.d.ts +12 -0
  63. package/dist/mcp-server/index.js +84 -2
  64. package/dist/mcp-wrap/index.js +8 -4
  65. package/dist/otlp/index.d.ts +155 -0
  66. package/dist/otlp/index.js +468 -0
  67. package/dist/otlp/protobuf.d.ts +7 -0
  68. package/dist/otlp/protobuf.js +314 -0
  69. package/dist/packs/index.d.ts +2 -0
  70. package/dist/packs/index.js +5 -1
  71. package/dist/pdf/arabic.d.ts +45 -0
  72. package/dist/pdf/arabic.js +373 -0
  73. package/dist/pdf/index.d.ts +77 -0
  74. package/dist/pdf/index.js +673 -0
  75. package/dist/policy/index.d.ts +0 -4
  76. package/dist/policy/index.js +13 -5
  77. package/dist/realtime/index.d.ts +33 -0
  78. package/dist/realtime/index.js +204 -0
  79. package/dist/reconcile/record.d.ts +14 -0
  80. package/dist/reconcile/record.js +161 -66
  81. package/dist/session/index.d.ts +43 -0
  82. package/dist/session/index.js +83 -0
  83. package/dist/undo/index.js +3 -3
  84. package/dist/verify/anchor.d.ts +5 -1
  85. package/dist/verify/anchor.js +13 -4
  86. package/dist/verify/chain.d.ts +4 -0
  87. package/dist/verify/chain.js +4 -3
  88. package/dist/verify/envelope.d.ts +1 -1
  89. package/dist/verify/envelope.js +5 -0
  90. package/dist/version.d.ts +1 -1
  91. package/dist/version.js +1 -1
  92. package/dist/walls/index.js +2 -2
  93. package/dist/warehouse/index.d.ts +62 -0
  94. package/dist/warehouse/index.js +142 -0
  95. package/package.json +6 -3
@@ -4,6 +4,8 @@ import { checkDuty } from "../duty/index.js";
4
4
  import { callsOf } from "../reconcile/record.js";
5
5
  import { isObj } from "../reconcile/shared.js";
6
6
  import { toolCallsOf, toolResultsOf } from "./detectors.js";
7
+ import { answerText } from "./hallucination.js";
8
+ import { checkPredicate, judgeAnswer, judgeArgs } from "./plan-checks.js";
7
9
  /** Every tool call in the record, with what its result said (provider tool_use ids; MCP call_seq). */
8
10
  function usesOf(events, lines, bodies) {
9
11
  const calls = callsOf(lines, bodies);
@@ -13,16 +15,26 @@ function usesOf(events, lines, bodies) {
13
15
  results.set(r.id, r);
14
16
  const uses = toolCallsOf(calls).map((t) => {
15
17
  const r = t.id === undefined ? undefined : results.get(t.id);
16
- return r
17
- ? { seq: t.seq, tool: t.tool, ok: !r.error, resultSeq: r.seq }
18
- : { seq: t.seq, tool: t.tool };
18
+ const base = { seq: t.seq, tool: t.tool, args: t.args ?? null, hasArgs: true };
19
+ return r ? { ...base, ok: !r.error, resultSeq: r.seq } : base;
19
20
  });
20
21
  const mcp = new Map();
21
22
  for (const e of events) {
22
23
  if (e.kind === "tool.call" &&
23
24
  e.meta.method === "tools/call" &&
24
25
  typeof e.meta.tool === "string") {
25
- const u = { seq: e.seq, tool: e.meta.tool };
26
+ const u = { seq: e.seq, tool: e.meta.tool, hasArgs: false };
27
+ // the arguments are the request body's params.arguments (gone when the body was erased)
28
+ try {
29
+ const body = bodies(e.body_hash);
30
+ if (body !== undefined) {
31
+ const rpc = JSON.parse(new TextDecoder().decode(body));
32
+ const params = isObj(rpc) ? rpc.params : undefined;
33
+ u.args = isObj(params) && "arguments" in params ? params.arguments : {};
34
+ u.hasArgs = true;
35
+ }
36
+ }
37
+ catch { }
26
38
  mcp.set(e.seq, u);
27
39
  uses.push(u);
28
40
  }
@@ -62,13 +74,33 @@ function plansOf(events) {
62
74
  return { plan: null, invalid };
63
75
  }
64
76
  const listOf = (v) => (Array.isArray(v) ? v : []);
65
- /** One predicate over the tool calls (and results) recorded before `before`. */
66
- function judge(p, uses, before) {
77
+ /** The final answers on the record (a complete model response with text and no tool call). */
78
+ function answersOf(lines, bodies) {
79
+ const calls = callsOf(lines, bodies);
80
+ const ends = new Set(toolCallsOf(calls).map((t) => t.seq));
81
+ return [...calls]
82
+ .sort((a, b) => a.endSeq - b.endSeq)
83
+ .filter((c) => c.complete && c.request && !ends.has(c.endSeq))
84
+ .map((c) => ({ seq: c.endSeq, text: answerText(c) }))
85
+ .filter((a) => a.text.length > 0);
86
+ }
87
+ /** One predicate over the tool calls (and results, and answers) recorded before `before`. */
88
+ function judge(p, uses, before, answers = []) {
67
89
  const seen = uses.filter((u) => u.seq < before);
68
90
  const one = isObj(p) && Object.keys(p).length === 1 ? Object.entries(p)[0] : null;
69
91
  const [key, arg] = one ?? ["", null];
70
92
  const named = typeof arg === "string" ? seen.filter((u) => u.tool === arg) : [];
71
93
  const out = (result, gap) => ({ predicate: p, result, ...(gap ? { gap } : {}) });
94
+ if (key === "tool_args" || key === "answer") {
95
+ // spec/findings.md §5a: a claim's own asserts aren't checked when filed, so here
96
+ const bad = checkPredicate(p);
97
+ if (bad)
98
+ return out("cannot_verify", `invalid predicate: ${bad}`);
99
+ const r = key === "tool_args"
100
+ ? judgeArgs(arg, uses, before)
101
+ : judgeAnswer(arg, answers, before);
102
+ return out(r.result, r.gap);
103
+ }
72
104
  if (key === "tool_called" && typeof arg === "string")
73
105
  return named.length ? out("pass") : out("fail", `${arg} was never called`);
74
106
  if (key === "tool_not_called" && typeof arg === "string")
@@ -94,6 +126,7 @@ function judge(p, uses, before) {
94
126
  export function landing(events, lines, bodies) {
95
127
  const plan = planOf(events);
96
128
  const uses = usesOf(events, lines, bodies);
129
+ const answers = answersOf(lines, bodies);
97
130
  const claims = [];
98
131
  for (const e of events) {
99
132
  if (e.kind !== "sdk.event" || e.meta.type !== "claim")
@@ -102,11 +135,11 @@ export function landing(events, lines, bodies) {
102
135
  const criteria = [
103
136
  ...listOf(plan?.criteria).map((p, i) => ({
104
137
  criterion: `plan:${i}`,
105
- ...judge(p, uses, e.seq),
138
+ ...judge(p, uses, e.seq, answers),
106
139
  })),
107
140
  ...listOf(data.asserts).map((p, i) => ({
108
141
  criterion: `assert:${i}`,
109
- ...judge(p, uses, e.seq),
142
+ ...judge(p, uses, e.seq, answers),
110
143
  })),
111
144
  ];
112
145
  const verdict = criteria.some((c) => c.result === "fail")
@@ -145,7 +178,9 @@ export function flightPlan(events, lines, bodies) {
145
178
  }
146
179
  }
147
180
  listOf(plan.criteria).forEach((p, i) => {
148
- if (!isObj(p) || !("tool_not_called" in p || "max_tool_calls" in p))
181
+ // broken as soon as it is: a limit, or a rule on every call's arguments (§5a.2)
182
+ const every = isObj(p) && isObj(p.tool_args) && p.tool_args.for === "every";
183
+ if (!isObj(p) || !("tool_not_called" in p || "max_tool_calls" in p || every))
149
184
  return;
150
185
  const r = judge(p, uses, Number.POSITIVE_INFINITY);
151
186
  if (r.result === "fail")
@@ -196,11 +231,22 @@ export function checkFlightPlan(plan) {
196
231
  tools.every((x) => typeof x === "string" && x.length > 0 && x.length <= 128)))
197
232
  return "flight_plan.expected_tools must be at most 100 tool names";
198
233
  const value = (v) => typeof v === "string" ? v.length <= 128 : Number.isSafeInteger(v) && v >= 0;
199
- if (criteria !== undefined &&
200
- !(Array.isArray(criteria) &&
201
- criteria.length <= 50 &&
202
- criteria.every((c) => isObj(c) && Object.keys(c).length === 1 && value(Object.values(c)[0]))))
203
- return 'flight_plan.criteria must be at most 50 predicates like {"tool_called": "run_tests"}';
234
+ const legacy = 'flight_plan.criteria must be at most 50 predicates like {"tool_called": "run_tests"}';
235
+ if (criteria !== undefined) {
236
+ if (!Array.isArray(criteria) || criteria.length > 50)
237
+ return legacy;
238
+ for (const [i, c] of criteria.entries()) {
239
+ if (!isObj(c) || Object.keys(c).length !== 1)
240
+ return legacy;
241
+ if ("tool_args" in c || "answer" in c) {
242
+ const bad = checkPredicate(c); // spec/findings.md §5a
243
+ if (bad)
244
+ return `flight_plan.criteria[${i}]: ${bad}`;
245
+ }
246
+ else if (!value(Object.values(c)[0]))
247
+ return legacy;
248
+ }
249
+ }
204
250
  const name = (x) => typeof x === "string" && x.length > 0 && x.length <= 128;
205
251
  const { sterile } = plan;
206
252
  if (sterile !== undefined &&
@@ -0,0 +1,55 @@
1
+ type Test = (c: string) => boolean;
2
+ type Inst = {
3
+ op: "char";
4
+ test: Test;
5
+ } | {
6
+ op: "split";
7
+ x: number;
8
+ y: number;
9
+ } | {
10
+ op: "jmp";
11
+ x: number;
12
+ } | {
13
+ op: "assert";
14
+ kind: "bol" | "eol" | "word" | "nonword";
15
+ } | {
16
+ op: "match";
17
+ };
18
+ export interface Pattern {
19
+ prog: Inst[];
20
+ }
21
+ /** Text longer than this (in code points) isn't matched (cannot_verify). */
22
+ export declare const MAX_MATCH_TEXT = 100000;
23
+ /** Parses and compiles a pattern, or says why it isn't one (spec/findings.md §5a.1). */
24
+ export declare function compilePattern(source: unknown): Pattern | string;
25
+ /** Whether the pattern matches anywhere in the text (a search, not a full match). */
26
+ export declare function patternMatches(p: Pattern, text: string): boolean;
27
+ /** A value in integer milli-units (spec/findings.md §5a.2), or null. */
28
+ export declare function milliOf(v: unknown): number | null;
29
+ /** Why a schema is outside the subset, or undefined. */
30
+ export declare function checkSchema(schema: unknown): string | undefined;
31
+ /** The first place a value breaks a (checked) schema, or undefined (spec/findings.md §5a.3). */
32
+ export declare function schemaError(value: unknown, schema: unknown, path?: string): string | undefined;
33
+ /** Why a `tool_args` or `answer` predicate is invalid, or undefined. */
34
+ export declare function checkPredicate(p: unknown): string | undefined;
35
+ /** A tool call with its arguments, when they're on the record (`args` absent: unknown). */
36
+ export interface ArgUse {
37
+ seq: number;
38
+ tool: string;
39
+ args?: unknown;
40
+ hasArgs: boolean;
41
+ }
42
+ type Out = {
43
+ result: "pass" | "fail" | "cannot_verify";
44
+ gap?: string;
45
+ };
46
+ /** A `tool_args` predicate over the tool calls before `before` (spec/findings.md §5a.2). */
47
+ export declare function judgeArgs(arg: Record<string, unknown>, uses: readonly ArgUse[], before: number): Out;
48
+ /** The JSON an answer holds: the whole text, or one ``` fence around it; ABSENT when it isn't JSON. */
49
+ export declare function answerJson(text: string): unknown;
50
+ /** An `answer` predicate over the last final answer before `before` (spec/findings.md §5a.4). */
51
+ export declare function judgeAnswer(arg: Record<string, unknown>, answers: ReadonlyArray<{
52
+ seq: number;
53
+ text: string;
54
+ }>, before: number): Out;
55
+ export {};