@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.
package/dist/index.js CHANGED
@@ -1,14 +1,19 @@
1
1
  import {
2
- openCall,
2
+ BelticDisabledError,
3
+ DEFAULT_OPEN_RETRY_MS,
4
+ Session,
5
+ Sessions,
3
6
  recordCall
4
- } from "./chunk-GSH5APZW.js";
7
+ } from "./chunk-4MG6VNAU.js";
5
8
  import {
6
- Chain,
9
+ canonicalBytes,
10
+ canonicalize,
7
11
  didKeyFromEd25519,
8
12
  fromHex,
9
13
  memorySigner,
14
+ sha256,
10
15
  toHex
11
- } from "./chunk-SFGM7KOG.js";
16
+ } from "./chunk-X3W2Z5GC.js";
12
17
  import {
13
18
  Verdict
14
19
  } from "./chunk-46QN2KEZ.js";
@@ -115,212 +120,256 @@ var MemoryCorrelationStore = class {
115
120
  }
116
121
  };
117
122
 
118
- // src/core/session.ts
119
- var Session = class {
120
- constructor(deps, id, source, expiresAt, born) {
121
- this.deps = deps;
122
- this.id = id;
123
- this.source = source;
124
- this.expiresAt = expiresAt;
125
- this.born = born;
126
- this.chain = Chain.genesis(id, source);
127
- this.now = deps.now ?? (() => /* @__PURE__ */ new Date());
128
- }
129
- chain;
130
- building = Promise.resolve();
131
- dropped = 0;
132
- droppedFirstTs = null;
133
- droppedLastTs = null;
134
- closed = false;
135
- now;
136
- get head() {
137
- return this.chain.head;
123
+ // src/core/identity.ts
124
+ import { mkdirSync, readFileSync, writeFileSync } from "fs";
125
+ import { dirname } from "path";
126
+ function identityFromSeed(seed, credential) {
127
+ const signer = memorySigner(seed);
128
+ const did = didKeyFromEd25519(signer.publicKey);
129
+ return { did, signer: { ...signer, keyId: did }, ...credential ? { credential } : {} };
130
+ }
131
+ function ephemeralIdentity(credential) {
132
+ return identityFromSeed(memorySigner().seed, credential);
133
+ }
134
+ function fileIdentity(path, credential) {
135
+ let seed;
136
+ try {
137
+ seed = fromHex(JSON.parse(readFileSync(path, "utf8")).seed);
138
+ } catch {
139
+ seed = memorySigner().seed;
140
+ mkdirSync(dirname(path), { recursive: true });
141
+ writeFileSync(path, `${JSON.stringify({ seed: toHex(seed) })}
142
+ `, { mode: 384 });
138
143
  }
139
- get droppedCount() {
140
- return this.dropped;
144
+ return identityFromSeed(seed, credential);
145
+ }
146
+
147
+ // src/core/decision.ts
148
+ var Decision = class _Decision {
149
+ constructor(evaluation) {
150
+ this.evaluation = evaluation;
141
151
  }
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
- */
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
- }
152
+ static ABSENT = new _Decision(null);
153
+ static of(evaluation) {
154
+ return new _Decision(evaluation);
155
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) {
162
- const halted = this.deps.transport.haltedError(this.id, this.source);
163
- if (halted) throw halted;
164
- const ts = this.now().toISOString();
165
- if (!this.deps.transport.hasRoom()) {
166
- this.dropped++;
167
- this.droppedFirstTs ??= ts;
168
- this.droppedLastTs = ts;
169
- return false;
170
- }
171
- if (this.dropped > 0) {
172
- this.deps.transport.enqueue(
173
- await this.next(
174
- "transport.gap",
175
- { dropped: this.dropped, firstTs: this.droppedFirstTs, lastTs: this.droppedLastTs },
176
- ts
177
- )
178
- );
179
- this.dropped = 0;
180
- this.droppedFirstTs = this.droppedLastTs = null;
181
- }
182
- const body = payload;
183
- this.deps.transport.enqueue(
184
- await this.next(kind, this.deps.redact ? this.deps.redact(kind, body) : body, ts)
185
- );
186
- return true;
156
+ static absent() {
157
+ return _Decision.ABSENT;
187
158
  }
188
- async close(reason = "completed", extra = {}) {
189
- if (this.closed) return;
190
- this.closed = true;
191
- await this.emit("session.close", { reason, ...extra });
192
- await this.flush();
193
- this.deps.onClosed?.(this);
159
+ get value() {
160
+ return this.evaluation?.decision ?? null;
194
161
  }
195
- /** Read-your-writes: the platform must hold the evidence before anyone judges it (GAP-16/66). */
196
- flush() {
197
- return this.deps.transport.flush();
198
- }
199
- /** Serialized: two concurrent emits get consecutive seqs, never the same one. */
200
- next(kind, payload, ts) {
201
- const run = this.building.then(async () => {
202
- const built = await this.chain.append({ ts, kind, payload }, this.deps.signer);
203
- this.chain = built.chain;
204
- return built.event;
205
- });
206
- this.building = run.catch(() => void 0);
207
- return run;
162
+ get reasonCodes() {
163
+ return this.evaluation?.reasonCodes ?? [];
164
+ }
165
+ get decisionId() {
166
+ return this.evaluation?.decisionId ?? null;
167
+ }
168
+ get allowed() {
169
+ return this.value === "ALLOW";
170
+ }
171
+ get denied() {
172
+ return this.value === "DENY";
173
+ }
174
+ get review() {
175
+ return this.value === "REVIEW";
176
+ }
177
+ get absent() {
178
+ return this.evaluation === null;
179
+ }
180
+ /** Whether a gate must stop the payment (GAP-52); an absent verdict never blocks. */
181
+ blocks(onReview) {
182
+ return this.evaluation ? Verdict.of(this.evaluation.decision).blocks(onReview) : false;
183
+ }
184
+ /** One sentence for the agent or the person: what Beltic said and why. */
185
+ explain() {
186
+ if (!this.evaluation) return "Beltic could not be asked about this payment.";
187
+ const verb = this.denied ? "denied" : this.review ? "asked for review of" : "allowed";
188
+ const why = this.reasonCodes.length > 0 ? ` (${this.reasonCodes.join(", ")})` : "";
189
+ return `Beltic ${verb} this payment${why}.`;
190
+ }
191
+ };
192
+
193
+ // src/core/run.ts
194
+ var MEMORY = 256;
195
+ var Memory = class {
196
+ map = /* @__PURE__ */ new Map();
197
+ get(key) {
198
+ return this.map.get(key);
199
+ }
200
+ set(key, value) {
201
+ this.map.delete(key);
202
+ this.map.set(key, value);
203
+ if (this.map.size > MEMORY) this.map.delete(this.map.keys().next().value);
208
204
  }
209
205
  };
210
- var DEFAULT_OPEN_RETRY_MS = 6e4;
211
- var Sessions = class {
212
- constructor(deps) {
206
+ var Run = class _Run {
207
+ constructor(deps, key, opts = {}) {
213
208
  this.deps = deps;
209
+ this.key = key;
210
+ this.opts = opts;
211
+ }
212
+ opened = null;
213
+ current = null;
214
+ /** JCS hash of the mandate on the chain, and of the one the open input carried. */
215
+ declared = null;
216
+ openedWith = null;
217
+ closed = false;
218
+ timer = null;
219
+ calls = new Memory();
220
+ decisions = new Memory();
221
+ byPayment = new Memory();
222
+ /** The session this run records into — opened on first use, `null` when there is none. */
223
+ session() {
224
+ const next = this.deps.sessions.open(this.key, this.opener);
225
+ this.opened = next;
226
+ return next.then((session) => {
227
+ if (session !== this.current) {
228
+ this.current = session;
229
+ this.declared = this.openedWith;
230
+ }
231
+ return session;
232
+ });
233
+ }
234
+ opener = async () => {
235
+ const open = this.opts.open;
236
+ const input = typeof open === "function" ? await open() : open ?? {};
237
+ this.openedWith = input.intent ? _Run.hash(input.intent) : null;
238
+ return input;
239
+ };
240
+ /** `intent.declared`, unless the mandate is the one already on the chain. */
241
+ async declare(intent) {
242
+ const session = await this.session();
243
+ if (!session) return false;
244
+ const hash = _Run.hash(intent);
245
+ if (hash === this.declared) return false;
246
+ const ok = await session.emit("intent.declared", intent);
247
+ if (ok) this.declared = hash;
248
+ this.touch();
249
+ return ok;
214
250
  }
215
251
  /**
216
- * One session object per (session, source) per process: a chain's head
217
- * lives in it, so two objects for the same chain would both start at
218
- * seq 0 and fork it. Closed sessions are forgotten; a process restart
219
- * mid-session still loses the head (GAP-67).
252
+ * The platform's verdict on a payment about to be presented. Asked once
253
+ * per call id: a host that re-runs its approval step reads the same
254
+ * `Decision`. An absent verdict is not memoized, so the next attempt
255
+ * asks again.
220
256
  */
221
- attached = /* @__PURE__ */ new Map();
222
- /** Buyer sessions by the host's own key (GAP-71). */
223
- opened = /* @__PURE__ */ new Map();
224
- retryAt = 0;
257
+ async decide(payment, opts = {}) {
258
+ const known = opts.callId ? this.decisions.get(opts.callId) : void 0;
259
+ if (known) return known;
260
+ const session = await this.session();
261
+ if (!session) return Decision.absent();
262
+ if (opts.intent) await this.declare(opts.intent);
263
+ const summary = summaryOf(payment);
264
+ const evaluation = await this.deps.evaluate(session.id, summary);
265
+ if (!evaluation) return Decision.absent();
266
+ const decision = Decision.of(evaluation);
267
+ if (opts.callId) this.decisions.set(opts.callId, decision);
268
+ for (const key of _Run.paymentKeys(summary)) this.byPayment.set(key, decision);
269
+ const call = opts.callId ? this.calls.get(opts.callId)?.call : void 0;
270
+ await session.emit("gateway.decision", {
271
+ gateway: "beltic",
272
+ call: _Run.callOf(call),
273
+ decision: evaluation.decision,
274
+ reasonCodes: [...evaluation.reasonCodes],
275
+ record: {
276
+ decisionId: evaluation.decisionId,
277
+ callId: opts.callId ?? null,
278
+ payment: summary
279
+ }
280
+ });
281
+ this.touch();
282
+ return decision;
283
+ }
284
+ /** The decision given for a call id, or absent. */
285
+ decision(callId) {
286
+ return this.decisions.get(callId) ?? Decision.absent();
287
+ }
225
288
  /**
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.
289
+ * The decision given for a payment with the same comparable core (payee,
290
+ * amount, payer or payee and amount when one side names no payer), or
291
+ * absent.
234
292
  */
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;
293
+ decisionFor(payment) {
294
+ for (const key of _Run.paymentKeys(summaryOf(payment))) {
295
+ const known = this.byPayment.get(key);
296
+ if (known) return known;
260
297
  }
261
- }
262
- /** Buyer half: create an AGENT_TRACE session bound to the agent identity, then announce it on the chain. */
263
- start(input = {}) {
264
- return this.create(input);
265
- }
266
- identityFor(entry) {
267
- const identity = this.deps.identity;
268
- if (!identity)
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");
274
- const body = {
275
- source: "AGENT_TRACE",
276
- agent: { did: identity.did, credential: identity.credential ?? identity.did },
277
- ...input.intent ? { intent: input.intent } : {}
278
- };
279
- const out = await this.deps.api.post("/v1/sessions", body);
280
- const session = this.attach(out.sessionId, "AGENT_TRACE", out.expiresAt, "buyer", onClosed);
281
- await session.emit("session.open", {
282
- runtime: {
283
- sdk: "@belticlabs/agent-risk-sdk",
284
- version: this.deps.sdkVersion,
285
- ...input.runtime
286
- },
287
- ...input.attestations ? { attestations: input.attestations } : {}
288
- });
289
- if (input.intent) await session.emit("intent.declared", input.intent);
290
- return session;
291
- }
292
- /** Seller half: emit INTERNAL_NETWORK evidence into a session the buyer bound, or open a seller-born one. */
293
- async ensure(sessionId) {
294
- if (sessionId) return this.attach(sessionId, "INTERNAL_NETWORK", null, "buyer");
295
- const out = await this.deps.api.post("/v1/sessions", {
296
- source: "INTERNAL_NETWORK"
298
+ return Decision.absent();
299
+ }
300
+ /** A tool call the host runs itself, reported as two events by its own call id. */
301
+ tools = {
302
+ start: async (call) => {
303
+ const session = await this.session();
304
+ if (!session) return false;
305
+ const span = session.toolCall(call);
306
+ this.calls.set(call.callId, { call, span });
307
+ this.touch();
308
+ return span.opened;
309
+ },
310
+ end: async (callId, outcome) => {
311
+ const span = this.take(callId);
312
+ if (!span) return false;
313
+ this.touch();
314
+ return span.end(outcome);
315
+ },
316
+ fail: async (callId, error, outcome) => {
317
+ const span = this.take(callId);
318
+ if (!span) return false;
319
+ this.touch();
320
+ return span.fail(error, outcome);
321
+ }
322
+ };
323
+ /** A person's answer about a call, as the decision it was (GAP-75). */
324
+ async humanDecided(callId, input) {
325
+ const session = await this.session();
326
+ if (!session) return false;
327
+ const ok = await session.emit("gateway.decision", {
328
+ gateway: "human",
329
+ call: _Run.callOf(this.calls.get(callId)?.call),
330
+ decision: input.allowed ? "ALLOW" : "DENY",
331
+ reasonCodes: [`USER_${input.outcome.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}`],
332
+ record: {
333
+ callId,
334
+ outcome: input.outcome,
335
+ responder: input.responder ?? null,
336
+ ...input.record ?? {}
337
+ }
297
338
  });
298
- return this.attach(out.sessionId, "INTERNAL_NETWORK", out.expiresAt, "seller");
339
+ this.touch();
340
+ return ok;
299
341
  }
300
- attach(id, source, expiresAt, born, onClosed) {
301
- const key = `${id}:${source}`;
302
- const existing = this.attached.get(key);
303
- if (existing) return existing;
304
- const session = new Session(
305
- {
306
- transport: this.deps.transport,
307
- signer: source === "AGENT_TRACE" ? this.deps.identity?.signer : void 0,
308
- redact: this.deps.redact,
309
- now: this.deps.now,
310
- failOpen: this.deps.failOpen,
311
- onError: this.deps.onError,
312
- onClosed: () => {
313
- this.attached.delete(key);
314
- onClosed?.();
315
- }
316
- },
317
- id,
318
- source,
319
- expiresAt,
320
- born
321
- );
322
- this.attached.set(key, session);
323
- return session;
342
+ async close(reason = "completed") {
343
+ if (this.closed) return;
344
+ this.closed = true;
345
+ if (this.timer) clearTimeout(this.timer);
346
+ this.deps.onClosed(this);
347
+ const session = this.opened ? await this.opened.catch(() => null) : null;
348
+ await session?.close(reason);
349
+ }
350
+ take(callId) {
351
+ const known = this.calls.get(callId);
352
+ if (!known?.span) return null;
353
+ const { span } = known;
354
+ known.span = null;
355
+ return span;
356
+ }
357
+ touch() {
358
+ if (!this.opts.idleMs || this.closed) return;
359
+ if (this.timer) clearTimeout(this.timer);
360
+ this.timer = setTimeout(() => void this.close("expired"), this.opts.idleMs);
361
+ this.timer.unref?.();
362
+ }
363
+ static hash(intent) {
364
+ return toHex(sha256(canonicalBytes(intent)));
365
+ }
366
+ /** With the payer first, then without it. */
367
+ static paymentKeys(summary) {
368
+ const { payer, ...core } = summary;
369
+ return payer ? [canonicalize(summary), canonicalize(core)] : [canonicalize(core)];
370
+ }
371
+ static callOf(call) {
372
+ return call ? { tool: call.toolName, args: call.input } : { tool: "unknown" };
324
373
  }
325
374
  };
326
375
 
@@ -486,8 +535,10 @@ var Transport = class {
486
535
  };
487
536
 
488
537
  // src/client.ts
489
- var SDK_VERSION = "0.2.0";
490
- var Beltic = class {
538
+ var SDK_VERSION = "0.3.0";
539
+ var ENV_REQUIRED = ["BELTIC_API_KEY", "BELTIC_BASE_URL", "BELTIC_AGENT_SEED"];
540
+ var ENV_CREDENTIAL = "BELTIC_AGENT_CREDENTIAL";
541
+ var Beltic = class _Beltic {
491
542
  api;
492
543
  transport;
493
544
  sessions;
@@ -495,8 +546,43 @@ var Beltic = class {
495
546
  correlation;
496
547
  onReview;
497
548
  failOpen;
549
+ /** `false` for a disabled client (GAP-78): nothing is posted, `run`/`sessions.open` answer without a session. */
550
+ enabled;
498
551
  onError;
552
+ runs = /* @__PURE__ */ new Map();
553
+ /**
554
+ * The client the environment describes: `BELTIC_API_KEY`,
555
+ * `BELTIC_BASE_URL`, `BELTIC_AGENT_SEED` (64 hex) and optionally
556
+ * `BELTIC_AGENT_CREDENTIAL`, fail-open by default. None set → a disabled
557
+ * client; some set → a configuration error, thrown (GAP-78).
558
+ */
559
+ static fromEnv(env = _Beltic.processEnv(), opts = {}) {
560
+ const missing = ENV_REQUIRED.filter((name) => !env[name]);
561
+ if (missing.length === ENV_REQUIRED.length) return _Beltic.disabled(opts);
562
+ if (missing.length > 0)
563
+ throw new Error(
564
+ `Beltic.fromEnv: ${missing.join(", ")} missing \u2014 set all of ${ENV_REQUIRED.join(", ")}, or none to disable`
565
+ );
566
+ return new _Beltic({
567
+ failOpen: true,
568
+ ...opts,
569
+ apiKey: env.BELTIC_API_KEY,
570
+ baseUrl: env.BELTIC_BASE_URL,
571
+ identity: identityFromSeed(fromHex(env.BELTIC_AGENT_SEED), env[ENV_CREDENTIAL])
572
+ });
573
+ }
574
+ /** A client that records nothing and never throws into the work: the null object for "no evidence stream" (GAP-78). */
575
+ static disabled(opts = {}) {
576
+ return new _Beltic({
577
+ ...opts,
578
+ apiKey: "",
579
+ baseUrl: "http://beltic.disabled.invalid",
580
+ failOpen: true,
581
+ enabled: false
582
+ });
583
+ }
499
584
  constructor(opts) {
585
+ this.enabled = opts.enabled ?? true;
500
586
  this.failOpen = opts.failOpen ?? false;
501
587
  this.onError = opts.onError ?? ((err) => console.error("[beltic]", err));
502
588
  this.api = new ApiClient({ ...opts, userAgent: `@belticlabs/agent-risk-sdk/${SDK_VERSION}` });
@@ -514,7 +600,8 @@ var Beltic = class {
514
600
  now: opts.now,
515
601
  failOpen: this.failOpen,
516
602
  onError: this.onError,
517
- openRetryMs: opts.openRetryMs
603
+ openRetryMs: opts.openRetryMs,
604
+ enabled: this.enabled
518
605
  });
519
606
  this.identity = opts.identity;
520
607
  this.correlation = opts.correlation ?? new MemoryCorrelationStore();
@@ -529,6 +616,7 @@ var Beltic = class {
529
616
  * platform could not be asked.
530
617
  */
531
618
  async evaluate(sessionId, payment) {
619
+ if (!this.enabled) return null;
532
620
  const input = { sessionId, payment: summaryOf(payment) };
533
621
  if (!this.failOpen) return this.decide(input);
534
622
  try {
@@ -543,48 +631,52 @@ var Beltic = class {
543
631
  const out = await this.api.post("/v1/evaluate", input);
544
632
  return { ...out, verdict: Verdict.of(out.decision) };
545
633
  }
634
+ /**
635
+ * The run for a key of the host's own — one object per key until it
636
+ * closes (the options count on the first call only). See `Run`.
637
+ */
638
+ run(key, opts = {}) {
639
+ const existing = this.runs.get(key);
640
+ if (existing) return existing;
641
+ const run = new Run(
642
+ {
643
+ sessions: this.sessions,
644
+ evaluate: (sessionId, payment) => this.evaluate(sessionId, payment),
645
+ onClosed: (closed) => {
646
+ if (this.runs.get(key) === closed) this.runs.delete(key);
647
+ }
648
+ },
649
+ key,
650
+ opts
651
+ );
652
+ this.runs.set(key, run);
653
+ return run;
654
+ }
546
655
  flush() {
547
656
  return this.transport.flush();
548
657
  }
549
658
  shutdown() {
550
659
  return this.transport.close();
551
660
  }
661
+ /** `process.env` where there is a `process` (Node); `{}` on workerd, where the shell passes its `env`. */
662
+ static processEnv() {
663
+ return globalThis.process?.env ?? {};
664
+ }
552
665
  };
553
666
  function createBeltic(opts) {
554
667
  return new Beltic(opts);
555
668
  }
556
-
557
- // src/core/identity.ts
558
- import { mkdirSync, readFileSync, writeFileSync } from "fs";
559
- import { dirname } from "path";
560
- function identityFromSeed(seed, credential) {
561
- const signer = memorySigner(seed);
562
- const did = didKeyFromEd25519(signer.publicKey);
563
- return { did, signer: { ...signer, keyId: did }, ...credential ? { credential } : {} };
564
- }
565
- function ephemeralIdentity(credential) {
566
- return identityFromSeed(memorySigner().seed, credential);
567
- }
568
- function fileIdentity(path, credential) {
569
- let seed;
570
- try {
571
- seed = fromHex(JSON.parse(readFileSync(path, "utf8")).seed);
572
- } catch {
573
- seed = memorySigner().seed;
574
- mkdirSync(dirname(path), { recursive: true });
575
- writeFileSync(path, `${JSON.stringify({ seed: toHex(seed) })}
576
- `, { mode: 384 });
577
- }
578
- return identityFromSeed(seed, credential);
579
- }
580
669
  export {
581
670
  ApiClient,
582
671
  Beltic,
583
672
  BelticApiError,
673
+ BelticDisabledError,
584
674
  ChainRejectedError,
585
675
  DEFAULT_OPEN_RETRY_MS,
586
676
  DEFAULT_TRANSPORT,
677
+ Decision,
587
678
  MemoryCorrelationStore,
679
+ Run,
588
680
  SDK_VERSION,
589
681
  Session,
590
682
  Sessions,
@@ -1,8 +1,6 @@
1
- import { a as PaymentSummary, P as PaymentMomentPayload } from '../index-Bjs3BPPU.js';
2
- import { B as Beltic } from '../client-C-mV_3A0.js';
3
- import { S as Session } from '../session-5TClPLI4.js';
1
+ import { a as PaymentSummary, P as PaymentMomentPayload } from '../verdict-6vCyoAHE.js';
2
+ import { B as Beltic, S as SessionSource } from '../session-DsBWEP8d.js';
4
3
  import 'zod';
5
- import '../verdict-BAahb5po.js';
6
4
 
7
5
  interface CallToolParams {
8
6
  name: string;
@@ -13,7 +11,7 @@ interface CallToolParams {
13
11
  interface McpClientLike {
14
12
  callTool(params: CallToolParams, ...rest: unknown[]): Promise<unknown>;
15
13
  }
16
- declare function wrapClient<C extends McpClientLike>(session: Session | null | undefined, client: C, opts?: {
14
+ declare function wrapClient<C extends McpClientLike>(source: SessionSource, client: C, opts?: {
17
15
  server?: string;
18
16
  }): C;
19
17
  /**