@belticlabs/agent-risk-sdk 0.2.0 → 0.3.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.
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  guardedPaymentMiddleware
3
- } from "../chunk-U7HM37CB.js";
3
+ } from "../chunk-NJVO2WIV.js";
4
4
  import {
5
5
  attachX402
6
- } from "../chunk-SO6HPRJT.js";
7
- import "../chunk-VM7MK43J.js";
8
- import "../chunk-SFGM7KOG.js";
6
+ } from "../chunk-OKC6VMFH.js";
7
+ import "../chunk-FAQ442YH.js";
8
+ import "../chunk-X3W2Z5GC.js";
9
9
  import "../chunk-46QN2KEZ.js";
10
10
  import "../chunk-LM4NIYE5.js";
11
11
  import "../chunk-FQDHFTVR.js";
@@ -1,12 +1,10 @@
1
1
  import { RoutesConfig, x402ResourceServer } from '@x402/core/server';
2
2
  import { MiddlewareHandler } from 'hono';
3
- import { B as Beltic } from '../client-C-mV_3A0.js';
4
- import { G as GuardedMiddlewareOptions } from '../middleware-BwAYpBTl.js';
5
- export { a as attachX402 } from '../adapter-CF-cUYSA.js';
6
- import '../index-Bjs3BPPU.js';
3
+ import { B as Beltic } from '../session-DsBWEP8d.js';
4
+ import { G as GuardedMiddlewareOptions } from '../middleware-9gI0ou2i.js';
5
+ export { a as attachX402 } from '../adapter-BEpzr2R3.js';
6
+ import '../verdict-6vCyoAHE.js';
7
7
  import 'zod';
8
- import '../verdict-BAahb5po.js';
9
- import '../session-5TClPLI4.js';
10
8
 
11
9
  /** Seller half for hono: `@x402/hono`'s payment middleware with the Beltic hooks attached. */
12
10
 
package/dist/x402/hono.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  guardedPaymentMiddleware
3
- } from "../chunk-U7HM37CB.js";
3
+ } from "../chunk-NJVO2WIV.js";
4
4
  import {
5
5
  attachX402
6
- } from "../chunk-SO6HPRJT.js";
7
- import "../chunk-VM7MK43J.js";
8
- import "../chunk-SFGM7KOG.js";
6
+ } from "../chunk-OKC6VMFH.js";
7
+ import "../chunk-FAQ442YH.js";
8
+ import "../chunk-X3W2Z5GC.js";
9
9
  import "../chunk-46QN2KEZ.js";
10
10
  import "../chunk-LM4NIYE5.js";
11
11
  import "../chunk-FQDHFTVR.js";
@@ -1,45 +1,31 @@
1
- export { A as AttachOptions, b as AttachedX402, C as CorrelationContext, a as attachX402 } from '../adapter-CF-cUYSA.js';
2
- import { S as Session } from '../session-5TClPLI4.js';
3
- import { v as DeclaredIntent, P as PaymentMomentPayload, J as JsonObject, a as PaymentSummary } from '../index-Bjs3BPPU.js';
1
+ export { A as AttachOptions, b as AttachedX402, C as CorrelationContext, a as attachX402 } from '../adapter-BEpzr2R3.js';
2
+ import { S as SessionSource } from '../session-DsBWEP8d.js';
3
+ import { v as DeclaredIntent, P as PaymentMomentPayload, J as JsonObject, a as PaymentSummary } from '../verdict-6vCyoAHE.js';
4
4
  import '@x402/core/server';
5
- import '../client-C-mV_3A0.js';
6
- import '../verdict-BAahb5po.js';
7
5
  import 'zod';
8
6
 
9
7
  /**
10
8
  * Session binding on the x402 rail (Fraud SDK RFC › Protocol Adapter — x402:
11
9
  * "`PAYMENT-SIGNATURE` extension `beltic.sessionId`"). Where exactly it
12
10
  * lives is GAP-30; that it is outside the wallet-signed payload is GAP-56.
11
+ * A presentation the buyer had evaluated first also carries the
12
+ * `decisionId` the platform answered with, next to the session (GAP-80).
13
13
  */
