@atbash/sdk 0.3.9-dev.2 → 0.3.9-dev.4
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.cjs +307 -120
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +305 -120
- package/package.json +5 -1
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,8 @@ __export(index_exports, {
|
|
|
60
60
|
resolve: () => resolve,
|
|
61
61
|
resolveKeyPath: () => resolveKeyPath,
|
|
62
62
|
saveUserConfig: () => saveUserConfig,
|
|
63
|
+
setupTelemetry: () => setupTelemetry,
|
|
64
|
+
shutdownTelemetry: () => shutdownTelemetry,
|
|
63
65
|
toPubkeyHex: () => toPubkeyHex,
|
|
64
66
|
validateJudgeEndpoint: () => validateJudgeEndpoint,
|
|
65
67
|
verifyJudgeResponseSignature: () => verifyJudgeResponseSignature
|
|
@@ -96,6 +98,69 @@ function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
|
|
|
96
98
|
return isValid ? { ok: true } : { ok: false, reason: "signature does not verify against configured verifyPubKey" };
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
// src/opentel/telemetry.ts
|
|
102
|
+
var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
|
|
103
|
+
var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
|
|
104
|
+
var import_resources = require("@opentelemetry/resources");
|
|
105
|
+
var meterProvider = null;
|
|
106
|
+
var callCounter = null;
|
|
107
|
+
var durationHistogram = null;
|
|
108
|
+
var defaultSource = "sdk";
|
|
109
|
+
function setupTelemetry(config) {
|
|
110
|
+
if (!config.enabled) return;
|
|
111
|
+
if (meterProvider) return;
|
|
112
|
+
defaultSource = config.source ?? "sdk";
|
|
113
|
+
const ATBASH_HONEYCOMB_KEY = "YOUR_INGEST_KEY_HERE";
|
|
114
|
+
const apiKey = process.env.HONEYCOMB_API_KEY ?? ATBASH_HONEYCOMB_KEY;
|
|
115
|
+
const exporter = new import_exporter_metrics_otlp_http.OTLPMetricExporter({
|
|
116
|
+
url: "https://api.honeycomb.io/v1/metrics",
|
|
117
|
+
headers: {
|
|
118
|
+
"x-honeycomb-team": apiKey
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
const reader = new import_sdk_metrics.PeriodicExportingMetricReader({
|
|
122
|
+
exporter,
|
|
123
|
+
exportIntervalMillis: config.exportIntervalMs ?? 6e4
|
|
124
|
+
});
|
|
125
|
+
meterProvider = new import_sdk_metrics.MeterProvider({
|
|
126
|
+
resource: (0, import_resources.resourceFromAttributes)({
|
|
127
|
+
"service.name": "atbash-sdk"
|
|
128
|
+
}),
|
|
129
|
+
readers: [reader]
|
|
130
|
+
});
|
|
131
|
+
const meter = meterProvider.getMeter("atbash-sdk");
|
|
132
|
+
callCounter = meter.createCounter("atbash.sdk.function.calls", {
|
|
133
|
+
description: "Number of SDK function calls"
|
|
134
|
+
});
|
|
135
|
+
durationHistogram = meter.createHistogram("atbash.sdk.function.duration_ms", {
|
|
136
|
+
description: "SDK function execution duration",
|
|
137
|
+
unit: "ms"
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function recordCall(functionName, source, agentPubkey) {
|
|
141
|
+
if (!callCounter) return;
|
|
142
|
+
callCounter.add(1, {
|
|
143
|
+
"function.name": functionName,
|
|
144
|
+
"source": source ?? defaultSource,
|
|
145
|
+
...agentPubkey && { "agent.pubkey": agentPubkey }
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function recordDuration(functionName, durationMs, status, source) {
|
|
149
|
+
if (!durationHistogram) return;
|
|
150
|
+
durationHistogram.record(durationMs, {
|
|
151
|
+
"function.name": functionName,
|
|
152
|
+
"status": status,
|
|
153
|
+
"source": source ?? defaultSource
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async function shutdownTelemetry() {
|
|
157
|
+
if (!meterProvider) return;
|
|
158
|
+
await meterProvider.shutdown();
|
|
159
|
+
meterProvider = null;
|
|
160
|
+
callCounter = null;
|
|
161
|
+
durationHistogram = null;
|
|
162
|
+
}
|
|
163
|
+
|
|
99
164
|
// src/client.ts
|
|
100
165
|
var { createClient, encryption: encryption2, newSignatureProvider } = import_postchain_client2.default;
|
|
101
166
|
var DEFAULT_ENDPOINT = "https://chromia-verified-ai-dev-two.vercel.app";
|
|
@@ -168,13 +233,24 @@ async function buildSignedTx(opName, args, auth, chainOpts) {
|
|
|
168
233
|
return Buffer.from(signed).toString("hex");
|
|
169
234
|
}
|
|
170
235
|
async function checkAgentExists(pubkey, opts) {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
236
|
+
const start = performance.now();
|
|
237
|
+
recordCall("checkAgentExists", void 0, pubkey);
|
|
238
|
+
try {
|
|
239
|
+
const url = `${baseUrl(opts)}/api/ai/exists?pubkey=${encodeURIComponent(pubkey)}`;
|
|
240
|
+
const data = await getJson(url, opts);
|
|
241
|
+
recordDuration("checkAgentExists", performance.now() - start, "success");
|
|
242
|
+
return Boolean(data.registered);
|
|
243
|
+
} catch (err) {
|
|
244
|
+
recordDuration("checkAgentExists", performance.now() - start, "error");
|
|
245
|
+
throw err;
|
|
246
|
+
}
|
|
174
247
|
}
|
|
175
248
|
async function logToolCall(action, context, auth, chainOpts, extra, clientOpts) {
|
|
249
|
+
const start = performance.now();
|
|
250
|
+
recordCall("logToolCall", void 0, auth.pubkey);
|
|
176
251
|
const exists = await checkAgentExists(auth.pubkey, clientOpts);
|
|
177
252
|
if (!exists) {
|
|
253
|
+
recordDuration("logToolCall", performance.now() - start, "error");
|
|
178
254
|
return {
|
|
179
255
|
success: false,
|
|
180
256
|
toolCallId: null,
|
|
@@ -195,8 +271,10 @@ async function logToolCall(action, context, auth, chainOpts, extra, clientOpts)
|
|
|
195
271
|
auth,
|
|
196
272
|
chainOpts
|
|
197
273
|
);
|
|
274
|
+
recordDuration("logToolCall", performance.now() - start, "success");
|
|
198
275
|
return { success: true, toolCallId, signedHex };
|
|
199
276
|
} catch (err) {
|
|
277
|
+
recordDuration("logToolCall", performance.now() - start, "error");
|
|
200
278
|
return {
|
|
201
279
|
success: false,
|
|
202
280
|
toolCallId: null,
|
|
@@ -290,66 +368,83 @@ async function postJudgeRequest(url, body, opts) {
|
|
|
290
368
|
return JSON.parse(new TextDecoder().decode(buf));
|
|
291
369
|
}
|
|
292
370
|
async function judgeAction(action, context = "", auth, opts) {
|
|
371
|
+
const start = performance.now();
|
|
372
|
+
recordCall("judgeAction", void 0, auth.pubkey);
|
|
293
373
|
if (!action || !action.trim()) {
|
|
294
374
|
throw new Error("action is required and cannot be empty.");
|
|
295
375
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
opts?.chainOpts,
|
|
301
|
-
{ toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson },
|
|
302
|
-
opts
|
|
303
|
-
);
|
|
304
|
-
if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
|
|
305
|
-
throw new Error(logResult.error || "Failed to sign log_tool_call");
|
|
306
|
-
}
|
|
307
|
-
let signedJudgeActionHex;
|
|
308
|
-
if (!opts?.provider) {
|
|
309
|
-
const judgmentId = generateToolCallId();
|
|
310
|
-
signedJudgeActionHex = await buildSignedTx(
|
|
311
|
-
"judge_action",
|
|
312
|
-
[judgmentId, action, context || "", ""],
|
|
376
|
+
try {
|
|
377
|
+
const logResult = await logToolCall(
|
|
378
|
+
action,
|
|
379
|
+
context,
|
|
313
380
|
auth,
|
|
314
|
-
opts?.chainOpts
|
|
381
|
+
opts?.chainOpts,
|
|
382
|
+
{ toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson },
|
|
383
|
+
opts
|
|
315
384
|
);
|
|
385
|
+
if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
|
|
386
|
+
throw new Error(logResult.error || "Failed to sign log_tool_call");
|
|
387
|
+
}
|
|
388
|
+
let signedJudgeActionHex;
|
|
389
|
+
if (!opts?.provider) {
|
|
390
|
+
const judgmentId = generateToolCallId();
|
|
391
|
+
signedJudgeActionHex = await buildSignedTx(
|
|
392
|
+
"judge_action",
|
|
393
|
+
[judgmentId, action, context || "", ""],
|
|
394
|
+
auth,
|
|
395
|
+
opts?.chainOpts
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
const url = `${baseUrl(opts)}/api/v1/judge`;
|
|
399
|
+
const body = {
|
|
400
|
+
tool_call_id: logResult.toolCallId,
|
|
401
|
+
agent_pubkey: auth.pubkey,
|
|
402
|
+
action,
|
|
403
|
+
signed_log_tool_call: logResult.signedHex,
|
|
404
|
+
...signedJudgeActionHex && { signed_judge_action: signedJudgeActionHex },
|
|
405
|
+
...context && { context },
|
|
406
|
+
...opts?.provider && { provider: opts.provider },
|
|
407
|
+
...opts?.toolName && { tool_name: opts.toolName },
|
|
408
|
+
...opts?.model && { model: opts.model }
|
|
409
|
+
};
|
|
410
|
+
const data = await postJudgeRequest(url, body, opts);
|
|
411
|
+
const result = {
|
|
412
|
+
verdict: normalizeVerdict(data.verdict),
|
|
413
|
+
action_type: String(data.action_type || ""),
|
|
414
|
+
reason: String(data.reason || ""),
|
|
415
|
+
confidence: Number(data.confidence ?? 0),
|
|
416
|
+
provider: String(data.provider || ""),
|
|
417
|
+
latency_ms: Number(data.latency_ms ?? 0),
|
|
418
|
+
tool_call_id: String(data.tool_call_id || logResult.toolCallId),
|
|
419
|
+
on_chain: Boolean(data.on_chain)
|
|
420
|
+
};
|
|
421
|
+
recordDuration("judgeAction", performance.now() - start, "success");
|
|
422
|
+
return result;
|
|
423
|
+
} catch (err) {
|
|
424
|
+
recordDuration("judgeAction", performance.now() - start, "error");
|
|
425
|
+
throw err;
|
|
316
426
|
}
|
|
317
|
-
const url = `${baseUrl(opts)}/api/v1/judge`;
|
|
318
|
-
const body = {
|
|
319
|
-
tool_call_id: logResult.toolCallId,
|
|
320
|
-
agent_pubkey: auth.pubkey,
|
|
321
|
-
action,
|
|
322
|
-
signed_log_tool_call: logResult.signedHex,
|
|
323
|
-
...signedJudgeActionHex && { signed_judge_action: signedJudgeActionHex },
|
|
324
|
-
...context && { context },
|
|
325
|
-
...opts?.provider && { provider: opts.provider },
|
|
326
|
-
...opts?.toolName && { tool_name: opts.toolName },
|
|
327
|
-
...opts?.model && { model: opts.model }
|
|
328
|
-
};
|
|
329
|
-
const data = await postJudgeRequest(url, body, opts);
|
|
330
|
-
return {
|
|
331
|
-
verdict: normalizeVerdict(data.verdict),
|
|
332
|
-
action_type: String(data.action_type || ""),
|
|
333
|
-
reason: String(data.reason || ""),
|
|
334
|
-
confidence: Number(data.confidence ?? 0),
|
|
335
|
-
provider: String(data.provider || ""),
|
|
336
|
-
latency_ms: Number(data.latency_ms ?? 0),
|
|
337
|
-
tool_call_id: String(data.tool_call_id || logResult.toolCallId),
|
|
338
|
-
on_chain: Boolean(data.on_chain)
|
|
339
|
-
};
|
|
340
427
|
}
|
|
341
428
|
async function getJudgmentStatus(judgmentId, agentPubkey, opts) {
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
429
|
+
const start = performance.now();
|
|
430
|
+
recordCall("getJudgmentStatus", void 0, agentPubkey);
|
|
431
|
+
try {
|
|
432
|
+
const url = `${baseUrl(opts)}/api/v1/judge?tool_call_id=${encodeURIComponent(judgmentId)}&agent_pubkey=${encodeURIComponent(agentPubkey)}`;
|
|
433
|
+
const data = await getJson(url, opts);
|
|
434
|
+
recordDuration("getJudgmentStatus", performance.now() - start, "success");
|
|
435
|
+
return {
|
|
436
|
+
status: normalizeStatus(data.status),
|
|
437
|
+
verdict: normalizeVerdict(data.verdict),
|
|
438
|
+
reason: String(data.reason || ""),
|
|
439
|
+
judgmentId: String(data.judgmentId || judgmentId),
|
|
440
|
+
onChain: Boolean(data.onChain),
|
|
441
|
+
cached: Boolean(data.cached),
|
|
442
|
+
responseTimeMs: Number(data.responseTimeMs ?? 0)
|
|
443
|
+
};
|
|
444
|
+
} catch (err) {
|
|
445
|
+
recordDuration("getJudgmentStatus", performance.now() - start, "error");
|
|
446
|
+
throw err;
|
|
447
|
+
}
|
|
353
448
|
}
|
|
354
449
|
function riskEngineUrl(action, params, opts) {
|
|
355
450
|
const url = new URL(`${baseUrl(opts)}/api/risk-engine`);
|
|
@@ -360,98 +455,188 @@ function riskEngineUrl(action, params, opts) {
|
|
|
360
455
|
return url.toString();
|
|
361
456
|
}
|
|
362
457
|
async function getToolCalls(maxCount, opts) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
458
|
+
const start = performance.now();
|
|
459
|
+
recordCall("getToolCalls");
|
|
460
|
+
try {
|
|
461
|
+
const result = await getJson(
|
|
462
|
+
riskEngineUrl("tool-calls", { limit: String(maxCount) }, opts),
|
|
463
|
+
opts
|
|
464
|
+
);
|
|
465
|
+
recordDuration("getToolCalls", performance.now() - start, "success");
|
|
466
|
+
return result;
|
|
467
|
+
} catch (err) {
|
|
468
|
+
recordDuration("getToolCalls", performance.now() - start, "error");
|
|
469
|
+
throw err;
|
|
470
|
+
}
|
|
367
471
|
}
|
|
368
472
|
async function getOrgToolCalls(orgName, maxCount, opts) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
473
|
+
const start = performance.now();
|
|
474
|
+
recordCall("getOrgToolCalls");
|
|
475
|
+
try {
|
|
476
|
+
const result = await getJson(
|
|
477
|
+
riskEngineUrl(
|
|
478
|
+
"org-tool-calls",
|
|
479
|
+
{ org: orgName, limit: String(maxCount) },
|
|
480
|
+
opts
|
|
481
|
+
),
|
|
373
482
|
opts
|
|
374
|
-
)
|
|
375
|
-
|
|
376
|
-
|
|
483
|
+
);
|
|
484
|
+
recordDuration("getOrgToolCalls", performance.now() - start, "success");
|
|
485
|
+
return result;
|
|
486
|
+
} catch (err) {
|
|
487
|
+
recordDuration("getOrgToolCalls", performance.now() - start, "error");
|
|
488
|
+
throw err;
|
|
489
|
+
}
|
|
377
490
|
}
|
|
378
491
|
async function getAgentToolCalls(agentPubkey, maxCount, opts) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
492
|
+
const start = performance.now();
|
|
493
|
+
recordCall("getAgentToolCalls", void 0, agentPubkey);
|
|
494
|
+
try {
|
|
495
|
+
const result = await getJson(
|
|
496
|
+
riskEngineUrl(
|
|
497
|
+
"agent-tool-calls",
|
|
498
|
+
{ agent: agentPubkey, limit: String(maxCount) },
|
|
499
|
+
opts
|
|
500
|
+
),
|
|
383
501
|
opts
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
|
|
502
|
+
);
|
|
503
|
+
recordDuration("getAgentToolCalls", performance.now() - start, "success");
|
|
504
|
+
return result;
|
|
505
|
+
} catch (err) {
|
|
506
|
+
recordDuration("getAgentToolCalls", performance.now() - start, "error");
|
|
507
|
+
throw err;
|
|
508
|
+
}
|
|
387
509
|
}
|
|
388
510
|
async function getToolCallCount(opts) {
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
511
|
+
const start = performance.now();
|
|
512
|
+
recordCall("getToolCallCount");
|
|
513
|
+
try {
|
|
514
|
+
const result = await getJson(
|
|
515
|
+
riskEngineUrl("tool-call-count", {}, opts),
|
|
516
|
+
opts
|
|
517
|
+
);
|
|
518
|
+
recordDuration("getToolCallCount", performance.now() - start, "success");
|
|
519
|
+
return typeof result === "number" ? result : Number(result ?? 0);
|
|
520
|
+
} catch (err) {
|
|
521
|
+
recordDuration("getToolCallCount", performance.now() - start, "error");
|
|
522
|
+
throw err;
|
|
523
|
+
}
|
|
394
524
|
}
|
|
395
525
|
async function getToolCallFull(toolCallId, opts) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
526
|
+
const start = performance.now();
|
|
527
|
+
recordCall("getToolCallFull");
|
|
528
|
+
try {
|
|
529
|
+
const result = await getJson(
|
|
530
|
+
riskEngineUrl("tool-call-full", { tool_call_id: toolCallId }, opts),
|
|
531
|
+
opts
|
|
532
|
+
);
|
|
533
|
+
recordDuration("getToolCallFull", performance.now() - start, "success");
|
|
534
|
+
return result;
|
|
535
|
+
} catch (err) {
|
|
536
|
+
recordDuration("getToolCallFull", performance.now() - start, "error");
|
|
537
|
+
throw err;
|
|
538
|
+
}
|
|
400
539
|
}
|
|
401
540
|
async function getOrgTierInfo(orgName, opts) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
541
|
+
const start = performance.now();
|
|
542
|
+
recordCall("getOrgTierInfo");
|
|
543
|
+
try {
|
|
544
|
+
const result = await getJson(
|
|
545
|
+
riskEngineUrl("org-tier-info", { org: orgName }, opts),
|
|
546
|
+
opts
|
|
547
|
+
);
|
|
548
|
+
recordDuration("getOrgTierInfo", performance.now() - start, "success");
|
|
549
|
+
return result;
|
|
550
|
+
} catch (err) {
|
|
551
|
+
recordDuration("getOrgTierInfo", performance.now() - start, "error");
|
|
552
|
+
throw err;
|
|
553
|
+
}
|
|
406
554
|
}
|
|
407
555
|
async function getPendingHeldActions(orgName, maxCount, opts) {
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
556
|
+
const start = performance.now();
|
|
557
|
+
recordCall("getPendingHeldActions");
|
|
558
|
+
try {
|
|
559
|
+
const raw = await getJson(
|
|
560
|
+
riskEngineUrl(
|
|
561
|
+
"pending-held-actions",
|
|
562
|
+
{ org: orgName, limit: String(maxCount) },
|
|
563
|
+
opts
|
|
564
|
+
),
|
|
412
565
|
opts
|
|
413
|
-
)
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
566
|
+
);
|
|
567
|
+
recordDuration("getPendingHeldActions", performance.now() - start, "success");
|
|
568
|
+
return raw.map((h) => ({ ...h, verdict: normalizeVerdict(h.verdict) }));
|
|
569
|
+
} catch (err) {
|
|
570
|
+
recordDuration("getPendingHeldActions", performance.now() - start, "error");
|
|
571
|
+
throw err;
|
|
572
|
+
}
|
|
417
573
|
}
|
|
418
574
|
async function getHeldActionReviews(orgName, maxCount, opts) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
575
|
+
const start = performance.now();
|
|
576
|
+
recordCall("getHeldActionReviews");
|
|
577
|
+
try {
|
|
578
|
+
const result = await getJson(
|
|
579
|
+
riskEngineUrl(
|
|
580
|
+
"held-action-reviews",
|
|
581
|
+
{ org: orgName, limit: String(maxCount) },
|
|
582
|
+
opts
|
|
583
|
+
),
|
|
423
584
|
opts
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
|
|
585
|
+
);
|
|
586
|
+
recordDuration("getHeldActionReviews", performance.now() - start, "success");
|
|
587
|
+
return result;
|
|
588
|
+
} catch (err) {
|
|
589
|
+
recordDuration("getHeldActionReviews", performance.now() - start, "error");
|
|
590
|
+
throw err;
|
|
591
|
+
}
|
|
427
592
|
}
|
|
428
593
|
function riskEnginePostUrl(opts) {
|
|
429
594
|
return `${baseUrl(opts)}/api/risk-engine`;
|
|
430
595
|
}
|
|
431
596
|
async function getAgentDetail(agentPubkey, opts) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
597
|
+
const start = performance.now();
|
|
598
|
+
recordCall("getAgentDetail", void 0, agentPubkey);
|
|
599
|
+
try {
|
|
600
|
+
const result = await postJson(
|
|
601
|
+
riskEnginePostUrl(opts),
|
|
602
|
+
{ action: "agent-detail-batch", agent: agentPubkey },
|
|
603
|
+
opts
|
|
604
|
+
);
|
|
605
|
+
recordDuration("getAgentDetail", performance.now() - start, "success");
|
|
606
|
+
return result;
|
|
607
|
+
} catch (err) {
|
|
608
|
+
recordDuration("getAgentDetail", performance.now() - start, "error");
|
|
609
|
+
throw err;
|
|
610
|
+
}
|
|
440
611
|
}
|
|
441
612
|
async function getAgentPolicy(agentPubkey, opts) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
613
|
+
const start = performance.now();
|
|
614
|
+
recordCall("getAgentPolicy", void 0, agentPubkey);
|
|
615
|
+
try {
|
|
616
|
+
const result = await postJson(
|
|
617
|
+
riskEnginePostUrl(opts),
|
|
618
|
+
{ action: "agent-policy-batch", agent: agentPubkey },
|
|
619
|
+
opts
|
|
620
|
+
);
|
|
621
|
+
recordDuration("getAgentPolicy", performance.now() - start, "success");
|
|
622
|
+
return result;
|
|
623
|
+
} catch (err) {
|
|
624
|
+
recordDuration("getAgentPolicy", performance.now() - start, "error");
|
|
625
|
+
throw err;
|
|
626
|
+
}
|
|
450
627
|
}
|
|
451
628
|
async function getSafetyStats(opts) {
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
629
|
+
const start = performance.now();
|
|
630
|
+
recordCall("getSafetyStats");
|
|
631
|
+
try {
|
|
632
|
+
const url = `${baseUrl(opts)}/api/insurance?action=safety-stats`;
|
|
633
|
+
const result = await getJson(url, opts);
|
|
634
|
+
recordDuration("getSafetyStats", performance.now() - start, "success");
|
|
635
|
+
return result?.data || result;
|
|
636
|
+
} catch (err) {
|
|
637
|
+
recordDuration("getSafetyStats", performance.now() - start, "error");
|
|
638
|
+
throw err;
|
|
639
|
+
}
|
|
455
640
|
}
|
|
456
641
|
|
|
457
642
|
// src/config.ts
|
|
@@ -820,6 +1005,8 @@ function resolve(key, flagValue) {
|
|
|
820
1005
|
resolve,
|
|
821
1006
|
resolveKeyPath,
|
|
822
1007
|
saveUserConfig,
|
|
1008
|
+
setupTelemetry,
|
|
1009
|
+
shutdownTelemetry,
|
|
823
1010
|
toPubkeyHex,
|
|
824
1011
|
validateJudgeEndpoint,
|
|
825
1012
|
verifyJudgeResponseSignature
|
package/dist/index.d.cts
CHANGED
|
@@ -204,6 +204,31 @@ declare function verifyJudgeResponseSignature(bodyBytes: Uint8Array, signatureHe
|
|
|
204
204
|
reason?: string;
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Atbash SDK Telemetry — OpenTelemetry metrics for usage tracking.
|
|
209
|
+
*
|
|
210
|
+
* Tracks: function call counts, latency, source (CLI/plugin/SDK),
|
|
211
|
+
* and agent identity. Opt-in — no data sent unless enabled.
|
|
212
|
+
*/
|
|
213
|
+
type ClientSource = "cli" | "sdk" | "plugin:openclaw" | "plugin:claude-hook" | "plugin:langchain" | "plugin:langgraph" | "plugin:hermes" | "plugin:eliza" | "plugin:crewai" | "plugin:mcp" | "plugin:autogen" | "plugin:jeenai" | (string & {});
|
|
214
|
+
interface TelemetryConfig {
|
|
215
|
+
/** Must be true to send any telemetry. Default: false */
|
|
216
|
+
enabled: boolean;
|
|
217
|
+
/** Where calls originate */
|
|
218
|
+
source?: ClientSource;
|
|
219
|
+
/** Flush interval in ms. Default: 60000 */
|
|
220
|
+
exportIntervalMs?: number;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Initialize telemetry. Call once at startup.
|
|
224
|
+
* Does nothing if config.enabled is false.
|
|
225
|
+
*/
|
|
226
|
+
declare function setupTelemetry(config: TelemetryConfig): void;
|
|
227
|
+
/**
|
|
228
|
+
* Flush pending metrics and shut down. Call before process exits.
|
|
229
|
+
*/
|
|
230
|
+
declare function shutdownTelemetry(): Promise<void>;
|
|
231
|
+
|
|
207
232
|
interface AtbashUserConfig {
|
|
208
233
|
agentKey?: string;
|
|
209
234
|
orgName?: string;
|
|
@@ -218,4 +243,4 @@ declare function loadUserConfig(): AtbashUserConfig;
|
|
|
218
243
|
declare function saveUserConfig(config: AtbashUserConfig): void;
|
|
219
244
|
declare function resolve(key: keyof AtbashUserConfig, flagValue?: string): string;
|
|
220
245
|
|
|
221
|
-
export { type ActionType, type AgentAuth, type AgentPolicy, type AtbashClient, type AtbashClientConfig, type AtbashUserConfig, type ChainOpts, type ClientOpts, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, type Decision, type DecisionVerdict, type HeldAction, type HeldActionReview, type JudgeEndpointConfig, type JudgeOptions, type JudgeResult, type JudgmentStatus, type JudgmentStatusState, type LogToolCallResult, type Provider, type PubkeyValue, type Tier, type TierInfo, type ToolCallFull, type ToolCallInput, type ToolCallRecord, type ValidatedEndpoint, type Verdict, checkAgentExists, createAtbashClient, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getConfigDir, getConfigPath, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, loadAgent, loadAgentFromFile, loadUserConfig, logToolCall, resolve, resolveKeyPath, saveUserConfig, toPubkeyHex, validateJudgeEndpoint, verifyJudgeResponseSignature };
|
|
246
|
+
export { type ActionType, type AgentAuth, type AgentPolicy, type AtbashClient, type AtbashClientConfig, type AtbashUserConfig, type ChainOpts, type ClientOpts, type ClientSource, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, type Decision, type DecisionVerdict, type HeldAction, type HeldActionReview, type JudgeEndpointConfig, type JudgeOptions, type JudgeResult, type JudgmentStatus, type JudgmentStatusState, type LogToolCallResult, type Provider, type PubkeyValue, type TelemetryConfig, type Tier, type TierInfo, type ToolCallFull, type ToolCallInput, type ToolCallRecord, type ValidatedEndpoint, type Verdict, checkAgentExists, createAtbashClient, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getConfigDir, getConfigPath, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, loadAgent, loadAgentFromFile, loadUserConfig, logToolCall, resolve, resolveKeyPath, saveUserConfig, setupTelemetry, shutdownTelemetry, toPubkeyHex, validateJudgeEndpoint, verifyJudgeResponseSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -204,6 +204,31 @@ declare function verifyJudgeResponseSignature(bodyBytes: Uint8Array, signatureHe
|
|
|
204
204
|
reason?: string;
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Atbash SDK Telemetry — OpenTelemetry metrics for usage tracking.
|
|
209
|
+
*
|
|
210
|
+
* Tracks: function call counts, latency, source (CLI/plugin/SDK),
|
|
211
|
+
* and agent identity. Opt-in — no data sent unless enabled.
|
|
212
|
+
*/
|
|
213
|
+
type ClientSource = "cli" | "sdk" | "plugin:openclaw" | "plugin:claude-hook" | "plugin:langchain" | "plugin:langgraph" | "plugin:hermes" | "plugin:eliza" | "plugin:crewai" | "plugin:mcp" | "plugin:autogen" | "plugin:jeenai" | (string & {});
|
|
214
|
+
interface TelemetryConfig {
|
|
215
|
+
/** Must be true to send any telemetry. Default: false */
|
|
216
|
+
enabled: boolean;
|
|
217
|
+
/** Where calls originate */
|
|
218
|
+
source?: ClientSource;
|
|
219
|
+
/** Flush interval in ms. Default: 60000 */
|
|
220
|
+
exportIntervalMs?: number;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Initialize telemetry. Call once at startup.
|
|
224
|
+
* Does nothing if config.enabled is false.
|
|
225
|
+
*/
|
|
226
|
+
declare function setupTelemetry(config: TelemetryConfig): void;
|
|
227
|
+
/**
|
|
228
|
+
* Flush pending metrics and shut down. Call before process exits.
|
|
229
|
+
*/
|
|
230
|
+
declare function shutdownTelemetry(): Promise<void>;
|
|
231
|
+
|
|
207
232
|
interface AtbashUserConfig {
|
|
208
233
|
agentKey?: string;
|
|
209
234
|
orgName?: string;
|
|
@@ -218,4 +243,4 @@ declare function loadUserConfig(): AtbashUserConfig;
|
|
|
218
243
|
declare function saveUserConfig(config: AtbashUserConfig): void;
|
|
219
244
|
declare function resolve(key: keyof AtbashUserConfig, flagValue?: string): string;
|
|
220
245
|
|
|
221
|
-
export { type ActionType, type AgentAuth, type AgentPolicy, type AtbashClient, type AtbashClientConfig, type AtbashUserConfig, type ChainOpts, type ClientOpts, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, type Decision, type DecisionVerdict, type HeldAction, type HeldActionReview, type JudgeEndpointConfig, type JudgeOptions, type JudgeResult, type JudgmentStatus, type JudgmentStatusState, type LogToolCallResult, type Provider, type PubkeyValue, type Tier, type TierInfo, type ToolCallFull, type ToolCallInput, type ToolCallRecord, type ValidatedEndpoint, type Verdict, checkAgentExists, createAtbashClient, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getConfigDir, getConfigPath, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, loadAgent, loadAgentFromFile, loadUserConfig, logToolCall, resolve, resolveKeyPath, saveUserConfig, toPubkeyHex, validateJudgeEndpoint, verifyJudgeResponseSignature };
|
|
246
|
+
export { type ActionType, type AgentAuth, type AgentPolicy, type AtbashClient, type AtbashClientConfig, type AtbashUserConfig, type ChainOpts, type ClientOpts, type ClientSource, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, type Decision, type DecisionVerdict, type HeldAction, type HeldActionReview, type JudgeEndpointConfig, type JudgeOptions, type JudgeResult, type JudgmentStatus, type JudgmentStatusState, type LogToolCallResult, type Provider, type PubkeyValue, type TelemetryConfig, type Tier, type TierInfo, type ToolCallFull, type ToolCallInput, type ToolCallRecord, type ValidatedEndpoint, type Verdict, checkAgentExists, createAtbashClient, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getConfigDir, getConfigPath, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, loadAgent, loadAgentFromFile, loadUserConfig, logToolCall, resolve, resolveKeyPath, saveUserConfig, setupTelemetry, shutdownTelemetry, toPubkeyHex, validateJudgeEndpoint, verifyJudgeResponseSignature };
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,69 @@ function verifyJudgeResponseSignature(bodyBytes, signatureHex, pubKeyHex) {
|
|
|
28
28
|
return isValid ? { ok: true } : { ok: false, reason: "signature does not verify against configured verifyPubKey" };
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// src/opentel/telemetry.ts
|
|
32
|
+
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
33
|
+
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
34
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
35
|
+
var meterProvider = null;
|
|
36
|
+
var callCounter = null;
|
|
37
|
+
var durationHistogram = null;
|
|
38
|
+
var defaultSource = "sdk";
|
|
39
|
+
function setupTelemetry(config) {
|
|
40
|
+
if (!config.enabled) return;
|
|
41
|
+
if (meterProvider) return;
|
|
42
|
+
defaultSource = config.source ?? "sdk";
|
|
43
|
+
const ATBASH_HONEYCOMB_KEY = "YOUR_INGEST_KEY_HERE";
|
|
44
|
+
const apiKey = process.env.HONEYCOMB_API_KEY ?? ATBASH_HONEYCOMB_KEY;
|
|
45
|
+
const exporter = new OTLPMetricExporter({
|
|
46
|
+
url: "https://api.honeycomb.io/v1/metrics",
|
|
47
|
+
headers: {
|
|
48
|
+
"x-honeycomb-team": apiKey
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
const reader = new PeriodicExportingMetricReader({
|
|
52
|
+
exporter,
|
|
53
|
+
exportIntervalMillis: config.exportIntervalMs ?? 6e4
|
|
54
|
+
});
|
|
55
|
+
meterProvider = new MeterProvider({
|
|
56
|
+
resource: resourceFromAttributes({
|
|
57
|
+
"service.name": "atbash-sdk"
|
|
58
|
+
}),
|
|
59
|
+
readers: [reader]
|
|
60
|
+
});
|
|
61
|
+
const meter = meterProvider.getMeter("atbash-sdk");
|
|
62
|
+
callCounter = meter.createCounter("atbash.sdk.function.calls", {
|
|
63
|
+
description: "Number of SDK function calls"
|
|
64
|
+
});
|
|
65
|
+
durationHistogram = meter.createHistogram("atbash.sdk.function.duration_ms", {
|
|
66
|
+
description: "SDK function execution duration",
|
|
67
|
+
unit: "ms"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function recordCall(functionName, source, agentPubkey) {
|
|
71
|
+
if (!callCounter) return;
|
|
72
|
+
callCounter.add(1, {
|
|
73
|
+
"function.name": functionName,
|
|
74
|
+
"source": source ?? defaultSource,
|
|
75
|
+
...agentPubkey && { "agent.pubkey": agentPubkey }
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function recordDuration(functionName, durationMs, status, source) {
|
|
79
|
+
if (!durationHistogram) return;
|
|
80
|
+
durationHistogram.record(durationMs, {
|
|
81
|
+
"function.name": functionName,
|
|
82
|
+
"status": status,
|
|
83
|
+
"source": source ?? defaultSource
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async function shutdownTelemetry() {
|
|
87
|
+
if (!meterProvider) return;
|
|
88
|
+
await meterProvider.shutdown();
|
|
89
|
+
meterProvider = null;
|
|
90
|
+
callCounter = null;
|
|
91
|
+
durationHistogram = null;
|
|
92
|
+
}
|
|
93
|
+
|
|
31
94
|
// src/client.ts
|
|
32
95
|
var { createClient, encryption: encryption2, newSignatureProvider } = postchain2;
|
|
33
96
|
var DEFAULT_ENDPOINT = "https://chromia-verified-ai-dev-two.vercel.app";
|
|
@@ -100,13 +163,24 @@ async function buildSignedTx(opName, args, auth, chainOpts) {
|
|
|
100
163
|
return Buffer.from(signed).toString("hex");
|
|
101
164
|
}
|
|
102
165
|
async function checkAgentExists(pubkey, opts) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
166
|
+
const start = performance.now();
|
|
167
|
+
recordCall("checkAgentExists", void 0, pubkey);
|
|
168
|
+
try {
|
|
169
|
+
const url = `${baseUrl(opts)}/api/ai/exists?pubkey=${encodeURIComponent(pubkey)}`;
|
|
170
|
+
const data = await getJson(url, opts);
|
|
171
|
+
recordDuration("checkAgentExists", performance.now() - start, "success");
|
|
172
|
+
return Boolean(data.registered);
|
|
173
|
+
} catch (err) {
|
|
174
|
+
recordDuration("checkAgentExists", performance.now() - start, "error");
|
|
175
|
+
throw err;
|
|
176
|
+
}
|
|
106
177
|
}
|
|
107
178
|
async function logToolCall(action, context, auth, chainOpts, extra, clientOpts) {
|
|
179
|
+
const start = performance.now();
|
|
180
|
+
recordCall("logToolCall", void 0, auth.pubkey);
|
|
108
181
|
const exists = await checkAgentExists(auth.pubkey, clientOpts);
|
|
109
182
|
if (!exists) {
|
|
183
|
+
recordDuration("logToolCall", performance.now() - start, "error");
|
|
110
184
|
return {
|
|
111
185
|
success: false,
|
|
112
186
|
toolCallId: null,
|
|
@@ -127,8 +201,10 @@ async function logToolCall(action, context, auth, chainOpts, extra, clientOpts)
|
|
|
127
201
|
auth,
|
|
128
202
|
chainOpts
|
|
129
203
|
);
|
|
204
|
+
recordDuration("logToolCall", performance.now() - start, "success");
|
|
130
205
|
return { success: true, toolCallId, signedHex };
|
|
131
206
|
} catch (err) {
|
|
207
|
+
recordDuration("logToolCall", performance.now() - start, "error");
|
|
132
208
|
return {
|
|
133
209
|
success: false,
|
|
134
210
|
toolCallId: null,
|
|
@@ -222,66 +298,83 @@ async function postJudgeRequest(url, body, opts) {
|
|
|
222
298
|
return JSON.parse(new TextDecoder().decode(buf));
|
|
223
299
|
}
|
|
224
300
|
async function judgeAction(action, context = "", auth, opts) {
|
|
301
|
+
const start = performance.now();
|
|
302
|
+
recordCall("judgeAction", void 0, auth.pubkey);
|
|
225
303
|
if (!action || !action.trim()) {
|
|
226
304
|
throw new Error("action is required and cannot be empty.");
|
|
227
305
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
opts?.chainOpts,
|
|
233
|
-
{ toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson },
|
|
234
|
-
opts
|
|
235
|
-
);
|
|
236
|
-
if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
|
|
237
|
-
throw new Error(logResult.error || "Failed to sign log_tool_call");
|
|
238
|
-
}
|
|
239
|
-
let signedJudgeActionHex;
|
|
240
|
-
if (!opts?.provider) {
|
|
241
|
-
const judgmentId = generateToolCallId();
|
|
242
|
-
signedJudgeActionHex = await buildSignedTx(
|
|
243
|
-
"judge_action",
|
|
244
|
-
[judgmentId, action, context || "", ""],
|
|
306
|
+
try {
|
|
307
|
+
const logResult = await logToolCall(
|
|
308
|
+
action,
|
|
309
|
+
context,
|
|
245
310
|
auth,
|
|
246
|
-
opts?.chainOpts
|
|
311
|
+
opts?.chainOpts,
|
|
312
|
+
{ toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson },
|
|
313
|
+
opts
|
|
247
314
|
);
|
|
315
|
+
if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
|
|
316
|
+
throw new Error(logResult.error || "Failed to sign log_tool_call");
|
|
317
|
+
}
|
|
318
|
+
let signedJudgeActionHex;
|
|
319
|
+
if (!opts?.provider) {
|
|
320
|
+
const judgmentId = generateToolCallId();
|
|
321
|
+
signedJudgeActionHex = await buildSignedTx(
|
|
322
|
+
"judge_action",
|
|
323
|
+
[judgmentId, action, context || "", ""],
|
|
324
|
+
auth,
|
|
325
|
+
opts?.chainOpts
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
const url = `${baseUrl(opts)}/api/v1/judge`;
|
|
329
|
+
const body = {
|
|
330
|
+
tool_call_id: logResult.toolCallId,
|
|
331
|
+
agent_pubkey: auth.pubkey,
|
|
332
|
+
action,
|
|
333
|
+
signed_log_tool_call: logResult.signedHex,
|
|
334
|
+
...signedJudgeActionHex && { signed_judge_action: signedJudgeActionHex },
|
|
335
|
+
...context && { context },
|
|
336
|
+
...opts?.provider && { provider: opts.provider },
|
|
337
|
+
...opts?.toolName && { tool_name: opts.toolName },
|
|
338
|
+
...opts?.model && { model: opts.model }
|
|
339
|
+
};
|
|
340
|
+
const data = await postJudgeRequest(url, body, opts);
|
|
341
|
+
const result = {
|
|
342
|
+
verdict: normalizeVerdict(data.verdict),
|
|
343
|
+
action_type: String(data.action_type || ""),
|
|
344
|
+
reason: String(data.reason || ""),
|
|
345
|
+
confidence: Number(data.confidence ?? 0),
|
|
346
|
+
provider: String(data.provider || ""),
|
|
347
|
+
latency_ms: Number(data.latency_ms ?? 0),
|
|
348
|
+
tool_call_id: String(data.tool_call_id || logResult.toolCallId),
|
|
349
|
+
on_chain: Boolean(data.on_chain)
|
|
350
|
+
};
|
|
351
|
+
recordDuration("judgeAction", performance.now() - start, "success");
|
|
352
|
+
return result;
|
|
353
|
+
} catch (err) {
|
|
354
|
+
recordDuration("judgeAction", performance.now() - start, "error");
|
|
355
|
+
throw err;
|
|
248
356
|
}
|
|
249
|
-
const url = `${baseUrl(opts)}/api/v1/judge`;
|
|
250
|
-
const body = {
|
|
251
|
-
tool_call_id: logResult.toolCallId,
|
|
252
|
-
agent_pubkey: auth.pubkey,
|
|
253
|
-
action,
|
|
254
|
-
signed_log_tool_call: logResult.signedHex,
|
|
255
|
-
...signedJudgeActionHex && { signed_judge_action: signedJudgeActionHex },
|
|
256
|
-
...context && { context },
|
|
257
|
-
...opts?.provider && { provider: opts.provider },
|
|
258
|
-
...opts?.toolName && { tool_name: opts.toolName },
|
|
259
|
-
...opts?.model && { model: opts.model }
|
|
260
|
-
};
|
|
261
|
-
const data = await postJudgeRequest(url, body, opts);
|
|
262
|
-
return {
|
|
263
|
-
verdict: normalizeVerdict(data.verdict),
|
|
264
|
-
action_type: String(data.action_type || ""),
|
|
265
|
-
reason: String(data.reason || ""),
|
|
266
|
-
confidence: Number(data.confidence ?? 0),
|
|
267
|
-
provider: String(data.provider || ""),
|
|
268
|
-
latency_ms: Number(data.latency_ms ?? 0),
|
|
269
|
-
tool_call_id: String(data.tool_call_id || logResult.toolCallId),
|
|
270
|
-
on_chain: Boolean(data.on_chain)
|
|
271
|
-
};
|
|
272
357
|
}
|
|
273
358
|
async function getJudgmentStatus(judgmentId, agentPubkey, opts) {
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
359
|
+
const start = performance.now();
|
|
360
|
+
recordCall("getJudgmentStatus", void 0, agentPubkey);
|
|
361
|
+
try {
|
|
362
|
+
const url = `${baseUrl(opts)}/api/v1/judge?tool_call_id=${encodeURIComponent(judgmentId)}&agent_pubkey=${encodeURIComponent(agentPubkey)}`;
|
|
363
|
+
const data = await getJson(url, opts);
|
|
364
|
+
recordDuration("getJudgmentStatus", performance.now() - start, "success");
|
|
365
|
+
return {
|
|
366
|
+
status: normalizeStatus(data.status),
|
|
367
|
+
verdict: normalizeVerdict(data.verdict),
|
|
368
|
+
reason: String(data.reason || ""),
|
|
369
|
+
judgmentId: String(data.judgmentId || judgmentId),
|
|
370
|
+
onChain: Boolean(data.onChain),
|
|
371
|
+
cached: Boolean(data.cached),
|
|
372
|
+
responseTimeMs: Number(data.responseTimeMs ?? 0)
|
|
373
|
+
};
|
|
374
|
+
} catch (err) {
|
|
375
|
+
recordDuration("getJudgmentStatus", performance.now() - start, "error");
|
|
376
|
+
throw err;
|
|
377
|
+
}
|
|
285
378
|
}
|
|
286
379
|
function riskEngineUrl(action, params, opts) {
|
|
287
380
|
const url = new URL(`${baseUrl(opts)}/api/risk-engine`);
|
|
@@ -292,98 +385,188 @@ function riskEngineUrl(action, params, opts) {
|
|
|
292
385
|
return url.toString();
|
|
293
386
|
}
|
|
294
387
|
async function getToolCalls(maxCount, opts) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
388
|
+
const start = performance.now();
|
|
389
|
+
recordCall("getToolCalls");
|
|
390
|
+
try {
|
|
391
|
+
const result = await getJson(
|
|
392
|
+
riskEngineUrl("tool-calls", { limit: String(maxCount) }, opts),
|
|
393
|
+
opts
|
|
394
|
+
);
|
|
395
|
+
recordDuration("getToolCalls", performance.now() - start, "success");
|
|
396
|
+
return result;
|
|
397
|
+
} catch (err) {
|
|
398
|
+
recordDuration("getToolCalls", performance.now() - start, "error");
|
|
399
|
+
throw err;
|
|
400
|
+
}
|
|
299
401
|
}
|
|
300
402
|
async function getOrgToolCalls(orgName, maxCount, opts) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
403
|
+
const start = performance.now();
|
|
404
|
+
recordCall("getOrgToolCalls");
|
|
405
|
+
try {
|
|
406
|
+
const result = await getJson(
|
|
407
|
+
riskEngineUrl(
|
|
408
|
+
"org-tool-calls",
|
|
409
|
+
{ org: orgName, limit: String(maxCount) },
|
|
410
|
+
opts
|
|
411
|
+
),
|
|
305
412
|
opts
|
|
306
|
-
)
|
|
307
|
-
|
|
308
|
-
|
|
413
|
+
);
|
|
414
|
+
recordDuration("getOrgToolCalls", performance.now() - start, "success");
|
|
415
|
+
return result;
|
|
416
|
+
} catch (err) {
|
|
417
|
+
recordDuration("getOrgToolCalls", performance.now() - start, "error");
|
|
418
|
+
throw err;
|
|
419
|
+
}
|
|
309
420
|
}
|
|
310
421
|
async function getAgentToolCalls(agentPubkey, maxCount, opts) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
422
|
+
const start = performance.now();
|
|
423
|
+
recordCall("getAgentToolCalls", void 0, agentPubkey);
|
|
424
|
+
try {
|
|
425
|
+
const result = await getJson(
|
|
426
|
+
riskEngineUrl(
|
|
427
|
+
"agent-tool-calls",
|
|
428
|
+
{ agent: agentPubkey, limit: String(maxCount) },
|
|
429
|
+
opts
|
|
430
|
+
),
|
|
315
431
|
opts
|
|
316
|
-
)
|
|
317
|
-
|
|
318
|
-
|
|
432
|
+
);
|
|
433
|
+
recordDuration("getAgentToolCalls", performance.now() - start, "success");
|
|
434
|
+
return result;
|
|
435
|
+
} catch (err) {
|
|
436
|
+
recordDuration("getAgentToolCalls", performance.now() - start, "error");
|
|
437
|
+
throw err;
|
|
438
|
+
}
|
|
319
439
|
}
|
|
320
440
|
async function getToolCallCount(opts) {
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
441
|
+
const start = performance.now();
|
|
442
|
+
recordCall("getToolCallCount");
|
|
443
|
+
try {
|
|
444
|
+
const result = await getJson(
|
|
445
|
+
riskEngineUrl("tool-call-count", {}, opts),
|
|
446
|
+
opts
|
|
447
|
+
);
|
|
448
|
+
recordDuration("getToolCallCount", performance.now() - start, "success");
|
|
449
|
+
return typeof result === "number" ? result : Number(result ?? 0);
|
|
450
|
+
} catch (err) {
|
|
451
|
+
recordDuration("getToolCallCount", performance.now() - start, "error");
|
|
452
|
+
throw err;
|
|
453
|
+
}
|
|
326
454
|
}
|
|
327
455
|
async function getToolCallFull(toolCallId, opts) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
456
|
+
const start = performance.now();
|
|
457
|
+
recordCall("getToolCallFull");
|
|
458
|
+
try {
|
|
459
|
+
const result = await getJson(
|
|
460
|
+
riskEngineUrl("tool-call-full", { tool_call_id: toolCallId }, opts),
|
|
461
|
+
opts
|
|
462
|
+
);
|
|
463
|
+
recordDuration("getToolCallFull", performance.now() - start, "success");
|
|
464
|
+
return result;
|
|
465
|
+
} catch (err) {
|
|
466
|
+
recordDuration("getToolCallFull", performance.now() - start, "error");
|
|
467
|
+
throw err;
|
|
468
|
+
}
|
|
332
469
|
}
|
|
333
470
|
async function getOrgTierInfo(orgName, opts) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
471
|
+
const start = performance.now();
|
|
472
|
+
recordCall("getOrgTierInfo");
|
|
473
|
+
try {
|
|
474
|
+
const result = await getJson(
|
|
475
|
+
riskEngineUrl("org-tier-info", { org: orgName }, opts),
|
|
476
|
+
opts
|
|
477
|
+
);
|
|
478
|
+
recordDuration("getOrgTierInfo", performance.now() - start, "success");
|
|
479
|
+
return result;
|
|
480
|
+
} catch (err) {
|
|
481
|
+
recordDuration("getOrgTierInfo", performance.now() - start, "error");
|
|
482
|
+
throw err;
|
|
483
|
+
}
|
|
338
484
|
}
|
|
339
485
|
async function getPendingHeldActions(orgName, maxCount, opts) {
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
486
|
+
const start = performance.now();
|
|
487
|
+
recordCall("getPendingHeldActions");
|
|
488
|
+
try {
|
|
489
|
+
const raw = await getJson(
|
|
490
|
+
riskEngineUrl(
|
|
491
|
+
"pending-held-actions",
|
|
492
|
+
{ org: orgName, limit: String(maxCount) },
|
|
493
|
+
opts
|
|
494
|
+
),
|
|
344
495
|
opts
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
496
|
+
);
|
|
497
|
+
recordDuration("getPendingHeldActions", performance.now() - start, "success");
|
|
498
|
+
return raw.map((h) => ({ ...h, verdict: normalizeVerdict(h.verdict) }));
|
|
499
|
+
} catch (err) {
|
|
500
|
+
recordDuration("getPendingHeldActions", performance.now() - start, "error");
|
|
501
|
+
throw err;
|
|
502
|
+
}
|
|
349
503
|
}
|
|
350
504
|
async function getHeldActionReviews(orgName, maxCount, opts) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
505
|
+
const start = performance.now();
|
|
506
|
+
recordCall("getHeldActionReviews");
|
|
507
|
+
try {
|
|
508
|
+
const result = await getJson(
|
|
509
|
+
riskEngineUrl(
|
|
510
|
+
"held-action-reviews",
|
|
511
|
+
{ org: orgName, limit: String(maxCount) },
|
|
512
|
+
opts
|
|
513
|
+
),
|
|
355
514
|
opts
|
|
356
|
-
)
|
|
357
|
-
|
|
358
|
-
|
|
515
|
+
);
|
|
516
|
+
recordDuration("getHeldActionReviews", performance.now() - start, "success");
|
|
517
|
+
return result;
|
|
518
|
+
} catch (err) {
|
|
519
|
+
recordDuration("getHeldActionReviews", performance.now() - start, "error");
|
|
520
|
+
throw err;
|
|
521
|
+
}
|
|
359
522
|
}
|
|
360
523
|
function riskEnginePostUrl(opts) {
|
|
361
524
|
return `${baseUrl(opts)}/api/risk-engine`;
|
|
362
525
|
}
|
|
363
526
|
async function getAgentDetail(agentPubkey, opts) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
527
|
+
const start = performance.now();
|
|
528
|
+
recordCall("getAgentDetail", void 0, agentPubkey);
|
|
529
|
+
try {
|
|
530
|
+
const result = await postJson(
|
|
531
|
+
riskEnginePostUrl(opts),
|
|
532
|
+
{ action: "agent-detail-batch", agent: agentPubkey },
|
|
533
|
+
opts
|
|
534
|
+
);
|
|
535
|
+
recordDuration("getAgentDetail", performance.now() - start, "success");
|
|
536
|
+
return result;
|
|
537
|
+
} catch (err) {
|
|
538
|
+
recordDuration("getAgentDetail", performance.now() - start, "error");
|
|
539
|
+
throw err;
|
|
540
|
+
}
|
|
372
541
|
}
|
|
373
542
|
async function getAgentPolicy(agentPubkey, opts) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
543
|
+
const start = performance.now();
|
|
544
|
+
recordCall("getAgentPolicy", void 0, agentPubkey);
|
|
545
|
+
try {
|
|
546
|
+
const result = await postJson(
|
|
547
|
+
riskEnginePostUrl(opts),
|
|
548
|
+
{ action: "agent-policy-batch", agent: agentPubkey },
|
|
549
|
+
opts
|
|
550
|
+
);
|
|
551
|
+
recordDuration("getAgentPolicy", performance.now() - start, "success");
|
|
552
|
+
return result;
|
|
553
|
+
} catch (err) {
|
|
554
|
+
recordDuration("getAgentPolicy", performance.now() - start, "error");
|
|
555
|
+
throw err;
|
|
556
|
+
}
|
|
382
557
|
}
|
|
383
558
|
async function getSafetyStats(opts) {
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
559
|
+
const start = performance.now();
|
|
560
|
+
recordCall("getSafetyStats");
|
|
561
|
+
try {
|
|
562
|
+
const url = `${baseUrl(opts)}/api/insurance?action=safety-stats`;
|
|
563
|
+
const result = await getJson(url, opts);
|
|
564
|
+
recordDuration("getSafetyStats", performance.now() - start, "success");
|
|
565
|
+
return result?.data || result;
|
|
566
|
+
} catch (err) {
|
|
567
|
+
recordDuration("getSafetyStats", performance.now() - start, "error");
|
|
568
|
+
throw err;
|
|
569
|
+
}
|
|
387
570
|
}
|
|
388
571
|
|
|
389
572
|
// src/config.ts
|
|
@@ -751,6 +934,8 @@ export {
|
|
|
751
934
|
resolve,
|
|
752
935
|
resolveKeyPath,
|
|
753
936
|
saveUserConfig,
|
|
937
|
+
setupTelemetry,
|
|
938
|
+
shutdownTelemetry,
|
|
754
939
|
toPubkeyHex,
|
|
755
940
|
validateJudgeEndpoint,
|
|
756
941
|
verifyJudgeResponseSignature
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atbash/sdk",
|
|
3
|
-
"version": "0.3.9-dev.
|
|
3
|
+
"version": "0.3.9-dev.4",
|
|
4
4
|
"description": "Atbash SDK — control boundary before the last irreversible step in an agent workflow",
|
|
5
5
|
"homepage": "https://atbash.ai",
|
|
6
6
|
"author": "Atbash",
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
"ai-safety"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
+
"@opentelemetry/api": "^1.9.1",
|
|
45
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.217.0",
|
|
46
|
+
"@opentelemetry/resources": "^2.7.1",
|
|
47
|
+
"@opentelemetry/sdk-metrics": "^2.7.1",
|
|
44
48
|
"postchain-client": "^2.1.5"
|
|
45
49
|
}
|
|
46
50
|
}
|