aira-sdk 0.4.0 → 2.1.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/README.md +302 -108
- package/dist/client.d.ts +112 -4
- package/dist/client.js +162 -8
- package/dist/extras/index.d.ts +49 -2
- package/dist/extras/index.js +90 -3
- package/dist/extras/langchain.d.ts +69 -18
- package/dist/extras/langchain.js +118 -35
- package/dist/extras/mcp.d.ts +24 -3
- package/dist/extras/mcp.js +75 -10
- package/dist/extras/openai-agents.d.ts +48 -16
- package/dist/extras/openai-agents.js +85 -29
- package/dist/extras/vercel-ai.d.ts +54 -17
- package/dist/extras/vercel-ai.js +104 -30
- package/dist/index.d.ts +1 -1
- package/dist/session.d.ts +15 -4
- package/dist/session.js +11 -3
- package/dist/types.d.ts +74 -20
- package/dist/types.js +15 -4
- package/package.json +2 -2
|
@@ -1,48 +1,85 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Vercel AI SDK integration —
|
|
2
|
+
* Vercel AI SDK integration — pre-execution gate via tool wrapping.
|
|
3
3
|
*
|
|
4
4
|
* Requires: ai (Vercel AI SDK, peer dependency)
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* ---------------------------------------------------------------------------
|
|
7
|
+
* LIFECYCLE & DESIGN NOTES
|
|
8
|
+
* ---------------------------------------------------------------------------
|
|
9
|
+
*
|
|
10
|
+
* Vercel AI SDK exposes two integration points:
|
|
11
|
+
*
|
|
12
|
+
* 1. `onStepFinish` / `onFinish` callbacks on `generateText` / `streamText`
|
|
13
|
+
* — these fire AFTER each step or after the whole generation completes.
|
|
14
|
+
* They are post-hoc only; they cannot block a tool from running.
|
|
15
|
+
*
|
|
16
|
+
* 2. The per-tool `execute` function (user code) — this runs BEFORE the
|
|
17
|
+
* model sees the tool result. Wrapping it is the only place where we
|
|
18
|
+
* can synchronously gate execution.
|
|
19
|
+
*
|
|
20
|
+
* Therefore the `wrapTool()` method is the real authorization gate: it calls
|
|
21
|
+
* `aira.authorize()` before invoking the underlying tool and `aira.notarize()`
|
|
22
|
+
* after. If authorize returns `pending_approval` we throw so the tool does
|
|
23
|
+
* NOT run; the model will see the tool result as an error and react
|
|
24
|
+
* accordingly (typically by stopping or asking the user).
|
|
25
|
+
*
|
|
26
|
+
* The `onStepFinish` / `onFinish` helpers below are AUDIT-ONLY: they cannot
|
|
27
|
+
* gate execution (Vercel AI has no pre-step hook), and they run after the
|
|
28
|
+
* tool has already executed. They produce receipts for the overall
|
|
29
|
+
* generation as an audit trail, not as an authorization boundary.
|
|
10
30
|
*/
|
|
11
31
|
import type { Aira } from "../client";
|
|
12
32
|
import type { TrustPolicy, TrustContext } from "./trust";
|
|
13
33
|
export type { TrustPolicy, TrustContext } from "./trust";
|
|
34
|
+
export interface AiraVercelMiddlewareOptions {
|
|
35
|
+
modelId?: string;
|
|
36
|
+
trustPolicy?: TrustPolicy;
|
|
37
|
+
/** Fail closed if authorize() fails (network, 5xx). Default: false. */
|
|
38
|
+
strict?: boolean;
|
|
39
|
+
}
|
|
14
40
|
export declare class AiraVercelMiddleware {
|
|
15
41
|
private client;
|
|
16
42
|
private agentId;
|
|
17
43
|
private modelId?;
|
|
18
44
|
private trustPolicy?;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
trustPolicy?: TrustPolicy;
|
|
22
|
-
});
|
|
45
|
+
private strict;
|
|
46
|
+
constructor(client: Aira, agentId: string, options?: AiraVercelMiddlewareOptions);
|
|
23
47
|
/**
|
|
24
48
|
* Check trust for a counterparty agent before interacting.
|
|
25
49
|
* Advisory by default — only blocks on revoked VC or unregistered agent if configured.
|
|
26
50
|
*/
|
|
27
51
|
checkTrust(counterpartyId: string): Promise<TrustContext>;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* AUDIT-ONLY: log a post-hoc receipt for a generation step.
|
|
54
|
+
* Vercel AI has no pre-step hook; this cannot gate execution.
|
|
55
|
+
*/
|
|
56
|
+
private auditFinish;
|
|
57
|
+
/**
|
|
58
|
+
* AUDIT-ONLY: called after a step finishes.
|
|
59
|
+
* Cannot block the step — it has already run.
|
|
60
|
+
*/
|
|
34
61
|
onStepFinish(stepType: string, tokenCount?: number): void;
|
|
35
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* AUDIT-ONLY: called after full generation finishes.
|
|
64
|
+
*/
|
|
36
65
|
onFinish(finishReason: string, totalTokens?: number): void;
|
|
37
66
|
/**
|
|
38
67
|
* Returns a Vercel AI SDK-compatible callbacks object for streamText/generateText.
|
|
68
|
+
* These callbacks are AUDIT-ONLY and cannot gate execution.
|
|
39
69
|
*
|
|
40
70
|
* Usage:
|
|
41
71
|
* const result = await streamText({ ...opts, ...middleware.asCallbacks() });
|
|
42
72
|
*/
|
|
43
73
|
asCallbacks(): Record<string, (...args: unknown[]) => void>;
|
|
44
74
|
/**
|
|
45
|
-
*
|
|
75
|
+
* REAL GATE: wraps a tool's execute function so that:
|
|
76
|
+
* 1. `aira.authorize()` runs BEFORE the tool — throws on POLICY_DENIED
|
|
77
|
+
* or pending_approval, which prevents the tool from executing.
|
|
78
|
+
* 2. If authorized, the tool runs.
|
|
79
|
+
* 3. `aira.notarize()` runs AFTER, with outcome "completed" or "failed".
|
|
80
|
+
*
|
|
81
|
+
* This is the recommended integration point for Vercel AI because it's
|
|
82
|
+
* the only place where pre-execution gating is possible.
|
|
46
83
|
*/
|
|
47
84
|
wrapTool<T extends (...args: unknown[]) => unknown>(toolFn: T, toolName: string): T;
|
|
48
85
|
}
|
package/dist/extras/vercel-ai.js
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Vercel AI SDK integration —
|
|
3
|
+
* Vercel AI SDK integration — pre-execution gate via tool wrapping.
|
|
4
4
|
*
|
|
5
5
|
* Requires: ai (Vercel AI SDK, peer dependency)
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* ---------------------------------------------------------------------------
|
|
8
|
+
* LIFECYCLE & DESIGN NOTES
|
|
9
|
+
* ---------------------------------------------------------------------------
|
|
10
|
+
*
|
|
11
|
+
* Vercel AI SDK exposes two integration points:
|
|
12
|
+
*
|
|
13
|
+
* 1. `onStepFinish` / `onFinish` callbacks on `generateText` / `streamText`
|
|
14
|
+
* — these fire AFTER each step or after the whole generation completes.
|
|
15
|
+
* They are post-hoc only; they cannot block a tool from running.
|
|
16
|
+
*
|
|
17
|
+
* 2. The per-tool `execute` function (user code) — this runs BEFORE the
|
|
18
|
+
* model sees the tool result. Wrapping it is the only place where we
|
|
19
|
+
* can synchronously gate execution.
|
|
20
|
+
*
|
|
21
|
+
* Therefore the `wrapTool()` method is the real authorization gate: it calls
|
|
22
|
+
* `aira.authorize()` before invoking the underlying tool and `aira.notarize()`
|
|
23
|
+
* after. If authorize returns `pending_approval` we throw so the tool does
|
|
24
|
+
* NOT run; the model will see the tool result as an error and react
|
|
25
|
+
* accordingly (typically by stopping or asking the user).
|
|
26
|
+
*
|
|
27
|
+
* The `onStepFinish` / `onFinish` helpers below are AUDIT-ONLY: they cannot
|
|
28
|
+
* gate execution (Vercel AI has no pre-step hook), and they run after the
|
|
29
|
+
* tool has already executed. They produce receipts for the overall
|
|
30
|
+
* generation as an audit trail, not as an authorization boundary.
|
|
11
31
|
*/
|
|
12
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
33
|
exports.AiraVercelMiddleware = void 0;
|
|
@@ -18,11 +38,13 @@ class AiraVercelMiddleware {
|
|
|
18
38
|
agentId;
|
|
19
39
|
modelId;
|
|
20
40
|
trustPolicy;
|
|
41
|
+
strict;
|
|
21
42
|
constructor(client, agentId, options) {
|
|
22
43
|
this.client = client;
|
|
23
44
|
this.agentId = agentId;
|
|
24
45
|
this.modelId = options?.modelId;
|
|
25
46
|
this.trustPolicy = options?.trustPolicy;
|
|
47
|
+
this.strict = options?.strict ?? false;
|
|
26
48
|
}
|
|
27
49
|
/**
|
|
28
50
|
* Check trust for a counterparty agent before interacting.
|
|
@@ -34,41 +56,43 @@ class AiraVercelMiddleware {
|
|
|
34
56
|
}
|
|
35
57
|
return (0, trust_1.checkTrust)(this.client, this.trustPolicy, counterpartyId);
|
|
36
58
|
}
|
|
37
|
-
|
|
59
|
+
/**
|
|
60
|
+
* AUDIT-ONLY: log a post-hoc receipt for a generation step.
|
|
61
|
+
* Vercel AI has no pre-step hook; this cannot gate execution.
|
|
62
|
+
*/
|
|
63
|
+
async auditFinish(actionType, details) {
|
|
38
64
|
try {
|
|
39
|
-
const
|
|
65
|
+
const auth = await this.client.authorize({
|
|
40
66
|
actionType,
|
|
41
67
|
details: details.slice(0, MAX_DETAILS),
|
|
42
68
|
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);
|
|
69
|
+
modelId: this.modelId,
|
|
48
70
|
});
|
|
71
|
+
if (auth.status === "authorized") {
|
|
72
|
+
await this.client.notarize({ actionId: auth.action_id, outcome: "completed" });
|
|
73
|
+
}
|
|
74
|
+
// If pending_approval — just leave it; nothing to execute for audit-only.
|
|
49
75
|
}
|
|
50
76
|
catch (e) {
|
|
51
|
-
console.warn("Aira
|
|
77
|
+
console.warn("Aira audit failed (non-blocking):", e);
|
|
52
78
|
}
|
|
53
79
|
}
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
/** Call after a tool returns to notarize the result. */
|
|
59
|
-
onToolResult(toolName, resultLength) {
|
|
60
|
-
this.notarize("tool_completed", `Tool '${toolName}' completed. Result length: ${resultLength} chars`);
|
|
61
|
-
}
|
|
62
|
-
/** Call when a text generation step completes. */
|
|
80
|
+
/**
|
|
81
|
+
* AUDIT-ONLY: called after a step finishes.
|
|
82
|
+
* Cannot block the step — it has already run.
|
|
83
|
+
*/
|
|
63
84
|
onStepFinish(stepType, tokenCount) {
|
|
64
|
-
this.
|
|
85
|
+
void this.auditFinish("step_completed", `Step '${stepType}' completed.${tokenCount != null ? ` Tokens: ${tokenCount}` : ""}`);
|
|
65
86
|
}
|
|
66
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* AUDIT-ONLY: called after full generation finishes.
|
|
89
|
+
*/
|
|
67
90
|
onFinish(finishReason, totalTokens) {
|
|
68
|
-
this.
|
|
91
|
+
void this.auditFinish("generation_completed", `Generation completed. Reason: ${finishReason}.${totalTokens != null ? ` Total tokens: ${totalTokens}` : ""}`);
|
|
69
92
|
}
|
|
70
93
|
/**
|
|
71
94
|
* Returns a Vercel AI SDK-compatible callbacks object for streamText/generateText.
|
|
95
|
+
* These callbacks are AUDIT-ONLY and cannot gate execution.
|
|
72
96
|
*
|
|
73
97
|
* Usage:
|
|
74
98
|
* const result = await streamText({ ...opts, ...middleware.asCallbacks() });
|
|
@@ -86,15 +110,65 @@ class AiraVercelMiddleware {
|
|
|
86
110
|
};
|
|
87
111
|
}
|
|
88
112
|
/**
|
|
89
|
-
*
|
|
113
|
+
* REAL GATE: wraps a tool's execute function so that:
|
|
114
|
+
* 1. `aira.authorize()` runs BEFORE the tool — throws on POLICY_DENIED
|
|
115
|
+
* or pending_approval, which prevents the tool from executing.
|
|
116
|
+
* 2. If authorized, the tool runs.
|
|
117
|
+
* 3. `aira.notarize()` runs AFTER, with outcome "completed" or "failed".
|
|
118
|
+
*
|
|
119
|
+
* This is the recommended integration point for Vercel AI because it's
|
|
120
|
+
* the only place where pre-execution gating is possible.
|
|
90
121
|
*/
|
|
91
122
|
wrapTool(toolFn, toolName) {
|
|
92
123
|
const self = this;
|
|
93
124
|
const wrapped = async function (...args) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
125
|
+
const argKeys = args.length > 0 && typeof args[0] === "object" && args[0]
|
|
126
|
+
? Object.keys(args[0])
|
|
127
|
+
: [];
|
|
128
|
+
let actionId = null;
|
|
129
|
+
try {
|
|
130
|
+
const auth = await self.client.authorize({
|
|
131
|
+
actionType: "tool_call",
|
|
132
|
+
details: `Tool '${toolName}' called. Arg keys: [${argKeys.join(", ")}]`.slice(0, MAX_DETAILS),
|
|
133
|
+
agentId: self.agentId,
|
|
134
|
+
modelId: self.modelId,
|
|
135
|
+
});
|
|
136
|
+
if (auth.status === "pending_approval") {
|
|
137
|
+
const err = new Error(`Aira: tool '${toolName}' is pending human approval (action_id=${auth.action_id}). Tool execution blocked.`);
|
|
138
|
+
err.code = "PENDING_APPROVAL";
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
actionId = auth.action_id;
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
const err = e;
|
|
145
|
+
if (err.code === "POLICY_DENIED" || err.code === "PENDING_APPROVAL")
|
|
146
|
+
throw e;
|
|
147
|
+
if (self.strict)
|
|
148
|
+
throw e;
|
|
149
|
+
console.warn("Aira authorize failed (fail-open):", err);
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const result = await toolFn.apply(this, args);
|
|
153
|
+
if (actionId) {
|
|
154
|
+
await self.client.notarize({
|
|
155
|
+
actionId,
|
|
156
|
+
outcome: "completed",
|
|
157
|
+
outcomeDetails: `Tool '${toolName}' completed. Result length: ${String(result).length} chars`.slice(0, MAX_DETAILS),
|
|
158
|
+
}).catch((e) => console.warn("Aira notarize failed (non-blocking):", e));
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
if (actionId) {
|
|
164
|
+
await self.client.notarize({
|
|
165
|
+
actionId,
|
|
166
|
+
outcome: "failed",
|
|
167
|
+
outcomeDetails: `Tool '${toolName}' failed: ${err?.message ?? String(err)}`.slice(0, MAX_DETAILS),
|
|
168
|
+
}).catch((e) => console.warn("Aira notarize failed (non-blocking):", e));
|
|
169
|
+
}
|
|
170
|
+
throw err;
|
|
171
|
+
}
|
|
98
172
|
};
|
|
99
173
|
return wrapped;
|
|
100
174
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export type { AiraOptions } from "./client";
|
|
|
3
3
|
export { AiraSession } from "./session";
|
|
4
4
|
export { OfflineQueue } from "./offline";
|
|
5
5
|
export type { QueuedRequest } from "./offline";
|
|
6
|
-
export { AiraError, type ActionReceipt, type ActionDetail, type AgentDetail, type AgentVersion, type EvidencePackage, type ComplianceSnapshot, type EscrowAccount, type EscrowTransaction, type VerifyResult, type PaginatedList, } from "./types";
|
|
6
|
+
export { AiraError, type Authorization, type ActionReceipt, type ActionDetail, type AgentDetail, type AgentVersion, type CosignResult, type EvidencePackage, type ComplianceSnapshot, type EscrowAccount, type EscrowTransaction, type VerifyResult, type PaginatedList, } from "./types";
|
package/dist/session.d.ts
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AiraSession — scoped session with pre-filled defaults
|
|
2
|
+
* AiraSession — scoped session with pre-filled defaults for `authorize()`.
|
|
3
|
+
*
|
|
4
|
+
* Under the two-step flow, only `authorize()` takes agent/model metadata;
|
|
5
|
+
* `notarize()` operates on an existing action_id. This session therefore
|
|
6
|
+
* merges defaults on `authorize()` only and provides a thin passthrough
|
|
7
|
+
* for `notarize()` so callers can use a single object end-to-end.
|
|
3
8
|
*/
|
|
4
9
|
import type { Aira } from "./client";
|
|
5
|
-
import type { ActionReceipt } from "./types";
|
|
10
|
+
import type { Authorization, ActionReceipt } from "./types";
|
|
6
11
|
export declare class AiraSession {
|
|
7
12
|
private client;
|
|
8
13
|
private defaults;
|
|
9
14
|
constructor(client: Aira, agentId: string, defaults?: Record<string, unknown>);
|
|
10
|
-
|
|
15
|
+
authorize(params: {
|
|
11
16
|
actionType: string;
|
|
12
17
|
details: string;
|
|
18
|
+
instructionHash?: string;
|
|
13
19
|
modelId?: string;
|
|
14
20
|
modelVersion?: string;
|
|
15
|
-
instructionHash?: string;
|
|
16
21
|
parentActionId?: string;
|
|
22
|
+
endpointUrl?: string;
|
|
17
23
|
storeDetails?: boolean;
|
|
18
24
|
idempotencyKey?: string;
|
|
19
25
|
requireApproval?: boolean;
|
|
20
26
|
approvers?: string[];
|
|
27
|
+
}): Promise<Authorization>;
|
|
28
|
+
notarize(params: {
|
|
29
|
+
actionId: string;
|
|
30
|
+
outcome?: "completed" | "failed";
|
|
31
|
+
outcomeDetails?: string;
|
|
21
32
|
}): Promise<ActionReceipt>;
|
|
22
33
|
}
|
package/dist/session.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* AiraSession — scoped session with pre-filled defaults
|
|
3
|
+
* AiraSession — scoped session with pre-filled defaults for `authorize()`.
|
|
4
|
+
*
|
|
5
|
+
* Under the two-step flow, only `authorize()` takes agent/model metadata;
|
|
6
|
+
* `notarize()` operates on an existing action_id. This session therefore
|
|
7
|
+
* merges defaults on `authorize()` only and provides a thin passthrough
|
|
8
|
+
* for `notarize()` so callers can use a single object end-to-end.
|
|
4
9
|
*/
|
|
5
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
11
|
exports.AiraSession = void 0;
|
|
@@ -11,14 +16,17 @@ class AiraSession {
|
|
|
11
16
|
this.client = client;
|
|
12
17
|
this.defaults = { agentId, ...(defaults ?? {}) };
|
|
13
18
|
}
|
|
14
|
-
async
|
|
19
|
+
async authorize(params) {
|
|
15
20
|
const merged = {
|
|
16
21
|
agentId: this.defaults.agentId,
|
|
17
22
|
...(this.defaults.modelId ? { modelId: this.defaults.modelId } : {}),
|
|
18
23
|
...(this.defaults.agentVersion ? { agentVersion: this.defaults.agentVersion } : {}),
|
|
19
24
|
...params,
|
|
20
25
|
};
|
|
21
|
-
return this.client.
|
|
26
|
+
return this.client.authorize(merged);
|
|
27
|
+
}
|
|
28
|
+
async notarize(params) {
|
|
29
|
+
return this.client.notarize(params);
|
|
22
30
|
}
|
|
23
31
|
}
|
|
24
32
|
exports.AiraSession = AiraSession;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Authorization result from `authorize()` — Step 1 of the two-step flow.
|
|
3
|
+
*
|
|
4
|
+
* Status tells you what to do next:
|
|
5
|
+
* - "authorized" → execute the action, then call `notarize()`
|
|
6
|
+
* - "pending_approval" → enqueue the action_id and wait for human approval
|
|
7
|
+
*
|
|
8
|
+
* POLICY_DENIED is raised as an `AiraError` — not returned as a status.
|
|
9
|
+
*/
|
|
10
|
+
export interface Authorization {
|
|
11
|
+
action_id: string;
|
|
12
|
+
status: "authorized" | "pending_approval";
|
|
13
|
+
created_at: string;
|
|
14
|
+
request_id: string;
|
|
15
|
+
warnings: string[] | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Cryptographic receipt from notarizing an action — Step 2 of the two-step flow.
|
|
19
|
+
*
|
|
20
|
+
* Only populated when `status === "notarized"`. For "failed" outcomes,
|
|
21
|
+
* the receipt fields stay null — only the audit trail is recorded.
|
|
22
|
+
*/
|
|
2
23
|
export interface ActionReceipt {
|
|
3
24
|
action_id: string;
|
|
4
|
-
|
|
5
|
-
payload_hash: string;
|
|
6
|
-
signature: string;
|
|
7
|
-
timestamp_token: string | null;
|
|
25
|
+
status: "notarized" | "failed";
|
|
8
26
|
created_at: string;
|
|
9
27
|
request_id: string;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
policy_id: string;
|
|
16
|
-
policy_name: string;
|
|
17
|
-
decision: string;
|
|
18
|
-
reasoning: string | null;
|
|
19
|
-
confidence: number | null;
|
|
20
|
-
} | null;
|
|
28
|
+
receipt_id: string | null;
|
|
29
|
+
payload_hash: string | null;
|
|
30
|
+
signature: string | null;
|
|
31
|
+
timestamp_token: string | null;
|
|
32
|
+
warnings: string[] | null;
|
|
21
33
|
}
|
|
22
34
|
/** Full action details including receipt and authorizations. */
|
|
23
35
|
export interface ActionDetail {
|
|
@@ -71,6 +83,7 @@ export interface AgentVersion {
|
|
|
71
83
|
changelog: string | null;
|
|
72
84
|
status: string;
|
|
73
85
|
published_at: string | null;
|
|
86
|
+
created_at: string;
|
|
74
87
|
}
|
|
75
88
|
/** Sealed evidence package. */
|
|
76
89
|
export interface EvidencePackage {
|
|
@@ -124,7 +137,18 @@ export interface EscrowTransaction {
|
|
|
124
137
|
description?: string | null;
|
|
125
138
|
reference_action_id?: string | null;
|
|
126
139
|
}
|
|
127
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* Result of a public action receipt verification.
|
|
142
|
+
*
|
|
143
|
+
* The endpoint actually recomputes the SHA-256 hash and verifies the
|
|
144
|
+
* Ed25519 signature against the published public key — `valid` is the
|
|
145
|
+
* result of that real cryptographic check, not just an existence check.
|
|
146
|
+
*
|
|
147
|
+
* On a successful (or tamper-detected) verification the result includes
|
|
148
|
+
* the full evidence — `signature`, `public_key`, `signed_payload`,
|
|
149
|
+
* `timestamp_token` — so an external auditor can re-run the same check
|
|
150
|
+
* with OpenSSL or any Ed25519 library without trusting Aira's verdict.
|
|
151
|
+
*/
|
|
128
152
|
export interface VerifyResult {
|
|
129
153
|
valid: boolean;
|
|
130
154
|
public_key_id: string;
|
|
@@ -133,6 +157,12 @@ export interface VerifyResult {
|
|
|
133
157
|
request_id: string;
|
|
134
158
|
receipt_id?: string | null;
|
|
135
159
|
action_id?: string | null;
|
|
160
|
+
payload_hash?: string | null;
|
|
161
|
+
signature?: string | null;
|
|
162
|
+
public_key?: string | null;
|
|
163
|
+
algorithm?: string | null;
|
|
164
|
+
timestamp_token?: string | null;
|
|
165
|
+
signed_payload?: Record<string, unknown> | null;
|
|
136
166
|
}
|
|
137
167
|
/** Paginated list response. */
|
|
138
168
|
export interface PaginatedList<T = Record<string, unknown>> {
|
|
@@ -142,9 +172,33 @@ export interface PaginatedList<T = Record<string, unknown>> {
|
|
|
142
172
|
per_page: number;
|
|
143
173
|
has_more: boolean;
|
|
144
174
|
}
|
|
145
|
-
/**
|
|
175
|
+
/**
|
|
176
|
+
* Human co-signature on an action.
|
|
177
|
+
*
|
|
178
|
+
* Returned by `Aira.cosign()`. Records that a specific human has
|
|
179
|
+
* acknowledged or signed off on an action that was already authorized
|
|
180
|
+
* (and optionally already notarized).
|
|
181
|
+
*/
|
|
182
|
+
export interface CosignResult {
|
|
183
|
+
cosignature_id: string;
|
|
184
|
+
action_id: string;
|
|
185
|
+
cosigner_email: string;
|
|
186
|
+
cosigned_at: string;
|
|
187
|
+
request_id: string;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Aira API error.
|
|
191
|
+
*
|
|
192
|
+
* There is a single error type — catch `AiraError` and branch on
|
|
193
|
+
* `e.code` (`"POLICY_DENIED"`, `"INVALID_STATE"`, `"NOT_FOUND"`, ...).
|
|
194
|
+
* There are no subclasses per error code.
|
|
195
|
+
*/
|
|
146
196
|
export declare class AiraError extends Error {
|
|
147
|
-
status
|
|
197
|
+
/** HTTP status code from the backend response. */
|
|
198
|
+
statusCode: number;
|
|
199
|
+
/** Error code string (e.g. "POLICY_DENIED", "INVALID_STATE"). */
|
|
148
200
|
code: string;
|
|
149
|
-
|
|
201
|
+
/** Optional backend-supplied context (policy_id, action_id, etc.). */
|
|
202
|
+
details: Record<string, unknown>;
|
|
203
|
+
constructor(statusCode: number, code: string, message: string, details?: Record<string, unknown>);
|
|
150
204
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AiraError = void 0;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Aira API error.
|
|
6
|
+
*
|
|
7
|
+
* There is a single error type — catch `AiraError` and branch on
|
|
8
|
+
* `e.code` (`"POLICY_DENIED"`, `"INVALID_STATE"`, `"NOT_FOUND"`, ...).
|
|
9
|
+
* There are no subclasses per error code.
|
|
10
|
+
*/
|
|
5
11
|
class AiraError extends Error {
|
|
6
|
-
status
|
|
12
|
+
/** HTTP status code from the backend response. */
|
|
13
|
+
statusCode;
|
|
14
|
+
/** Error code string (e.g. "POLICY_DENIED", "INVALID_STATE"). */
|
|
7
15
|
code;
|
|
8
|
-
|
|
16
|
+
/** Optional backend-supplied context (policy_id, action_id, etc.). */
|
|
17
|
+
details;
|
|
18
|
+
constructor(statusCode, code, message, details = {}) {
|
|
9
19
|
super(`[${code}] ${message}`);
|
|
10
20
|
this.name = "AiraError";
|
|
11
|
-
this.
|
|
21
|
+
this.statusCode = statusCode;
|
|
12
22
|
this.code = code;
|
|
23
|
+
this.details = details;
|
|
13
24
|
}
|
|
14
25
|
}
|
|
15
26
|
exports.AiraError = AiraError;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aira-sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "The authorization and audit layer for AI agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|