@atbash/sdk 0.1.5 → 0.3.1
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/README.md +54 -16
- package/dist/index.cjs +72 -8
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +59 -8
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -8,19 +8,21 @@ TypeScript SDK for the Atbash judge and risk-engine APIs. Evaluate agent actions
|
|
|
8
8
|
npm install @atbash/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Requires Node.js 18 or higher. Server-side only — private keys are
|
|
11
|
+
Requires Node.js 18 or higher. Server-side only — private keys are used for local signing and must never be exposed to browsers.
|
|
12
12
|
|
|
13
13
|
## Quickstart
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
|
-
import {
|
|
16
|
+
import { loadAgent, judgeAction } from "@atbash/sdk";
|
|
17
17
|
|
|
18
18
|
// 1. Load your agent identity — paste the private key from the Atbash
|
|
19
|
-
// dashboard (https://atbash.ai/risk-engine/agents).
|
|
19
|
+
// dashboard (https://atbash.ai/risk-engine/agents). loadAgent()
|
|
20
20
|
// validates the key and derives the matching public key for you.
|
|
21
|
-
const agent =
|
|
21
|
+
const agent = loadAgent(process.env.ATBASH_AGENT_PRIVKEY!);
|
|
22
22
|
|
|
23
|
-
// 2. Submit an action for judgment, before executing it
|
|
23
|
+
// 2. Submit an action for judgment, before executing it.
|
|
24
|
+
// The SDK signs and broadcasts log_tool_call to the Chromia chain
|
|
25
|
+
// (private key stays local), then requests a verdict from the judge API.
|
|
24
26
|
const result = await judgeAction(
|
|
25
27
|
"Transfer $50,000 to external wallet 0xabc",
|
|
26
28
|
"Outbound AML check — new recipient, over threshold",
|
|
@@ -44,23 +46,32 @@ switch (result.verdict) {
|
|
|
44
46
|
|
|
45
47
|
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
48
|
|
|
49
|
+
### How it works
|
|
50
|
+
|
|
51
|
+
`judgeAction()` performs a two-step flow:
|
|
52
|
+
|
|
53
|
+
1. **Sign on-chain** — signs and broadcasts a `log_tool_call` transaction to the Chromia blockchain using the agent's private key. The key never leaves your machine.
|
|
54
|
+
2. **Request verdict** — sends the resulting `tool_call_id` and `agent_pubkey` to the Atbash judge API. No private key is transmitted over HTTP.
|
|
55
|
+
|
|
56
|
+
If you need finer control, you can call `logToolCall()` and the judge API separately.
|
|
57
|
+
|
|
47
58
|
### Don't have an agent yet?
|
|
48
59
|
|
|
49
60
|
Generate one programmatically for local development:
|
|
50
61
|
|
|
51
62
|
```ts
|
|
52
|
-
import { generateKeyPair,
|
|
63
|
+
import { generateKeyPair, loadAgent } from "@atbash/sdk";
|
|
53
64
|
|
|
54
65
|
const { privKey } = generateKeyPair();
|
|
55
66
|
console.log("Save this private key somewhere safe:", privKey);
|
|
56
|
-
const agent =
|
|
67
|
+
const agent = loadAgent(privKey);
|
|
57
68
|
```
|
|
58
69
|
|
|
59
70
|
For production, always create agents in the dashboard so operators can attach policy packs and manage tier / jail state.
|
|
60
71
|
|
|
61
72
|
### Secret storage
|
|
62
73
|
|
|
63
|
-
The private key
|
|
74
|
+
The private key is used to sign on-chain transactions locally. Treat it like any other long-lived credential:
|
|
64
75
|
|
|
65
76
|
- Load it from an environment variable (`ATBASH_AGENT_PRIVKEY`) or a secret manager (AWS Secrets Manager, HashiCorp Vault, 1Password, etc.) — never hardcode it.
|
|
66
77
|
- Never commit `.env` files containing the key. Add them to `.gitignore`.
|
|
@@ -90,23 +101,29 @@ judgeAction(
|
|
|
90
101
|
): Promise<JudgeResult>
|
|
91
102
|
```
|
|
92
103
|
|
|
93
|
-
Submit an action for judgment before execution. Returns the verdict, reason, confidence, provider, latency, and tool call ID.
|
|
104
|
+
Submit an action for judgment before execution. Signs `log_tool_call` on-chain, then requests a verdict. Returns the verdict, reason, confidence, provider, latency, and tool call ID.
|
|
94
105
|
|
|
95
106
|
```ts
|
|
96
107
|
interface AgentAuth {
|
|
97
108
|
pubkey: string; // 66-char hex, secp256k1 compressed public key
|
|
98
|
-
privkey: string; // 64-char hex private key
|
|
109
|
+
privkey: string; // 64-char hex private key (used for local signing only)
|
|
99
110
|
}
|
|
100
111
|
|
|
101
112
|
interface JudgeOptions {
|
|
102
113
|
endpoint?: string; // API base URL (default: https://atbash.ai)
|
|
103
114
|
timeout?: number; // Request timeout in ms
|
|
104
|
-
provider?: string; // "
|
|
105
|
-
apiKey?: string; // API key for
|
|
115
|
+
provider?: string; // "openai" | "google" | "microsoft" | "custom"
|
|
116
|
+
apiKey?: string; // API key for the AI provider
|
|
106
117
|
providerEndpoint?: string; // Endpoint for microsoft/custom providers
|
|
107
118
|
model?: string; // Model override (e.g. "gpt-4o-mini")
|
|
108
119
|
toolName?: string; // Tool name for audit trail
|
|
109
120
|
toolArgsJson?: string; // Tool arguments JSON for audit trail
|
|
121
|
+
chainOpts?: ChainOpts; // Override Chromia chain connection
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface ChainOpts {
|
|
125
|
+
nodeUrls?: string[]; // Chromia node URLs (defaults to testnet)
|
|
126
|
+
blockchainRid?: string; // Blockchain RID (defaults to testnet)
|
|
110
127
|
}
|
|
111
128
|
|
|
112
129
|
interface JudgeResult {
|
|
@@ -121,6 +138,20 @@ interface JudgeResult {
|
|
|
121
138
|
}
|
|
122
139
|
```
|
|
123
140
|
|
|
141
|
+
### Log tool call (low-level)
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
logToolCall(
|
|
145
|
+
action: string,
|
|
146
|
+
context: string,
|
|
147
|
+
auth: AgentAuth,
|
|
148
|
+
chainOpts?: ChainOpts,
|
|
149
|
+
extra?: { toolName?: string; toolArgsJson?: string },
|
|
150
|
+
): Promise<string>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Sign and broadcast `log_tool_call` to the Chromia chain. Returns the `tool_call_id`. Use this if you need to separate the on-chain logging step from the verdict request.
|
|
154
|
+
|
|
124
155
|
### Poll judgment status
|
|
125
156
|
|
|
126
157
|
```ts
|
|
@@ -144,14 +175,14 @@ interface JudgmentStatus {
|
|
|
144
175
|
### Agent identity
|
|
145
176
|
|
|
146
177
|
```ts
|
|
147
|
-
|
|
178
|
+
loadAgent(privkey: string): AgentAuth
|
|
148
179
|
generateKeyPair(): { privKey: string; pubKey: string }
|
|
149
180
|
derivePublicKey(privKeyHex: string): string
|
|
150
181
|
isValidPrivateKey(hex: string): boolean
|
|
151
182
|
toPubkeyHex(val: unknown): string
|
|
152
183
|
```
|
|
153
184
|
|
|
154
|
-
`
|
|
185
|
+
`loadAgent(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
186
|
|
|
156
187
|
### Query APIs
|
|
157
188
|
|
|
@@ -168,7 +199,7 @@ getToolCallFull(toolCallId: string, opts?: ClientOpts): Promise<ToolCallFull | n
|
|
|
168
199
|
// Org and agent info
|
|
169
200
|
getOrgTierInfo(orgName: string, opts?: ClientOpts): Promise<TierInfo | null>
|
|
170
201
|
getAgentDetail(agentPubkey: string, opts?: ClientOpts): Promise<Record<string, unknown>>
|
|
171
|
-
getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<
|
|
202
|
+
getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<AgentPolicy>
|
|
172
203
|
|
|
173
204
|
// Operator review queue
|
|
174
205
|
getPendingHeldActions(orgName: string, maxCount: number, opts?: ClientOpts): Promise<HeldAction[]>
|
|
@@ -203,6 +234,13 @@ const result = await judgeAction(action, context, auth, {
|
|
|
203
234
|
apiKey: process.env.OPENAI_API_KEY,
|
|
204
235
|
model: "gpt-4o",
|
|
205
236
|
});
|
|
237
|
+
|
|
238
|
+
// Custom Chromia chain (e.g. production RID)
|
|
239
|
+
const result = await judgeAction(action, context, auth, {
|
|
240
|
+
chainOpts: {
|
|
241
|
+
blockchainRid: "YOUR_PRODUCTION_BLOCKCHAIN_RID",
|
|
242
|
+
},
|
|
243
|
+
});
|
|
206
244
|
```
|
|
207
245
|
|
|
208
246
|
## Integration patterns
|
|
@@ -231,7 +269,7 @@ async function waitForApproval(toolCallId: string): Promise<string> {
|
|
|
231
269
|
}
|
|
232
270
|
```
|
|
233
271
|
|
|
234
|
-
### Checking agent jail status
|
|
272
|
+
### Checking agent jail status
|
|
235
273
|
|
|
236
274
|
```ts
|
|
237
275
|
const policy = await getAgentPolicy(pubKey);
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,13 +17,22 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
33
|
+
DEFAULT_BLOCKCHAIN_RID: () => DEFAULT_BLOCKCHAIN_RID,
|
|
34
|
+
DEFAULT_CHROMIA_NODE_URLS: () => DEFAULT_CHROMIA_NODE_URLS,
|
|
23
35
|
DEFAULT_ENDPOINT: () => DEFAULT_ENDPOINT,
|
|
24
|
-
createAgent: () => createAgent,
|
|
25
36
|
derivePublicKey: () => derivePublicKey,
|
|
26
37
|
generateKeyPair: () => generateKeyPair,
|
|
27
38
|
getAgentDetail: () => getAgentDetail,
|
|
@@ -38,13 +49,23 @@ __export(index_exports, {
|
|
|
38
49
|
getToolCalls: () => getToolCalls,
|
|
39
50
|
isValidPrivateKey: () => isValidPrivateKey,
|
|
40
51
|
judgeAction: () => judgeAction,
|
|
52
|
+
loadAgent: () => loadAgent,
|
|
53
|
+
logToolCall: () => logToolCall,
|
|
41
54
|
toPubkeyHex: () => toPubkeyHex
|
|
42
55
|
});
|
|
43
56
|
module.exports = __toCommonJS(index_exports);
|
|
44
57
|
|
|
45
58
|
// src/client.ts
|
|
46
59
|
var import_crypto = require("crypto");
|
|
60
|
+
var import_postchain_client = __toESM(require("postchain-client"), 1);
|
|
61
|
+
var { createClient, encryption, newSignatureProvider } = import_postchain_client.default;
|
|
47
62
|
var DEFAULT_ENDPOINT = "https://atbash.ai";
|
|
63
|
+
var DEFAULT_CHROMIA_NODE_URLS = [
|
|
64
|
+
"https://node6.testnet.chromia.com:7740",
|
|
65
|
+
"https://node7.testnet.chromia.com:7740",
|
|
66
|
+
"https://node8.testnet.chromia.com:7740"
|
|
67
|
+
];
|
|
68
|
+
var DEFAULT_BLOCKCHAIN_RID = "25B41DF620C489349C54944496FF5C6E58CFCEFED0C51658780B67299D40E8ED";
|
|
48
69
|
function isValidPrivateKey(hex) {
|
|
49
70
|
return /^[0-9a-fA-F]{64}$/.test(hex);
|
|
50
71
|
}
|
|
@@ -61,7 +82,7 @@ function generateKeyPair() {
|
|
|
61
82
|
pubKey: ecdh.getPublicKey("hex", "compressed")
|
|
62
83
|
};
|
|
63
84
|
}
|
|
64
|
-
function
|
|
85
|
+
function loadAgent(privkey) {
|
|
65
86
|
const clean = privkey.replace(/^0x/, "").trim().toLowerCase();
|
|
66
87
|
if (!isValidPrivateKey(clean)) {
|
|
67
88
|
throw new Error(
|
|
@@ -83,6 +104,40 @@ function toPubkeyHex(val) {
|
|
|
83
104
|
function baseUrl(opts) {
|
|
84
105
|
return opts?.endpoint || DEFAULT_ENDPOINT;
|
|
85
106
|
}
|
|
107
|
+
function generateToolCallId() {
|
|
108
|
+
const ts = Date.now();
|
|
109
|
+
const rand = (0, import_crypto.randomBytes)(4).toString("hex");
|
|
110
|
+
return `tc-${ts}-${rand}`;
|
|
111
|
+
}
|
|
112
|
+
async function logToolCall(action, context, auth, chainOpts, extra) {
|
|
113
|
+
const nodeUrls = chainOpts?.nodeUrls ?? DEFAULT_CHROMIA_NODE_URLS;
|
|
114
|
+
const blockchainRid = chainOpts?.blockchainRid ?? DEFAULT_BLOCKCHAIN_RID;
|
|
115
|
+
const client = await createClient({
|
|
116
|
+
nodeUrlPool: nodeUrls,
|
|
117
|
+
blockchainRid
|
|
118
|
+
});
|
|
119
|
+
const privKeyBuf = Buffer.from(auth.privkey, "hex");
|
|
120
|
+
const keyPair = encryption.makeKeyPair(privKeyBuf);
|
|
121
|
+
const sigProvider = newSignatureProvider({
|
|
122
|
+
privKey: keyPair.privKey,
|
|
123
|
+
pubKey: keyPair.pubKey
|
|
124
|
+
});
|
|
125
|
+
const toolCallId = generateToolCallId();
|
|
126
|
+
await client.signAndSendUniqueTransaction(
|
|
127
|
+
{
|
|
128
|
+
name: "log_tool_call",
|
|
129
|
+
args: [
|
|
130
|
+
toolCallId,
|
|
131
|
+
action,
|
|
132
|
+
context || "",
|
|
133
|
+
extra?.toolName || "",
|
|
134
|
+
extra?.toolArgsJson || ""
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
sigProvider
|
|
138
|
+
);
|
|
139
|
+
return toolCallId;
|
|
140
|
+
}
|
|
86
141
|
function normalizeVerdict(raw) {
|
|
87
142
|
const v = String(raw || "").toUpperCase();
|
|
88
143
|
if (v === "ALLOW" || v === "GREEN") return "ALLOW";
|
|
@@ -142,17 +197,23 @@ async function getJson(url, opts) {
|
|
|
142
197
|
return resp.json();
|
|
143
198
|
}
|
|
144
199
|
async function judgeAction(action, context, auth, opts) {
|
|
200
|
+
const toolCallId = await logToolCall(
|
|
201
|
+
action,
|
|
202
|
+
context,
|
|
203
|
+
auth,
|
|
204
|
+
opts?.chainOpts,
|
|
205
|
+
{ toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson }
|
|
206
|
+
);
|
|
145
207
|
const url = `${baseUrl(opts)}/api/v1/judge`;
|
|
146
208
|
const data = await postJson(
|
|
147
209
|
url,
|
|
148
210
|
{
|
|
149
|
-
|
|
211
|
+
tool_call_id: toolCallId,
|
|
212
|
+
agent_pubkey: auth.pubkey,
|
|
150
213
|
action,
|
|
151
214
|
context: context || "",
|
|
152
|
-
|
|
153
|
-
agent_privkey: auth.privkey,
|
|
215
|
+
provider: opts?.provider || "",
|
|
154
216
|
tool_name: opts?.toolName || "",
|
|
155
|
-
tool_args_json: opts?.toolArgsJson || "",
|
|
156
217
|
api_key: opts?.apiKey || "",
|
|
157
218
|
endpoint_url: opts?.providerEndpoint || "",
|
|
158
219
|
model: opts?.model || ""
|
|
@@ -166,7 +227,7 @@ async function judgeAction(action, context, auth, opts) {
|
|
|
166
227
|
confidence: Number(data.confidence ?? 0),
|
|
167
228
|
provider: String(data.provider || ""),
|
|
168
229
|
latency_ms: Number(data.latency_ms ?? 0),
|
|
169
|
-
tool_call_id: String(data.tool_call_id ||
|
|
230
|
+
tool_call_id: String(data.tool_call_id || toolCallId),
|
|
170
231
|
on_chain: Boolean(data.on_chain)
|
|
171
232
|
};
|
|
172
233
|
}
|
|
@@ -287,8 +348,9 @@ async function getSafetyStats(opts) {
|
|
|
287
348
|
}
|
|
288
349
|
// Annotate the CommonJS export names for ESM import in node:
|
|
289
350
|
0 && (module.exports = {
|
|
351
|
+
DEFAULT_BLOCKCHAIN_RID,
|
|
352
|
+
DEFAULT_CHROMIA_NODE_URLS,
|
|
290
353
|
DEFAULT_ENDPOINT,
|
|
291
|
-
createAgent,
|
|
292
354
|
derivePublicKey,
|
|
293
355
|
generateKeyPair,
|
|
294
356
|
getAgentDetail,
|
|
@@ -305,5 +367,7 @@ async function getSafetyStats(opts) {
|
|
|
305
367
|
getToolCalls,
|
|
306
368
|
isValidPrivateKey,
|
|
307
369
|
judgeAction,
|
|
370
|
+
loadAgent,
|
|
371
|
+
logToolCall,
|
|
308
372
|
toPubkeyHex
|
|
309
373
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
declare const DEFAULT_ENDPOINT = "https://atbash.ai";
|
|
2
|
+
declare const DEFAULT_CHROMIA_NODE_URLS: string[];
|
|
3
|
+
declare const DEFAULT_BLOCKCHAIN_RID = "25B41DF620C489349C54944496FF5C6E58CFCEFED0C51658780B67299D40E8ED";
|
|
2
4
|
type Verdict = "ALLOW" | "HOLD" | "BLOCK";
|
|
3
5
|
type Provider = "atbash" | "openai" | "google" | "microsoft" | "custom" | (string & {});
|
|
4
6
|
type Tier = "audit" | "audit_plus" | "enforcement" | (string & {});
|
|
@@ -17,12 +19,26 @@ interface AgentAuth {
|
|
|
17
19
|
pubkey: string;
|
|
18
20
|
privkey: string;
|
|
19
21
|
}
|
|
20
|
-
declare function
|
|
22
|
+
declare function loadAgent(privkey: string): AgentAuth;
|
|
21
23
|
declare function toPubkeyHex(val: unknown): string;
|
|
22
24
|
interface ClientOpts {
|
|
23
25
|
endpoint?: string;
|
|
24
26
|
timeout?: number;
|
|
25
27
|
}
|
|
28
|
+
interface ChainOpts {
|
|
29
|
+
nodeUrls?: string[];
|
|
30
|
+
blockchainRid?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Sign and broadcast `log_tool_call` to the Chromia chain.
|
|
34
|
+
*
|
|
35
|
+
* The agent's private key is used to sign the transaction locally —
|
|
36
|
+
* it is never sent over the network. Returns the tool_call_id.
|
|
37
|
+
*/
|
|
38
|
+
declare function logToolCall(action: string, context: string, auth: AgentAuth, chainOpts?: ChainOpts, extra?: {
|
|
39
|
+
toolName?: string;
|
|
40
|
+
toolArgsJson?: string;
|
|
41
|
+
}): Promise<string>;
|
|
26
42
|
interface JudgeResult {
|
|
27
43
|
verdict: Verdict;
|
|
28
44
|
action_type: ActionType;
|
|
@@ -99,6 +115,7 @@ interface JudgeOptions extends ClientOpts {
|
|
|
99
115
|
model?: string;
|
|
100
116
|
toolName?: string;
|
|
101
117
|
toolArgsJson?: string;
|
|
118
|
+
chainOpts?: ChainOpts;
|
|
102
119
|
}
|
|
103
120
|
interface AgentPolicy {
|
|
104
121
|
policy: string;
|
|
@@ -120,4 +137,4 @@ declare function getAgentDetail(agentPubkey: string, opts?: ClientOpts): Promise
|
|
|
120
137
|
declare function getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<AgentPolicy>;
|
|
121
138
|
declare function getSafetyStats(opts?: ClientOpts): Promise<Record<string, unknown>>;
|
|
122
139
|
|
|
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,
|
|
140
|
+
export { type AgentAuth, type ChainOpts, type ClientOpts, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, type HeldAction, type HeldActionReview, type JudgeOptions, type JudgeResult, type JudgmentStatus, type TierInfo, type ToolCallFull, type ToolCallRecord, type Verdict, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, loadAgent, logToolCall, toPubkeyHex };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
declare const DEFAULT_ENDPOINT = "https://atbash.ai";
|
|
2
|
+
declare const DEFAULT_CHROMIA_NODE_URLS: string[];
|
|
3
|
+
declare const DEFAULT_BLOCKCHAIN_RID = "25B41DF620C489349C54944496FF5C6E58CFCEFED0C51658780B67299D40E8ED";
|
|
2
4
|
type Verdict = "ALLOW" | "HOLD" | "BLOCK";
|
|
3
5
|
type Provider = "atbash" | "openai" | "google" | "microsoft" | "custom" | (string & {});
|
|
4
6
|
type Tier = "audit" | "audit_plus" | "enforcement" | (string & {});
|
|
@@ -17,12 +19,26 @@ interface AgentAuth {
|
|
|
17
19
|
pubkey: string;
|
|
18
20
|
privkey: string;
|
|
19
21
|
}
|
|
20
|
-
declare function
|
|
22
|
+
declare function loadAgent(privkey: string): AgentAuth;
|
|
21
23
|
declare function toPubkeyHex(val: unknown): string;
|
|
22
24
|
interface ClientOpts {
|
|
23
25
|
endpoint?: string;
|
|
24
26
|
timeout?: number;
|
|
25
27
|
}
|
|
28
|
+
interface ChainOpts {
|
|
29
|
+
nodeUrls?: string[];
|
|
30
|
+
blockchainRid?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Sign and broadcast `log_tool_call` to the Chromia chain.
|
|
34
|
+
*
|
|
35
|
+
* The agent's private key is used to sign the transaction locally —
|
|
36
|
+
* it is never sent over the network. Returns the tool_call_id.
|
|
37
|
+
*/
|
|
38
|
+
declare function logToolCall(action: string, context: string, auth: AgentAuth, chainOpts?: ChainOpts, extra?: {
|
|
39
|
+
toolName?: string;
|
|
40
|
+
toolArgsJson?: string;
|
|
41
|
+
}): Promise<string>;
|
|
26
42
|
interface JudgeResult {
|
|
27
43
|
verdict: Verdict;
|
|
28
44
|
action_type: ActionType;
|
|
@@ -99,6 +115,7 @@ interface JudgeOptions extends ClientOpts {
|
|
|
99
115
|
model?: string;
|
|
100
116
|
toolName?: string;
|
|
101
117
|
toolArgsJson?: string;
|
|
118
|
+
chainOpts?: ChainOpts;
|
|
102
119
|
}
|
|
103
120
|
interface AgentPolicy {
|
|
104
121
|
policy: string;
|
|
@@ -120,4 +137,4 @@ declare function getAgentDetail(agentPubkey: string, opts?: ClientOpts): Promise
|
|
|
120
137
|
declare function getAgentPolicy(agentPubkey: string, opts?: ClientOpts): Promise<AgentPolicy>;
|
|
121
138
|
declare function getSafetyStats(opts?: ClientOpts): Promise<Record<string, unknown>>;
|
|
122
139
|
|
|
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,
|
|
140
|
+
export { type AgentAuth, type ChainOpts, type ClientOpts, DEFAULT_BLOCKCHAIN_RID, DEFAULT_CHROMIA_NODE_URLS, DEFAULT_ENDPOINT, type HeldAction, type HeldActionReview, type JudgeOptions, type JudgeResult, type JudgmentStatus, type TierInfo, type ToolCallFull, type ToolCallRecord, type Verdict, derivePublicKey, generateKeyPair, getAgentDetail, getAgentPolicy, getAgentToolCalls, getHeldActionReviews, getJudgmentStatus, getOrgTierInfo, getOrgToolCalls, getPendingHeldActions, getSafetyStats, getToolCallCount, getToolCallFull, getToolCalls, isValidPrivateKey, judgeAction, loadAgent, logToolCall, toPubkeyHex };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
|
-
import { createECDH } from "crypto";
|
|
2
|
+
import { createECDH, randomBytes } from "crypto";
|
|
3
|
+
import postchain from "postchain-client";
|
|
4
|
+
var { createClient, encryption, newSignatureProvider } = postchain;
|
|
3
5
|
var DEFAULT_ENDPOINT = "https://atbash.ai";
|
|
6
|
+
var DEFAULT_CHROMIA_NODE_URLS = [
|
|
7
|
+
"https://node6.testnet.chromia.com:7740",
|
|
8
|
+
"https://node7.testnet.chromia.com:7740",
|
|
9
|
+
"https://node8.testnet.chromia.com:7740"
|
|
10
|
+
];
|
|
11
|
+
var DEFAULT_BLOCKCHAIN_RID = "25B41DF620C489349C54944496FF5C6E58CFCEFED0C51658780B67299D40E8ED";
|
|
4
12
|
function isValidPrivateKey(hex) {
|
|
5
13
|
return /^[0-9a-fA-F]{64}$/.test(hex);
|
|
6
14
|
}
|
|
@@ -17,7 +25,7 @@ function generateKeyPair() {
|
|
|
17
25
|
pubKey: ecdh.getPublicKey("hex", "compressed")
|
|
18
26
|
};
|
|
19
27
|
}
|
|
20
|
-
function
|
|
28
|
+
function loadAgent(privkey) {
|
|
21
29
|
const clean = privkey.replace(/^0x/, "").trim().toLowerCase();
|
|
22
30
|
if (!isValidPrivateKey(clean)) {
|
|
23
31
|
throw new Error(
|
|
@@ -39,6 +47,40 @@ function toPubkeyHex(val) {
|
|
|
39
47
|
function baseUrl(opts) {
|
|
40
48
|
return opts?.endpoint || DEFAULT_ENDPOINT;
|
|
41
49
|
}
|
|
50
|
+
function generateToolCallId() {
|
|
51
|
+
const ts = Date.now();
|
|
52
|
+
const rand = randomBytes(4).toString("hex");
|
|
53
|
+
return `tc-${ts}-${rand}`;
|
|
54
|
+
}
|
|
55
|
+
async function logToolCall(action, context, auth, chainOpts, extra) {
|
|
56
|
+
const nodeUrls = chainOpts?.nodeUrls ?? DEFAULT_CHROMIA_NODE_URLS;
|
|
57
|
+
const blockchainRid = chainOpts?.blockchainRid ?? DEFAULT_BLOCKCHAIN_RID;
|
|
58
|
+
const client = await createClient({
|
|
59
|
+
nodeUrlPool: nodeUrls,
|
|
60
|
+
blockchainRid
|
|
61
|
+
});
|
|
62
|
+
const privKeyBuf = Buffer.from(auth.privkey, "hex");
|
|
63
|
+
const keyPair = encryption.makeKeyPair(privKeyBuf);
|
|
64
|
+
const sigProvider = newSignatureProvider({
|
|
65
|
+
privKey: keyPair.privKey,
|
|
66
|
+
pubKey: keyPair.pubKey
|
|
67
|
+
});
|
|
68
|
+
const toolCallId = generateToolCallId();
|
|
69
|
+
await client.signAndSendUniqueTransaction(
|
|
70
|
+
{
|
|
71
|
+
name: "log_tool_call",
|
|
72
|
+
args: [
|
|
73
|
+
toolCallId,
|
|
74
|
+
action,
|
|
75
|
+
context || "",
|
|
76
|
+
extra?.toolName || "",
|
|
77
|
+
extra?.toolArgsJson || ""
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
sigProvider
|
|
81
|
+
);
|
|
82
|
+
return toolCallId;
|
|
83
|
+
}
|
|
42
84
|
function normalizeVerdict(raw) {
|
|
43
85
|
const v = String(raw || "").toUpperCase();
|
|
44
86
|
if (v === "ALLOW" || v === "GREEN") return "ALLOW";
|
|
@@ -98,17 +140,23 @@ async function getJson(url, opts) {
|
|
|
98
140
|
return resp.json();
|
|
99
141
|
}
|
|
100
142
|
async function judgeAction(action, context, auth, opts) {
|
|
143
|
+
const toolCallId = await logToolCall(
|
|
144
|
+
action,
|
|
145
|
+
context,
|
|
146
|
+
auth,
|
|
147
|
+
opts?.chainOpts,
|
|
148
|
+
{ toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson }
|
|
149
|
+
);
|
|
101
150
|
const url = `${baseUrl(opts)}/api/v1/judge`;
|
|
102
151
|
const data = await postJson(
|
|
103
152
|
url,
|
|
104
153
|
{
|
|
105
|
-
|
|
154
|
+
tool_call_id: toolCallId,
|
|
155
|
+
agent_pubkey: auth.pubkey,
|
|
106
156
|
action,
|
|
107
157
|
context: context || "",
|
|
108
|
-
|
|
109
|
-
agent_privkey: auth.privkey,
|
|
158
|
+
provider: opts?.provider || "",
|
|
110
159
|
tool_name: opts?.toolName || "",
|
|
111
|
-
tool_args_json: opts?.toolArgsJson || "",
|
|
112
160
|
api_key: opts?.apiKey || "",
|
|
113
161
|
endpoint_url: opts?.providerEndpoint || "",
|
|
114
162
|
model: opts?.model || ""
|
|
@@ -122,7 +170,7 @@ async function judgeAction(action, context, auth, opts) {
|
|
|
122
170
|
confidence: Number(data.confidence ?? 0),
|
|
123
171
|
provider: String(data.provider || ""),
|
|
124
172
|
latency_ms: Number(data.latency_ms ?? 0),
|
|
125
|
-
tool_call_id: String(data.tool_call_id ||
|
|
173
|
+
tool_call_id: String(data.tool_call_id || toolCallId),
|
|
126
174
|
on_chain: Boolean(data.on_chain)
|
|
127
175
|
};
|
|
128
176
|
}
|
|
@@ -242,8 +290,9 @@ async function getSafetyStats(opts) {
|
|
|
242
290
|
return result?.data || result;
|
|
243
291
|
}
|
|
244
292
|
export {
|
|
293
|
+
DEFAULT_BLOCKCHAIN_RID,
|
|
294
|
+
DEFAULT_CHROMIA_NODE_URLS,
|
|
245
295
|
DEFAULT_ENDPOINT,
|
|
246
|
-
createAgent,
|
|
247
296
|
derivePublicKey,
|
|
248
297
|
generateKeyPair,
|
|
249
298
|
getAgentDetail,
|
|
@@ -260,5 +309,7 @@ export {
|
|
|
260
309
|
getToolCalls,
|
|
261
310
|
isValidPrivateKey,
|
|
262
311
|
judgeAction,
|
|
312
|
+
loadAgent,
|
|
313
|
+
logToolCall,
|
|
263
314
|
toPubkeyHex
|
|
264
315
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atbash/sdk",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "TypeScript SDK for the Atbash risk-engine / judge API",
|
|
5
5
|
"homepage": "https://atbash.ai",
|
|
6
6
|
"author": "Atbash",
|
|
@@ -38,5 +38,8 @@
|
|
|
38
38
|
"risk-engine",
|
|
39
39
|
"agent-safety",
|
|
40
40
|
"ai-safety"
|
|
41
|
-
]
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"postchain-client": "^2.1.5"
|
|
44
|
+
}
|
|
42
45
|
}
|