14
14
  declare const SESSION_EXTENSION = "beltic.sessionId";
15
15
  declare const SESSION_HEADER = "Beltic-Session-Id";
16
+ declare const DECISION_EXTENSION = "beltic.decisionId";
17
+ declare const DECISION_HEADER = "Beltic-Decision-Id";
16
18
  declare function sessionIdOf(extensions: Readonly<Record<string, unknown>> | undefined): string | null;
19
+ declare function decisionIdOf(extensions: Readonly<Record<string, unknown>> | undefined): string | null;
17
20
 
18
21
  /**
19
- * Buyer half the x402 fetch wrapper. Sits *inside* the agent's paying
20
- * fetch (e.g. `wrapFetchWithPayment(belticFetch(session))`), so it sees the
21
- * 402 challenge `payment.requested`, and the retry carrying the payment
22
- * `payment.presented`, into which it injects the session binding
23
- * (GAP-30). It never pays and never decides.
24
- *
25
- * Before a request that presents payment leaves, the buffered evidence is
26
- * flushed: the seller will evaluate as soon as it sees the payment, and
27
- * the platform must already hold the buyer's side of the story (GAP-66).
28
- *
29
- * Both x402 generations are read: v2 (`PAYMENT-REQUIRED` header,
30
- * `PAYMENT-SIGNATURE` retry, binding in `extensions`) and v1 (challenge in
31
- * the 402 body, `X-PAYMENT` retry, binding by header only — a v1 payload
32
- * has no extensions and names no asset, so the challenge this wrapper saw
33
- * for the same URL supplies it; GAP-72). The header codec is base64 JSON,
34
- * kept here so a buyer needs no `@x402/*` package to be observed.
22
+ * The paying fetch, observed. Takes a session or the run that owns one;
23
+ * without either (the evidence stream is not configured, or the platform
24
+ * refused to open one) the inner fetch is returned as is — or runs as is
25
+ * per request when the run has no session yet — so a host wires it
26
+ * unconditionally.
35
27
  */
36
-
37
- /**
38
- * The paying fetch, observed. Without a session (the evidence stream is
39
- * not configured, or the platform refused to open one) the inner fetch is
40
- * returned as is, so a host wires it unconditionally.
41
- */
42
- declare function belticFetch(session: Session | null | undefined, inner?: typeof globalThis.fetch): typeof globalThis.fetch;
28
+ declare function belticFetch(source: SessionSource, inner?: typeof globalThis.fetch): typeof globalThis.fetch;
43
29
 
44
30
  /**
45
31
  * The declared intent for an x402 mandate (Fraud SDK RFC › Session ›
@@ -127,4 +113,4 @@ declare const x402Moments: {
127
113
  payload(payload: PaymentPayloadLike, accepts?: AcceptsLike | undefined): PaymentMomentPayload;
128
114
  };
129
115
 
130
- export { type AcceptsLike, type PaymentPayloadLike, type PaymentRequiredLike, SESSION_EXTENSION, SESSION_HEADER, type X402IntentInput, belticFetch, payerOf, sessionIdOf, x402Currency, x402Intent, x402Moments, x402Summary };
116
+ export { type AcceptsLike, DECISION_EXTENSION, DECISION_HEADER, type PaymentPayloadLike, type PaymentRequiredLike, SESSION_EXTENSION, SESSION_HEADER, type X402IntentInput, belticFetch, decisionIdOf, payerOf, sessionIdOf, x402Currency, x402Intent, x402Moments, x402Summary };
@@ -1,12 +1,19 @@
1
1
  import {
2
2
  attachX402
3
- } from "../chunk-SO6HPRJT.js";
3
+ } from "../chunk-OKC6VMFH.js";
4
4
  import {
5
+ Session,
6
+ Sessions
7
+ } from "../chunk-4MG6VNAU.js";
8
+ import {
9
+ DECISION_EXTENSION,
10
+ DECISION_HEADER,
5
11
  SESSION_EXTENSION,
6
12
  SESSION_HEADER,
13
+ decisionIdOf,
7
14
  sessionIdOf
8
- } from "../chunk-VM7MK43J.js";
9
- import "../chunk-SFGM7KOG.js";
15
+ } from "../chunk-FAQ442YH.js";
16
+ import "../chunk-X3W2Z5GC.js";
10
17
  import "../chunk-46QN2KEZ.js";
11
18
  import {
12
19
  payerOf,
@@ -19,10 +26,13 @@ import "../chunk-FQDHFTVR.js";
19
26
  // src/x402/fetch.ts
20
27
  var BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
21
28
  var CHALLENGE_MEMORY = 32;
22
- function belticFetch(session, inner = globalThis.fetch) {
23
- if (!session) return inner;
29
+ function belticFetch(source, inner = globalThis.fetch) {
30
+ if (!source) return inner;
31
+ const run = source instanceof Session ? null : source;
24
32
  const challenges = /* @__PURE__ */ new Map();
