agentcheck-sdk 0.1.0 → 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.d.ts CHANGED
@@ -3,7 +3,7 @@ export declare class AgentCheckClient {
3
3
  private apiKey;
4
4
  private baseUrl;
5
5
  constructor(apiKey: string, baseUrl?: string);
6
- private request;
6
+ request<T>(method: string, path: string, body?: unknown, auth?: boolean): Promise<T>;
7
7
  /** Create a new agreement and send approval email. */
8
8
  record(params: CreateRecordParams): Promise<Agreement>;
9
9
  /** Get agreement details by ID. */
@@ -0,0 +1,36 @@
1
+ import { AgentCheckClient } from "./client";
2
+ export interface DashboardConfig {
3
+ /** Title shown at the top */
4
+ title?: string;
5
+ /** Auto-refresh interval in seconds (0 = off) */
6
+ refreshInterval?: number;
7
+ /** Max records to show */
8
+ limit?: number;
9
+ }
10
+ /**
11
+ * DelegationDashboard - Embeddable HTML widget for agent delegation status.
12
+ *
13
+ * Generates a self-contained HTML snippet that shows:
14
+ * - Active delegations with status badges
15
+ * - Recent execution logs
16
+ * - Quick actions (revoke)
17
+ *
18
+ * Usage (Express):
19
+ * app.get('/admin/delegations', async (req, res) => {
20
+ * const html = await dashboard.render();
21
+ * res.send(html);
22
+ * });
23
+ *
24
+ * Usage (embed in existing page):
25
+ * const html = await dashboard.renderWidget();
26
+ * // Insert into your page's <div id="delegation-widget">
27
+ */
28
+ export declare class DelegationDashboard {
29
+ private client;
30
+ private config;
31
+ constructor(client: AgentCheckClient, config?: DashboardConfig);
32
+ /** Render full HTML page with dashboard. */
33
+ render(): Promise<string>;
34
+ /** Render widget HTML (for embedding in existing pages). */
35
+ renderWidget(): Promise<string>;
36
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DelegationDashboard = void 0;
4
+ /**
5
+ * DelegationDashboard - Embeddable HTML widget for agent delegation status.
6
+ *
7
+ * Generates a self-contained HTML snippet that shows:
8
+ * - Active delegations with status badges
9
+ * - Recent execution logs
10
+ * - Quick actions (revoke)
11
+ *
12
+ * Usage (Express):
13
+ * app.get('/admin/delegations', async (req, res) => {
14
+ * const html = await dashboard.render();
15
+ * res.send(html);
16
+ * });
17
+ *
18
+ * Usage (embed in existing page):
19
+ * const html = await dashboard.renderWidget();
20
+ * // Insert into your page's <div id="delegation-widget">
21
+ */
22
+ class DelegationDashboard {
23
+ constructor(client, config = {}) {
24
+ this.client = client;
25
+ this.config = {
26
+ title: config.title ?? "Agent Delegations",
27
+ refreshInterval: config.refreshInterval ?? 30,
28
+ limit: config.limit ?? 20,
29
+ };
30
+ }
31
+ /** Render full HTML page with dashboard. */
32
+ async render() {
33
+ const widget = await this.renderWidget();
34
+ const refresh = this.config.refreshInterval > 0
35
+ ? `<meta http-equiv="refresh" content="${this.config.refreshInterval}">`
36
+ : "";
37
+ return `<!DOCTYPE html>
38
+ <html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
39
+ ${refresh}
40
+ <title>${this.config.title}</title>
41
+ <style>${DASHBOARD_CSS}</style>
42
+ </head><body>${widget}</body></html>`;
43
+ }
44
+ /** Render widget HTML (for embedding in existing pages). */
45
+ async renderWidget() {
46
+ const list = await this.client.list({ limit: this.config.limit });
47
+ const records = list.records;
48
+ const statusCounts = {};
49
+ for (const r of records) {
50
+ statusCounts[r.status] = (statusCounts[r.status] || 0) + 1;
51
+ }
52
+ const summaryCards = Object.entries(statusCounts)
53
+ .map(([status, count]) => `<div class="ac-card"><div class="ac-card-num">${count}</div><div class="ac-card-label">${status}</div></div>`).join("\n");
54
+ const rows = records
55
+ .map((r) => {
56
+ const statusClass = r.status === "approved" ? "ac-approved"
57
+ : r.status === "revoked" ? "ac-revoked"
58
+ : r.status === "expired" ? "ac-expired"
59
+ : "ac-pending";
60
+ return `<tr>
61
+ <td><span class="ac-badge ${statusClass}">${r.status}</span></td>
62
+ <td>${r.agent}</td>
63
+ <td title="${r.scope}">${r.scope.length > 60 ? r.scope.slice(0, 60) + "..." : r.scope}</td>
64
+ <td>${r.authorized_by}</td>
65
+ <td>${new Date(r.created_at).toLocaleDateString()}</td>
66
+ <td><a href="${r.verify_url}" target="_blank">Verify</a></td>
67
+ </tr>`;
68
+ }).join("\n");
69
+ return `<div class="ac-dashboard">
70
+ <h2 class="ac-title">${this.config.title}</h2>
71
+ <div class="ac-cards">${summaryCards}</div>
72
+ <table class="ac-table">
73
+ <thead><tr>
74
+ <th>Status</th><th>Agent</th><th>Scope</th><th>Authorized by</th><th>Created</th><th>Verify</th>
75
+ </tr></thead>
76
+ <tbody>${rows}</tbody>
77
+ </table>
78
+ <div class="ac-footer">${records.length} delegation(s) | ${this.config.refreshInterval > 0 ? `Auto-refresh: ${this.config.refreshInterval}s` : "Manual refresh"}</div>
79
+ </div>
80
+ <style>${DASHBOARD_CSS}</style>`;
81
+ }
82
+ }
83
+ exports.DelegationDashboard = DelegationDashboard;
84
+ const DASHBOARD_CSS = `
85
+ .ac-dashboard{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;max-width:960px;margin:0 auto;padding:24px;}
86
+ .ac-title{font-size:20px;font-weight:700;margin:0 0 20px;color:#1e293b;}
87
+ .ac-cards{display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap;}
88
+ .ac-card{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:16px 20px;min-width:100px;text-align:center;}
89
+ .ac-card-num{font-size:28px;font-weight:800;color:#1e293b;}
90
+ .ac-card-label{font-size:12px;color:#64748b;text-transform:uppercase;letter-spacing:.5px;margin-top:4px;}
91
+ .ac-table{width:100%;border-collapse:collapse;background:#fff;border-radius:10px;overflow:hidden;border:1px solid #e5e7eb;}
92
+ .ac-table th{padding:10px 14px;text-align:left;font-size:12px;font-weight:700;color:#475569;background:#f8fafc;border-bottom:2px solid #e5e7eb;}
93
+ .ac-table td{padding:10px 14px;font-size:13px;color:#555;border-bottom:1px solid #f0f0f0;}
94
+ .ac-table a{color:#2563eb;font-size:12px;}
95
+ .ac-badge{display:inline-block;padding:2px 10px;border-radius:9999px;font-size:11px;font-weight:700;color:#fff;}
96
+ .ac-approved{background:#16a34a;}
97
+ .ac-pending{background:#ca8a04;}
98
+ .ac-revoked{background:#dc2626;}
99
+ .ac-expired{background:#6b7280;}
100
+ .ac-footer{text-align:center;color:#94a3b8;font-size:12px;margin-top:16px;}
101
+ `;
@@ -0,0 +1,31 @@
1
+ import { DelegationProvider } from "./provider";
2
+ type RequestLike = {
3
+ headers: Record<string, string | string[] | undefined>;
4
+ body?: any;
5
+ path?: string;
6
+ method?: string;
7
+ };
8
+ type ResponseLike = {
9
+ status: (code: number) => ResponseLike;
10
+ json: (body: any) => void;
11
+ };
12
+ type NextFn = () => void | Promise<void>;
13
+ export interface GuardConfig {
14
+ /** Extract agent name from request (e.g. from header, body, or JWT) */
15
+ getAgent: (req: RequestLike) => string | undefined;
16
+ /** Extract action name from request (e.g. from path or body) */
17
+ getAction: (req: RequestLike) => string;
18
+ }
19
+ /**
20
+ * DelegationGuard - Express/Fastify middleware.
21
+ *
22
+ * Automatically checks delegation before each request.
23
+ *
24
+ * Usage:
25
+ * app.use('/api/agent/*', delegationGuard(provider, {
26
+ * getAgent: (req) => req.headers['x-agent-id'],
27
+ * getAction: (req) => `${req.method} ${req.path}`,
28
+ * }));
29
+ */
30
+ export declare function delegationGuard(provider: DelegationProvider, config: GuardConfig): (req: RequestLike, res: ResponseLike, next: NextFn) => Promise<void>;
31
+ export {};
package/dist/guard.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.delegationGuard = delegationGuard;
4
+ /**
5
+ * DelegationGuard - Express/Fastify middleware.
6
+ *
7
+ * Automatically checks delegation before each request.
8
+ *
9
+ * Usage:
10
+ * app.use('/api/agent/*', delegationGuard(provider, {
11
+ * getAgent: (req) => req.headers['x-agent-id'],
12
+ * getAction: (req) => `${req.method} ${req.path}`,
13
+ * }));
14
+ */
15
+ function delegationGuard(provider, config) {
16
+ return async (req, res, next) => {
17
+ const agent = config.getAgent(req);
18
+ if (!agent) {
19
+ res.status(403).json({ error: "No agent identified in request" });
20
+ return;
21
+ }
22
+ const action = config.getAction(req);
23
+ const check = await provider.canAct(agent, action);
24
+ if (!check.allowed) {
25
+ res.status(403).json({
26
+ error: "Delegation check failed",
27
+ reason: check.reason,
28
+ agent,
29
+ action,
30
+ });
31
+ return;
32
+ }
33
+ await next();
34
+ // Log execution after success
35
+ provider
36
+ .logExecution(agent, action, check.agreement?.id, "success")
37
+ .catch(() => { });
38
+ };
39
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  export { AgentCheckClient } from "./client";
2
2
  export { WebhookHandler } from "./webhook";
3
+ export { DelegationProvider } from "./provider";
4
+ export { delegationGuard } from "./guard";
5
+ export { AgentToolChecker } from "./langchain";
6
+ export { DelegationDashboard } from "./dashboard";
3
7
  export type { WebhookEvent } from "./webhook";
8
+ export type { ScopeVerifier, DelegationProviderConfig } from "./provider";
9
+ export type { GuardConfig } from "./guard";
4
10
  export { AgentCheckError, AuthenticationError, NotFoundError, ValidationError, RateLimitError, } from "./errors";
5
11
  export type { Agreement, AgreementList, SignupResult, WebhookResult, CreateRecordParams, ListParams, AmendParams, } from "./types";
package/dist/index.js CHANGED
@@ -1,10 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RateLimitError = exports.ValidationError = exports.NotFoundError = exports.AuthenticationError = exports.AgentCheckError = exports.WebhookHandler = exports.AgentCheckClient = void 0;
3
+ exports.RateLimitError = exports.ValidationError = exports.NotFoundError = exports.AuthenticationError = exports.AgentCheckError = exports.DelegationDashboard = exports.AgentToolChecker = exports.delegationGuard = exports.DelegationProvider = exports.WebhookHandler = exports.AgentCheckClient = void 0;
4
+ // Individual commands (basic menu)
4
5
  var client_1 = require("./client");
5
6
  Object.defineProperty(exports, "AgentCheckClient", { enumerable: true, get: function () { return client_1.AgentCheckClient; } });
6
7
  var webhook_1 = require("./webhook");
7
8
  Object.defineProperty(exports, "WebhookHandler", { enumerable: true, get: function () { return webhook_1.WebhookHandler; } });
9
+ // Set menus (high-level wrappers)
10
+ var provider_1 = require("./provider");
11
+ Object.defineProperty(exports, "DelegationProvider", { enumerable: true, get: function () { return provider_1.DelegationProvider; } });
12
+ var guard_1 = require("./guard");
13
+ Object.defineProperty(exports, "delegationGuard", { enumerable: true, get: function () { return guard_1.delegationGuard; } });
14
+ var langchain_1 = require("./langchain");
15
+ Object.defineProperty(exports, "AgentToolChecker", { enumerable: true, get: function () { return langchain_1.AgentToolChecker; } });
16
+ var dashboard_1 = require("./dashboard");
17
+ Object.defineProperty(exports, "DelegationDashboard", { enumerable: true, get: function () { return dashboard_1.DelegationDashboard; } });
8
18
  var errors_1 = require("./errors");
9
19
  Object.defineProperty(exports, "AgentCheckError", { enumerable: true, get: function () { return errors_1.AgentCheckError; } });
10
20
  Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_1.AuthenticationError; } });
