aira-sdk 0.1.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Aira = void 0;
4
4
  const types_1 = require("./types");
5
+ const offline_1 = require("./offline");
6
+ const session_1 = require("./session");
5
7
  const DEFAULT_BASE_URL = "https://api.airaproof.com";
6
8
  const DEFAULT_TIMEOUT = 30_000;
7
9
  const MAX_DETAILS_LENGTH = 50_000;
@@ -15,6 +17,7 @@ class Aira {
15
17
  baseUrl;
16
18
  apiKey;
17
19
  timeout;
20
+ queue;
18
21
  constructor(options) {
19
22
  if (!options.apiKey)
20
23
  throw new Error("apiKey is required");
@@ -24,6 +27,7 @@ class Aira {
24
27
  this.apiKey = options.apiKey;
25
28
  this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "") + "/api/v1";
26
29
  this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
30
+ this.queue = options.offline ? new offline_1.OfflineQueue() : null;
27
31
  }
28
32
  async request(method, path, body, auth = true) {
29
33
  const controller = new AbortController();
@@ -51,10 +55,17 @@ class Aira {
51
55
  }
52
56
  }
53
57
  get(path, params, auth = true) {
58
+ if (this.queue) {
59
+ throw new types_1.AiraError(0, "OFFLINE", "GET requests not available in offline mode");
60
+ }
54
61
  const qs = params ? "?" + new URLSearchParams(Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])).toString() : "";
55
62
  return this.request("GET", path + qs, undefined, auth);
56
63
  }
57
64
  post(path, body) {
65
+ if (this.queue) {
66
+ const qid = this.queue.enqueue("POST", path, body);
67
+ return Promise.resolve({ _offline: true, _queue_id: qid });
68
+ }
58
69
  return this.request("POST", path, body);
59
70
  }
