shadowkey-agent-sdk 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ShadowKey Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # ShadowKey Agent SDK
2
+
3
+ Official SDK for integrating AI agents with ShadowKey's privacy-preserving data vault.
4
+
5
+ ## Features
6
+
7
+ - 🔐 Secure API key authentication with request signing
8
+ - 🔄 Automatic retry logic with exponential backoff
9
+ - âąī¸ Configurable timeouts and polling
10
+ - đŸŽ¯ TypeScript-first with full type definitions
11
+ - đŸĒļ Zero dependencies for minimal bundle size
12
+ - 🔍 Debug mode for development
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @shadowkey/agent-sdk
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ import { ShadowKeyClient } from '@shadowkey/agent-sdk';
24
+
25
+ const client = new ShadowKeyClient({
26
+ apiUrl: 'https://your-project.supabase.co/functions/v1',
27
+ apiKey: 'your-api-key',
28
+ debug: true // Enable logging during development
29
+ });
30
+
31
+ // Request access to user data
32
+ const response = await client.requestAccess({
33
+ agentId: 'shopping-assistant-001',
34
+ agentName: 'Smart Shopping Assistant',
35
+ requestedFields: ['creditCard', 'shippingAddress'],
36
+ purpose: 'Complete your purchase of wireless headphones',
37
+ category: 'shopping'
38
+ });
39
+
40
+ console.log('Request ID:', response.requestId);
41
+
42
+ // Wait for user approval (with timeout)
43
+ const result = await client.waitForApproval(response.requestId, 300000);
44
+
45
+ if (result.status === 'approved') {
46
+ console.log('Access granted!', result.grantedData);
47
+ } else {
48
+ console.log('Access denied:', result.message);
49
+ }
50
+ ```
51
+
52
+ ## API Reference
53
+
54
+ ### Constructor
55
+
56
+ ```typescript
57
+ new ShadowKeyClient(config: ShadowKeyConfig)
58
+ ```
59
+
60
+ **Config Options:**
61
+ - `apiUrl` (required): Your Supabase project URL + `/functions/v1`
62
+ - `apiKey` (required): API key generated from ShadowKey settings
63
+ - `timeout` (optional): Request timeout in ms (default: 30000)
64
+ - `retryAttempts` (optional): Number of retry attempts (default: 3)
65
+ - `debug` (optional): Enable debug logging (default: false)
66
+
67
+ ### Methods
68
+
69
+ #### `requestAccess(request: AccessRequest): Promise<AccessResponse>`
70
+
71
+ Request access to user's vault data.
72
+
73
+ **Parameters:**
74
+ ```typescript
75
+ {
76
+ agentId: string; // Unique identifier for your agent
77
+ agentName: string; // Human-readable agent name
78
+ requestedFields: string[]; // Array of field names to request
79
+ purpose: string; // Clear explanation of why you need access
80
+ category?: string; // Optional category (shopping, travel, etc)
81
+ expiresIn?: number; // Optional expiration time in seconds
82
+ }
83
+ ```
84
+
85
+ **Returns:**
86
+ ```typescript
87
+ {
88
+ requestId: string; // Use this to check status
89
+ status: 'pending' | 'approved' | 'denied' | 'expired';
90
+ grantedData?: Record<string, any>; // Present if approved
91
+ expiresAt?: string; // ISO timestamp
92
+ message?: string;
93
+ }
94
+ ```
95
+
96
+ #### `checkStatus(requestId: string): Promise<DisclosureStatus>`
97
+
98
+ Check the current status of an access request.
99
+
100
+ #### `waitForApproval(requestId: string, maxWaitMs?: number, pollIntervalMs?: number): Promise<AccessResponse>`
101
+
102
+ Poll for approval with automatic retries.
103
+
104
+ **Parameters:**
105
+ - `requestId`: The ID returned from `requestAccess()`
106
+ - `maxWaitMs`: Maximum time to wait (default: 300000 = 5 minutes)
107
+ - `pollIntervalMs`: Time between polls (default: 2000 = 2 seconds)
108
+
109
+ #### `submitReverseDisclosure(request: ReverseDisclosureRequest): Promise<ReverseDisclosureResponse>`
110
+
111
+ Submit data to user's vault (reverse data flow).
112
+
113
+ **Parameters:**
114
+ ```typescript
115
+ {
116
+ serviceId: string;
117
+ serviceName: string;
118
+ dataOffered: Array<{
119
+ field: string;
120
+ value: string;
121
+ category: string;
122
+ }>;
123
+ purpose: string;
124
+ }
125
+ ```
126
+
127
+ ## Examples
128
+
129
+ See the `/examples` directory for complete integration examples:
130
+
131
+ - `openrouter/` - AI agent using OpenRouter free models
132
+ - `node-express/` - Express.js server with webhook handling
133
+ - `langchain/` - LangChain tool integration
134
+ - `python/` - Python SDK wrapper
135
+
136
+ ## Error Handling
137
+
138
+ ```typescript
139
+ try {
140
+ const response = await client.requestAccess({...});
141
+ } catch (error) {
142
+ if (error.message.includes('timeout')) {
143
+ console.error('Request timed out');
144
+ } else if (error.message.includes('401')) {
145
+ console.error('Invalid API key');
146
+ } else {
147
+ console.error('Request failed:', error.message);
148
+ }
149
+ }
150
+ ```
151
+
152
+ ## Security Best Practices
153
+
154
+ 1. **Never expose your API key** in client-side code
155
+ 2. **Use environment variables** to store credentials
156
+ 3. **Rotate keys regularly** using the ShadowKey dashboard
157
+ 4. **Set appropriate rate limits** for your use case
158
+ 5. **Validate all data** received from the vault
159
+ 6. **Use HTTPS** for all requests (enforced by default)
160
+
161
+ ## Rate Limits
162
+
163
+ Default rate limits per API key:
164
+ - 100 requests per minute
165
+ - 1000 requests per hour
166
+ - 10000 requests per day
167
+
168
+ Contact support for enterprise limits.
169
+
170
+ ## Support
171
+
172
+ - Documentation: https://shadowkey.dev/docs
173
+ - Issues: https://github.com/shadowkey/agent-sdk/issues
174
+ - Discord: https://discord.gg/shadowkey
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,72 @@
1
+ interface ShadowKeyConfig {
2
+ apiUrl: string;
3
+ apiKey: string;
4
+ timeout?: number;
5
+ retryAttempts?: number;
6
+ debug?: boolean;
7
+ }
8
+ interface AccessRequest {
9
+ agentId: string;
10
+ agentName: string;
11
+ requestedFields: string[];
12
+ purpose: string;
13
+ category?: string;
14
+ expiresIn?: number;
15
+ }
16
+ interface AccessResponse {
17
+ requestId: string;
18
+ status: 'pending' | 'approved' | 'denied' | 'expired';
19
+ grantedFields?: string[];
20
+ grantedData?: Record<string, any>;
21
+ expiresAt?: string;
22
+ message?: string;
23
+ }
24
+ interface ReverseDisclosureRequest {
25
+ serviceId: string;
26
+ serviceName: string;
27
+ dataOffered: Array<{
28
+ field: string;
29
+ value: string;
30
+ category: string;
31
+ }>;
32
+ purpose: string;
33
+ }
34
+ interface ReverseDisclosureResponse {
35
+ receiptId: string;
36
+ status: 'accepted' | 'rejected';
37
+ storedFields?: string[];
38
+ message?: string;
39
+ }
40
+ interface DisclosureStatus {
41
+ requestId: string;
42
+ status: 'pending' | 'approved' | 'denied' | 'expired';
43
+ approvedAt?: string;
44
+ deniedAt?: string;
45
+ expiresAt?: string;
46
+ grantedFields?: string[];
47
+ grantedData?: Record<string, any>;
48
+ }
49
+ interface APIError {
50
+ code: string;
51
+ message: string;
52
+ details?: any;
53
+ }
54
+ interface RequestMetadata {
55
+ timestamp: number;
56
+ signature: string;
57
+ nonce: string;
58
+ }
59
+
60
+ declare class ShadowKeyClient {
61
+ private config;
62
+ constructor(config: ShadowKeyConfig);
63
+ private log;
64
+ private generateSignature;
65
+ private makeRequest;
66
+ requestAccess(request: AccessRequest): Promise<AccessResponse>;
67
+ checkStatus(requestId: string): Promise<DisclosureStatus>;
68
+ submitReverseDisclosure(request: ReverseDisclosureRequest): Promise<ReverseDisclosureResponse>;
69
+ waitForApproval(requestId: string, maxWaitMs?: number, pollIntervalMs?: number): Promise<AccessResponse>;
70
+ }
71
+
72
+ export { type APIError, type AccessRequest, type AccessResponse, type DisclosureStatus, type RequestMetadata, type ReverseDisclosureRequest, type ReverseDisclosureResponse, ShadowKeyClient, type ShadowKeyConfig };
@@ -0,0 +1,72 @@
1
+ interface ShadowKeyConfig {
2
+ apiUrl: string;
3
+ apiKey: string;
4
+ timeout?: number;
5
+ retryAttempts?: number;
6
+ debug?: boolean;
7
+ }
8
+ interface AccessRequest {
9
+ agentId: string;
10
+ agentName: string;
11
+ requestedFields: string[];
12
+ purpose: string;
13
+ category?: string;
14
+ expiresIn?: number;
15
+ }
16
+ interface AccessResponse {
17
+ requestId: string;
18
+ status: 'pending' | 'approved' | 'denied' | 'expired';
19
+ grantedFields?: string[];
20
+ grantedData?: Record<string, any>;
21
+ expiresAt?: string;
22
+ message?: string;
23
+ }
24
+ interface ReverseDisclosureRequest {
25
+ serviceId: string;
26
+ serviceName: string;
27
+ dataOffered: Array<{
28
+ field: string;
29
+ value: string;
30
+ category: string;
31
+ }>;
32
+ purpose: string;
33
+ }
34
+ interface ReverseDisclosureResponse {
35
+ receiptId: string;
36
+ status: 'accepted' | 'rejected';
37
+ storedFields?: string[];
38
+ message?: string;
39
+ }
40
+ interface DisclosureStatus {
41
+ requestId: string;
42
+ status: 'pending' | 'approved' | 'denied' | 'expired';
43
+ approvedAt?: string;
44
+ deniedAt?: string;
45
+ expiresAt?: string;
46
+ grantedFields?: string[];
47
+ grantedData?: Record<string, any>;
48
+ }
49
+ interface APIError {
50
+ code: string;
51
+ message: string;
52
+ details?: any;
53
+ }
54
+ interface RequestMetadata {
55
+ timestamp: number;
56
+ signature: string;
57
+ nonce: string;
58
+ }
59
+
60
+ declare class ShadowKeyClient {
61
+ private config;
62
+ constructor(config: ShadowKeyConfig);
63
+ private log;
64
+ private generateSignature;
65
+ private makeRequest;
66
+ requestAccess(request: AccessRequest): Promise<AccessResponse>;
67
+ checkStatus(requestId: string): Promise<DisclosureStatus>;
68
+ submitReverseDisclosure(request: ReverseDisclosureRequest): Promise<ReverseDisclosureResponse>;
69
+ waitForApproval(requestId: string, maxWaitMs?: number, pollIntervalMs?: number): Promise<AccessResponse>;
70
+ }
71
+
72
+ export { type APIError, type AccessRequest, type AccessResponse, type DisclosureStatus, type RequestMetadata, type ReverseDisclosureRequest, type ReverseDisclosureResponse, ShadowKeyClient, type ShadowKeyConfig };
package/dist/index.js ADDED
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ShadowKeyClient: () => ShadowKeyClient
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/client.ts
28
+ var ShadowKeyClient = class {
29
+ constructor(config) {
30
+ this.config = {
31
+ timeout: 3e4,
32
+ retryAttempts: 3,
33
+ debug: false,
34
+ ...config
35
+ };
36
+ if (!this.config.apiUrl) {
37
+ throw new Error("apiUrl is required");
38
+ }
39
+ if (!this.config.apiKey) {
40
+ throw new Error("apiKey is required");
41
+ }
42
+ }
43
+ log(message, data) {
44
+ if (this.config.debug) {
45
+ if (data && typeof data === "object") {
46
+ const sanitized = { ...data };
47
+ const sensitiveFields = ["grantedData", "grantedFields", "response_data", "decrypted_data"];
48
+ sensitiveFields.forEach((field) => {
49
+ if (sanitized[field]) {
50
+ sanitized[field] = "[REDACTED]";
51
+ }
52
+ });
53
+ console.log("[ShadowKey SDK]", message, sanitized);
54
+ } else {
55
+ console.log("[ShadowKey SDK]", message, data);
56
+ }
57
+ }
58
+ }
59
+ async generateSignature(payload) {
60
+ const timestamp = Date.now();
61
+ const nonceBytes = new Uint8Array(12);
62
+ crypto.getRandomValues(nonceBytes);
63
+ const nonce = Array.from(nonceBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
64
+ const message = JSON.stringify({ ...payload, timestamp, nonce });
65
+ const encoder = new TextEncoder();
66
+ const data = encoder.encode(message + this.config.apiKey);
67
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
68
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
69
+ const signature = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
70
+ return { timestamp, nonce, signature };
71
+ }
72
+ async makeRequest(endpoint, method, body, attempt = 1) {
73
+ const metadata = await this.generateSignature(body || {});
74
+ const url = `${this.config.apiUrl}${endpoint}`;
75
+ this.log(`${method} ${url}`, body);
76
+ try {
77
+ const controller = new AbortController();
78
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
79
+ const response = await fetch(url, {
80
+ method,
81
+ headers: {
82
+ "Content-Type": "application/json",
83
+ "Authorization": `Bearer ${this.config.apiKey}`,
84
+ "X-Timestamp": metadata.timestamp.toString(),
85
+ "X-Nonce": metadata.nonce,
86
+ "X-Signature": metadata.signature
87
+ },
88
+ body: body ? JSON.stringify(body) : void 0,
89
+ signal: controller.signal
90
+ });
91
+ clearTimeout(timeoutId);
92
+ if (!response.ok) {
93
+ const error = await response.json().catch(() => ({
94
+ code: "UNKNOWN_ERROR",
95
+ message: `HTTP ${response.status}: ${response.statusText}`
96
+ }));
97
+ const isClientError = response.status >= 400 && response.status < 500;
98
+ if (isClientError) {
99
+ const err = new Error(error.message || "Request failed");
100
+ err.isClientError = true;
101
+ throw err;
102
+ }
103
+ throw new Error(error.message || "Request failed");
104
+ }
105
+ const data = await response.json();
106
+ this.log("Response:", data);
107
+ return data;
108
+ } catch (error) {
109
+ this.log("Request failed:", error.message);
110
+ const shouldRetry = attempt < this.config.retryAttempts && error.name !== "AbortError" && !error.isClientError;
111
+ if (shouldRetry) {
112
+ const delay = Math.pow(2, attempt) * 1e3;
113
+ this.log(`Retrying in ${delay}ms...`, { attempt: attempt + 1, max: this.config.retryAttempts });
114
+ await new Promise((resolve) => setTimeout(resolve, delay));
115
+ return this.makeRequest(endpoint, method, body, attempt + 1);
116
+ }
117
+ throw error;
118
+ }
119
+ }
120
+ async requestAccess(request) {
121
+ return this.makeRequest("/access-request", "POST", request);
122
+ }
123
+ async checkStatus(requestId) {
124
+ return this.makeRequest(`/access-status/${requestId}`, "GET");
125
+ }
126
+ async submitReverseDisclosure(request) {
127
+ return this.makeRequest("/reverse-disclosure", "POST", request);
128
+ }
129
+ async waitForApproval(requestId, maxWaitMs = 3e5, pollIntervalMs = 2e3) {
130
+ const startTime = Date.now();
131
+ while (Date.now() - startTime < maxWaitMs) {
132
+ const status = await this.checkStatus(requestId);
133
+ if (status.status === "approved") {
134
+ return {
135
+ requestId,
136
+ status: "approved",
137
+ grantedFields: status.grantedFields || [],
138
+ grantedData: status.grantedData || {},
139
+ expiresAt: status.expiresAt,
140
+ message: "Access granted"
141
+ };
142
+ }
143
+ if (status.status === "denied") {
144
+ return {
145
+ requestId,
146
+ status: "denied",
147
+ message: "Access denied by user"
148
+ };
149
+ }
150
+ if (status.status === "expired") {
151
+ return {
152
+ requestId,
153
+ status: "expired",
154
+ message: "Request expired"
155
+ };
156
+ }
157
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
158
+ }
159
+ throw new Error("Timeout waiting for approval");
160
+ }
161
+ };
162
+ // Annotate the CommonJS export names for ESM import in node:
163
+ 0 && (module.exports = {
164
+ ShadowKeyClient
165
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,138 @@
1
+ // src/client.ts
2
+ var ShadowKeyClient = class {
3
+ constructor(config) {
4
+ this.config = {
5
+ timeout: 3e4,
6
+ retryAttempts: 3,
7
+ debug: false,
8
+ ...config
9
+ };
10
+ if (!this.config.apiUrl) {
11
+ throw new Error("apiUrl is required");
12
+ }
13
+ if (!this.config.apiKey) {
14
+ throw new Error("apiKey is required");
15
+ }
16
+ }
17
+ log(message, data) {
18
+ if (this.config.debug) {
19
+ if (data && typeof data === "object") {
20
+ const sanitized = { ...data };
21
+ const sensitiveFields = ["grantedData", "grantedFields", "response_data", "decrypted_data"];
22
+ sensitiveFields.forEach((field) => {
23
+ if (sanitized[field]) {
24
+ sanitized[field] = "[REDACTED]";
25
+ }
26
+ });
27
+ console.log("[ShadowKey SDK]", message, sanitized);
28
+ } else {
29
+ console.log("[ShadowKey SDK]", message, data);
30
+ }
31
+ }
32
+ }
33
+ async generateSignature(payload) {
34
+ const timestamp = Date.now();
35
+ const nonceBytes = new Uint8Array(12);
36
+ crypto.getRandomValues(nonceBytes);
37
+ const nonce = Array.from(nonceBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
38
+ const message = JSON.stringify({ ...payload, timestamp, nonce });
39
+ const encoder = new TextEncoder();
40
+ const data = encoder.encode(message + this.config.apiKey);
41
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
42
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
43
+ const signature = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
44
+ return { timestamp, nonce, signature };
45
+ }
46
+ async makeRequest(endpoint, method, body, attempt = 1) {
47
+ const metadata = await this.generateSignature(body || {});
48
+ const url = `${this.config.apiUrl}${endpoint}`;
49
+ this.log(`${method} ${url}`, body);
50
+ try {
51
+ const controller = new AbortController();
52
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
53
+ const response = await fetch(url, {
54
+ method,
55
+ headers: {
56
+ "Content-Type": "application/json",
57
+ "Authorization": `Bearer ${this.config.apiKey}`,
58
+ "X-Timestamp": metadata.timestamp.toString(),
59
+ "X-Nonce": metadata.nonce,
60
+ "X-Signature": metadata.signature
61
+ },
62
+ body: body ? JSON.stringify(body) : void 0,
63
+ signal: controller.signal
64
+ });
65
+ clearTimeout(timeoutId);
66
+ if (!response.ok) {
67
+ const error = await response.json().catch(() => ({
68
+ code: "UNKNOWN_ERROR",
69
+ message: `HTTP ${response.status}: ${response.statusText}`
70
+ }));
71
+ const isClientError = response.status >= 400 && response.status < 500;
72
+ if (isClientError) {
73
+ const err = new Error(error.message || "Request failed");
74
+ err.isClientError = true;
75
+ throw err;
76
+ }
77
+ throw new Error(error.message || "Request failed");
78
+ }
79
+ const data = await response.json();
80
+ this.log("Response:", data);
81
+ return data;
82
+ } catch (error) {
83
+ this.log("Request failed:", error.message);
84
+ const shouldRetry = attempt < this.config.retryAttempts && error.name !== "AbortError" && !error.isClientError;
85
+ if (shouldRetry) {
86
+ const delay = Math.pow(2, attempt) * 1e3;
87
+ this.log(`Retrying in ${delay}ms...`, { attempt: attempt + 1, max: this.config.retryAttempts });
88
+ await new Promise((resolve) => setTimeout(resolve, delay));
89
+ return this.makeRequest(endpoint, method, body, attempt + 1);
90
+ }
91
+ throw error;
92
+ }
93
+ }
94
+ async requestAccess(request) {
95
+ return this.makeRequest("/access-request", "POST", request);
96
+ }
97
+ async checkStatus(requestId) {
98
+ return this.makeRequest(`/access-status/${requestId}`, "GET");
99
+ }
100
+ async submitReverseDisclosure(request) {
101
+ return this.makeRequest("/reverse-disclosure", "POST", request);
102
+ }
103
+ async waitForApproval(requestId, maxWaitMs = 3e5, pollIntervalMs = 2e3) {
104
+ const startTime = Date.now();
105
+ while (Date.now() - startTime < maxWaitMs) {
106
+ const status = await this.checkStatus(requestId);
107
+ if (status.status === "approved") {
108
+ return {
109
+ requestId,
110
+ status: "approved",
111
+ grantedFields: status.grantedFields || [],
112
+ grantedData: status.grantedData || {},
113
+ expiresAt: status.expiresAt,
114
+ message: "Access granted"
115
+ };
116
+ }
117
+ if (status.status === "denied") {
118
+ return {
119
+ requestId,
120
+ status: "denied",
121
+ message: "Access denied by user"
122
+ };
123
+ }
124
+ if (status.status === "expired") {
125
+ return {
126
+ requestId,
127
+ status: "expired",
128
+ message: "Request expired"
129
+ };
130
+ }
131
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
132
+ }
133
+ throw new Error("Timeout waiting for approval");
134
+ }
135
+ };
136
+ export {
137
+ ShadowKeyClient
138
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "shadowkey-agent-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Official SDK for integrating AI agents with ShadowKey privacy vault",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.mjs",
17
+ "require": "./dist/index.js"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts",
22
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
23
+ "test": "vitest",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "keywords": [
27
+ "shadowkey",
28
+ "privacy",
29
+ "ai-agent",
30
+ "data-vault",
31
+ "zero-knowledge"
32
+ ],
33
+ "author": "ShadowKey Team",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/kimboltpro3-create/shadowkey"
38
+ },
39
+ "dependencies": {},
40
+ "devDependencies": {
41
+ "tsup": "^8.0.0",
42
+ "typescript": "^5.5.3",
43
+ "vitest": "^1.0.0"
44
+ }
45
+ }