25
33
  return async (input, init) => {
34
+ const session = await Sessions.resolve(source);
35
+ if (!session) return inner(input, init);
26
36
  const url = urlOf(input);
27
37
  const headers = new Headers(
28
38
  init?.headers ?? (input instanceof Request ? input.headers : void 0)
@@ -32,9 +42,19 @@ function belticFetch(session, inner = globalThis.fetch) {
32
42
  const presented = signature ?? headers.get("X-PAYMENT");
33
43
  const payload = presented ? decodeHeader(presented) : null;
34
44
  if (payload) {
35
- const bound = signature ? { ...payload, extensions: { ...payload.extensions, [SESSION_EXTENSION]: session.id } } : payload;
45
+ const accepts = payload.accepted ?? answeredAccepts(challenges.get(url), payload);
46
+ const decision = run?.decisionFor(x402Moments.payload(payload, accepts));
47
+ const decisionId = decision && !decision.absent ? decision.decisionId : null;
48
+ const bound = signature ? {
49
+ ...payload,
50
+ extensions: {
51
+ ...payload.extensions,
52
+ [SESSION_EXTENSION]: session.id,
53
+ ...decisionId ? { [DECISION_EXTENSION]: decisionId } : {}
54
+ }
55
+ } : payload;
36
56
  if (signature) headers.set("PAYMENT-SIGNATURE", encodeHeader(bound));
37
- const accepts = bound.accepted ?? answeredAccepts(challenges.get(url), bound);
57
+ else if (decisionId) headers.set(DECISION_HEADER, decisionId);
38
58
  await session.emit("payment.presented", x402Moments.payload(bound, accepts));
39
59
  await session.flush();
40
60
  }
@@ -105,10 +125,13 @@ function x402Intent(input) {
105
125
  };
106
126
  }
107
127
  export {
128
+ DECISION_EXTENSION,
129
+ DECISION_HEADER,
108
130
  SESSION_EXTENSION,
109
131
  SESSION_HEADER,
110
132
  attachX402,
111
133
  belticFetch,
134
+ decisionIdOf,
112
135
  payerOf,
113
136
  sessionIdOf,
114
137
  x402Currency,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@belticlabs/agent-risk-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "The Beltic Agent Risk SDK — one client, two halves: instrument the buyer agent (AI SDK, x402 fetch, MCP client) and guard the seller boundary (x402, MCP server, evaluate).",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -1,39 +0,0 @@
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
- function openCall(session, kind, callId, start) {
7
- const started = Date.now();
8
- const opened = session.emit(`${kind}.start`, { callId, ...start });
9
- const close = async (outcome) => {
10
- await opened;
11
- return session.emit(
12
- `${kind}.end`,
13
- { callId, ...outcome, durationMs: Date.now() - started }
14
- );
15
- };
16
- return {
17
- callId,
18
- opened,
19
- end: (outcome = {}) => close(outcome),
20
- fail: (error, outcome = {}) => close({ error: errorOf(error), ...outcome })
21
- };
22
- }
23
- async function recordCall(session, kind, callId, start, run, end = () => ({})) {
24
- const span = openCall(session, kind, callId, start);
25
- await span.opened;
26
- try {
27
- const result = await run();
28
- await span.end(await end(result));
29
- return result;
30
- } catch (err) {
31
- await span.fail(err);
32
- throw err;
33
- }
34
- }
35
-
36
- export {
37
- openCall,
38
- recordCall
39
- };
@@ -1,13 +0,0 @@
1
- // src/x402/binding.ts
2
- var SESSION_EXTENSION = "beltic.sessionId";
3
- var SESSION_HEADER = "Beltic-Session-Id";
4
- function sessionIdOf(extensions) {
5
- const v = extensions?.[SESSION_EXTENSION];
6
- return typeof v === "string" && v.length > 0 ? v : null;
7
- }
8
-
9
- export {
10
- SESSION_EXTENSION,
11
- SESSION_HEADER,
12
- sessionIdOf
13
- };
@@ -1,91 +0,0 @@
1
- import { a as PaymentSummary, P as PaymentMomentPayload, B as EvaluateOutput } from './index-Bjs3BPPU.js';
2
- import { O as OnReview, V as Verdict } from './verdict-BAahb5po.js';
3
- import { a as ApiClient, g as Transport, e as Sessions, A as AgentIdentity, b as ApiClientOptions, i as TransportOptions, R as RedactFn } from './session-5TClPLI4.js';
4
-
5
- /**
6
- * Correlation without binding (Fraud SDK RFC › Protocol Adapter — x402:
7
- * "binding travels on the call that initiates the purchase, not
8
- * necessarily on the payment artifact"). The merchant binds a key it will
9
- * see again (a checkout session id, a challenge nonce) to the buyer's
10
- * session; the adapter resolves it when the settlement arrives (GAP-31).
11
- */
12
- interface CorrelationStore {
13
- bind(key: string, sessionId: string, ttlMs?: number): Promise<void>;
14
- resolve(key: string): Promise<string | null>;
15
- }
16
- declare class MemoryCorrelationStore implements CorrelationStore {
17
- private readonly defaultTtlMs;
18
- private readonly entries;
19
- constructor(defaultTtlMs?: number);
20
- bind(key: string, sessionId: string, ttlMs?: number): Promise<void>;
21
- resolve(key: string): Promise<string | null>;
22
- }
23
-
24
- /**
25
- * One SDK, two halves (Fraud SDK RFC › Summary). `Beltic` is the single
26
- * client: sessions and evidence for both halves, `evaluate` for whichever
27
- * half is about to let a payment through. Protocol integrations are plain
28
- * functions behind subpath exports, each pulling exactly one optional peer:
29
- *
30
- * @belticlabs/agent-risk-sdk/ai → middleware(session), wrapTools(session, …)
31
- * @belticlabs/agent-risk-sdk/x402 → belticFetch(session), x402Summary(…), attachX402(beltic, …)
32
- * @belticlabs/agent-risk-sdk/hono → belticPaymentMiddleware(beltic, …) (and /express)
33
- * @belticlabs/agent-risk-sdk/mcp → wrapClient(session, …), wrapServer(beltic, …)
34
- *
35
- * Neither half decides risk locally: verdicts are platform-side.
36
- *
37
- * Evidence is a side channel of the work it observes. With `failOpen`
38
- * nothing the SDK does throws into that work: `Session.emit` reports and
39
- * answers `false`, `sessions.open` answers `null`, `evaluate` answers
40
- * `null` — never an invented verdict; the host decides what to do without
41
- * one (GAP-70). `sessions.start` and `sessions.ensure` throw either way:
42
- * they are the primitives the fail-open entries are built on.
43
- */
44
-
45
- declare const SDK_VERSION = "0.2.0";
46
- interface BelticOptions extends Omit<ApiClientOptions, 'userAgent'> {
47
- /** Buyer half. Without it, `sessions.start` is unavailable; the seller half works. */
48
- identity?: AgentIdentity | undefined;
49
- transport?: Partial<TransportOptions> | undefined;
50
- /** What a synchronous seller hook does with REVIEW (GAP-52). */
51
- onReview?: OnReview | undefined;
52
- correlation?: CorrelationStore | undefined;
53
- redact?: RedactFn | undefined;
54
- now?: (() => Date) | undefined;
55
- /** Evidence never fails the work it observes; see the module note (GAP-70). */
56
- failOpen?: boolean | undefined;
57
- /** Where fail-open failures go (and transport delivery failures unless `transport` names its own). Default: `console.error`. */
58
- onError?: ((err: Error) => void) | undefined;
59
- /** Fail-open only: how long `sessions.open` answers null after the platform refused to open a session (GAP-71). */
60
- openRetryMs?: number | undefined;
61
- }
62
- /** The platform's answer, with the verdict as a value the caller can ask `blocks(onReview)`. */
63
- type Evaluation = EvaluateOutput & {
64
- verdict: Verdict;
65
- };
66
- declare class Beltic {
67
- readonly api: ApiClient;
68
- readonly transport: Transport;
69
- readonly sessions: Sessions;
70
- readonly identity: AgentIdentity | undefined;
71
- readonly correlation: CorrelationStore;
72
- readonly onReview: OnReview;
73
- readonly failOpen: boolean;
74
- private readonly onError;
75
- constructor(opts: BelticOptions);
76
- /**
77
- * The platform's verdict on a payment — the seller's before it verifies,
78
- * the buyer's before it presents. Read-your-writes: the buffered evidence
79
- * is flushed first so the platform judges what the caller already saw
80
- * (GAP-16). A recorded moment is accepted as is: only its comparable core
81
- * (payee, amount, payer) is sent. `null` only under `failOpen`, when the
82
- * platform could not be asked.
83
- */
84
- evaluate(sessionId: string, payment: PaymentSummary | PaymentMomentPayload): Promise<Evaluation | null>;
85
- private decide;
86
- flush(): Promise<void>;
87
- shutdown(): Promise<void>;
88
- }
89
- declare function createBeltic(opts: BelticOptions): Beltic;
90
-
91
- export { Beltic as B, type CorrelationStore as C, type Evaluation as E, MemoryCorrelationStore as M, SDK_VERSION as S, type BelticOptions as a, createBeltic as c };
@@ -1,250 +0,0 @@
1
- import { L as EvidenceAck, G as EventResult, R as EvidenceEvent, V as EvidenceSource, aC as WireEvidenceKind, J as JsonObject, C as ChainHead, aa as PayloadByKind, aw as ToolCallStartPayload, b as JsonValue, am as SessionClosePayload, v as DeclaredIntent } from './index-Bjs3BPPU.js';
2
-
3
- /**
4
- * The edge signs event digests (Fraud SDK RFC › Modules › Identity Module);
5
- * the platform signs its own PLATFORM chain and epoch anchors. Both are the
6
- * same operation over different keys, so one interface.
7
- */
8
- interface Signer {
9
- /** Raw 32-byte Ed25519 public key. */
10
- readonly publicKey: Uint8Array;
11
- /** Stable identifier for logs and key rotation; `did:key` for agents. */
12
- readonly keyId: string;
13
- sign(message: Uint8Array): Promise<Uint8Array>;
14
- }
15
-
16
- interface ApiClientOptions {
17
- baseUrl: string;
18
- apiKey: string;
19
- fetch?: typeof globalThis.fetch;
20
- timeoutMs?: number;
21
- userAgent?: string;
22
- }
23
- declare class BelticApiError extends Error {
24
- readonly status: number;
25
- readonly code: string;
26
- readonly details?: unknown | undefined;
27
- readonly requestId?: string | undefined;
28
- constructor(status: number, code: string, message: string, details?: unknown | undefined, requestId?: string | undefined);
29
- /** 5xx and network failures are retried by the transport; 4xx are not. */
30
- get retryable(): boolean;
31
- }
32
- declare class ApiClient {
33
- private readonly baseUrl;
34
- private readonly fetchImpl;
35
- private readonly timeoutMs;
36
- private readonly headers;
37
- constructor(opts: ApiClientOptions);
38
- post<T>(path: string, body: unknown, headers?: Record<string, string>): Promise<T>;
39
- get<T>(path: string, query?: Record<string, string | undefined>): Promise<T>;
40
- private request;
41
- }
42
-
43
- interface AgentIdentity {
44
- did: string;
45
- signer: Signer;
46
- /** Opaque credential presented at session start (stored, not verified this phase). */
47
- credential?: string;
48
- }
49
- declare function identityFromSeed(seed: Uint8Array, credential?: string): AgentIdentity;
50
- declare function ephemeralIdentity(credential?: string): AgentIdentity;
51
- /** A JSON keystore on disk: `{ "seed": "<64 hex>" }`, created 0600 when missing. */
52
- declare function fileIdentity(path: string, credential?: string): AgentIdentity;
53
-
54
- /**
55
- * Transport (Fraud SDK RFC › Modules: "buffering, batching, chained delivery
56
- * to the Collector"). Contract as assumed in GAP-18/38: one FIFO per
57
- * chain; at most one batch in flight per chain, so order is preserved;
58
- * exponential backoff on network / 5xx; a `fork` or `rejected` ack halts
59
- * the chain and surfaces `ChainRejectedError` — an SDK must not silently
60
- * keep chaining onto a head the platform never accepted.
61
- */
62
-
63
- interface TransportOptions {
64
- maxBatch: number;
65
- flushMs: number;
66
- /** Total buffered events across chains; beyond this new events are dropped (GAP-38). */
67
- maxBuffered: number;
68
- backoff: {
69
- baseMs: number;
70
- maxMs: number;
71
- maxAttempts: number;
72
- };
73
- onAck?: (ack: EvidenceAck) => void;
74
- onError?: (err: Error) => void;
75
- onChainHalted?: (err: ChainRejectedError) => void;
76
- setTimeout?: typeof globalThis.setTimeout;
77
- clearTimeout?: typeof globalThis.clearTimeout;
78
- }
79
- declare const DEFAULT_TRANSPORT: TransportOptions;
80
- declare class ChainRejectedError extends Error {
81
- readonly sessionId: string;
82
- readonly source: string;
83
- readonly result: EventResult;
84
- constructor(sessionId: string, source: string, result: EventResult);
85
- }
86
- declare class TransportClosedError extends Error {
87
- constructor();
88
- }
89
- declare class Transport {
90
- private readonly api;
91
- private readonly opts;
92
- private readonly chains;
93
- private buffered;
94
- private timer;
95
- private closed;
96
- private inFlightCount;
97
- private drainWaiters;
98
- constructor(api: ApiClient, opts?: Partial<TransportOptions>);
99
- get size(): number;
100
- hasRoom(): boolean;
101
- haltedError(sessionId: string, source: string): ChainRejectedError | null;
102
- /** Callers check `hasRoom()` first and assign `seq` only then (GAP-38). */
103
- enqueue(ev: EvidenceEvent): void;
104
- /** Send everything pending and wait for every in-flight batch to settle (ack or halt). */
105
- flush(): Promise<void>;
106
- close(): Promise<void>;
107
- private schedule;
108
- private unschedule;
109
- private drained;
110
- private settleWaiters;
111
- private flushChain;
112
- private send;
113
- }
114
-
115
- /**
116
- * A risk session as the SDK sees it: one chain per (sessionId, source),
117
- * built at the edge (Fraud SDK RFC › Wire contract). The buyer half opens
118
- * AGENT_TRACE sessions and announces them with `session.open` (seq 0) and
119
- * `intent.declared` (seq 1; GAP-23/60); the seller half attaches to a bound
120
- * session or opens its own INTERNAL_NETWORK session (GAP-13).
121
- *
122
- * `seq` is handed out only when the transport has room for the event
123
- * (GAP-38): a dropped event never leaves a hole — the next accepted event
124
- * is preceded by a `transport.gap` that counts the drops. `redact` is off
125
- * by default (GAP-33).
126
- *
127
- * Evidence is a side channel of the agent's work: with `failOpen` an emit
128
- * that cannot be chained (halted chain, closed transport) is reported and
129
- * returns `false` instead of throwing into the model or tool call it
130
- * observes (GAP-70).
131
- */
132
-
133
- type RedactFn = (kind: WireEvidenceKind, payload: JsonObject) => JsonObject;
134
- /** Who created the session — the seller half treats a bound session as buyer-born. */
135
- type SessionBorn = 'buyer' | 'seller';
136
- interface SessionDeps {
137
- transport: Transport;
138
- signer?: Signer | undefined;
139
- redact?: RedactFn | undefined;
140
- now?: (() => Date) | undefined;
141
- /** Called once the session closed, so the registry can forget it. */
142
- onClosed?: ((session: Session) => void) | undefined;
143
- /** Report instead of throw when an event cannot be chained (GAP-70). */
144
- failOpen?: boolean | undefined;
145
- onError?: ((err: Error) => void) | undefined;
146
- }
147
- /**
148
- * One tool call as a span: `tool_call.start` now, `tool_call.end` with the
149
- * outcome and the elapsed time when the host reports it. For hosts that run
150
- * their own tool loop and cannot hand the SDK an `execute` to wrap.
151
- */
152
- interface ToolCallSpan {
153
- readonly callId: string;
154
- end(outcome?: {
155
- output?: JsonValue;
156
- }): Promise<boolean>;
157
- fail(error: unknown, outcome?: {
158
- output?: JsonValue;
159
- }): Promise<boolean>;
160
- }
161
- declare class Session {
162
- private readonly deps;
163
- readonly id: string;
164
- readonly source: EvidenceSource;
165
- readonly expiresAt: string | null;
166
- readonly born: SessionBorn;
167
- private chain;
168
- private building;
169
- private dropped;
170
- private droppedFirstTs;
171
- private droppedLastTs;
172
- private closed;
173
- private readonly now;
174
- constructor(deps: SessionDeps, id: string, source: EvidenceSource, expiresAt: string | null, born: SessionBorn);
175
- get head(): ChainHead | null;
176
- get droppedCount(): number;
177
- /**
178
- * Resolves once the event is sequenced and buffered — not once it is
179
- * acknowledged. `false` when the event was dropped, or (fail-open) when
180
- * the chain can no longer take it.
181
- */
182
- emit<K extends WireEvidenceKind>(kind: K, payload: PayloadByKind[K]): Promise<boolean>;
183
- /** The tool call whose `execute` the host runs itself; see `ToolCallSpan`. */
184
- toolCall(call: ToolCallStartPayload): ToolCallSpan;
185
- private chainEvent;
186
- close(reason?: SessionClosePayload['reason'], extra?: JsonObject): Promise<void>;
187
- /** Read-your-writes: the platform must hold the evidence before anyone judges it (GAP-16/66). */
188
- flush(): Promise<void>;
189
- /** Serialized: two concurrent emits get consecutive seqs, never the same one. */
190
- private next;
191
- }
192
- interface StartSessionInput {
193
- intent?: DeclaredIntent;
194
- runtime?: {
195
- framework?: string;
196
- model?: string;
197
- };
198
- attestations?: JsonObject;
199
- }
200
- /** What `open` sends when it actually opens: a value, or a resolver run only then. */
201
- type OpenSessionInput = StartSessionInput | (() => StartSessionInput | Promise<StartSessionInput>);
202
- interface SessionsDeps {
203
- api: ApiClient;
204
- transport: Transport;
205
- identity?: AgentIdentity | undefined;
206
- redact?: RedactFn | undefined;
207
- now?: (() => Date) | undefined;
208
- sdkVersion: string;
209
- failOpen?: boolean | undefined;
210
- onError?: ((err: Error) => void) | undefined;
211
- /** Fail-open only: after the platform refused to open a session, `open` resolves null for this long (GAP-71). */
212
- openRetryMs?: number | undefined;
213
- }
214
- declare const DEFAULT_OPEN_RETRY_MS = 60000;
215
- declare class Sessions {
216
- private readonly deps;
217
- /**
218
- * One session object per (session, source) per process: a chain's head
219
- * lives in it, so two objects for the same chain would both start at
220
- * seq 0 and fork it. Closed sessions are forgotten; a process restart
221
- * mid-session still loses the head (GAP-67).
222
- */
223
- private readonly attached;
224
- /** Buyer sessions by the host's own key (GAP-71). */
225
- private readonly opened;
226
- private retryAt;
227
- constructor(deps: SessionsDeps);
228
- /**
229
- * Buyer half: the evidence session for a key of the host's own (its
230
- * session, run or conversation id), opened on first use and reused
231
- * after. A halted chain is reopened as a fresh session that continues
232
- * the same key; a closed key is forgotten. When the platform refuses to
233
- * open one, a fail-open client resolves null — the host runs without
234
- * evidence — until `openRetryMs` has passed (GAP-71); otherwise the
235
- * refusal is thrown and the next call tries again. The identity is
236
- * required either way: that is configuration.
237
- */
238
- open(key: string, input?: OpenSessionInput): Promise<Session | null>;
239
- private forget;
240
- private openFresh;
241
- /** Buyer half: create an AGENT_TRACE session bound to the agent identity, then announce it on the chain. */
242
- start(input?: StartSessionInput): Promise<Session>;
243
- private identityFor;
244
- private create;
245
- /** Seller half: emit INTERNAL_NETWORK evidence into a session the buyer bound, or open a seller-born one. */
246
- ensure(sessionId?: string | null): Promise<Session>;
247
- private attach;
248
- }
249
-
250
- export { type AgentIdentity as A, BelticApiError as B, ChainRejectedError as C, DEFAULT_OPEN_RETRY_MS as D, type OpenSessionInput as O, type RedactFn as R, Session as S, type ToolCallSpan as T, ApiClient as a, type ApiClientOptions as b, DEFAULT_TRANSPORT as c, type SessionBorn as d, Sessions as e, type StartSessionInput as f, Transport as g, TransportClosedError as h, type TransportOptions as i, ephemeralIdentity as j, fileIdentity as k, identityFromSeed as l };
@@ -1,26 +0,0 @@
1
- import { D as Decision } from './index-Bjs3BPPU.js';
2
-
3
- /**
4
- * The verdict as a value (Fraud Engine RFC › API: ALLOW | DENY | REVIEW).
5
- * Layers combine by severity (GAP-45); a synchronous seller hook turns
6
- * REVIEW into a stop or a pass according to its `onReview` (GAP-52). Both
7
- * halves of the SDK and the engine share this one rule.
8
- */
9
-
10
- type OnReview = 'abort' | 'allow';
11
- declare class Verdict {
12
- readonly value: Decision;
13
- private constructor();
14
- static readonly ALLOW: Verdict;
15
- static readonly REVIEW: Verdict;
16
- static readonly DENY: Verdict;
17
- static of(value: Decision): Verdict;
18
- /** The more severe of the two. */
19
- atLeast(other: Verdict | Decision): Verdict;
20
- /** Whether a synchronous gate must stop the call (GAP-52). */
21
- blocks(onReview: OnReview): boolean;
22
- /** What the gate effectively did: DENY when it blocked, else the verdict itself. */
23
- effective(onReview: OnReview): Decision;
24
- }
25
-
26
- export { type OnReview as O, Verdict as V };