60
71
  put(path, body) {
@@ -250,5 +261,97 @@ class Aira {
250
261
  async ask(message, params) {
251
262
  return this.post("/chat", buildBody({ message, history: params?.history, model: params?.model }));
252
263
  }
264
+ // ==================== DID ====================
265
+ /** Get full DID info for an agent. */
266
+ async getAgentDid(slug) {
267
+ return this.get(`/agents/${slug}/did`);
268
+ }
269
+ /** Rotate an agent's DID keypair. */
270
+ async rotateAgentKeys(slug) {
271
+ return this.post(`/agents/${slug}/did/rotate`, {});
272
+ }
273
+ /** Resolve any did:web DID to its DID document. */
274
+ async resolveDid(did) {
275
+ return this.post("/dids/resolve", { did });
276
+ }
277
+ // ==================== Verifiable Credentials ====================
278
+ /** Get the current valid VC for an agent. */
279
+ async getAgentCredential(slug) {
280
+ return this.get(`/agents/${slug}/credential`);
281
+ }
282
+ /** Get full credential history for an agent. */
283
+ async getAgentCredentials(slug) {
284
+ return this.get(`/agents/${slug}/credentials`);
285
+ }
286
+ /** Revoke the current credential for an agent. */
287
+ async revokeCredential(slug, reason = "") {
288
+ return this.post(`/agents/${slug}/credentials/revoke`, { reason });
289
+ }
290
+ /** Verify a Verifiable Credential — checks signature, expiry, revocation. */
291
+ async verifyCredential(credential) {
292
+ return this.post("/credentials/verify", { credential });
293
+ }
294
+ // ==================== Mutual Notarization ====================
295
+ /** Initiate a mutual signing request for an action. */
296
+ async requestMutualSign(actionId, counterpartyDid) {
297
+ return this.post(`/actions/${actionId}/mutual-sign/request`, { counterparty_did: counterpartyDid });
298
+ }
299
+ /** Get the action payload awaiting counterparty signature. */
300
+ async getPendingMutualSign(actionId) {
301
+ return this.get(`/actions/${actionId}/mutual-sign/pending`);
302
+ }
303
+ /** Submit counterparty signature to complete mutual signing. */
304
+ async completeMutualSign(actionId, did, signature, signedPayloadHash) {
305
+ return this.post(`/actions/${actionId}/mutual-sign/complete`, { did, signature, signed_payload_hash: signedPayloadHash });
306
+ }
307
+ /** Get the co-signed receipt for a mutually signed action. */
308
+ async getMutualSignReceipt(actionId) {
309
+ return this.get(`/actions/${actionId}/mutual-sign/receipt`);
310
+ }
311
+ /** Reject a mutual signing request. */
312
+ async rejectMutualSign(actionId, reason = "") {
313
+ return this.post(`/actions/${actionId}/mutual-sign/reject`, { reason });
314
+ }
315
+ // ==================== Reputation ====================
316
+ /** Get current reputation score for an agent. */
317
+ async getReputation(slug) {
318
+ return this.get(`/agents/${slug}/reputation`);
319
+ }
320
+ /** Get full reputation history for an agent. */
321
+ async getReputationHistory(slug) {
322
+ return this.get(`/agents/${slug}/reputation/history`);
323
+ }
324
+ /** Submit a signed attestation of a successful interaction. */
325
+ async attestReputation(slug, counterpartyDid, actionId, attestation, signature) {
326
+ return this.post(`/agents/${slug}/reputation/attest`, {
327
+ counterparty_did: counterpartyDid, action_id: actionId, attestation, signature,
328
+ });
329
+ }
330
+ /** Verify a reputation score by returning inputs and score_hash. */
331
+ async verifyReputation(slug) {
332
+ return this.get(`/agents/${slug}/reputation/verify`);
333
+ }
334
+ // ==================== Session ====================
335
+ /** Create a scoped session with pre-filled defaults. */
336
+ session(agentId, defaults) {
337
+ return new session_1.AiraSession(this, agentId, defaults);
338
+ }
339
+ // ==================== Offline sync ====================
340
+ /** Number of queued offline requests. */
341
+ get pendingCount() {
342
+ return this.queue?.pendingCount ?? 0;
343
+ }
344
+ /** Flush offline queue to API. Returns list of API responses. */
345
+ async sync() {
346
+ if (!this.queue)
347
+ throw new Error("sync() is only available in offline mode");
348
+ const items = this.queue.drain();
349
+ const results = [];
350
+ for (const item of items) {
351
+ const res = await this.request(item.method, item.path, item.body);
352
+ results.push(res);
353
+ }
354
+ return results;
355
+ }
253
356
  }
254
357
  exports.Aira = Aira;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Aira SDK extras — framework integrations.
3
+ *
4
+ * Each integration is in its own file to avoid importing unnecessary dependencies.
5
+ * Import directly from the subpath:
6
+ *
7
+ * import { AiraCallbackHandler } from "aira-sdk/extras/langchain";
8
+ * import { AiraVercelMiddleware } from "aira-sdk/extras/vercel-ai";
9
+ * import { AiraGuardrail } from "aira-sdk/extras/openai-agents";
10
+ * import { createServer } from "aira-sdk/extras/mcp";
11
+ * import { verifySignature, parseEvent } from "aira-sdk/extras/webhooks";
12
+ */
13
+ export { AiraCallbackHandler } from "./langchain";
14
+ export { AiraVercelMiddleware } from "./vercel-ai";
15
+ export { AiraGuardrail } from "./openai-agents";
16
+ export { createServer, getTools, handleToolCall } from "./mcp";
17
+ export type { MCPTool, MCPTextContent } from "./mcp";
18
+ export { verifySignature, parseEvent, WebhookEventType } from "./webhooks";
19
+ export type { WebhookEvent, WebhookEventTypeName } from "./webhooks";
20
+ export { checkTrust } from "./trust";
21
+ export type { TrustPolicy, TrustContext } from "./trust";
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * Aira SDK extras — framework integrations.
4
+ *
5
+ * Each integration is in its own file to avoid importing unnecessary dependencies.
6
+ * Import directly from the subpath:
7
+ *
8
+ * import { AiraCallbackHandler } from "aira-sdk/extras/langchain";
9
+ * import { AiraVercelMiddleware } from "aira-sdk/extras/vercel-ai";
10
+ * import { AiraGuardrail } from "aira-sdk/extras/openai-agents";
11
+ * import { createServer } from "aira-sdk/extras/mcp";
12
+ * import { verifySignature, parseEvent } from "aira-sdk/extras/webhooks";
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.checkTrust = exports.WebhookEventType = exports.parseEvent = exports.verifySignature = exports.handleToolCall = exports.getTools = exports.createServer = exports.AiraGuardrail = exports.AiraVercelMiddleware = exports.AiraCallbackHandler = void 0;
16
+ var langchain_1 = require("./langchain");
17
+ Object.defineProperty(exports, "AiraCallbackHandler", { enumerable: true, get: function () { return langchain_1.AiraCallbackHandler; } });
18
+ var vercel_ai_1 = require("./vercel-ai");
19
+ Object.defineProperty(exports, "AiraVercelMiddleware", { enumerable: true, get: function () { return vercel_ai_1.AiraVercelMiddleware; } });
20
+ var openai_agents_1 = require("./openai-agents");
21
+ Object.defineProperty(exports, "AiraGuardrail", { enumerable: true, get: function () { return openai_agents_1.AiraGuardrail; } });
22
+ var mcp_1 = require("./mcp");
23
+ Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return mcp_1.createServer; } });
24
+ Object.defineProperty(exports, "getTools", { enumerable: true, get: function () { return mcp_1.getTools; } });
25
+ Object.defineProperty(exports, "handleToolCall", { enumerable: true, get: function () { return mcp_1.handleToolCall; } });
26
+ var webhooks_1 = require("./webhooks");
27
+ Object.defineProperty(exports, "verifySignature", { enumerable: true, get: function () { return webhooks_1.verifySignature; } });
28
+ Object.defineProperty(exports, "parseEvent", { enumerable: true, get: function () { return webhooks_1.parseEvent; } });
29
+ Object.defineProperty(exports, "WebhookEventType", { enumerable: true, get: function () { return webhooks_1.WebhookEventType; } });
30
+ var trust_1 = require("./trust");
31
+ Object.defineProperty(exports, "checkTrust", { enumerable: true, get: function () { return trust_1.checkTrust; } });
@@ -0,0 +1,42 @@
1
+ /**
2
+ * LangChain.js integration — auto-notarize tool and chain completions.
3
+ *
4
+ * Requires: @langchain/core (peer dependency)
5
+ *
6
+ * Usage:
7
+ * import { AiraCallbackHandler } from "aira-sdk/extras/langchain";
8
+ * const handler = new AiraCallbackHandler(aira, "my-agent");
9
+ * const chain = someChain.withConfig({ callbacks: [handler] });
10
+ */
11
+ import type { Aira } from "../client";
12
+ import type { TrustPolicy, TrustContext } from "./trust";
13
+ export type { TrustPolicy, TrustContext } from "./trust";
14
+ export declare class AiraCallbackHandler {
15
+ private client;
16
+ private agentId;
17
+ private modelId?;
18
+ private actionTypes;
19
+ private trustPolicy?;
20
+ constructor(client: Aira, agentId: string, options?: {
21
+ modelId?: string;
22
+ actionTypes?: Record<string, string>;
23
+ trustPolicy?: TrustPolicy;
24
+ });
25
+ /**
26
+ * Check trust for a counterparty agent before interacting.
27
+ * Advisory by default — only blocks on revoked VC or unregistered agent if configured.
28
+ */
29
+ checkTrust(counterpartyId: string): Promise<TrustContext>;
30
+ private notarize;
31
+ /** Called when a tool finishes. */
32
+ handleToolEnd(output: string, name?: string): void;
33
+ /** Called when a chain finishes. */
34
+ handleChainEnd(outputs: Record<string, unknown>): void;
35
+ /** Called when an LLM finishes. */
36
+ handleLLMEnd(generationCount: number): void;
37
+ /**
38
+ * Returns a LangChain-compatible callbacks object.
39
+ * Use with: chain.invoke(input, { callbacks: [handler.asCallbacks()] })
40
+ */
41
+ asCallbacks(): Record<string, (...args: unknown[]) => void>;
42
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * LangChain.js integration — auto-notarize tool and chain completions.
4
+ *
5
+ * Requires: @langchain/core (peer dependency)
6
+ *
7
+ * Usage:
8
+ * import { AiraCallbackHandler } from "aira-sdk/extras/langchain";
9
+ * const handler = new AiraCallbackHandler(aira, "my-agent");
10
+ * const chain = someChain.withConfig({ callbacks: [handler] });
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AiraCallbackHandler = void 0;
14
+ const trust_1 = require("./trust");
15
+ const MAX_DETAILS = 5000;
16
+ class AiraCallbackHandler {
17
+ client;
18
+ agentId;
19
+ modelId;
20
+ actionTypes;
21
+ trustPolicy;
22
+ constructor(client, agentId, options) {
23
+ this.client = client;
24
+ this.agentId = agentId;
25
+ this.modelId = options?.modelId;
26
+ this.trustPolicy = options?.trustPolicy;
27
+ this.actionTypes = {
28
+ tool_end: "tool_call",
29
+ chain_end: "chain_completed",
30
+ llm_end: "llm_completion",
31
+ ...(options?.actionTypes ?? {}),
32
+ };
33
+ }
34
+ /**
35
+ * Check trust for a counterparty agent before interacting.
36
+ * Advisory by default — only blocks on revoked VC or unregistered agent if configured.
37
+ */
38
+ async checkTrust(counterpartyId) {
39
+ if (!this.trustPolicy) {
40
+ return { counterpartyId, blocked: false, recommendation: "No trust policy configured" };
41
+ }
42
+ return (0, trust_1.checkTrust)(this.client, this.trustPolicy, counterpartyId);
43
+ }
44
+ notarize(actionType, details) {
45
+ try {
46
+ const params = {
47
+ actionType,
48
+ details: details.slice(0, MAX_DETAILS),
49
+ agentId: this.agentId,
50
+ };
51
+ if (this.modelId)
52
+ params.modelId = this.modelId;
53
+ this.client.notarize(params).catch((e) => {
54
+ console.warn("Aira notarize failed (non-blocking):", e);
55
+ });
56
+ }
57
+ catch (e) {
58
+ console.warn("Aira notarize failed (non-blocking):", e);
59
+ }
60
+ }
61
+ /** Called when a tool finishes. */
62
+ handleToolEnd(output, name = "unknown") {
63
+ this.notarize(this.actionTypes.tool_end, `Tool '${name}' completed. Output length: ${String(output).length} chars`);
64
+ }
65
+ /** Called when a chain finishes. */
66
+ handleChainEnd(outputs) {
67
+ const keys = typeof outputs === "object" && outputs ? Object.keys(outputs) : [];
68
+ this.notarize(this.actionTypes.chain_end, `Chain completed. Output keys: [${keys.join(", ")}]`);
69
+ }
70
+ /** Called when an LLM finishes. */
71
+ handleLLMEnd(generationCount) {
72
+ this.notarize(this.actionTypes.llm_end, `LLM completed. Generations: ${generationCount}`);
73
+ }
74
+ /**
75
+ * Returns a LangChain-compatible callbacks object.
76
+ * Use with: chain.invoke(input, { callbacks: [handler.asCallbacks()] })
77
+ */
78
+ asCallbacks() {
79
+ return {
80
+ handleToolEnd: (output, ...args) => {
81
+ const runId = args[1];
82
+ const name = args[2]?.name ?? "unknown";
83
+ this.handleToolEnd(String(output), name);
84
+ },
85
+ handleChainEnd: (outputs) => {
86
+ this.handleChainEnd((outputs ?? {}));
87
+ },
88
+ handleLLMEnd: (response) => {
89
+ const resp = response;
90
+ this.handleLLMEnd(resp?.generations?.length ?? 0);
91
+ },
92
+ };
93
+ }
94
+ }
95
+ exports.AiraCallbackHandler = AiraCallbackHandler;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * MCP server exposing Aira actions as tools for AI agents.
3
+ *
4
+ * Requires: @modelcontextprotocol/sdk (peer dependency)
5
+ *
6
+ * Usage:
7
+ * import { createServer } from "aira-sdk/extras/mcp";
8
+ * const server = createServer({ apiKey: "aira_live_xxx" });
9
+ */
10
+ import type { Aira } from "../client";
11
+ /** Tool definition for MCP list_tools response. */
12
+ export interface MCPTool {
13
+ name: string;
14
+ description: string;
15
+ inputSchema: Record<string, unknown>;
16
+ }
17
+ /** Text content for MCP call_tool response. */
18
+ export interface MCPTextContent {
19
+ type: "text";
20
+ text: string;
21
+ }
22
+ /** MCP tool definitions exposed by the Aira server. */
23
+ export declare function getTools(): MCPTool[];
24
+ /** Handle an MCP tool call and return text content. */
25
+ export declare function handleToolCall(client: Aira, name: string, args: Record<string, unknown>): Promise<MCPTextContent[]>;
26
+ /**
27
+ * Create an MCP-compatible server handler object.
28
+ *
29
+ * This returns plain objects; wire it into @modelcontextprotocol/sdk's Server:
30
+ *
31
+ * import { Server } from "@modelcontextprotocol/sdk/server/index.js";
32
+ * import { createServer } from "aira-sdk/extras/mcp";
33
+ * const { listTools, callTool } = createServer(airaClient);
34
+ * server.setRequestHandler(ListToolsRequestSchema, listTools);
35
+ * server.setRequestHandler(CallToolRequestSchema, callTool);
36
+ */
37
+ export declare function createServer(client: Aira): {
38
+ listTools: () => Promise<{
39
+ tools: MCPTool[];
40
+ }>;
41
+ callTool: (request: {
42
+ params: {
43
+ name: string;
44
+ arguments?: Record<string, unknown>;
45
+ };
46
+ }) => Promise<{
47
+ content: MCPTextContent[];
48
+ }>;
49
+ };
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ /**
3
+ * MCP server exposing Aira actions as tools for AI agents.
4
+ *
5
+ * Requires: @modelcontextprotocol/sdk (peer dependency)
6
+ *
7
+ * Usage:
8
+ * import { createServer } from "aira-sdk/extras/mcp";
9
+ * const server = createServer({ apiKey: "aira_live_xxx" });
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getTools = getTools;
13
+ exports.handleToolCall = handleToolCall;
14
+ exports.createServer = createServer;
15
+ /** MCP tool definitions exposed by the Aira server. */
16
+ function getTools() {
17
+ return [
18
+ {
19
+ name: "notarize_action",
20
+ description: "Notarize an AI agent action with a cryptographic receipt",
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ action_type: { type: "string", description: "e.g. email_sent, loan_approved, claim_processed" },
25
+ details: { type: "string", description: "What happened" },
26
+ agent_id: { type: "string", description: "Agent slug" },
27
+ model_id: { type: "string", description: "Model used (optional)" },
28
+ },
29
+ required: ["action_type", "details"],
30
+ },
31
+ },
32
+ {
33
+ name: "verify_action",
34
+ description: "Verify a notarized action's cryptographic receipt",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ action_id: { type: "string", description: "Action UUID" },
39
+ },
40
+ required: ["action_id"],
41
+ },
42
+ },
43
+ {
44
+ name: "get_receipt",
45
+ description: "Get the cryptographic receipt for a notarized action",
46
+ inputSchema: {
47
+ type: "object",
48
+ properties: {
49
+ receipt_id: { type: "string", description: "Receipt UUID" },
50
+ },
51
+ required: ["receipt_id"],
52
+ },
53
+ },
54
+ {
55
+ name: "resolve_did",
56
+ description: "Resolve a did:web DID to its DID document",
57
+ inputSchema: {
58
+ type: "object",
59
+ properties: {
60
+ did: { type: "string", description: "The DID to resolve (e.g. did:web:airaproof.com:agents:my-agent)" },
61
+ },
62
+ required: ["did"],
63
+ },
64
+ },
65
+ {
66
+ name: "verify_credential",
67
+ description: "Verify a Verifiable Credential — checks signature, expiry, and revocation status",
68
+ inputSchema: {
69
+ type: "object",
70
+ properties: {
71
+ agent_id: { type: "string", description: "Agent slug whose credential to verify" },
72
+ },
73
+ required: ["agent_id"],
74
+ },
75
+ },
76
+ {
77
+ name: "get_reputation",
78
+ description: "Get the current reputation score and tier for an agent",
79
+ inputSchema: {
80
+ type: "object",
81
+ properties: {
82
+ agent_id: { type: "string", description: "Agent slug" },
83
+ },
84
+ required: ["agent_id"],
85
+ },
86
+ },
87
+ {
88
+ name: "request_mutual_sign",
89
+ description: "Initiate a mutual signing request for an action with a counterparty",
90
+ inputSchema: {
91
+ type: "object",
92
+ properties: {
93
+ action_id: { type: "string", description: "Action UUID to co-sign" },
94
+ counterparty_did: { type: "string", description: "DID of the counterparty agent" },
95
+ },
96
+ required: ["action_id", "counterparty_did"],
97
+ },
98
+ },
99
+ ];
100
+ }
101
+ /** Handle an MCP tool call and return text content. */
102
+ async function handleToolCall(client, name, args) {
103
+ try {
104
+ if (name === "notarize_action") {
105
+ const result = await client.notarize({
106
+ actionType: args.action_type,
107
+ details: args.details,
108
+ agentId: args.agent_id,
109
+ modelId: args.model_id,
110
+ });
111
+ return [{ type: "text", text: JSON.stringify(result) }];
112
+ }
113
+ if (name === "verify_action") {
114
+ const result = await client.verifyAction(args.action_id);
115
+ return [{ type: "text", text: JSON.stringify(result) }];
116
+ }
117
+ if (name === "get_receipt") {
118
+ const result = await client.getReceipt(args.receipt_id);
119
+ return [{ type: "text", text: JSON.stringify(result) }];
120
+ }
121
+ if (name === "resolve_did") {
122
+ const result = await client.resolveDid(args.did);
123
+ return [{ type: "text", text: JSON.stringify(result) }];
124
+ }
125
+ if (name === "verify_credential") {
126
+ const cred = await client.getAgentCredential(args.agent_id);
127
+ const result = await client.verifyCredential(cred);
128
+ return [{ type: "text", text: JSON.stringify(result) }];
129
+ }
130
+ if (name === "get_reputation") {
131
+ const result = await client.getReputation(args.agent_id);
132
+ return [{ type: "text", text: JSON.stringify(result) }];
133
+ }
134
+ if (name === "request_mutual_sign") {
135
+ const result = await client.requestMutualSign(args.action_id, args.counterparty_did);
136
+ return [{ type: "text", text: JSON.stringify(result) }];
137
+ }
138
+ return [{ type: "text", text: JSON.stringify({ error: `Unknown tool: ${name}` }) }];
139
+ }
140
+ catch (e) {
141
+ return [{ type: "text", text: JSON.stringify({ error: String(e) }) }];
142
+ }
143
+ }
144
+ /**
145
+ * Create an MCP-compatible server handler object.
146
+ *
147
+ * This returns plain objects; wire it into @modelcontextprotocol/sdk's Server:
148
+ *
149
+ * import { Server } from "@modelcontextprotocol/sdk/server/index.js";
150
+ * import { createServer } from "aira-sdk/extras/mcp";
151
+ * const { listTools, callTool } = createServer(airaClient);
152
+ * server.setRequestHandler(ListToolsRequestSchema, listTools);
153
+ * server.setRequestHandler(CallToolRequestSchema, callTool);
154
+ */
155
+ function createServer(client) {
156
+ return {
157
+ listTools: async () => ({ tools: getTools() }),
158
+ callTool: async (request) => {
159
+ const content = await handleToolCall(client, request.params.name, request.params.arguments ?? {});
160
+ return { content };
161
+ },
162
+ };
163
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * OpenAI Node SDK integration — guardrail that notarizes tool calls.
3
+ *
4
+ * Requires: openai (peer dependency)
5
+ *
6
+ * Usage:
7
+ * import { AiraGuardrail } from "aira-sdk/extras/openai-agents";
8
+ * const guardrail = new AiraGuardrail(aira, "my-agent");
9
+ * guardrail.onToolCall("search", { query: "test" });
10
+ */
11
+ import type { Aira } from "../client";
12
+ import type { TrustPolicy, TrustContext } from "./trust";
13
+ export type { TrustPolicy, TrustContext } from "./trust";
14
+ export declare class AiraGuardrail {
15
+ private client;
16
+ private agentId;
17
+ private modelId?;
18
+ private trustPolicy?;
19
+ constructor(client: Aira, agentId: string, options?: {
20
+ modelId?: string;
21
+ trustPolicy?: TrustPolicy;
22
+ });
23
+ /**
24
+ * Check trust for a counterparty agent before interacting.
25
+ * Advisory by default — only blocks on revoked VC or unregistered agent if configured.
26
+ */
27
+ checkTrust(counterpartyId: string): Promise<TrustContext>;
28
+ private notarize;
29
+ /** Call after a tool execution to notarize it. */
30
+ onToolCall(toolName: string, args?: Record<string, unknown>): void;
31
+ /** Call after a tool returns to notarize the result. */
32
+ onToolResult(toolName: string, result?: unknown): void;
33
+ /**
34
+ * Wraps a tool function to auto-notarize calls and results.
35
+ * No raw user data is sent — only tool name, arg keys, and output length.
36
+ */
37
+ wrapTool<T extends (...args: unknown[]) => unknown>(toolFn: T, toolName?: string): T;
38
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAI Node SDK integration — guardrail that notarizes tool calls.
4
+ *
5
+ * Requires: openai (peer dependency)
6
+ *
7
+ * Usage:
8
+ * import { AiraGuardrail } from "aira-sdk/extras/openai-agents";
9
+ * const guardrail = new AiraGuardrail(aira, "my-agent");
10
+ * guardrail.onToolCall("search", { query: "test" });
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AiraGuardrail = void 0;
14
+ const trust_1 = require("./trust");
15
+ const MAX_DETAILS = 5000;
16
+ class AiraGuardrail {
17
+ client;
18
+ agentId;
19
+ modelId;
20
+ trustPolicy;
21
+ constructor(client, agentId, options) {
22
+ this.client = client;
23
+ this.agentId = agentId;
24
+ this.modelId = options?.modelId;
25
+ this.trustPolicy = options?.trustPolicy;
26
+ }
27
+ /**
28
+ * Check trust for a counterparty agent before interacting.
29
+ * Advisory by default — only blocks on revoked VC or unregistered agent if configured.
30
+ */
31
+ async checkTrust(counterpartyId) {
32
+ if (!this.trustPolicy) {
33
+ return { counterpartyId, blocked: false, recommendation: "No trust policy configured" };
34
+ }
35
+ return (0, trust_1.checkTrust)(this.client, this.trustPolicy, counterpartyId);
36
+ }
37
+ notarize(actionType, details) {
38
+ try {
39
+ const params = {
40
+ actionType,
41
+ details: details.slice(0, MAX_DETAILS),
42
+ agentId: this.agentId,
43
+ };
44
+ if (this.modelId)
45
+ params.modelId = this.modelId;
46
+ this.client.notarize(params).catch((e) => {
47
+ console.warn("Aira notarize failed (non-blocking):", e);
48
+ });
49
+ }
50
+ catch (e) {
51
+ console.warn("Aira notarize failed (non-blocking):", e);
52
+ }
53
+ }
54
+ /** Call after a tool execution to notarize it. */
55
+ onToolCall(toolName, args) {
56
+ const argKeys = Object.keys(args ?? {});
57
+ this.notarize("tool_call", `Tool '${toolName}' called. Arg keys: [${argKeys.join(", ")}]`);
58
+ }
59
+ /** Call after a tool returns to notarize the result. */
60
+ onToolResult(toolName, result) {
61
+ this.notarize("tool_completed", `Tool '${toolName}' completed. Result length: ${String(result).length} chars`);
62
+ }
63
+ /**
64
+ * Wraps a tool function to auto-notarize calls and results.
65
+ * No raw user data is sent — only tool name, arg keys, and output length.
66
+ */
67
+ wrapTool(toolFn, toolName) {
68
+ const name = toolName ?? toolFn.name ?? "unknown";
69
+ const self = this;
70
+ const wrapped = async function (...args) {
71
+ const kwargs = args.length > 0 && typeof args[0] === "object" && args[0]
72
+ ? args[0]
73
+ : undefined;
74
+ self.onToolCall(name, kwargs);
75
+ const result = await toolFn.apply(this, args);
76
+ self.onToolResult(name, result);
77
+ return result;
78
+ };
79
+ return wrapped;
80
+ }
81
+ }
82
+ exports.AiraGuardrail = AiraGuardrail;