@belticlabs/agent-risk-sdk 0.1.1 → 0.2.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/{middleware-D-ejQIoE.d.ts → adapter-CF-cUYSA.d.ts} +4 -16
- package/dist/ai/index.d.ts +4 -4
- package/dist/ai/index.js +4 -3
- package/dist/chunk-GSH5APZW.js +39 -0
- package/dist/{chunk-U5Z5Z2BQ.js → chunk-LM4NIYE5.js} +26 -20
- package/dist/{chunk-W2OY7QXV.js → chunk-SO6HPRJT.js} +10 -23
- package/dist/chunk-U7HM37CB.js +17 -0
- package/dist/client-C-mV_3A0.d.ts +91 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.js +117 -16
- package/dist/mcp/index.d.ts +3 -3
- package/dist/mcp/index.js +11 -8
- package/dist/middleware-BwAYpBTl.d.ts +15 -0
- package/dist/seller/anti-fraud-gateway.d.ts +11 -2
- package/dist/seller/anti-fraud-gateway.js +13 -14
- package/dist/{session-B2mfurae.d.ts → session-5TClPLI4.d.ts} +57 -3
- package/dist/x402/express.d.ts +4 -4
- package/dist/x402/express.js +6 -5
- package/dist/x402/hono.d.ts +4 -4
- package/dist/x402/hono.js +6 -5
- package/dist/x402/index.d.ts +93 -18
- package/dist/x402/index.js +83 -32
- package/package.json +1 -1
- package/dist/chunk-5TWO73OD.js +0 -35
- package/dist/client-NxpD_384.d.ts +0 -64
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { x402ResourceServer, x402HTTPResourceServer, PaywallConfig, RoutesConfig } from '@x402/core/server';
|
|
2
|
-
import { B as Beltic } from './client-NxpD_384.js';
|
|
3
1
|
import { D as Decision } from './index-Bjs3BPPU.js';
|
|
4
|
-
import {
|
|
2
|
+
import { x402ResourceServer, x402HTTPResourceServer } from '@x402/core/server';
|
|
3
|
+
import { B as Beltic } from './client-C-mV_3A0.js';
|
|
4
|
+
import { d as SessionBorn, S as Session } from './session-5TClPLI4.js';
|
|
5
5
|
|
|
6
6
|
interface CorrelationContext {
|
|
7
7
|
path: string;
|
|
@@ -25,16 +25,4 @@ interface AttachedX402 {
|
|
|
25
25
|
}
|
|
26
26
|
declare function attachX402(beltic: Beltic, server: x402ResourceServer, http?: x402HTTPResourceServer, opts?: AttachOptions): AttachedX402;
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
* The seller half as one middleware: the framework's `@x402/*` payment
|
|
30
|
-
* middleware over an `x402HTTPResourceServer` with the Beltic hooks
|
|
31
|
-
* attached. `@belticlabs/agent-risk-sdk/hono` and `@belticlabs/agent-risk-sdk/express` differ only in
|
|
32
|
-
* which `paymentMiddlewareFromHTTPServer` they hand in.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
type GuardedMiddlewareOptions = AttachOptions & {
|
|
36
|
-
paywall?: PaywallConfig | undefined;
|
|
37
|
-
};
|
|
38
|
-
declare function guardedPaymentMiddleware<M>(fromHTTPServer: (http: x402HTTPResourceServer, paywall?: PaywallConfig) => M, beltic: Beltic, routes: RoutesConfig, server: x402ResourceServer, opts?: GuardedMiddlewareOptions): M;
|
|
39
|
-
|
|
40
|
-
export { type AttachOptions as A, type CorrelationContext as C, type GuardedMiddlewareOptions as G, attachX402 as a, type AttachedX402 as b, guardedPaymentMiddleware as g };
|
|
28
|
+
export { type AttachOptions as A, type CorrelationContext as C, attachX402 as a, type AttachedX402 as b };
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { P as PaymentMomentPayload } from '../index-Bjs3BPPU.js';
|
|
2
2
|
import { LanguageModelMiddleware, Tool, ToolSet } from 'ai';
|
|
3
|
-
import { S as Session } from '../session-
|
|
3
|
+
import { S as Session } from '../session-5TClPLI4.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
6
6
|
interface PaymentMoments {
|
|
@@ -12,8 +12,8 @@ interface WrapToolOptions<I = unknown, O = unknown> {
|
|
|
12
12
|
/** When the tool performs a purchase, map its input/output to the payment moments it produced. */
|
|
13
13
|
payment?: (input: I, output: O) => PaymentMoments | null;
|
|
14
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;
|
|
15
|
+
declare function middleware(session: Session | null | undefined): LanguageModelMiddleware;
|
|
16
|
+
declare function wrapTool<T extends Tool>(session: Session | null | undefined, tool: T, opts?: WrapToolOptions): T;
|
|
17
|
+
declare function wrapTools<T extends ToolSet>(session: Session | null | undefined, tools: T, opts?: Record<string, WrapToolOptions>): T;
|
|
18
18
|
|
|
19
19
|
export { type PaymentMoments, type WrapToolOptions, middleware, wrapTool, wrapTools };
|
package/dist/ai/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
recordCall
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-GSH5APZW.js";
|
|
4
4
|
import {
|
|
5
5
|
uuidv7
|
|
6
6
|
} from "../chunk-SFGM7KOG.js";
|
|
7
|
+
import "../chunk-46QN2KEZ.js";
|
|
7
8
|
import {
|
|
8
9
|
toJson,
|
|
9
10
|
toJsonObject
|
|
10
11
|
} from "../chunk-FQDHFTVR.js";
|
|
11
|
-
import "../chunk-46QN2KEZ.js";
|
|
12
12
|
|
|
13
13
|
// src/ai/index.ts
|
|
14
14
|
var PARAM_KEYS = [
|
|
@@ -24,6 +24,7 @@ var PARAM_KEYS = [
|
|
|
24
24
|
"stopSequences"
|
|
25
25
|
];
|
|
26
26
|
function middleware(session) {
|
|
27
|
+
if (!session) return {};
|
|
27
28
|
return {
|
|
28
29
|
wrapGenerate: ({ doGenerate, params, model }) => recordCall(
|
|
29
30
|
session,
|
|
@@ -73,7 +74,7 @@ function middleware(session) {
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
function wrapTool(session, tool, opts = {}) {
|
|
76
|
-
if (!tool.execute) return tool;
|
|
77
|
+
if (!session || !tool.execute) return tool;
|
|
77
78
|
const original = tool.execute;
|
|
78
79
|
const toolName = opts.name ?? tool.name ?? "tool";
|
|
79
80
|
const execute = (input, options) => recordCall(
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
};
|
|
@@ -6,20 +6,23 @@ import {
|
|
|
6
6
|
function x402Currency(network, asset) {
|
|
7
7
|
return `${network}/${asset}`;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function x402Summary(accepts, opts = {}) {
|
|
10
|
+
const payer = opts.payer?.toLowerCase();
|
|
10
11
|
return {
|
|
11
12
|
protocol: "x402",
|
|
12
|
-
payee:
|
|
13
|
+
payee: accepts?.payTo ?? "unknown",
|
|
13
14
|
amount: {
|
|
14
|
-
value:
|
|
15
|
-
currency:
|
|
15
|
+
value: accepts?.amount ?? accepts?.maxAmountRequired ?? "0",
|
|
16
|
+
currency: accepts ? x402Currency(accepts.network ?? "unknown", accepts.asset ?? "unknown") : "unknown"
|
|
16
17
|
},
|
|
17
|
-
|
|
18
|
-
raw
|
|
18
|
+
...payer ? { payer } : {}
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
+
function fromAccepts(a, artifact, raw, payer) {
|
|
22
|
+
return { ...x402Summary(a, { payer }), artifact, raw };
|
|
23
|
+
}
|
|
21
24
|
function payerOf(payload) {
|
|
22
|
-
const p = payload.payload;
|
|
25
|
+
const p = payload.payload ?? {};
|
|
23
26
|
const auth = p.authorization;
|
|
24
27
|
const candidates = [
|
|
25
28
|
auth?.from,
|
|
@@ -32,15 +35,13 @@ function payerOf(payload) {
|
|
|
32
35
|
return typeof hit === "string" ? hit.toLowerCase() : void 0;
|
|
33
36
|
}
|
|
34
37
|
var x402Moments = {
|
|
35
|
-
/** The 402 challenge as the buyer saw it. */
|
|
38
|
+
/** The 402 challenge as the buyer saw it, v2 header or v1 body. */
|
|
36
39
|
required(required) {
|
|
37
|
-
|
|
38
|
-
return fromAccepts(r.accepts[0], "http-402", toJsonObject(r));
|
|
40
|
+
return fromAccepts(required.accepts?.[0], "http-402", toJsonObject(required));
|
|
39
41
|
},
|
|
40
42
|
/** The requirements the seller's resource server resolved for a request. */
|
|
41
43
|
requirements(req) {
|
|
42
|
-
|
|
43
|
-
return fromAccepts(r, "http-402", toJsonObject(r));
|
|
44
|
+
return fromAccepts(req, "http-402", toJsonObject(req));
|
|
44
45
|
},
|
|
45
46
|
/** A route's static `accepts` config, before any payment header exists. */
|
|
46
47
|
route(route, raw) {
|
|
@@ -61,14 +62,18 @@ var x402Moments = {
|
|
|
61
62
|
ask(first, raw) {
|
|
62
63
|
return fromAccepts(first, "mrtr-input-required", raw);
|
|
63
64
|
},
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
/**
|
|
66
|
+
* The signed payment the buyer presented. A v2 payload carries the
|
|
67
|
+
* requirement it accepted; a v1 payload does not, so the caller passes
|
|
68
|
+
* the `accepts` entry it answered.
|
|
69
|
+
*/
|
|
70
|
+
payload(payload, accepts) {
|
|
71
|
+
return fromAccepts(
|
|
72
|
+
accepts ?? payload.accepted,
|
|
73
|
+
"payment-signature",
|
|
74
|
+
toJsonObject(payload),
|
|
75
|
+
payerOf(payload)
|
|
76
|
+
);
|
|
72
77
|
}
|
|
73
78
|
};
|
|
74
79
|
function priceValue(price) {
|
|
@@ -81,6 +86,7 @@ function priceValue(price) {
|
|
|
81
86
|
|
|
82
87
|
export {
|
|
83
88
|
x402Currency,
|
|
89
|
+
x402Summary,
|
|
84
90
|
payerOf,
|
|
85
91
|
x402Moments
|
|
86
92
|
};
|
|
@@ -7,13 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-SFGM7KOG.js";
|
|
8
8
|
import {
|
|
9
9
|
x402Moments
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import {
|
|
12
|
-
summaryOf
|
|
13
|
-
} from "./chunk-7G5EHNVW.js";
|
|
14
|
-
import {
|
|
15
|
-
Verdict
|
|
16
|
-
} from "./chunk-46QN2KEZ.js";
|
|
10
|
+
} from "./chunk-LM4NIYE5.js";
|
|
17
11
|
|
|
18
12
|
// src/x402/adapter.ts
|
|
19
13
|
function attachX402(beltic, server, http, opts = {}) {
|
|
@@ -56,16 +50,20 @@ function attachX402(beltic, server, http, opts = {}) {
|
|
|
56
50
|
const presented = x402Moments.payload(payload);
|
|
57
51
|
await session.emit("payment.presented", presented);
|
|
58
52
|
inFlight.set(payloadDigest(payload), session);
|
|
59
|
-
const out = await beltic.evaluate(session.id,
|
|
53
|
+
const out = await beltic.evaluate(session.id, presented);
|
|
54
|
+
if (!out) return;
|
|
60
55
|
opts.onDecision?.({
|
|
61
56
|
sessionId: session.id,
|
|
62
57
|
decision: out.decision,
|
|
63
58
|
reasonCodes: out.reasonCodes,
|
|
64
59
|
born: session.born
|
|
65
60
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
if (out.verdict.blocks(beltic.onReview)) {
|
|
62
|
+
return {
|
|
63
|
+
abort: true,
|
|
64
|
+
reason: `BELTIC_${out.verdict.value}`,
|
|
65
|
+
message: out.reasonCodes.join(",")
|
|
66
|
+
};
|
|
69
67
|
}
|
|
70
68
|
return;
|
|
71
69
|
});
|
|
@@ -79,17 +77,6 @@ function attachX402(beltic, server, http, opts = {}) {
|
|
|
79
77
|
return { inFlight };
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
// src/x402/middleware.ts
|
|
83
|
-
import {
|
|
84
|
-
x402HTTPResourceServer
|
|
85
|
-
} from "@x402/core/server";
|
|
86
|
-
function guardedPaymentMiddleware(fromHTTPServer, beltic, routes, server, opts = {}) {
|
|
87
|
-
const http = new x402HTTPResourceServer(server, routes);
|
|
88
|
-
attachX402(beltic, server, http, opts);
|
|
89
|
-
return fromHTTPServer(http, opts.paywall);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
80
|
export {
|
|
93
|
-
attachX402
|
|
94
|
-
guardedPaymentMiddleware
|
|
81
|
+
attachX402
|
|
95
82
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attachX402
|
|
3
|
+
} from "./chunk-SO6HPRJT.js";
|
|
4
|
+
|
|
5
|
+
// src/x402/middleware.ts
|
|
6
|
+
import {
|
|
7
|
+
x402HTTPResourceServer
|
|
8
|
+
} from "@x402/core/server";
|
|
9
|
+
function guardedPaymentMiddleware(fromHTTPServer, beltic, routes, server, opts = {}) {
|
|
10
|
+
const http = new x402HTTPResourceServer(server, routes);
|
|
11
|
+
attachX402(beltic, server, http, opts);
|
|
12
|
+
return fromHTTPServer(http, opts.paywall);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
guardedPaymentMiddleware
|
|
17
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { B as Beltic, a as BelticOptions, C as CorrelationStore, M as MemoryCorrelationStore, S as SDK_VERSION, c as createBeltic } from './client-
|
|
2
|
-
import { S as Session } from './session-
|
|
3
|
-
export { A as AgentIdentity, a as ApiClient, b as ApiClientOptions, B as BelticApiError, C as ChainRejectedError, D as DEFAULT_TRANSPORT, R as RedactFn,
|
|
1
|
+
export { B as Beltic, a as BelticOptions, C as CorrelationStore, E as Evaluation, M as MemoryCorrelationStore, S as SDK_VERSION, c as createBeltic } from './client-C-mV_3A0.js';
|
|
2
|
+
import { S as Session } from './session-5TClPLI4.js';
|
|
3
|
+
export { A as AgentIdentity, a as ApiClient, b as ApiClientOptions, B as BelticApiError, C as ChainRejectedError, D as DEFAULT_OPEN_RETRY_MS, c as DEFAULT_TRANSPORT, O as OpenSessionInput, R as RedactFn, d as SessionBorn, e as Sessions, f as StartSessionInput, T as ToolCallSpan, g as Transport, h as TransportClosedError, i as TransportOptions, j as ephemeralIdentity, k as fileIdentity, l as identityFromSeed } from './session-5TClPLI4.js';
|
|
4
4
|
import { a as PaymentSummary, J as JsonObject, P as PaymentMomentPayload } from './index-Bjs3BPPU.js';
|
|
5
5
|
import './verdict-BAahb5po.js';
|
|
6
6
|
import 'zod';
|
|
@@ -12,15 +12,16 @@ import 'zod';
|
|
|
12
12
|
* sides of one purchase compare (`EVIDENCE_MISMATCH`, GAP-50).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
declare function summaryOf(m: PaymentMomentPayload): PaymentSummary;
|
|
15
|
+
declare function summaryOf(m: PaymentSummary | PaymentMomentPayload): PaymentSummary;
|
|
16
16
|
/** A presentation the seller side saw as a signed payment, in any protocol. */
|
|
17
17
|
declare function presentedFrom(summary: PaymentSummary, raw: JsonObject): PaymentMomentPayload;
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* One instrumented call = a `*.start` event, the work, a `*.end` event
|
|
21
21
|
* carrying the outcome or the error (GAP-07 correlates them by `callId`).
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* `openCall` is the span; `recordCall` runs the work inside one. The AI
|
|
23
|
+
* middleware, the tool wrapper, the MCP client and a host's own tool loop
|
|
24
|
+
* (`Session.toolCall`) all record the same way.
|
|
24
25
|
*/
|
|
25
26
|
|
|
26
27
|
type CallKind = 'llm_call' | 'tool_call';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
openCall,
|
|
2
3
|
recordCall
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GSH5APZW.js";
|
|
4
5
|
import {
|
|
5
6
|
Chain,
|
|
6
7
|
didKeyFromEd25519,
|
|
@@ -8,11 +9,13 @@ import {
|
|
|
8
9
|
memorySigner,
|
|
9
10
|
toHex
|
|
10
11
|
} from "./chunk-SFGM7KOG.js";
|
|
12
|
+
import {
|
|
13
|
+
Verdict
|
|
14
|
+
} from "./chunk-46QN2KEZ.js";
|
|
11
15
|
import {
|
|
12
16
|
presentedFrom,
|
|
13
17
|
summaryOf
|
|
14
18
|
} from "./chunk-7G5EHNVW.js";
|
|
15
|
-
import "./chunk-46QN2KEZ.js";
|
|
16
19
|
|
|
17
20
|
// src/core/api-client.ts
|
|
18
21
|
var BelticApiError = class extends Error {
|
|
@@ -136,8 +139,26 @@ var Session = class {
|
|
|
136
139
|
get droppedCount() {
|
|
137
140
|
return this.dropped;
|
|
138
141
|
}
|
|
139
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Resolves once the event is sequenced and buffered — not once it is
|
|
144
|
+
* acknowledged. `false` when the event was dropped, or (fail-open) when
|
|
145
|
+
* the chain can no longer take it.
|
|
146
|
+
*/
|
|
140
147
|
async emit(kind, payload) {
|
|
148
|
+
if (!this.deps.failOpen) return this.chainEvent(kind, payload);
|
|
149
|
+
try {
|
|
150
|
+
return await this.chainEvent(kind, payload);
|
|
151
|
+
} catch (err) {
|
|
152
|
+
this.deps.onError?.(err);
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** The tool call whose `execute` the host runs itself; see `ToolCallSpan`. */
|
|
157
|
+
toolCall(call) {
|
|
158
|
+
const { callId, ...start } = call;
|
|
159
|
+
return openCall(this, "tool_call", callId, { transport: "local", ...start });
|
|
160
|
+
}
|
|
161
|
+
async chainEvent(kind, payload) {
|
|
141
162
|
const halted = this.deps.transport.haltedError(this.id, this.source);
|
|
142
163
|
if (halted) throw halted;
|
|
143
164
|
const ts = this.now().toISOString();
|
|
@@ -186,6 +207,7 @@ var Session = class {
|
|
|
186
207
|
return run;
|
|
187
208
|
}
|
|
188
209
|
};
|
|
210
|
+
var DEFAULT_OPEN_RETRY_MS = 6e4;
|
|
189
211
|
var Sessions = class {
|
|
190
212
|
constructor(deps) {
|
|
191
213
|
this.deps = deps;
|
|
@@ -197,18 +219,65 @@ var Sessions = class {
|
|
|
197
219
|
* mid-session still loses the head (GAP-67).
|
|
198
220
|
*/
|
|
199
221
|
attached = /* @__PURE__ */ new Map();
|
|
222
|
+
/** Buyer sessions by the host's own key (GAP-71). */
|
|
223
|
+
opened = /* @__PURE__ */ new Map();
|
|
224
|
+
retryAt = 0;
|
|
225
|
+
/**
|
|
226
|
+
* Buyer half: the evidence session for a key of the host's own (its
|
|
227
|
+
* session, run or conversation id), opened on first use and reused
|
|
228
|
+
* after. A halted chain is reopened as a fresh session that continues
|
|
229
|
+
* the same key; a closed key is forgotten. When the platform refuses to
|
|
230
|
+
* open one, a fail-open client resolves null — the host runs without
|
|
231
|
+
* evidence — until `openRetryMs` has passed (GAP-71); otherwise the
|
|
232
|
+
* refusal is thrown and the next call tries again. The identity is
|
|
233
|
+
* required either way: that is configuration.
|
|
234
|
+
*/
|
|
235
|
+
open(key, input = {}) {
|
|
236
|
+
const prior = this.opened.get(key) ?? Promise.resolve(null);
|
|
237
|
+
const next = prior.catch(() => null).then(
|
|
238
|
+
(session) => session && !this.deps.transport.haltedError(session.id, session.source) ? session : this.openFresh(input, () => this.forget(key, next))
|
|
239
|
+
);
|
|
240
|
+
this.opened.set(key, next);
|
|
241
|
+
next.catch(() => this.forget(key, next));
|
|
242
|
+
return next;
|
|
243
|
+
}
|
|
244
|
+
forget(key, entry) {
|
|
245
|
+
if (this.opened.get(key) === entry) this.opened.delete(key);
|
|
246
|
+
}
|
|
247
|
+
async openFresh(input, onClosed) {
|
|
248
|
+
this.identityFor("open");
|
|
249
|
+
const create = async () => this.create(typeof input === "function" ? await input() : input, onClosed);
|
|
250
|
+
if (!this.deps.failOpen) return create();
|
|
251
|
+
if (Date.now() < this.retryAt) return null;
|
|
252
|
+
try {
|
|
253
|
+
const session = await create();
|
|
254
|
+
this.retryAt = 0;
|
|
255
|
+
return session;
|
|
256
|
+
} catch (err) {
|
|
257
|
+
this.retryAt = Date.now() + (this.deps.openRetryMs ?? DEFAULT_OPEN_RETRY_MS);
|
|
258
|
+
this.deps.onError?.(err);
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
200
262
|
/** Buyer half: create an AGENT_TRACE session bound to the agent identity, then announce it on the chain. */
|
|
201
|
-
|
|
263
|
+
start(input = {}) {
|
|
264
|
+
return this.create(input);
|
|
265
|
+
}
|
|
266
|
+
identityFor(entry) {
|
|
202
267
|
const identity = this.deps.identity;
|
|
203
268
|
if (!identity)
|
|
204
|
-
throw new Error(
|
|
269
|
+
throw new Error(`sessions.${entry} needs an agent identity (createBeltic({ identity }))`);
|
|
270
|
+
return identity;
|
|
271
|
+
}
|
|
272
|
+
async create(input, onClosed) {
|
|
273
|
+
const identity = this.identityFor("start");
|
|
205
274
|
const body = {
|
|
206
275
|
source: "AGENT_TRACE",
|
|
207
276
|
agent: { did: identity.did, credential: identity.credential ?? identity.did },
|
|
208
277
|
...input.intent ? { intent: input.intent } : {}
|
|
209
278
|
};
|
|
210
279
|
const out = await this.deps.api.post("/v1/sessions", body);
|
|
211
|
-
const session = this.attach(out.sessionId, "AGENT_TRACE", out.expiresAt, "buyer");
|
|
280
|
+
const session = this.attach(out.sessionId, "AGENT_TRACE", out.expiresAt, "buyer", onClosed);
|
|
212
281
|
await session.emit("session.open", {
|
|
213
282
|
runtime: {
|
|
214
283
|
sdk: "@belticlabs/agent-risk-sdk",
|
|
@@ -228,7 +297,7 @@ var Sessions = class {
|
|
|
228
297
|
});
|
|
229
298
|
return this.attach(out.sessionId, "INTERNAL_NETWORK", out.expiresAt, "seller");
|
|
230
299
|
}
|
|
231
|
-
attach(id, source, expiresAt, born) {
|
|
300
|
+
attach(id, source, expiresAt, born, onClosed) {
|
|
232
301
|
const key = `${id}:${source}`;
|
|
233
302
|
const existing = this.attached.get(key);
|
|
234
303
|
if (existing) return existing;
|
|
@@ -238,7 +307,12 @@ var Sessions = class {
|
|
|
238
307
|
signer: source === "AGENT_TRACE" ? this.deps.identity?.signer : void 0,
|
|
239
308
|
redact: this.deps.redact,
|
|
240
309
|
now: this.deps.now,
|
|
241
|
-
|
|
310
|
+
failOpen: this.deps.failOpen,
|
|
311
|
+
onError: this.deps.onError,
|
|
312
|
+
onClosed: () => {
|
|
313
|
+
this.attached.delete(key);
|
|
314
|
+
onClosed?.();
|
|
315
|
+
}
|
|
242
316
|
},
|
|
243
317
|
id,
|
|
244
318
|
source,
|
|
@@ -412,7 +486,7 @@ var Transport = class {
|
|
|
412
486
|
};
|
|
413
487
|
|
|
414
488
|
// src/client.ts
|
|
415
|
-
var SDK_VERSION = "0.
|
|
489
|
+
var SDK_VERSION = "0.2.0";
|
|
416
490
|
var Beltic = class {
|
|
417
491
|
api;
|
|
418
492
|
transport;
|
|
@@ -420,28 +494,54 @@ var Beltic = class {
|
|
|
420
494
|
identity;
|
|
421
495
|
correlation;
|
|
422
496
|
onReview;
|
|
497
|
+
failOpen;
|
|
498
|
+
onError;
|
|
423
499
|
constructor(opts) {
|
|
500
|
+
this.failOpen = opts.failOpen ?? false;
|
|
501
|
+
this.onError = opts.onError ?? ((err) => console.error("[beltic]", err));
|
|
424
502
|
this.api = new ApiClient({ ...opts, userAgent: `@belticlabs/agent-risk-sdk/${SDK_VERSION}` });
|
|
425
|
-
this.transport = new Transport(this.api,
|
|
503
|
+
this.transport = new Transport(this.api, {
|
|
504
|
+
onError: this.onError,
|
|
505
|
+
onChainHalted: this.onError,
|
|
506
|
+
...opts.transport
|
|
507
|
+
});
|
|
426
508
|
this.sessions = new Sessions({
|
|
427
509
|
api: this.api,
|
|
428
510
|
transport: this.transport,
|
|
429
511
|
sdkVersion: SDK_VERSION,
|
|
430
512
|
identity: opts.identity,
|
|
431
513
|
redact: opts.redact,
|
|
432
|
-
now: opts.now
|
|
514
|
+
now: opts.now,
|
|
515
|
+
failOpen: this.failOpen,
|
|
516
|
+
onError: this.onError,
|
|
517
|
+
openRetryMs: opts.openRetryMs
|
|
433
518
|
});
|
|
434
519
|
this.identity = opts.identity;
|
|
435
520
|
this.correlation = opts.correlation ?? new MemoryCorrelationStore();
|
|
436
521
|
this.onReview = opts.onReview ?? "abort";
|
|
437
522
|
}
|
|
438
|
-
/**
|
|
523
|
+
/**
|
|
524
|
+
* The platform's verdict on a payment — the seller's before it verifies,
|
|
525
|
+
* the buyer's before it presents. Read-your-writes: the buffered evidence
|
|
526
|
+
* is flushed first so the platform judges what the caller already saw
|
|
527
|
+
* (GAP-16). A recorded moment is accepted as is: only its comparable core
|
|
528
|
+
* (payee, amount, payer) is sent. `null` only under `failOpen`, when the
|
|
529
|
+
* platform could not be asked.
|
|
530
|
+
*/
|
|
439
531
|
async evaluate(sessionId, payment) {
|
|
532
|
+
const input = { sessionId, payment: summaryOf(payment) };
|
|
533
|
+
if (!this.failOpen) return this.decide(input);
|
|
534
|
+
try {
|
|
535
|
+
return await this.decide(input);
|
|
536
|
+
} catch (err) {
|
|
537
|
+
this.onError(err);
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
async decide(input) {
|
|
440
542
|
await this.transport.flush();
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
payment
|
|
444
|
-
});
|
|
543
|
+
const out = await this.api.post("/v1/evaluate", input);
|
|
544
|
+
return { ...out, verdict: Verdict.of(out.decision) };
|
|
445
545
|
}
|
|
446
546
|
flush() {
|
|
447
547
|
return this.transport.flush();
|
|
@@ -482,6 +582,7 @@ export {
|
|
|
482
582
|
Beltic,
|
|
483
583
|
BelticApiError,
|
|
484
584
|
ChainRejectedError,
|
|
585
|
+
DEFAULT_OPEN_RETRY_MS,
|
|
485
586
|
DEFAULT_TRANSPORT,
|
|
486
587
|
MemoryCorrelationStore,
|
|
487
588
|
SDK_VERSION,
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as PaymentSummary, P as PaymentMomentPayload } from '../index-Bjs3BPPU.js';
|
|
2
|
-
import { B as Beltic } from '../client-
|
|
3
|
-
import { S as Session } from '../session-
|
|
2
|
+
import { B as Beltic } from '../client-C-mV_3A0.js';
|
|
3
|
+
import { S as Session } from '../session-5TClPLI4.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../verdict-BAahb5po.js';
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ interface CallToolParams {
|
|
|
13
13
|
interface McpClientLike {
|
|
14
14
|
callTool(params: CallToolParams, ...rest: unknown[]): Promise<unknown>;
|
|
15
15
|
}
|
|
16
|
-
declare function wrapClient<C extends McpClientLike>(session: Session, client: C, opts?: {
|
|
16
|
+
declare function wrapClient<C extends McpClientLike>(session: Session | null | undefined, client: C, opts?: {
|
|
17
17
|
server?: string;
|
|
18
18
|
}): C;
|
|
19
19
|
/**
|