@atbash/sdk 0.3.4 → 0.3.5

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 CHANGED
@@ -128,8 +128,8 @@ interface JudgeOptions {
128
128
  }
129
129
 
130
130
  interface ChainOpts {
131
- nodeUrls?: string[]; // Chromia node URLs (defaults to testnet)
132
- blockchainRid?: string; // Blockchain RID (defaults to testnet)
131
+ nodeUrls?: string[]; // Chromia node URLs (uses the default nodeurls)
132
+ blockchainRid?: string; // Blockchain RID (uses the default chromia rid)
133
133
  }
134
134
 
135
135
  interface JudgeResult {
package/dist/index.cjs CHANGED
@@ -110,6 +110,25 @@ function generateToolCallId() {
110
110
  const rand = (0, import_crypto.randomBytes)(4).toString("hex");
111
111
  return `tc-${ts}-${rand}`;
112
112
  }
113
+ async function buildSignedTx(opName, args, auth, chainOpts) {
114
+ const nodeUrls = chainOpts?.nodeUrls ?? DEFAULT_CHROMIA_NODE_URLS;
115
+ const blockchainRid = chainOpts?.blockchainRid ?? DEFAULT_BLOCKCHAIN_RID;
116
+ const client = await createClient({ nodeUrlPool: nodeUrls, blockchainRid });
117
+ const privKeyBuf = Buffer.from(auth.privkey, "hex");
118
+ const keyPair = encryption.makeKeyPair(privKeyBuf);
119
+ const sigProvider = newSignatureProvider({
120
+ privKey: keyPair.privKey,
121
+ pubKey: keyPair.pubKey
122
+ });
123
+ const signed = await client.signTransaction(
124
+ {
125
+ operations: [{ name: opName, args }],
126
+ signers: [keyPair.pubKey]
127
+ },
128
+ sigProvider
129
+ );
130
+ return Buffer.from(signed).toString("hex");
131
+ }
113
132
  async function checkAgentExists(pubkey, opts) {
114
133
  const url = `${baseUrl(opts)}/api/ai/exists?pubkey=${encodeURIComponent(pubkey)}`;
115
134
  const data = await getJson(url, opts);
@@ -125,38 +144,25 @@ async function logToolCall(action, context, auth, chainOpts, extra, clientOpts)
125
144
  };
126
145
  }
127
146
  try {
128
- const nodeUrls = chainOpts?.nodeUrls ?? DEFAULT_CHROMIA_NODE_URLS;
129
- const blockchainRid = chainOpts?.blockchainRid ?? DEFAULT_BLOCKCHAIN_RID;
130
- const client = await createClient({
131
- nodeUrlPool: nodeUrls,
132
- blockchainRid
133
- });
134
- const privKeyBuf = Buffer.from(auth.privkey, "hex");
135
- const keyPair = encryption.makeKeyPair(privKeyBuf);
136
- const sigProvider = newSignatureProvider({
137
- privKey: keyPair.privKey,
138
- pubKey: keyPair.pubKey
139
- });
140
147
  const toolCallId = generateToolCallId();
141
- await client.signAndSendUniqueTransaction(
142
- {
143
- name: "log_tool_call",
144
- args: [
145
- toolCallId,
146
- action,
147
- context || "",
148
- extra?.toolName || "",
149
- extra?.toolArgsJson || ""
150
- ]
151
- },
152
- sigProvider
148
+ const signedHex = await buildSignedTx(
149
+ "log_tool_call",
150
+ [
151
+ toolCallId,
152
+ action,
153
+ context || "",
154
+ extra?.toolName || "",
155
+ extra?.toolArgsJson || ""
156
+ ],
157
+ auth,
158
+ chainOpts
153
159
  );
154
- return { success: true, toolCallId };
160
+ return { success: true, toolCallId, signedHex };
155
161
  } catch (err) {
156
162
  return {
157
163
  success: false,
158
164
  toolCallId: null,
159
- error: err instanceof Error ? err.message : "Failed to log tool call on-chain"
165
+ error: err instanceof Error ? err.message : "Failed to sign log_tool_call"
160
166
  };
161
167
  }
162
168
  }
@@ -220,7 +226,7 @@ async function getJson(url, opts) {
220
226
  }
221
227
  return resp.json();
222
228
  }