@@ -0,0 +1,25 @@
1
+ import { DelegationProvider } from "./provider";
2
+ /**
3
+ * AgentToolChecker - LangChain/CrewAI tool execution guard.
4
+ *
5
+ * Wraps a tool function to check delegation before execution.
6
+ *
7
+ * Usage:
8
+ * const checker = new AgentToolChecker(provider, "my-bot");
9
+ *
10
+ * // Wrap any tool
11
+ * const safeTool = checker.wrap("send-email", originalSendEmail);
12
+ * await safeTool({ to: "user@example.com", body: "Hello" });
13
+ *
14
+ * // Or check manually
15
+ * if (await checker.canUseTool("send-email")) { ... }
16
+ */
17
+ export declare class AgentToolChecker {
18
+ private provider;
19
+ private agentName;
20
+ constructor(provider: DelegationProvider, agentName: string);
21
+ /** Check if agent can use a specific tool. */
22
+ canUseTool(toolName: string): Promise<boolean>;
23
+ /** Wrap a tool function with delegation check. */
24
+ wrap<T extends (...args: any[]) => Promise<any>>(toolName: string, toolFn: T): T;
25
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgentToolChecker = void 0;
4
+ /**
5
+ * AgentToolChecker - LangChain/CrewAI tool execution guard.
6
+ *
7
+ * Wraps a tool function to check delegation before execution.
8
+ *
9
+ * Usage:
10
+ * const checker = new AgentToolChecker(provider, "my-bot");
11
+ *
12
+ * // Wrap any tool
13
+ * const safeTool = checker.wrap("send-email", originalSendEmail);
14
+ * await safeTool({ to: "user@example.com", body: "Hello" });
15
+ *
16
+ * // Or check manually
17
+ * if (await checker.canUseTool("send-email")) { ... }
18
+ */
19
+ class AgentToolChecker {
20
+ constructor(provider, agentName) {
21
+ this.provider = provider;
22
+ this.agentName = agentName;
23
+ }
24
+ /** Check if agent can use a specific tool. */
25
+ async canUseTool(toolName) {
26
+ const check = await this.provider.canAct(this.agentName, toolName);
27
+ return check.allowed;
28
+ }
29
+ /** Wrap a tool function with delegation check. */
30
+ wrap(toolName, toolFn) {
31
+ const self = this;
32
+ return (async (...args) => {
33
+ return self.provider.executeWithGuard(self.agentName, toolName, () => toolFn(...args));
34
+ });
35
+ }
36
+ }
37
+ exports.AgentToolChecker = AgentToolChecker;
@@ -0,0 +1,40 @@
1
+ import { AgentCheckClient } from "./client";
2
+ import { Agreement } from "./types";
3
+ export interface ScopeVerifier {
4
+ (scope: string, action: string, params?: Record<string, unknown>): boolean;
5
+ }
6
+ export interface DelegationProviderConfig {
7
+ /** Function to check if an action is within scope. You define the rules. */
8
+ verifyScope?: ScopeVerifier;
9
+ }
10
+ /**
11
+ * DelegationProvider - Universal set menu for AI agent delegation.
12
+ *
13
+ * Wraps individual SDK methods into high-level operations:
14
+ * - canAct(): "Can this agent do this action right now?"
15
+ * - hasActiveDelegation(): "Does this agent have any valid delegation?"
16
+ * - logExecution(): "Record what the agent actually did"
17
+ *
18
+ * Usage:
19
+ * const provider = new DelegationProvider(client, {
20
+ * verifyScope: (scope, action) => scope.includes(action),
21
+ * });
22
+ * if (await provider.canAct("my-bot", "send-email")) { ... }
23
+ */
24
+ export declare class DelegationProvider {
25
+ private client;
26
+ private verifyScope;
27
+ constructor(client: AgentCheckClient, config?: DelegationProviderConfig);
28
+ /** Check if agent has valid delegation AND action is in scope. */
29
+ canAct(agentName: string, action: string, params?: Record<string, unknown>): Promise<{
30
+ allowed: boolean;
31
+ agreement?: Agreement;
32
+ reason?: string;
33
+ }>;
34
+ /** Check if agent has any active (approved) delegation. */
35
+ hasActiveDelegation(agentName: string): Promise<boolean>;
36
+ /** Log what an agent actually did (audit trail). */
37
+ logExecution(agentName: string, action: string, agreementId?: string, result?: string, metadata?: Record<string, unknown>): Promise<void>;
38
+ /** Full flow: check permission, execute, log. */
39
+ executeWithGuard<T>(agentName: string, action: string, executeFn: () => Promise<T>, params?: Record<string, unknown>): Promise<T>;
40
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DelegationProvider = void 0;
4
+ /**
5
+ * DelegationProvider - Universal set menu for AI agent delegation.
6
+ *
7
+ * Wraps individual SDK methods into high-level operations:
8
+ * - canAct(): "Can this agent do this action right now?"
9
+ * - hasActiveDelegation(): "Does this agent have any valid delegation?"
10
+ * - logExecution(): "Record what the agent actually did"
11
+ *
12
+ * Usage:
13
+ * const provider = new DelegationProvider(client, {
14
+ * verifyScope: (scope, action) => scope.includes(action),
15
+ * });
16
+ * if (await provider.canAct("my-bot", "send-email")) { ... }
17
+ */
18
+ class DelegationProvider {
19
+ constructor(client, config = {}) {
20
+ this.client = client;
21
+ this.verifyScope = config.verifyScope ?? (() => true);
22
+ }
23
+ /** Check if agent has valid delegation AND action is in scope. */
24
+ async canAct(agentName, action, params) {
25
+ const list = await this.client.list({ agent: agentName, status: "approved" });
26
+ if (!list.records.length) {
27
+ return { allowed: false, reason: "No active delegation" };
28
+ }
29
+ const agreement = list.records[0];
30
+ // Check expiry client-side (server also checks, but belt-and-suspenders)
31
+ if (agreement.expires_at && new Date(agreement.expires_at) < new Date()) {
32
+ return { allowed: false, reason: "Delegation expired", agreement };
33
+ }
34
+ // Check scope
35
+ if (!this.verifyScope(agreement.scope, action, params)) {
36
+ return { allowed: false, reason: "Action not in scope", agreement };
37
+ }
38
+ return { allowed: true, agreement };
39
+ }
40
+ /** Check if agent has any active (approved) delegation. */
41
+ async hasActiveDelegation(agentName) {
42
+ const list = await this.client.list({ agent: agentName, status: "approved" });
43
+ return list.records.length > 0;
44
+ }
45
+ /** Log what an agent actually did (audit trail). */
46
+ async logExecution(agentName, action, agreementId, result, metadata) {
47
+ await this.client.request("POST", "/api/v1/executions", {
48
+ agent: agentName,
49
+ action,
50
+ agreement_id: agreementId,
51
+ result,
52
+ metadata,
53
+ });
54
+ }
55
+ /** Full flow: check permission, execute, log. */
56
+ async executeWithGuard(agentName, action, executeFn, params) {
57
+ const check = await this.canAct(agentName, action, params);
58
+ if (!check.allowed) {
59
+ throw new Error(`Agent "${agentName}" cannot "${action}": ${check.reason}`);
60
+ }
61
+ const result = await executeFn();
62
+ await this.logExecution(agentName, action, check.agreement?.id, "success", params);
63
+ return result;
64
+ }
65
+ }
66
+ exports.DelegationProvider = DelegationProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentcheck-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Record what your AI agent is allowed to do",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",