@atbash/sdk 0.1.2

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/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Atbash CLI — Proprietary Software License
2
+
3
+ Copyright (c) 2026 Atbash,
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ The views and conclusions contained in the software and documentation are those
27
+ of the authors and should not be interpreted as representing official policies,
28
+ either expressed or implied, Atbash.
package/README.md ADDED
@@ -0,0 +1,296 @@
1
+ # @atbash/sdk
2
+
3
+ TypeScript SDK for the Atbash judge and risk-engine APIs. Evaluate agent actions against operator-defined policy before execution — programmatically, from any Node.js backend.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @atbash/sdk
9
+ ```
10
+
11
+ Requires Node.js 18 or higher. Server-side only — private keys are sent in request bodies and must never be exposed to browsers.
12
+
13
+ ## Quickstart
14
+
15
+ ```ts
16
+ import { createAgent, judgeAction } from "@atbash/sdk";
17
+
18
+ // 1. Load your agent identity — paste the private key from the Atbash
19
+ // dashboard (https://atbash.ai/risk-engine/agents). createAgent()
20
+ // validates the key and derives the matching public key for you.
21
+ const agent = createAgent(process.env.ATBASH_AGENT_PRIVKEY!);
22
+
23
+ // 2. Submit an action for judgment, before executing it
24
+ const result = await judgeAction(
25
+ "Transfer $50,000 to external wallet 0xabc",
26
+ "Outbound AML check — new recipient, over threshold",
27
+ agent,
28
+ );
29
+
30
+ // 3. Enforce the verdict
31
+ switch (result.verdict) {
32
+ case "ALLOW":
33
+ // Proceed with the action
34
+ break;
35
+ case "HOLD":
36
+ // Held — operator must approve in the dashboard
37
+ console.log("Held for review:", result.tool_call_id);
38
+ break;
39
+ case "BLOCK":
40
+ // Refused — agent is jailed in Enforcement tier
41
+ throw new Error(`Blocked: ${result.reason}`);
42
+ }
43
+ ```
44
+
45
+ Before this works, the agent must be onboarded at [atbash.ai](https://atbash.ai/) — assigned to an org, with a policy pack attached, and the org tier set to Audit+ or Enforcement.
46
+
47
+ ### Don't have an agent yet?
48
+
49
+ Generate one programmatically for local development:
50
+
51
+ ```ts
52
+ import { generateKeyPair, createAgent } from "@atbash/sdk";
53
+
54
+ const { privKey } = generateKeyPair();
55
+ console.log("Save this private key somewhere safe:", privKey);
56
+ const agent = createAgent(privKey);
57
+ ```
58
+
59
+ For production, always create agents in the dashboard so operators can attach policy packs and manage tier / jail state.
60
+
61
+ ### Secret storage
62
+
63
+ The private key authenticates every call. Treat it like any other long-lived credential:
64
+
65
+ - Load it from an environment variable (`ATBASH_AGENT_PRIVKEY`) or a secret manager (AWS Secrets Manager, HashiCorp Vault, 1Password, etc.) — never hardcode it.
66
+ - Never commit `.env` files containing the key. Add them to `.gitignore`.
67
+ - If a key leaks, revoke the agent and create a new one in the [Atbash dashboard](https://atbash.ai/risk-engine/agents).
68
+ - The SDK is **server-side only** — the key must never ship to a browser bundle.
69
+
70
+ ## Verdicts
71
+
72
+ Every `judgeAction` call returns one of three verdicts:
73
+
74
+ | Verdict | Meaning | What your code should do |
75
+ |---------|---------|-------------------------|
76
+ | `ALLOW` | Action is within policy | Proceed with execution |
77
+ | `HOLD` | Requires operator review | Pause — poll `getJudgmentStatus` until resolved |
78
+ | `BLOCK` | Violates a red line | Abort — agent is jailed in Enforcement tier |
79
+
80
+ ## API
81
+
82
+ ### Judge
83
+
84
+ ```ts
85
+ judgeAction(
86
+ action: string,
87
+ context: string,
88
+ auth: AgentAuth,
89
+ opts?: JudgeOptions,
90
+ ): Promise<JudgeResult>
91
+ ```
92
+
93
+ Submit an action for judgment before execution. Returns the verdict, reason, confidence, provider, latency, and tool call ID.
94
+
95
+ ```ts
96
+ interface AgentAuth {
97
+ pubkey: string; // 66-char hex, secp256k1 compressed public key
98
+ privkey: string; // 64-char hex private key
99
+ }
100
+
101
+ interface JudgeOptions {
102
+ endpoint?: string; // API base URL (default: https://atbash.ai)
103
+ timeout?: number; // Request timeout in ms
104
+ provider?: string; // "atbash" | "openai" | "google" | "microsoft" | "custom"
105
+ apiKey?: string; // API key for non-atbash providers
106
+ providerEndpoint?: string; // Endpoint for microsoft/custom providers
107
+ model?: string; // Model override (e.g. "gpt-4o-mini")
108
+ toolName?: string; // Tool name for audit trail
109
+ toolArgsJson?: string; // Tool arguments JSON for audit trail
110
+ }
111
+
112
+ interface JudgeResult {
113
+ verdict: string; // "ALLOW", "HOLD", or "BLOCK"
114
+ action_type: string; // "allow", "hold_for_user_confirm", or "block"
115
+ reason: string; // Human-readable explanation
116
+ confidence: number; // 0–1
117
+ provider: string; // Which provider evaluated the action
118
+ latency_ms: number; // Inference time
119
+ tool_call_id: string; // Unique ID for this judgment
120
+ on_chain: boolean; // Whether the record was written on-chain
121
+ }
122
+ ```
123
+
124
+ ### Poll judgment status
125
+
126
+ ```ts
127
+ getJudgmentStatus(judgmentId: string, opts?: ClientOpts): Promise<JudgmentStatus>
128
+ ```
129
+
130
+ Check whether a held action has been approved or rejected by an operator.
131
+
132
+ ```ts
133
+ interface JudgmentStatus {
134
+ status: "pending" | "answered" | "error";
135
+ verdict: string;
136
+ reason: string;
137
+ judgmentId: string;
138
+ onChain?: boolean;
139
+ cached?: boolean;
140
+ responseTimeMs?: number;
141
+ }
142
+ ```
143
+
144
+ ### Agent identity
145
+
146
+ ```ts
147
+ createAgent(privkey: string): AgentAuth
148
+ generateKeyPair(): { privKey: string; pubKey: string }
149
+ derivePublicKey(privKeyHex: string): string
150
+ isValidPrivateKey(hex: string): boolean
151
+ toPubkeyHex(val: unknown): string
152
+ ```
153
+
154
+ `createAgent(privkey)` is the canonical loader — pass in the private key from the dashboard, get back `{ pubkey, privkey }` ready for `judgeAction`. It accepts `0x`-prefixed, padded, or mixed-case input and throws on malformed keys. Use `generateKeyPair()` only for local development; for production, create agents in the dashboard so operators can attach policies.
155
+
156
+ ### Query APIs
157
+
158
+ Read from the Atbash audit trail and operator queues:
159
+
160
+ ```ts
161
+ // Tool call history
162
+ getToolCalls(maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>
163
+ getOrgToolCalls(orgName: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>
164
+ getAgentToolCalls(agentPubkey: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>
165
+ getToolCallCount(opts?: ClientOpts): Promise<number>
166
+ getToolCallFull(toolCallId: string, opts?: ClientOpts): Promise<ToolCallFull | null>
167
+
168
+ // Org and agent info
169
+ getOrgTierInfo(orgName: string, opts?: ClientOpts): Promise<TierInfo | null>
170
+ getAgentDetail(agentPubkey: string, opts?: ClientOpts): Promise<Record<string, unknown>>
171
+ getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<{ policy: string; is_jailed: boolean; is_custom: boolean; default_policy: string }>
172
+
173
+ // Operator review queue
174
+ getPendingHeldActions(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldAction[]>
175
+ getHeldActionReviews(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldActionReview[]>
176
+
177
+ // Chain-wide stats
178
+ getSafetyStats(opts?: ClientOpts): Promise<Record<string, unknown>>
179
+ ```
180
+
181
+ All query functions accept an optional `ClientOpts` to override the endpoint:
182
+
183
+ ```ts
184
+ interface ClientOpts {
185
+ endpoint?: string; // Default: https://atbash.ai
186
+ timeout?: number;
187
+ }
188
+ ```
189
+
190
+ ## Configuration
191
+
192
+ The SDK reads no environment variables and has no global state. Pass configuration explicitly:
193
+
194
+ ```ts
195
+ // Custom endpoint
196
+ const result = await judgeAction(action, context, auth, {
197
+ endpoint: "https://your-instance.example.com",
198
+ });
199
+
200
+ // Custom provider
201
+ const result = await judgeAction(action, context, auth, {
202
+ provider: "openai",
203
+ apiKey: process.env.OPENAI_API_KEY,
204
+ model: "gpt-4o",
205
+ });
206
+ ```
207
+
208
+ ## Integration patterns
209
+
210
+ ### Pre-execution gate
211
+
212
+ ```ts
213
+ async function safeExecute(action: string, context: string, execute: () => Promise<void>) {
214
+ const result = await judgeAction(action, context, auth);
215
+ if (result.verdict === "BLOCK") throw new Error(`Blocked: ${result.reason}`);
216
+ if (result.verdict === "HOLD") throw new Error(`Held for review: ${result.tool_call_id}`);
217
+ await execute();
218
+ }
219
+ ```
220
+
221
+ ### Polling a held action
222
+
223
+ ```ts
224
+ async function waitForApproval(toolCallId: string): Promise<string> {
225
+ while (true) {
226
+ const status = await getJudgmentStatus(toolCallId);
227
+ if (status.status === "answered") return status.verdict;
228
+ if (status.status === "error") throw new Error(status.reason);
229
+ await new Promise((r) => setTimeout(r, 5000));
230
+ }
231
+ }
232
+ ```
233
+
234
+ ### Checking agent jail status before a batch
235
+
236
+ ```ts
237
+ const policy = await getAgentPolicy(pubKey);
238
+ if (policy.is_jailed) {
239
+ console.error("Agent is jailed — unjail via dashboard before retrying.");
240
+ process.exit(1);
241
+ }
242
+ ```
243
+
244
+ ## Error handling
245
+
246
+ The SDK throws standard `Error` objects. Known failure modes are enriched with a pointer to the relevant dashboard page, so the error message tells you where to fix the problem:
247
+
248
+ ```
249
+ API error 404: {"error":"Agent not registered..."}
250
+ → Onboard the agent at https://atbash.ai/risk-engine/agents
251
+ ```
252
+
253
+ | Error | Cause | Where to fix |
254
+ |---|---|---|
255
+ | `API error 404: Agent not registered` | Agent not onboarded | [atbash.ai/risk-engine/agents](https://atbash.ai/risk-engine/agents) |
256
+ | `API error 400: Agent has no policy` | No policy attached to agent | [atbash.ai/risk-engine/agents](https://atbash.ai/risk-engine/agents) |
257
+ | `Agent is jailed` | BLOCK verdict triggered auto-jail (Enforcement tier) | [atbash.ai/risk-engine/agents](https://atbash.ai/risk-engine/agents) |
258
+ | `Org tier does not support verdicts` | Org is on Audit tier | [atbash.ai/risk-engine/settings](https://atbash.ai/risk-engine/settings) |
259
+ | `API error 400: action is required` | Empty action string | Fix caller |
260
+ | `API error 502: Incorrect API key` | Invalid provider API key | Check `apiKey` in `JudgeOptions` |
261
+
262
+ ```ts
263
+ try {
264
+ const result = await judgeAction(action, context, auth);
265
+ } catch (err) {
266
+ if (err.message.includes("Agent not registered")) {
267
+ // Point the user at https://atbash.ai/risk-engine/agents to onboard.
268
+ }
269
+ }
270
+ ```
271
+
272
+ ## SDK vs CLI
273
+
274
+ | | `@atbash/sdk` | `@atbash/cli` |
275
+ |---|---|---|
276
+ | Use case | Backend services, agents, pipelines | Terminal, operator review, interactive use |
277
+ | Programmatic control | Full | Shell commands |
278
+ | Install | `npm install @atbash/sdk` | `npm install -g @atbash/cli` |
279
+ | Policy authoring | No (dashboard only) | No (dashboard only) |
280
+
281
+ The CLI is built on top of the SDK. Both talk to the same APIs, the same policy engine, and the same on-chain audit trail.
282
+
283
+ ## Design
284
+
285
+ - **Zero runtime dependencies** — uses only `node:crypto` and global `fetch`
286
+ - **TypeScript-first** — full type definitions for all inputs and outputs
287
+ - **No global state** — every function takes explicit arguments
288
+ - **No browser support** — private keys in request bodies are not safe for client-side use
289
+
290
+ ## Dashboard
291
+
292
+ Policy authoring, operator reviews, and agent management happen at [atbash.ai](https://atbash.ai/). The SDK is the programmatic interface; the dashboard is the operator interface.
293
+
294
+ ## License
295
+
296
+ Proprietary — all rights reserved. See [LICENSE](./LICENSE).
package/dist/index.cjs ADDED
@@ -0,0 +1,309 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_ENDPOINT: () => DEFAULT_ENDPOINT,
24
+ createAgent: () => createAgent,
25
+ derivePublicKey: () => derivePublicKey,
26
+ generateKeyPair: () => generateKeyPair,
27
+ getAgentDetail: () => getAgentDetail,
28
+ getAgentPolicy: () => getAgentPolicy,
29
+ getAgentToolCalls: () => getAgentToolCalls,
30
+ getHeldActionReviews: () => getHeldActionReviews,
31
+ getJudgmentStatus: () => getJudgmentStatus,
32
+ getOrgTierInfo: () => getOrgTierInfo,
33
+ getOrgToolCalls: () => getOrgToolCalls,
34
+ getPendingHeldActions: () => getPendingHeldActions,
35
+ getSafetyStats: () => getSafetyStats,
36
+ getToolCallCount: () => getToolCallCount,
37
+ getToolCallFull: () => getToolCallFull,
38
+ getToolCalls: () => getToolCalls,
39
+ isValidPrivateKey: () => isValidPrivateKey,
40
+ judgeAction: () => judgeAction,
41
+ toPubkeyHex: () => toPubkeyHex
42
+ });
43
+ module.exports = __toCommonJS(index_exports);
44
+
45
+ // src/client.ts
46
+ var import_crypto = require("crypto");
47
+ var DEFAULT_ENDPOINT = "https://atbash.ai";
48
+ function isValidPrivateKey(hex) {
49
+ return /^[0-9a-fA-F]{64}$/.test(hex);
50
+ }
51
+ function derivePublicKey(privKeyHex) {
52
+ const ecdh = (0, import_crypto.createECDH)("secp256k1");
53
+ ecdh.setPrivateKey(Buffer.from(privKeyHex, "hex"));
54
+ return ecdh.getPublicKey("hex", "compressed");
55
+ }
56
+ function generateKeyPair() {
57
+ const ecdh = (0, import_crypto.createECDH)("secp256k1");
58
+ ecdh.generateKeys();
59
+ return {
60
+ privKey: ecdh.getPrivateKey("hex"),
61
+ pubKey: ecdh.getPublicKey("hex", "compressed")
62
+ };
63
+ }
64
+ function createAgent(privkey) {
65
+ const clean = privkey.replace(/^0x/, "").trim().toLowerCase();
66
+ if (!isValidPrivateKey(clean)) {
67
+ throw new Error(
68
+ "Invalid private key \u2014 must be 64 hex characters (secp256k1)."
69
+ );
70
+ }
71
+ return { privkey: clean, pubkey: derivePublicKey(clean) };
72
+ }
73
+ function hasDataArray(val) {
74
+ return typeof val === "object" && val !== null && "data" in val && Array.isArray(val.data);
75
+ }
76
+ function toPubkeyHex(val) {
77
+ if (!val) return "";
78
+ if (typeof val === "string") return val;
79
+ if (Buffer.isBuffer(val)) return val.toString("hex");
80
+ if (hasDataArray(val)) return Buffer.from(val.data).toString("hex");
81
+ return "";
82
+ }
83
+ function baseUrl(opts) {
84
+ return opts?.endpoint || DEFAULT_ENDPOINT;
85
+ }
86
+ function normalizeVerdict(raw) {
87
+ const v = String(raw || "").toUpperCase();
88
+ if (v === "ALLOW" || v === "GREEN") return "ALLOW";
89
+ if (v === "HOLD" || v === "YELLOW") return "HOLD";
90
+ if (v === "BLOCK" || v === "RED") return "BLOCK";
91
+ return "BLOCK";
92
+ }
93
+ function normalizeStatus(raw) {
94
+ const s = String(raw || "").toLowerCase();
95
+ if (s === "pending" || s === "answered" || s === "error") return s;
96
+ return "error";
97
+ }
98
+ function enrichError(status, body, statusText, opts) {
99
+ const dashboard = (opts?.endpoint || DEFAULT_ENDPOINT).replace(/\/$/, "");
100
+ let message = `API error ${status}: ${body || statusText}`;
101
+ if (/Agent not registered/i.test(body)) {
102
+ message += `
103
+ \u2192 Onboard the agent at ${dashboard}/risk-engine/agents`;
104
+ } else if (/Agent has no policy|no policy configured/i.test(body)) {
105
+ message += `
106
+ \u2192 Attach a policy at ${dashboard}/risk-engine/agents`;
107
+ } else if (/Agent is jailed|agent.*jailed/i.test(body)) {
108
+ message += `
109
+ \u2192 Unjail the agent at ${dashboard}/risk-engine/agents`;
110
+ } else if (/audit tier|verdict.*(disabled|not supported)/i.test(body)) {
111
+ message += `
112
+ \u2192 Upgrade the org tier at ${dashboard}/risk-engine/settings`;
113
+ } else if (status >= 400 && status < 500) {
114
+ message += `
115
+ \u2192 Dashboard: ${dashboard}/risk-engine/feed`;
116
+ }
117
+ return new Error(message);
118
+ }
119
+ async function postJson(url, body, opts) {
120
+ const resp = await fetch(url, {
121
+ method: "POST",
122
+ headers: { "Content-Type": "application/json" },
123
+ body: JSON.stringify(body),
124
+ signal: opts?.timeout ? AbortSignal.timeout(opts.timeout) : void 0
125
+ });
126
+ if (!resp.ok) {
127
+ const text = await resp.text().catch(() => "");
128
+ throw enrichError(resp.status, text, resp.statusText, opts);
129
+ }
130
+ const ct = resp.headers.get("content-type") || "";
131
+ return ct.includes("application/json") ? resp.json() : {};
132
+ }
133
+ async function getJson(url, opts) {
134
+ const resp = await fetch(url, {
135
+ method: "GET",
136
+ signal: opts?.timeout ? AbortSignal.timeout(opts.timeout) : void 0
137
+ });
138
+ if (!resp.ok) {
139
+ const text = await resp.text().catch(() => "");
140
+ throw enrichError(resp.status, text, resp.statusText, opts);
141
+ }
142
+ return resp.json();
143
+ }
144
+ async function judgeAction(action, context, auth, opts) {
145
+ const url = `${baseUrl(opts)}/api/v1/judge`;
146
+ const data = await postJson(
147
+ url,
148
+ {
149
+ provider: opts?.provider || "",
150
+ action,
151
+ context: context || "",
152
+ agent_pubkey: auth.pubkey,
153
+ agent_privkey: auth.privkey,
154
+ tool_name: opts?.toolName || "",
155
+ tool_args_json: opts?.toolArgsJson || "",
156
+ api_key: opts?.apiKey || "",
157
+ endpoint_url: opts?.providerEndpoint || "",
158
+ model: opts?.model || ""
159
+ },
160
+ opts
161
+ );
162
+ return {
163
+ verdict: normalizeVerdict(data.verdict),
164
+ action_type: String(data.action_type || ""),
165
+ reason: String(data.reason || ""),
166
+ confidence: Number(data.confidence ?? 0),
167
+ provider: String(data.provider || ""),
168
+ latency_ms: Number(data.latency_ms ?? 0),
169
+ tool_call_id: String(data.tool_call_id || ""),
170
+ on_chain: Boolean(data.on_chain)
171
+ };
172
+ }
173
+ async function getJudgmentStatus(judgmentId, opts) {
174
+ const url = `${baseUrl(opts)}/api/v1/judge?tool_call_id=${encodeURIComponent(judgmentId)}`;
175
+ const data = await getJson(url, opts);
176
+ return {
177
+ status: normalizeStatus(data.status),
178
+ verdict: normalizeVerdict(data.verdict),
179
+ reason: String(data.reason || ""),
180
+ judgmentId: String(data.judgmentId || judgmentId),
181
+ onChain: Boolean(data.onChain),
182
+ cached: Boolean(data.cached),
183
+ responseTimeMs: Number(data.responseTimeMs ?? 0)
184
+ };
185
+ }
186
+ function riskEngineUrl(action, params, opts) {
187
+ const url = new URL(`${baseUrl(opts)}/api/risk-engine`);
188
+ url.searchParams.set("action", action);
189
+ for (const [k, v] of Object.entries(params)) {
190
+ if (v) url.searchParams.set(k, v);
191
+ }
192
+ return url.toString();
193
+ }
194
+ async function getToolCalls(maxCount, opts) {
195
+ return getJson(
196
+ riskEngineUrl("tool-calls", { limit: String(maxCount) }, opts),
197
+ opts
198
+ );
199
+ }
200
+ async function getOrgToolCalls(orgName, maxCount, opts) {
201
+ return getJson(
202
+ riskEngineUrl(
203
+ "org-tool-calls",
204
+ { org: orgName, limit: String(maxCount) },
205
+ opts
206
+ ),
207
+ opts
208
+ );
209
+ }
210
+ async function getAgentToolCalls(agentPubkey, maxCount, opts) {
211
+ return getJson(
212
+ riskEngineUrl(
213
+ "agent-tool-calls",
214
+ { agent: agentPubkey, limit: String(maxCount) },
215
+ opts
216
+ ),
217
+ opts
218
+ );
219
+ }
220
+ async function getToolCallCount(opts) {
221
+ const result = await getJson(
222
+ riskEngineUrl("tool-call-count", {}, opts),
223
+ opts
224
+ );
225
+ return typeof result === "number" ? result : Number(result ?? 0);
226
+ }
227
+ async function getToolCallFull(toolCallId, opts) {
228
+ return getJson(
229
+ riskEngineUrl("tool-call-full", { tool_call_id: toolCallId }, opts),
230
+ opts
231
+ );
232
+ }
233
+ async function getOrgTierInfo(orgName, opts) {
234
+ return getJson(
235
+ riskEngineUrl("org-tier-info", { org: orgName }, opts),
236
+ opts
237
+ );
238
+ }
239
+ async function getPendingHeldActions(orgName, maxCount, opts) {
240
+ const raw = await getJson(
241
+ riskEngineUrl(
242
+ "pending-held-actions",
243
+ { org: orgName, limit: String(maxCount) },
244
+ opts
245
+ ),
246
+ opts
247
+ );
248
+ return raw.map((h) => ({ ...h, verdict: normalizeVerdict(h.verdict) }));
249
+ }
250
+ async function getHeldActionReviews(orgName, maxCount, opts) {
251
+ return getJson(
252
+ riskEngineUrl(
253
+ "held-action-reviews",
254
+ { org: orgName, limit: String(maxCount) },
255
+ opts
256
+ ),
257
+ opts
258
+ );
259
+ }
260
+ function riskEnginePostUrl(opts) {
261
+ return `${baseUrl(opts)}/api/risk-engine`;
262
+ }
263
+ async function getAgentDetail(agentPubkey, opts) {
264
+ return postJson(
265
+ riskEnginePostUrl(opts),
266
+ {
267
+ action: "agent-detail-batch",
268
+ agent: agentPubkey
269
+ },
270
+ opts
271
+ );
272
+ }
273
+ async function getAgentPolicy(agentPubkey, opts) {
274
+ return postJson(
275
+ riskEnginePostUrl(opts),
276
+ {
277
+ action: "agent-policy-batch",
278
+ agent: agentPubkey
279
+ },
280
+ opts
281
+ );
282
+ }
283
+ async function getSafetyStats(opts) {
284
+ const url = `${baseUrl(opts)}/api/insurance?action=safety-stats`;
285
+ const result = await getJson(url, opts);
286
+ return result?.data || result;
287
+ }
288
+ // Annotate the CommonJS export names for ESM import in node:
289
+ 0 && (module.exports = {
290
+ DEFAULT_ENDPOINT,
291
+ createAgent,
292
+ derivePublicKey,
293
+ generateKeyPair,
294
+ getAgentDetail,
295
+ getAgentPolicy,
296
+ getAgentToolCalls,
297
+ getHeldActionReviews,
298
+ getJudgmentStatus,
299
+ getOrgTierInfo,
300
+ getOrgToolCalls,
301
+ getPendingHeldActions,
302
+ getSafetyStats,
303
+ getToolCallCount,
304
+ getToolCallFull,
305
+ getToolCalls,
306
+ isValidPrivateKey,
307
+ judgeAction,
308
+ toPubkeyHex
309
+ });
@@ -0,0 +1,123 @@
1
+ declare const DEFAULT_ENDPOINT = "https://atbash.ai";
2
+ type Verdict = "ALLOW" | "HOLD" | "BLOCK";
3
+ type Provider = "atbash" | "openai" | "google" | "microsoft" | "custom" | (string & {});
4
+ type Tier = "audit" | "audit_plus" | "enforcement" | (string & {});
5
+ type ActionType = "allow" | "hold_for_user_confirm" | "block" | (string & {});
6
+ type PubkeyValue = string | Buffer | {
7
+ data: number[];
8
+ };
9
+ type JudgmentStatusState = "pending" | "answered" | "error";
10
+ declare function isValidPrivateKey(hex: string): boolean;
11
+ declare function derivePublicKey(privKeyHex: string): string;
12
+ declare function generateKeyPair(): {
13
+ privKey: string;
14
+ pubKey: string;
15
+ };
16
+ interface AgentAuth {
17
+ pubkey: string;
18
+ privkey: string;
19
+ }
20
+ declare function createAgent(privkey: string): AgentAuth;
21
+ declare function toPubkeyHex(val: unknown): string;
22
+ interface ClientOpts {
23
+ endpoint?: string;
24
+ timeout?: number;
25
+ }
26
+ interface JudgeResult {
27
+ verdict: Verdict;
28
+ action_type: ActionType;
29
+ reason: string;
30
+ confidence: number;
31
+ provider: Provider;
32
+ latency_ms: number;
33
+ tool_call_id: string;
34
+ on_chain: boolean;
35
+ }
36
+ interface TierInfo {
37
+ org_name: string;
38
+ tier: Tier;
39
+ verdict_enabled: boolean;
40
+ enforcement_enabled: boolean;
41
+ }
42
+ interface ToolCallRecord {
43
+ tool_call_id: string;
44
+ agent_pubkey: PubkeyValue;
45
+ tool_name: string;
46
+ command_text: string;
47
+ tool_args_json: string;
48
+ context_text: string;
49
+ org_name: string;
50
+ rowid: number;
51
+ }
52
+ interface ToolCallFull {
53
+ tool_call_id: string;
54
+ agent_pubkey: PubkeyValue;
55
+ tool_name: string;
56
+ command_text: string;
57
+ context_text: string;
58
+ tool_args_json?: string;
59
+ org_name: string;
60
+ created_at?: number;
61
+ action_type?: ActionType;
62
+ result_status?: string;
63
+ verdict_color?: string;
64
+ verdict_reason?: string;
65
+ verdict_source?: string;
66
+ verdict_response_time_ms?: number;
67
+ }
68
+ interface HeldAction {
69
+ judgment_id: string;
70
+ agent_pubkey: PubkeyValue;
71
+ action_text: string;
72
+ action_context: string;
73
+ verdict: Verdict;
74
+ reason: string;
75
+ created_at: number;
76
+ }
77
+ interface HeldActionReview {
78
+ judgment_id: string;
79
+ action_text: string;
80
+ status: string;
81
+ review_note: string;
82
+ reviewed_by: PubkeyValue | null;
83
+ reviewed_at: number;
84
+ created_at: number;
85
+ }
86
+ interface JudgmentStatus {
87
+ status: JudgmentStatusState;
88
+ verdict: Verdict;
89
+ reason: string;
90
+ judgmentId: string;
91
+ onChain?: boolean;
92
+ cached?: boolean;
93
+ responseTimeMs?: number;
94
+ }
95
+ interface JudgeOptions extends ClientOpts {
96
+ provider?: Provider;
97
+ apiKey?: string;
98
+ providerEndpoint?: string;
99
+ model?: string;
100
+ toolName?: string;
101
+ toolArgsJson?: string;
102
+ }
103
+ interface AgentPolicy {
104
+ policy: string;
105
+ is_jailed: boolean;
106
+ is_custom: boolean;
107
+ default_policy: string;
108
+ }
109
+ declare function judgeAction(action: string, context: string, auth: AgentAuth, opts?: JudgeOptions): Promise<JudgeResult>;
110
+ declare function getJudgmentStatus(judgmentId: string, opts?: ClientOpts): Promise<JudgmentStatus>;
111
+ declare function getToolCalls(maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
112
+ declare function getOrgToolCalls(orgName: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
113
+ declare function getAgentToolCalls(agentPubkey: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
114
+ declare function getToolCallCount(opts?: ClientOpts): Promise<number>;
115
+ declare function getToolCallFull(toolCallId: string, opts?: ClientOpts): Promise<ToolCallFull | null>;
116
+ declare function getOrgTierInfo(orgName: string, opts?: ClientOpts): Promise<TierInfo | null>;
117
+ declare function getPendingHeldActions(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldAction[]>;
118
+ declare function getHeldActionReviews(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldActionReview[]>;
119
+ declare function getAgentDetail(agentPubkey: string, opts?: ClientOpts): Promise<Record<string, unknown>>;
120
+ declare function getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<AgentPolicy>;
121
+ declare function getSafetyStats(opts?: ClientOpts): Promise<Record<string, unknown>>;
122
+
123
+ export { type AgentAuth, type ClientOpts, DEFAULT_ENDPOINT, type HeldAction, type HeldActionReview, type JudgeOptions, type JudgeResult, type JudgmentStatus, type TierInfo, type ToolCallFull, type ToolCallRecord, type Verdict, createAgent, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, toPubkeyHex };
@@ -0,0 +1,123 @@
1
+ declare const DEFAULT_ENDPOINT = "https://atbash.ai";
2
+ type Verdict = "ALLOW" | "HOLD" | "BLOCK";
3
+ type Provider = "atbash" | "openai" | "google" | "microsoft" | "custom" | (string & {});
4
+ type Tier = "audit" | "audit_plus" | "enforcement" | (string & {});
5
+ type ActionType = "allow" | "hold_for_user_confirm" | "block" | (string & {});
6
+ type PubkeyValue = string | Buffer | {
7
+ data: number[];
8
+ };
9
+ type JudgmentStatusState = "pending" | "answered" | "error";
10
+ declare function isValidPrivateKey(hex: string): boolean;
11
+ declare function derivePublicKey(privKeyHex: string): string;
12
+ declare function generateKeyPair(): {
13
+ privKey: string;
14
+ pubKey: string;
15
+ };
16
+ interface AgentAuth {
17
+ pubkey: string;
18
+ privkey: string;
19
+ }
20
+ declare function createAgent(privkey: string): AgentAuth;
21
+ declare function toPubkeyHex(val: unknown): string;
22
+ interface ClientOpts {
23
+ endpoint?: string;
24
+ timeout?: number;
25
+ }
26
+ interface JudgeResult {
27
+ verdict: Verdict;
28
+ action_type: ActionType;
29
+ reason: string;
30
+ confidence: number;
31
+ provider: Provider;
32
+ latency_ms: number;
33
+ tool_call_id: string;
34
+ on_chain: boolean;
35
+ }
36
+ interface TierInfo {
37
+ org_name: string;
38
+ tier: Tier;
39
+ verdict_enabled: boolean;
40
+ enforcement_enabled: boolean;
41
+ }
42
+ interface ToolCallRecord {
43
+ tool_call_id: string;
44
+ agent_pubkey: PubkeyValue;
45
+ tool_name: string;
46
+ command_text: string;
47
+ tool_args_json: string;
48
+ context_text: string;
49
+ org_name: string;
50
+ rowid: number;
51
+ }
52
+ interface ToolCallFull {
53
+ tool_call_id: string;
54
+ agent_pubkey: PubkeyValue;
55
+ tool_name: string;
56
+ command_text: string;
57
+ context_text: string;
58
+ tool_args_json?: string;
59
+ org_name: string;
60
+ created_at?: number;
61
+ action_type?: ActionType;
62
+ result_status?: string;
63
+ verdict_color?: string;
64
+ verdict_reason?: string;
65
+ verdict_source?: string;
66
+ verdict_response_time_ms?: number;
67
+ }
68
+ interface HeldAction {
69
+ judgment_id: string;
70
+ agent_pubkey: PubkeyValue;
71
+ action_text: string;
72
+ action_context: string;
73
+ verdict: Verdict;
74
+ reason: string;
75
+ created_at: number;
76
+ }
77
+ interface HeldActionReview {
78
+ judgment_id: string;
79
+ action_text: string;
80
+ status: string;
81
+ review_note: string;
82
+ reviewed_by: PubkeyValue | null;
83
+ reviewed_at: number;
84
+ created_at: number;
85
+ }
86
+ interface JudgmentStatus {
87
+ status: JudgmentStatusState;
88
+ verdict: Verdict;
89
+ reason: string;
90
+ judgmentId: string;
91
+ onChain?: boolean;
92
+ cached?: boolean;
93
+ responseTimeMs?: number;
94
+ }
95
+ interface JudgeOptions extends ClientOpts {
96
+ provider?: Provider;
97
+ apiKey?: string;
98
+ providerEndpoint?: string;
99
+ model?: string;
100
+ toolName?: string;
101
+ toolArgsJson?: string;
102
+ }
103
+ interface AgentPolicy {
104
+ policy: string;
105
+ is_jailed: boolean;
106
+ is_custom: boolean;
107
+ default_policy: string;
108
+ }
109
+ declare function judgeAction(action: string, context: string, auth: AgentAuth, opts?: JudgeOptions): Promise<JudgeResult>;
110
+ declare function getJudgmentStatus(judgmentId: string, opts?: ClientOpts): Promise<JudgmentStatus>;
111
+ declare function getToolCalls(maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
112
+ declare function getOrgToolCalls(orgName: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
113
+ declare function getAgentToolCalls(agentPubkey: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
114
+ declare function getToolCallCount(opts?: ClientOpts): Promise<number>;
115
+ declare function getToolCallFull(toolCallId: string, opts?: ClientOpts): Promise<ToolCallFull | null>;
116
+ declare function getOrgTierInfo(orgName: string, opts?: ClientOpts): Promise<TierInfo | null>;
117
+ declare function getPendingHeldActions(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldAction[]>;
118
+ declare function getHeldActionReviews(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldActionReview[]>;
119
+ declare function getAgentDetail(agentPubkey: string, opts?: ClientOpts): Promise<Record<string, unknown>>;
120
+ declare function getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<AgentPolicy>;
121
+ declare function getSafetyStats(opts?: ClientOpts): Promise<Record<string, unknown>>;
122
+
123
+ export { type AgentAuth, type ClientOpts, DEFAULT_ENDPOINT, type HeldAction, type HeldActionReview, type JudgeOptions, type JudgeResult, type JudgmentStatus, type TierInfo, type ToolCallFull, type ToolCallRecord, type Verdict, createAgent, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, toPubkeyHex };
package/dist/index.js ADDED
@@ -0,0 +1,264 @@
1
+ // src/client.ts
2
+ import { createECDH } from "crypto";
3
+ var DEFAULT_ENDPOINT = "https://atbash.ai";
4
+ function isValidPrivateKey(hex) {
5
+ return /^[0-9a-fA-F]{64}$/.test(hex);
6
+ }
7
+ function derivePublicKey(privKeyHex) {
8
+ const ecdh = createECDH("secp256k1");
9
+ ecdh.setPrivateKey(Buffer.from(privKeyHex, "hex"));
10
+ return ecdh.getPublicKey("hex", "compressed");
11
+ }
12
+ function generateKeyPair() {
13
+ const ecdh = createECDH("secp256k1");
14
+ ecdh.generateKeys();
15
+ return {
16
+ privKey: ecdh.getPrivateKey("hex"),
17
+ pubKey: ecdh.getPublicKey("hex", "compressed")
18
+ };
19
+ }
20
+ function createAgent(privkey) {
21
+ const clean = privkey.replace(/^0x/, "").trim().toLowerCase();
22
+ if (!isValidPrivateKey(clean)) {
23
+ throw new Error(
24
+ "Invalid private key \u2014 must be 64 hex characters (secp256k1)."
25
+ );
26
+ }
27
+ return { privkey: clean, pubkey: derivePublicKey(clean) };
28
+ }
29
+ function hasDataArray(val) {
30
+ return typeof val === "object" && val !== null && "data" in val && Array.isArray(val.data);
31
+ }
32
+ function toPubkeyHex(val) {
33
+ if (!val) return "";
34
+ if (typeof val === "string") return val;
35
+ if (Buffer.isBuffer(val)) return val.toString("hex");
36
+ if (hasDataArray(val)) return Buffer.from(val.data).toString("hex");
37
+ return "";
38
+ }
39
+ function baseUrl(opts) {
40
+ return opts?.endpoint || DEFAULT_ENDPOINT;
41
+ }
42
+ function normalizeVerdict(raw) {
43
+ const v = String(raw || "").toUpperCase();
44
+ if (v === "ALLOW" || v === "GREEN") return "ALLOW";
45
+ if (v === "HOLD" || v === "YELLOW") return "HOLD";
46
+ if (v === "BLOCK" || v === "RED") return "BLOCK";
47
+ return "BLOCK";
48
+ }
49
+ function normalizeStatus(raw) {
50
+ const s = String(raw || "").toLowerCase();
51
+ if (s === "pending" || s === "answered" || s === "error") return s;
52
+ return "error";
53
+ }
54
+ function enrichError(status, body, statusText, opts) {
55
+ const dashboard = (opts?.endpoint || DEFAULT_ENDPOINT).replace(/\/$/, "");
56
+ let message = `API error ${status}: ${body || statusText}`;
57
+ if (/Agent not registered/i.test(body)) {
58
+ message += `
59
+ \u2192 Onboard the agent at ${dashboard}/risk-engine/agents`;
60
+ } else if (/Agent has no policy|no policy configured/i.test(body)) {
61
+ message += `
62
+ \u2192 Attach a policy at ${dashboard}/risk-engine/agents`;
63
+ } else if (/Agent is jailed|agent.*jailed/i.test(body)) {
64
+ message += `
65
+ \u2192 Unjail the agent at ${dashboard}/risk-engine/agents`;
66
+ } else if (/audit tier|verdict.*(disabled|not supported)/i.test(body)) {
67
+ message += `
68
+ \u2192 Upgrade the org tier at ${dashboard}/risk-engine/settings`;
69
+ } else if (status >= 400 && status < 500) {
70
+ message += `
71
+ \u2192 Dashboard: ${dashboard}/risk-engine/feed`;
72
+ }
73
+ return new Error(message);
74
+ }
75
+ async function postJson(url, body, opts) {
76
+ const resp = await fetch(url, {
77
+ method: "POST",
78
+ headers: { "Content-Type": "application/json" },
79
+ body: JSON.stringify(body),
80
+ signal: opts?.timeout ? AbortSignal.timeout(opts.timeout) : void 0
81
+ });
82
+ if (!resp.ok) {
83
+ const text = await resp.text().catch(() => "");
84
+ throw enrichError(resp.status, text, resp.statusText, opts);
85
+ }
86
+ const ct = resp.headers.get("content-type") || "";
87
+ return ct.includes("application/json") ? resp.json() : {};
88
+ }
89
+ async function getJson(url, opts) {
90
+ const resp = await fetch(url, {
91
+ method: "GET",
92
+ signal: opts?.timeout ? AbortSignal.timeout(opts.timeout) : void 0
93
+ });
94
+ if (!resp.ok) {
95
+ const text = await resp.text().catch(() => "");
96
+ throw enrichError(resp.status, text, resp.statusText, opts);
97
+ }
98
+ return resp.json();
99
+ }
100
+ async function judgeAction(action, context, auth, opts) {
101
+ const url = `${baseUrl(opts)}/api/v1/judge`;
102
+ const data = await postJson(
103
+ url,
104
+ {
105
+ provider: opts?.provider || "",
106
+ action,
107
+ context: context || "",
108
+ agent_pubkey: auth.pubkey,
109
+ agent_privkey: auth.privkey,
110
+ tool_name: opts?.toolName || "",
111
+ tool_args_json: opts?.toolArgsJson || "",
112
+ api_key: opts?.apiKey || "",
113
+ endpoint_url: opts?.providerEndpoint || "",
114
+ model: opts?.model || ""
115
+ },
116
+ opts
117
+ );
118
+ return {
119
+ verdict: normalizeVerdict(data.verdict),
120
+ action_type: String(data.action_type || ""),
121
+ reason: String(data.reason || ""),
122
+ confidence: Number(data.confidence ?? 0),
123
+ provider: String(data.provider || ""),
124
+ latency_ms: Number(data.latency_ms ?? 0),
125
+ tool_call_id: String(data.tool_call_id || ""),
126
+ on_chain: Boolean(data.on_chain)
127
+ };
128
+ }
129
+ async function getJudgmentStatus(judgmentId, opts) {
130
+ const url = `${baseUrl(opts)}/api/v1/judge?tool_call_id=${encodeURIComponent(judgmentId)}`;
131
+ const data = await getJson(url, opts);
132
+ return {
133
+ status: normalizeStatus(data.status),
134
+ verdict: normalizeVerdict(data.verdict),
135
+ reason: String(data.reason || ""),
136
+ judgmentId: String(data.judgmentId || judgmentId),
137
+ onChain: Boolean(data.onChain),
138
+ cached: Boolean(data.cached),
139
+ responseTimeMs: Number(data.responseTimeMs ?? 0)
140
+ };
141
+ }
142
+ function riskEngineUrl(action, params, opts) {
143
+ const url = new URL(`${baseUrl(opts)}/api/risk-engine`);
144
+ url.searchParams.set("action", action);
145
+ for (const [k, v] of Object.entries(params)) {
146
+ if (v) url.searchParams.set(k, v);
147
+ }
148
+ return url.toString();
149
+ }
150
+ async function getToolCalls(maxCount, opts) {
151
+ return getJson(
152
+ riskEngineUrl("tool-calls", { limit: String(maxCount) }, opts),
153
+ opts
154
+ );
155
+ }
156
+ async function getOrgToolCalls(orgName, maxCount, opts) {
157
+ return getJson(
158
+ riskEngineUrl(
159
+ "org-tool-calls",
160
+ { org: orgName, limit: String(maxCount) },
161
+ opts
162
+ ),
163
+ opts
164
+ );
165
+ }
166
+ async function getAgentToolCalls(agentPubkey, maxCount, opts) {
167
+ return getJson(
168
+ riskEngineUrl(
169
+ "agent-tool-calls",
170
+ { agent: agentPubkey, limit: String(maxCount) },
171
+ opts
172
+ ),
173
+ opts
174
+ );
175
+ }
176
+ async function getToolCallCount(opts) {
177
+ const result = await getJson(
178
+ riskEngineUrl("tool-call-count", {}, opts),
179
+ opts
180
+ );
181
+ return typeof result === "number" ? result : Number(result ?? 0);
182
+ }
183
+ async function getToolCallFull(toolCallId, opts) {
184
+ return getJson(
185
+ riskEngineUrl("tool-call-full", { tool_call_id: toolCallId }, opts),
186
+ opts
187
+ );
188
+ }
189
+ async function getOrgTierInfo(orgName, opts) {
190
+ return getJson(
191
+ riskEngineUrl("org-tier-info", { org: orgName }, opts),
192
+ opts
193
+ );
194
+ }
195
+ async function getPendingHeldActions(orgName, maxCount, opts) {
196
+ const raw = await getJson(
197
+ riskEngineUrl(
198
+ "pending-held-actions",
199
+ { org: orgName, limit: String(maxCount) },
200
+ opts
201
+ ),
202
+ opts
203
+ );
204
+ return raw.map((h) => ({ ...h, verdict: normalizeVerdict(h.verdict) }));
205
+ }
206
+ async function getHeldActionReviews(orgName, maxCount, opts) {
207
+ return getJson(
208
+ riskEngineUrl(
209
+ "held-action-reviews",
210
+ { org: orgName, limit: String(maxCount) },
211
+ opts
212
+ ),
213
+ opts
214
+ );
215
+ }
216
+ function riskEnginePostUrl(opts) {
217
+ return `${baseUrl(opts)}/api/risk-engine`;
218
+ }
219
+ async function getAgentDetail(agentPubkey, opts) {
220
+ return postJson(
221
+ riskEnginePostUrl(opts),
222
+ {
223
+ action: "agent-detail-batch",
224
+ agent: agentPubkey
225
+ },
226
+ opts
227
+ );
228
+ }
229
+ async function getAgentPolicy(agentPubkey, opts) {
230
+ return postJson(
231
+ riskEnginePostUrl(opts),
232
+ {
233
+ action: "agent-policy-batch",
234
+ agent: agentPubkey
235
+ },
236
+ opts
237
+ );
238
+ }
239
+ async function getSafetyStats(opts) {
240
+ const url = `${baseUrl(opts)}/api/insurance?action=safety-stats`;
241
+ const result = await getJson(url, opts);
242
+ return result?.data || result;
243
+ }
244
+ export {
245
+ DEFAULT_ENDPOINT,
246
+ createAgent,
247
+ derivePublicKey,
248
+ generateKeyPair,
249
+ getAgentDetail,
250
+ getAgentPolicy,
251
+ getAgentToolCalls,
252
+ getHeldActionReviews,
253
+ getJudgmentStatus,
254
+ getOrgTierInfo,
255
+ getOrgToolCalls,
256
+ getPendingHeldActions,
257
+ getSafetyStats,
258
+ getToolCallCount,
259
+ getToolCallFull,
260
+ getToolCalls,
261
+ isValidPrivateKey,
262
+ judgeAction,
263
+ toPubkeyHex
264
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@atbash/sdk",
3
+ "version": "0.1.2",
4
+ "description": "TypeScript SDK for the Atbash risk-engine / judge API",
5
+ "homepage": "https://atbash.ai",
6
+ "author": "Atbash",
7
+ "license": "SEE LICENSE IN LICENSE",
8
+ "type": "module",
9
+ "main": "dist/index.cjs",
10
+ "module": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
29
+ "prepublishOnly": "npm run build",
30
+ "release": "npm version patch --no-git-tag-version && npm run build && npx npm@10 publish --access public"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^20.19.39",
34
+ "tsup": "^8.0.0",
35
+ "typescript": "^5.4.0"
36
+ },
37
+ "keywords": [
38
+ "atbash",
39
+ "risk-engine",
40
+ "agent-safety",
41
+ "ai-safety"
42
+ ]
43
+ }