223
- async function judgeAction(action, context, auth, opts) {
229
+ async function judgeAction(action, context = "", auth, opts) {
224
230
  if (!action || !action.trim()) {
225
231
  throw new Error("action is required and cannot be empty.");
226
232
  }
@@ -232,25 +238,32 @@ async function judgeAction(action, context, auth, opts) {
232
238
  { toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson },
233
239
  opts
234
240
  );
235
- if (!logResult.success || !logResult.toolCallId) {
236
- throw new Error(logResult.error || "Failed to log tool call on-chain");
241
+ if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
242
+ throw new Error(logResult.error || "Failed to sign log_tool_call");
243
+ }
244
+ let signedJudgeActionHex;
245
+ if (!opts?.provider) {
246
+ const judgmentId = generateToolCallId();
247
+ signedJudgeActionHex = await buildSignedTx(
248
+ "judge_action",
249
+ [judgmentId, action, context || "", ""],
250
+ auth,
251
+ opts?.chainOpts
252
+ );
237
253
  }
238
254
  const url = `${baseUrl(opts)}/api/v1/judge`;
239
- const data = await postJson(
240
- url,
241
- {
242
- tool_call_id: logResult.toolCallId,
243
- agent_pubkey: auth.pubkey,
244
- action,
245
- ...context && { context },
246
- ...opts?.provider && { provider: opts.provider },
247
- ...opts?.toolName && { tool_name: opts.toolName },
248
- ...opts?.apiKey && { api_key: opts.apiKey },
249
- ...opts?.providerEndpoint && { endpoint_url: opts.providerEndpoint },
250
- ...opts?.model && { model: opts.model }
251
- },
252
- opts
253
- );
255
+ const body = {
256
+ tool_call_id: logResult.toolCallId,
257
+ agent_pubkey: auth.pubkey,
258
+ action,
259
+ signed_log_tool_call: logResult.signedHex,
260
+ ...signedJudgeActionHex && { signed_judge_action: signedJudgeActionHex },
261
+ ...context && { context },
262
+ ...opts?.provider && { provider: opts.provider },
263
+ ...opts?.toolName && { tool_name: opts.toolName },
264
+ ...opts?.model && { model: opts.model }
265
+ };
266
+ const data = await postJson(url, body, opts);
254
267
  return {
255
268
  verdict: normalizeVerdict(data.verdict),
256
269
  action_type: String(data.action_type || ""),
package/dist/index.d.cts CHANGED
@@ -21,6 +21,7 @@ interface ChainOpts {
21
21
  interface LogToolCallResult {
22
22
  success: boolean;
23
23
  toolCallId: string | null;
24
+ signedHex?: string;
24
25
  error?: string;
25
26
  }
26
27
  interface JudgeResult {
@@ -35,8 +36,6 @@ interface JudgeResult {
35
36
  }
36
37
  interface JudgeOptions extends ClientOpts {
37
38
  provider?: Provider;
38
- apiKey?: string;
39
- providerEndpoint?: string;
40
39
  model?: string;
41
40
  toolName?: string;
42
41
  toolArgsJson?: string;
@@ -125,16 +124,17 @@ declare function toPubkeyHex(val: unknown): string;
125
124
  */
126
125
  declare function checkAgentExists(pubkey: string, opts?: ClientOpts): Promise<boolean>;
127
126
  /**
128
- * Sign and broadcast `log_tool_call` to the Chromia chain.
127
+ * Sign `log_tool_call` locally and return the signed transaction hex.
129
128
  *
130
- * Checks that the agent is onboarded before signing. The agent's private
131
- * key is used to sign the transaction locally — never sent over the network.
129
+ * Checks that the agent is onboarded before signing. The private key
130
+ * is used locally — never sent over the network. The server will
131
+ * broadcast the signed transaction to the chain.
132
132
  */
133
133
  declare function logToolCall(action: string, context: string, auth: AgentAuth, chainOpts?: ChainOpts, extra?: {
134
134
  toolName?: string;
135
135
  toolArgsJson?: string;
136
136
  }, clientOpts?: ClientOpts): Promise<LogToolCallResult>;
137
- declare function judgeAction(action: string, context: string, auth: AgentAuth, opts?: JudgeOptions): Promise<JudgeResult>;
137
+ declare function judgeAction(action: string, context: string | undefined, auth: AgentAuth, opts?: JudgeOptions): Promise<JudgeResult>;
138
138
  declare function getJudgmentStatus(judgmentId: string, opts?: ClientOpts): Promise<JudgmentStatus>;
139
139
  declare function getToolCalls(maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
140
140
  declare function getOrgToolCalls(orgName: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ interface ChainOpts {
21
21
  interface LogToolCallResult {
22
22
  success: boolean;
23
23
  toolCallId: string | null;
24
+ signedHex?: string;
24
25
  error?: string;
25
26
  }
26
27
  interface JudgeResult {
@@ -35,8 +36,6 @@ interface JudgeResult {
35
36
  }
36
37
  interface JudgeOptions extends ClientOpts {
37
38
  provider?: Provider;
38
- apiKey?: string;
39
- providerEndpoint?: string;
40
39
  model?: string;
41
40
  toolName?: string;
42
41
  toolArgsJson?: string;
@@ -125,16 +124,17 @@ declare function toPubkeyHex(val: unknown): string;
125
124
  */
126
125
  declare function checkAgentExists(pubkey: string, opts?: ClientOpts): Promise<boolean>;
127
126
  /**
128
- * Sign and broadcast `log_tool_call` to the Chromia chain.
127
+ * Sign `log_tool_call` locally and return the signed transaction hex.
129
128
  *
130
- * Checks that the agent is onboarded before signing. The agent's private
131
- * key is used to sign the transaction locally — never sent over the network.
129
+ * Checks that the agent is onboarded before signing. The private key
130
+ * is used locally — never sent over the network. The server will
131
+ * broadcast the signed transaction to the chain.
132
132
  */
133
133
  declare function logToolCall(action: string, context: string, auth: AgentAuth, chainOpts?: ChainOpts, extra?: {
134
134
  toolName?: string;
135
135
  toolArgsJson?: string;
136
136
  }, clientOpts?: ClientOpts): Promise<LogToolCallResult>;
137
- declare function judgeAction(action: string, context: string, auth: AgentAuth, opts?: JudgeOptions): Promise<JudgeResult>;
137
+ declare function judgeAction(action: string, context: string | undefined, auth: AgentAuth, opts?: JudgeOptions): Promise<JudgeResult>;
138
138
  declare function getJudgmentStatus(judgmentId: string, opts?: ClientOpts): Promise<JudgmentStatus>;
139
139
  declare function getToolCalls(maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
140
140
  declare function getOrgToolCalls(orgName: string, maxCount: number, opts?: ClientOpts): Promise<ToolCallRecord[]>;
package/dist/index.js CHANGED
@@ -52,6 +52,25 @@ function generateToolCallId() {
52
52
  const rand = randomBytes(4).toString("hex");
53
53
  return `tc-${ts}-${rand}`;
54
54
  }
55
+ async function buildSignedTx(opName, args, auth, chainOpts) {
56
+ const nodeUrls = chainOpts?.nodeUrls ?? DEFAULT_CHROMIA_NODE_URLS;
57
+ const blockchainRid = chainOpts?.blockchainRid ?? DEFAULT_BLOCKCHAIN_RID;
58
+ const client = await createClient({ nodeUrlPool: nodeUrls, blockchainRid });
59
+ const privKeyBuf = Buffer.from(auth.privkey, "hex");
60
+ const keyPair = encryption.makeKeyPair(privKeyBuf);
61
+ const sigProvider = newSignatureProvider({
62
+ privKey: keyPair.privKey,
63
+ pubKey: keyPair.pubKey
64
+ });
65
+ const signed = await client.signTransaction(
66
+ {
67
+ operations: [{ name: opName, args }],
68
+ signers: [keyPair.pubKey]
69
+ },
70
+ sigProvider
71
+ );
72
+ return Buffer.from(signed).toString("hex");
73
+ }
55
74
  async function checkAgentExists(pubkey, opts) {
56
75
  const url = `${baseUrl(opts)}/api/ai/exists?pubkey=${encodeURIComponent(pubkey)}`;
57
76
  const data = await getJson(url, opts);
@@ -67,38 +86,25 @@ async function logToolCall(action, context, auth, chainOpts, extra, clientOpts)
67
86
  };
68
87
  }
69
88
  try {
70
- const nodeUrls = chainOpts?.nodeUrls ?? DEFAULT_CHROMIA_NODE_URLS;
71
- const blockchainRid = chainOpts?.blockchainRid ?? DEFAULT_BLOCKCHAIN_RID;
72
- const client = await createClient({
73
- nodeUrlPool: nodeUrls,
74
- blockchainRid
75
- });
76
- const privKeyBuf = Buffer.from(auth.privkey, "hex");
77
- const keyPair = encryption.makeKeyPair(privKeyBuf);
78
- const sigProvider = newSignatureProvider({
79
- privKey: keyPair.privKey,
80
- pubKey: keyPair.pubKey
81
- });
82
89
  const toolCallId = generateToolCallId();
83
- await client.signAndSendUniqueTransaction(
84
- {
85
- name: "log_tool_call",
86
- args: [
87
- toolCallId,
88
- action,
89
- context || "",
90
- extra?.toolName || "",
91
- extra?.toolArgsJson || ""
92
- ]
93
- },
94
- sigProvider
90
+ const signedHex = await buildSignedTx(
91
+ "log_tool_call",
92
+ [
93
+ toolCallId,
94
+ action,
95
+ context || "",
96
+ extra?.toolName || "",
97
+ extra?.toolArgsJson || ""
98
+ ],
99
+ auth,
100
+ chainOpts
95
101
  );
96
- return { success: true, toolCallId };
102
+ return { success: true, toolCallId, signedHex };
97
103
  } catch (err) {
98
104
  return {
99
105
  success: false,
100
106
  toolCallId: null,
101
- error: err instanceof Error ? err.message : "Failed to log tool call on-chain"
107
+ error: err instanceof Error ? err.message : "Failed to sign log_tool_call"
102
108
  };
103
109
  }
104
110
  }
@@ -162,7 +168,7 @@ async function getJson(url, opts) {
162
168
  }
163
169
  return resp.json();
164
170
  }
165
- async function judgeAction(action, context, auth, opts) {
171
+ async function judgeAction(action, context = "", auth, opts) {
166
172
  if (!action || !action.trim()) {
167
173
  throw new Error("action is required and cannot be empty.");
168
174
  }
@@ -174,25 +180,32 @@ async function judgeAction(action, context, auth, opts) {
174
180
  { toolName: opts?.toolName, toolArgsJson: opts?.toolArgsJson },
175
181
  opts
176
182
  );
177
- if (!logResult.success || !logResult.toolCallId) {
178
- throw new Error(logResult.error || "Failed to log tool call on-chain");
183
+ if (!logResult.success || !logResult.toolCallId || !logResult.signedHex) {
184
+ throw new Error(logResult.error || "Failed to sign log_tool_call");
185
+ }
186
+ let signedJudgeActionHex;
187
+ if (!opts?.provider) {
188
+ const judgmentId = generateToolCallId();
189
+ signedJudgeActionHex = await buildSignedTx(
190
+ "judge_action",
191
+ [judgmentId, action, context || "", ""],
192
+ auth,
193
+ opts?.chainOpts
194
+ );
179
195
  }
180
196
  const url = `${baseUrl(opts)}/api/v1/judge`;
181
- const data = await postJson(
182
- url,
183
- {
184
- tool_call_id: logResult.toolCallId,
185
- agent_pubkey: auth.pubkey,
186
- action,
187
- ...context && { context },
188
- ...opts?.provider && { provider: opts.provider },
189
- ...opts?.toolName && { tool_name: opts.toolName },
190
- ...opts?.apiKey && { api_key: opts.apiKey },
191
- ...opts?.providerEndpoint && { endpoint_url: opts.providerEndpoint },
192
- ...opts?.model && { model: opts.model }
193
- },
194
- opts
195
- );
197
+ const body = {
198
+ tool_call_id: logResult.toolCallId,
199
+ agent_pubkey: auth.pubkey,
200
+ action,
201
+ signed_log_tool_call: logResult.signedHex,
202
+ ...signedJudgeActionHex && { signed_judge_action: signedJudgeActionHex },
203
+ ...context && { context },
204
+ ...opts?.provider && { provider: opts.provider },
205
+ ...opts?.toolName && { tool_name: opts.toolName },
206
+ ...opts?.model && { model: opts.model }
207
+ };
208
+ const data = await postJson(url, body, opts);
196
209
  return {
197
210
  verdict: normalizeVerdict(data.verdict),
198
211
  action_type: String(data.action_type || ""),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atbash/sdk",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
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",