@belticlabs/agent-risk-sdk 0.1.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.
@@ -0,0 +1,19 @@
1
+ import { PaymentMomentPayload } from './api.js';
2
+ import { LanguageModelMiddleware, Tool, ToolSet } from 'ai';
3
+ import { S as Session } from '../session-BMNB1N1g.js';
4
+ import './base58.js';
5
+
6
+ interface PaymentMoments {
7
+ requested?: PaymentMomentPayload;
8
+ presented?: PaymentMomentPayload;
9
+ }
10
+ interface WrapToolOptions<I = unknown, O = unknown> {
11
+ name?: string;
12
+ /** When the tool performs a purchase, map its input/output to the payment moments it produced. */
13
+ payment?: (input: I, output: O) => PaymentMoments | null;
14
+ }
15
+ declare function middleware(session: Session): LanguageModelMiddleware;
16
+ declare function wrapTool<T extends Tool>(session: Session, tool: T, opts?: WrapToolOptions): T;
17
+ declare function wrapTools<T extends ToolSet>(session: Session, tools: T, opts?: Record<string, WrapToolOptions>): T;
18
+
19
+ export { type PaymentMoments, type WrapToolOptions, middleware, wrapTool, wrapTools };
@@ -0,0 +1,120 @@
1
+ import {
2
+ recordCall
3
+ } from "../chunk-5TWO73OD.js";
4
+ import {
5
+ uuidv7
6
+ } from "../chunk-SFGM7KOG.js";
7
+ import {
8
+ toJson,
9
+ toJsonObject
10
+ } from "../chunk-FQDHFTVR.js";
11
+ import "../chunk-GCKCAKHA.js";
12
+
13
+ // src/ai/index.ts
14
+ var PARAM_KEYS = [
15
+ "prompt",
16
+ "tools",
17
+ "toolChoice",
18
+ "maxOutputTokens",
19
+ "temperature",
20
+ "topP",
21
+ "topK",
22
+ "seed",
23
+ "responseFormat",
24
+ "stopSequences"
25
+ ];
26
+ function middleware(session) {
27
+ return {
28
+ wrapGenerate: ({ doGenerate, params, model }) => recordCall(
29
+ session,
30
+ "llm_call",
31
+ uuidv7(),
32
+ { provider: model.provider, modelId: model.modelId, params: pick(params) },
33
+ doGenerate,
34
+ (result) => ({
35
+ content: toJson(result.content),
36
+ finishReason: result.finishReason.unified,
37
+ usage: toJsonObject(result.usage)
38
+ })
39
+ ),
40
+ // A stream ends when it drains, not when doStream resolves — so its end is emitted at flush.
41
+ wrapStream: async ({ doStream, params, model }) => {
42
+ const callId = uuidv7();
43
+ const started = Date.now();
44
+ await session.emit("llm_call.start", {
45
+ callId,
46
+ provider: model.provider,
47
+ modelId: model.modelId,
48
+ params: pick(params)
49
+ });
50
+ const { stream, ...rest } = await doStream();
51
+ const parts = [];
52
+ let finish = {};
53
+ const tap = new TransformStream({
54
+ transform(part, controller) {
55
+ const p = part;
56
+ if (p.type === "finish")
57
+ finish = { finishReason: p.finishReason?.unified, usage: p.usage };
58
+ else if (p.type !== "stream-start" && p.type !== "raw") parts.push(part);
59
+ controller.enqueue(part);
60
+ },
61
+ flush: async () => {
62
+ await session.emit("llm_call.end", {
63
+ callId,
64
+ content: toJson(parts),
65
+ ...finish.finishReason ? { finishReason: finish.finishReason } : {},
66
+ ...finish.usage ? { usage: toJsonObject(finish.usage) } : {},
67
+ durationMs: Date.now() - started
68
+ });
69
+ }
70
+ });
71
+ return { stream: stream.pipeThrough(tap), ...rest };
72
+ }
73
+ };
74
+ }
75
+ function wrapTool(session, tool, opts = {}) {
76
+ if (!tool.execute) return tool;
77
+ const original = tool.execute;
78
+ const toolName = opts.name ?? tool.name ?? "tool";
79
+ const execute = (input, options) => recordCall(
80
+ session,
81
+ "tool_call",
82
+ options?.toolCallId ?? uuidv7(),
83
+ { toolName, input: toJson(input), transport: "local" },
84
+ async () => {
85
+ const output = await original(input, options);
86
+ return output && typeof output === "object" && Symbol.asyncIterator in output ? collect(output) : output;
87
+ },
88
+ async (output) => {
89
+ const moments = opts.payment?.(input, output) ?? null;
90
+ if (moments?.requested) await session.emit("payment.requested", moments.requested);
91
+ if (moments?.presented) await session.emit("payment.presented", moments.presented);
92
+ return { output: toJson(output) };
93
+ }
94
+ );
95
+ return { ...tool, execute };
96
+ }
97
+ function wrapTools(session, tools, opts = {}) {
98
+ const out = {};
99
+ for (const [name, tool] of Object.entries(tools))
100
+ out[name] = wrapTool(session, tool, { name, ...opts[name] });
101
+ return out;
102
+ }
103
+ function pick(params) {
104
+ const out = {};
105
+ for (const k of PARAM_KEYS) {
106
+ const v = params[k];
107
+ if (v !== void 0) out[k] = toJson(v);
108
+ }
109
+ return out;
110
+ }
111
+ async function collect(it) {
112
+ const out = [];
113
+ for await (const x of it) out.push(x);
114
+ return out;
115
+ }
116
+ export {
117
+ middleware,
118
+ wrapTool,
119
+ wrapTools
120
+ };
@@ -0,0 +1,35 @@
1
+ // src/core/record.ts
2
+ function errorOf(err) {
3
+ const e = err;
4
+ return { name: String(e?.name ?? "Error"), message: String(e?.message ?? err) };
5
+ }
6
+ async function recordCall(session, kind, callId, start, run, end = () => ({})) {
7
+ const started = Date.now();
8
+ await session.emit(`${kind}.start`, { callId, ...start });
9
+ try {
10
+ const result = await run();
11
+ await session.emit(
12
+ `${kind}.end`,
13
+ {
14
+ callId,
15
+ ...await end(result),
16
+ durationMs: Date.now() - started
17
+ }
18
+ );
19
+ return result;
20
+ } catch (err) {
21
+ await session.emit(
22
+ `${kind}.end`,
23
+ {
24
+ callId,
25
+ error: errorOf(err),
26
+ durationMs: Date.now() - started
27
+ }
28
+ );
29
+ throw err;
30
+ }
31
+ }
32
+
33
+ export {
34
+ recordCall
35
+ };
@@ -0,0 +1,17 @@
1
+ // src/core/payment-moment.ts
2
+ function summaryOf(m) {
3
+ return {
4
+ protocol: m.protocol,
5
+ payee: m.payee,
6
+ amount: { value: m.amount.value, currency: m.amount.currency },
7
+ ...m.payer ? { payer: m.payer } : {}
8
+ };
9
+ }
10
+ function presentedFrom(summary, raw) {
11
+ return { ...summary, artifact: "payment-signature", raw };
12
+ }
13
+
14
+ export {
15
+ summaryOf,
16
+ presentedFrom
17
+ };
@@ -0,0 +1,29 @@
1
+ // src/core/json.ts
2
+ function toJson(value) {
3
+ if (value === null || value === void 0) return null;
4
+ if (typeof value === "string" || typeof value === "boolean") return value;
5
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
6
+ if (typeof value === "bigint") return value.toString();
7
+ if (value instanceof Uint8Array) return { $bytes: Buffer.from(value).toString("base64") };
8
+ if (value instanceof Date) return value.toISOString();
9
+ if (value instanceof URL) return value.toString();
10
+ if (Array.isArray(value)) return value.map(toJson);
11
+ if (typeof value === "object") {
12
+ const out = {};
13
+ for (const [k, v] of Object.entries(value)) {
14
+ if (v === void 0 || typeof v === "function") continue;
15
+ out[k] = toJson(v);
16
+ }
17
+ return out;
18
+ }
19
+ return null;
20
+ }
21
+ function toJsonObject(value) {
22
+ const j = toJson(value);
23
+ return j && typeof j === "object" && !Array.isArray(j) ? j : { value: j };
24
+ }
25
+
26
+ export {
27
+ toJson,
28
+ toJsonObject
29
+ };
@@ -0,0 +1,401 @@
1
+ // ../protocol/src/verdict.ts
2
+ var SEVERITY = { ALLOW: 0, REVIEW: 1, DENY: 2 };
3
+ var Verdict = class _Verdict {
4
+ constructor(value) {
5
+ this.value = value;
6
+ }
7
+ static ALLOW = new _Verdict("ALLOW");
8
+ static REVIEW = new _Verdict("REVIEW");
9
+ static DENY = new _Verdict("DENY");
10
+ static of(value) {
11
+ return value === "DENY" ? _Verdict.DENY : value === "REVIEW" ? _Verdict.REVIEW : _Verdict.ALLOW;
12
+ }
13
+ /** The more severe of the two. */
14
+ atLeast(other) {
15
+ const o = typeof other === "string" ? _Verdict.of(other) : other;
16
+ return SEVERITY[o.value] > SEVERITY[this.value] ? o : this;
17
+ }
18
+ /** Whether a synchronous gate must stop the call (GAP-52). */
19
+ blocks(onReview) {
20
+ return this.value === "DENY" || this.value === "REVIEW" && onReview === "abort";
21
+ }
22
+ /** What the gate effectively did: DENY when it blocked, else the verdict itself. */
23
+ effective(onReview) {
24
+ return this.blocks(onReview) ? "DENY" : this.value;
25
+ }
26
+ };
27
+
28
+ // ../protocol/src/api.ts
29
+ import { z as z4 } from "zod";
30
+
31
+ // ../protocol/src/evidence.ts
32
+ import { z } from "zod";
33
+ var WIRE_SOURCES = ["AGENT_TRACE", "INTERNAL_NETWORK"];
34
+ var ALL_SOURCES = ["AGENT_TRACE", "INTERNAL_NETWORK", "PLATFORM"];
35
+ var EvidenceSourceSchema = z.enum(WIRE_SOURCES);
36
+ var EvidenceSourceAllSchema = z.enum(ALL_SOURCES);
37
+ var WIRE_KINDS = [
38
+ "session.open",
39
+ "session.close",
40
+ "intent.declared",
41
+ "llm_call.start",
42
+ "llm_call.end",
43
+ "tool_call.start",
44
+ "tool_call.end",
45
+ "payment.requested",
46
+ "payment.presented",
47
+ "gateway.decision",
48
+ "transport.gap"
49
+ ];
50
+ var PLATFORM_KINDS = ["platform.observation", "platform.anomaly"];
51
+ var WireEvidenceKindSchema = z.enum(WIRE_KINDS);
52
+ var PlatformEvidenceKindSchema = z.enum(PLATFORM_KINDS);
53
+ var EvidenceKindSchema = z.enum([...WIRE_KINDS, ...PLATFORM_KINDS]);
54
+ var Hex64Schema = z.string().regex(/^[0-9a-f]{64}$/, "expected 64 lowercase hex chars");
55
+ var SigSchema = z.string().regex(/^ed25519:[A-Za-z0-9_-]{86}$/, "expected ed25519:<base64url>");
56
+ var SessionIdSchema = z.uuid();
57
+ var SeqSchema = z.number().int().min(0);
58
+ var TimestampSchema = z.iso.datetime({ offset: false });
59
+ var JsonValueSchema = z.lazy(
60
+ () => z.union([
61
+ z.null(),
62
+ z.boolean(),
63
+ z.number().finite(),
64
+ z.string(),
65
+ z.array(JsonValueSchema),
66
+ z.record(z.string(), JsonValueSchema)
67
+ ])
68
+ );
69
+ var EvidenceEventSchema = z.strictObject({
70
+ sessionId: SessionIdSchema,
71
+ source: EvidenceSourceSchema,
72
+ seq: SeqSchema,
73
+ ts: TimestampSchema,
74
+ kind: WireEvidenceKindSchema,
75
+ payload: z.record(z.string(), JsonValueSchema),
76
+ prevHash: Hex64Schema,
77
+ sig: SigSchema.optional()
78
+ });
79
+
80
+ // ../protocol/src/policy.ts
81
+ import { z as z3 } from "zod";
82
+
83
+ // ../protocol/src/reason-codes.ts
84
+ var REASON_CODE_PATTERN = /^[A-Z][A-Z0-9_]{1,63}$/;
85
+
86
+ // ../protocol/src/selector.ts
87
+ import { z as z2 } from "zod";
88
+ var SelectorSyntaxError = class extends Error {
89
+ constructor(input, at, detail) {
90
+ super(`invalid selector "${input}" at ${at}: ${detail}`);
91
+ this.input = input;
92
+ this.at = at;
93
+ this.name = "SelectorSyntaxError";
94
+ }
95
+ code = "SELECTOR_SYNTAX";
96
+ };
97
+ var IDENT = /^[A-Za-z_][A-Za-z0-9_-]*/;
98
+ var NAME = /^[A-Za-z_][A-Za-z0-9_.-]*/;
99
+ function parsePath(input, from) {
100
+ const path = [];
101
+ let i = from;
102
+ while (i < input.length) {
103
+ const ch = input[i];
104
+ if (ch === ".") {
105
+ const m = IDENT.exec(input.slice(i + 1));
106
+ if (!m) throw new SelectorSyntaxError(input, i + 1, 'expected identifier after "."');
107
+ path.push({ key: m[0] });
108
+ i += 1 + m[0].length;
109
+ } else if (ch === "[") {
110
+ const close = input.indexOf("]", i);
111
+ if (close < 0) throw new SelectorSyntaxError(input, i, 'unterminated "["');
112
+ const body = input.slice(i + 1, close);
113
+ if (!/^\d+$/.test(body))
114
+ throw new SelectorSyntaxError(input, i + 1, "expected integer index");
115
+ path.push({ index: Number(body) });
116
+ i = close + 1;
117
+ } else {
118
+ throw new SelectorSyntaxError(input, i, `unexpected "${ch}"`);
119
+ }
120
+ }
121
+ return { path, end: i };
122
+ }
123
+ function parseSelector(input) {
124
+ if (typeof input !== "string" || input.length === 0) {
125
+ throw new SelectorSyntaxError(String(input), 0, "empty selector");
126
+ }
127
+ if (input.length > 512)
128
+ throw new SelectorSyntaxError(input.slice(0, 32), 512, "selector too long");
129
+ for (const root of ["payment", "intent", "session"]) {
130
+ if (input === root || input.startsWith(`${root}.`) || input.startsWith(`${root}[`)) {
131
+ return { root, path: parsePath(input, root.length).path };
132
+ }
133
+ }
134
+ if (input.startsWith("signal[name=")) {
135
+ const rest = input.slice("signal[name=".length);
136
+ const m = NAME.exec(rest);
137
+ if (!m) throw new SelectorSyntaxError(input, "signal[name=".length, "expected signal name");
138
+ const after = "signal[name=".length + m[0].length;
139
+ if (input[after] !== "]") throw new SelectorSyntaxError(input, after, 'expected "]"');
140
+ return { root: "signal", name: m[0], path: parsePath(input, after + 1).path };
141
+ }
142
+ if (input === "evidence[*]" || input.startsWith("evidence[*]")) {
143
+ return {
144
+ root: "evidence",
145
+ kind: "*",
146
+ all: true,
147
+ path: parsePath(input, "evidence[*]".length).path
148
+ };
149
+ }
150
+ if (input.startsWith("evidence[kind=")) {
151
+ let i = "evidence[kind=".length;
152
+ const km = NAME.exec(input.slice(i));
153
+ if (!km) throw new SelectorSyntaxError(input, i, "expected evidence kind");
154
+ const kind = km[0];
155
+ i += kind.length;
156
+ let source;
157
+ if (input.startsWith(",source=", i)) {
158
+ i += ",source=".length;
159
+ const sm = /^[A-Z_]+/.exec(input.slice(i));
160
+ if (!sm || !ALL_SOURCES.includes(sm[0])) {
161
+ throw new SelectorSyntaxError(input, i, `expected one of ${ALL_SOURCES.join("|")}`);
162
+ }
163
+ source = sm[0];
164
+ i += sm[0].length;
165
+ }
166
+ if (input[i] !== "]") throw new SelectorSyntaxError(input, i, 'expected "]"');
167
+ i += 1;
168
+ let all = false;
169
+ if (input.startsWith("[*]", i)) {
170
+ all = true;
171
+ i += 3;
172
+ }
173
+ const sel = { root: "evidence", kind, all, path: parsePath(input, i).path };
174
+ if (source) sel.source = source;
175
+ return sel;
176
+ }
177
+ throw new SelectorSyntaxError(
178
+ input,
179
+ 0,
180
+ "unknown root (payment | intent | session | signal[name=\u2026] | evidence[\u2026])"
181
+ );
182
+ }
183
+ var SelectorStringSchema = z2.string().refine(
184
+ (s) => {
185
+ try {
186
+ parseSelector(s);
187
+ return true;
188
+ } catch {
189
+ return false;
190
+ }
191
+ },
192
+ { message: "invalid selector" }
193
+ );
194
+
195
+ // ../protocol/src/policy.ts
196
+ var PRIMITIVES = ["THRESHOLD", "MEMBERSHIP", "MATCH", "PRESENCE", "FRESHNESS"];
197
+ var PrimitiveSchema = z3.enum(PRIMITIVES);
198
+ var RuleVerdictSchema = z3.enum(["DENY", "REVIEW"]);
199
+ var RuleSchema = z3.strictObject({
200
+ id: z3.string().min(1).max(64),
201
+ primitive: PrimitiveSchema,
202
+ selector: SelectorStringSchema,
203
+ params: z3.record(z3.string(), JsonValueSchema),
204
+ onFail: RuleVerdictSchema,
205
+ /** What to do when the selector (or a `@ref`) resolves to nothing. Default: skip (GAP-44). */
206
+ onMissing: z3.enum(["skip", "DENY", "REVIEW"]).optional(),
207
+ /** Reason code surfaced to the caller when the rule fails (GAP-44). */
208
+ code: z3.string().regex(REASON_CODE_PATTERN)
209
+ });
210
+ var PolicyRulesSchema = z3.strictObject({
211
+ rules: z3.array(RuleSchema).max(200).refine((rules) => new Set(rules.map((r) => r.id)).size === rules.length, {
212
+ message: "rule ids must be unique"
213
+ }),
214
+ /** Domain-score thresholds — the only configurable part of the scores layer. */
215
+ scoreThresholds: z3.record(z3.string(), z3.number().min(0).max(1)).optional()
216
+ });
217
+
218
+ // ../protocol/src/api.ts
219
+ var AmountSchema = z4.strictObject({
220
+ /** Decimal string — never a float. For x402 this is the atomic amount (GAP-49). */
221
+ value: z4.string().regex(/^\d+(\.\d+)?$/, "expected a decimal string"),
222
+ /** ISO code, or `<network>/<asset>` for on-chain rails (GAP-49). */
223
+ currency: z4.string().min(1).max(128)
224
+ });
225
+ var DeclaredIntentSchema = z4.strictObject({
226
+ mandate: z4.string().min(1).max(4e3),
227
+ maxAmount: AmountSchema.optional(),
228
+ merchantAllowlist: z4.array(z4.string().min(1)).optional(),
229
+ validUntil: TimestampSchema
230
+ });
231
+ var CreateSessionInputSchema = z4.strictObject({
232
+ source: EvidenceSourceSchema,
233
+ /** Buyer-born sessions. `credential` is opaque this phase (GAP-11). */
234
+ agent: z4.strictObject({ did: z4.string().min(1), credential: z4.string().min(1) }).optional(),
235
+ intent: DeclaredIntentSchema.optional()
236
+ });
237
+ var CreateSessionOutputSchema = z4.strictObject({
238
+ sessionId: SessionIdSchema,
239
+ expiresAt: TimestampSchema
240
+ });
241
+ var MAX_BATCH_EVENTS = 500;
242
+ var EvidenceBatchInputSchema = z4.array(EvidenceEventSchema).min(1).max(MAX_BATCH_EVENTS);
243
+ var EventResultStatusSchema = z4.enum(["ok", "duplicate", "fork", "rejected"]);
244
+ var EventResultSchema = z4.strictObject({
245
+ index: z4.number().int().min(0),
246
+ sessionId: SessionIdSchema.nullable(),
247
+ source: EvidenceSourceSchema.nullable(),
248
+ seq: z4.number().int().min(0).nullable(),
249
+ status: EventResultStatusSchema,
250
+ code: z4.string().optional(),
251
+ eventDigest: Hex64Schema.optional()
252
+ });
253
+ var ChainHeadSchema = z4.strictObject({
254
+ seq: z4.number().int().min(0),
255
+ digest: Hex64Schema
256
+ });
257
+ var EvidenceAckSchema = z4.strictObject({
258
+ results: z4.array(EventResultSchema),
259
+ /** Head of every chain touched by the batch, after the batch. Keyed `sessionId:source`. */
260
+ heads: z4.record(z4.string(), ChainHeadSchema)
261
+ });
262
+ var PaymentSummarySchema = z4.strictObject({
263
+ protocol: z4.string().min(1),
264
+ payee: z4.string().min(1),
265
+ amount: AmountSchema,
266
+ /** Not in the RFC; needed by `principal-links` and `EVIDENCE_MISMATCH` (GAP-06). */
267
+ payer: z4.string().min(1).optional()
268
+ });
269
+ var EvaluateInputSchema = z4.strictObject({
270
+ sessionId: SessionIdSchema,
271
+ payment: PaymentSummarySchema
272
+ });
273
+ var DecisionSchema = z4.enum(["ALLOW", "DENY", "REVIEW"]);
274
+ var EvaluateOutputSchema = z4.strictObject({
275
+ decision: DecisionSchema,
276
+ reasonCodes: z4.array(z4.string().regex(REASON_CODE_PATTERN)),
277
+ sessionId: SessionIdSchema,
278
+ /** Additive (GAP-21). */
279
+ decisionId: z4.uuid()
280
+ });
281
+ var AnchorEntrySchema = z4.strictObject({
282
+ epoch: z4.string().min(1),
283
+ root: Hex64Schema,
284
+ sig: z4.string().min(1),
285
+ chainRef: z4.string().optional()
286
+ });
287
+ var AnchorsOutputSchema = z4.strictObject({ entries: z4.array(AnchorEntrySchema) });
288
+ var CreatePolicyInputSchema = z4.strictObject({ rules: PolicyRulesSchema });
289
+ var CreatePolicyOutputSchema = z4.strictObject({
290
+ policyId: z4.uuid(),
291
+ version: z4.number().int().min(1),
292
+ status: z4.enum(["ACTIVE", "SUPERSEDED", "DRAFT"])
293
+ });
294
+ var ApiErrorSchema = z4.strictObject({
295
+ error: z4.strictObject({
296
+ code: z4.string().min(1),
297
+ message: z4.string().min(1),
298
+ details: JsonValueSchema.optional(),
299
+ request_id: z4.string().optional()
300
+ })
301
+ });
302
+
303
+ // ../protocol/src/payloads/index.ts
304
+ import { z as z5 } from "zod";
305
+ var Json = JsonValueSchema;
306
+ var JsonRecord = z5.record(z5.string(), Json);
307
+ var SessionOpenPayloadSchema = z5.looseObject({
308
+ runtime: z5.looseObject({
309
+ sdk: z5.string().min(1),
310
+ version: z5.string().min(1),
311
+ framework: z5.string().optional(),
312
+ model: z5.string().optional()
313
+ }),
314
+ /** Runtime / repo attestations read by the (staged) Attestation Assurance score. */
315
+ attestations: JsonRecord.optional()
316
+ });
317
+ var SESSION_CLOSE_REASONS = ["completed", "settled", "aborted", "expired"];
318
+ var SessionClosePayloadSchema = z5.looseObject({
319
+ reason: z5.enum(SESSION_CLOSE_REASONS),
320
+ transaction: z5.string().optional()
321
+ });
322
+ var IntentDeclaredPayloadSchema = DeclaredIntentSchema.loose();
323
+ var LlmCallStartPayloadSchema = z5.looseObject({
324
+ callId: z5.string().min(1),
325
+ // GAP-07
326
+ provider: z5.string().min(1),
327
+ modelId: z5.string().min(1),
328
+ params: JsonRecord
329
+ });
330
+ var LlmCallEndPayloadSchema = z5.looseObject({
331
+ callId: z5.string().min(1),
332
+ content: Json.optional(),
333
+ finishReason: z5.string().optional(),
334
+ usage: JsonRecord.optional(),
335
+ durationMs: z5.number().int().min(0),
336
+ error: z5.looseObject({ name: z5.string(), message: z5.string() }).optional()
337
+ });
338
+ var ToolCallStartPayloadSchema = z5.looseObject({
339
+ callId: z5.string().min(1),
340
+ // GAP-07
341
+ toolName: z5.string().min(1),
342
+ input: Json,
343
+ transport: z5.enum(["local", "mcp"]).optional(),
344
+ server: z5.string().optional()
345
+ });
346
+ var ToolCallEndPayloadSchema = z5.looseObject({
347
+ callId: z5.string().min(1),
348
+ output: Json.optional(),
349
+ error: z5.looseObject({ name: z5.string(), message: z5.string() }).optional(),
350
+ durationMs: z5.number().int().min(0)
351
+ });
352
+ var PAYMENT_ARTIFACTS = [
353
+ "http-402",
354
+ "mrtr-input-required",
355
+ "payment-signature",
356
+ "checkout-url"
357
+ ];
358
+ var PaymentMomentPayloadSchema = z5.looseObject({
359
+ protocol: z5.string().min(1),
360
+ payee: z5.string().min(1),
361
+ amount: z5.looseObject({ value: z5.string().min(1), currency: z5.string().min(1) }),
362
+ payer: z5.string().optional(),
363
+ artifact: z5.enum(PAYMENT_ARTIFACTS),
364
+ raw: JsonRecord
365
+ });
366
+ var GatewayDecisionPayloadSchema = z5.looseObject({
367
+ gateway: z5.string().min(1),
368
+ call: z5.looseObject({ tool: z5.string().min(1), args: Json.optional() }),
369
+ decision: z5.enum(["ALLOW", "DENY", "REVIEW", "CHALLENGE"]),
370
+ reasonCodes: z5.array(z5.string()),
371
+ /** The gateway's own record of what it decided on — a black box to the platform. */
372
+ record: JsonRecord
373
+ });
374
+ var TransportGapPayloadSchema = z5.looseObject({
375
+ dropped: z5.number().int().min(1),
376
+ firstTs: z5.string(),
377
+ lastTs: z5.string()
378
+ });
379
+ var PlatformObservationPayloadSchema = z5.strictObject({
380
+ origin: z5.string().min(1),
381
+ params: Json,
382
+ response: Json
383
+ });
384
+ var ANOMALY_TYPES = [
385
+ "fork",
386
+ "seq_gap",
387
+ "prev_hash_mismatch",
388
+ "bad_sig",
389
+ "clock_skew",
390
+ "source_conflict"
391
+ ];
392
+ var PlatformAnomalyPayloadSchema = z5.looseObject({
393
+ type: z5.enum(ANOMALY_TYPES),
394
+ source: EvidenceSourceAllSchema,
395
+ seq: z5.number().int().min(0).nullable(),
396
+ detail: JsonRecord
397
+ });
398
+
399
+ export {
400
+ Verdict
401
+ };