@alter-ai/alter-sdk 0.2.2 → 0.3.1
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 +93 -51
- package/dist/index.cjs +142 -75
- package/dist/index.d.cts +24 -18
- package/dist/index.d.ts +24 -18
- package/dist/index.js +141 -75
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
# Alter SDK for TypeScript / Node.js
|
|
2
2
|
|
|
3
|
-
Official TypeScript SDK for [Alter Vault](https://alterai.dev) —
|
|
3
|
+
Official TypeScript SDK for [Alter Vault](https://alterai.dev) — Credential management for agents with policy enforcement.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Zero Token Exposure**: Tokens are never exposed to developers — injected automatically
|
|
8
8
|
- **Single Entry Point**: One method (`vault.request()`) for all provider APIs
|
|
9
|
-
- **Type-Safe Enums**: `
|
|
9
|
+
- **Type-Safe Enums**: `HttpMethod` enums with autocomplete
|
|
10
10
|
- **URL Templating**: Path parameter substitution with automatic URL encoding
|
|
11
11
|
- **Automatic Audit Logging**: All API calls logged with request metadata (HTTP method and URL) for full audit trail
|
|
12
12
|
- **Real-time Policy Enforcement**: Every token request checked against current policies
|
|
13
13
|
- **Automatic Token Refresh**: Tokens refreshed transparently by the backend
|
|
14
|
+
- **API Key and Custom Credential Support**: Handles OAuth tokens, API keys, and custom credential formats automatically
|
|
14
15
|
- **Actor Tracking**: First-class support for AI agent and MCP server observability
|
|
16
|
+
- **HMAC Request Signing**: All SDK-to-backend requests are signed with a derived HMAC-SHA256 key for integrity, authenticity, and replay protection
|
|
15
17
|
- **Native Promises**: Built on native `fetch` — no heavy dependencies
|
|
16
18
|
|
|
17
19
|
## Installation
|
|
@@ -23,17 +25,20 @@ npm install @alter-ai/alter-sdk
|
|
|
23
25
|
## Quick Start
|
|
24
26
|
|
|
25
27
|
```typescript
|
|
26
|
-
import { AlterVault, Provider, HttpMethod } from "@alter-ai/alter-sdk";
|
|
28
|
+
import { AlterVault, ActorType, Provider, HttpMethod } from "@alter-ai/alter-sdk";
|
|
27
29
|
|
|
28
|
-
const vault = new AlterVault({
|
|
30
|
+
const vault = new AlterVault({
|
|
31
|
+
apiKey: "alter_key_...",
|
|
32
|
+
actorType: ActorType.AI_AGENT,
|
|
33
|
+
actorIdentifier: "my-agent",
|
|
34
|
+
});
|
|
29
35
|
|
|
30
36
|
// Make API request — token injected automatically, never exposed
|
|
31
37
|
const response = await vault.request(
|
|
32
|
-
|
|
38
|
+
"CONNECTION_ID", // from Alter Connect (see below)
|
|
33
39
|
HttpMethod.GET,
|
|
34
40
|
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
35
41
|
{
|
|
36
|
-
user: { user_id: "alice" },
|
|
37
42
|
queryParams: { maxResults: "10" },
|
|
38
43
|
},
|
|
39
44
|
);
|
|
@@ -44,16 +49,38 @@ console.log(events);
|
|
|
44
49
|
await vault.close();
|
|
45
50
|
```
|
|
46
51
|
|
|
52
|
+
### Where does `connectionId` come from?
|
|
53
|
+
|
|
54
|
+
**OAuth connections:**
|
|
55
|
+
1. User completes OAuth via [Alter Connect](https://docs.alterai.dev/sdks/javascript/quickstart) (frontend widget)
|
|
56
|
+
2. The `onSuccess` callback returns a `connectionId` (UUID)
|
|
57
|
+
3. You save it in your database, mapped to your user
|
|
58
|
+
4. You pass it to `vault.request()` when making API calls
|
|
59
|
+
|
|
60
|
+
**Managed secrets** (API keys, service tokens):
|
|
61
|
+
1. Store credentials in the [Developer Portal](https://portal.alterai.dev) under **Managed Secrets**
|
|
62
|
+
2. Copy the `connectionId` returned
|
|
63
|
+
3. Use the same `vault.request()` — credentials are injected automatically
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// You can also discover connectionIds programmatically:
|
|
67
|
+
const result = await vault.listConnections({ providerId: "google" });
|
|
68
|
+
for (const conn of result.connections) {
|
|
69
|
+
console.log(`${conn.id}: ${conn.accountDisplayName}`);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
47
73
|
## Usage
|
|
48
74
|
|
|
75
|
+
The `request()` method returns the raw `Response` object. The token is injected automatically and never exposed. The backend token response includes `connectionId` and `providerId` for audit correlation.
|
|
76
|
+
|
|
49
77
|
### Simple GET Request
|
|
50
78
|
|
|
51
79
|
```typescript
|
|
52
80
|
const response = await vault.request(
|
|
53
|
-
|
|
81
|
+
connectionId,
|
|
54
82
|
HttpMethod.GET,
|
|
55
83
|
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
56
|
-
{ user: { user_id: "alice" } },
|
|
57
84
|
);
|
|
58
85
|
```
|
|
59
86
|
|
|
@@ -61,11 +88,10 @@ const response = await vault.request(
|
|
|
61
88
|
|
|
62
89
|
```typescript
|
|
63
90
|
const response = await vault.request(
|
|
64
|
-
|
|
91
|
+
connectionId,
|
|
65
92
|
HttpMethod.POST,
|
|
66
93
|
"https://api.example.com/v1/items",
|
|
67
94
|
{
|
|
68
|
-
user: { user_id: "alice" },
|
|
69
95
|
json: { name: "New Item", price: 99.99 },
|
|
70
96
|
reason: "Creating new item",
|
|
71
97
|
},
|
|
@@ -76,11 +102,10 @@ const response = await vault.request(
|
|
|
76
102
|
|
|
77
103
|
```typescript
|
|
78
104
|
const response = await vault.request(
|
|
79
|
-
|
|
105
|
+
connectionId,
|
|
80
106
|
HttpMethod.PUT,
|
|
81
107
|
"https://api.example.com/v1/items/{item_id}",
|
|
82
108
|
{
|
|
83
|
-
user: { user_id: "alice" },
|
|
84
109
|
pathParams: { item_id: "123" },
|
|
85
110
|
json: { price: 89.99 },
|
|
86
111
|
},
|
|
@@ -91,11 +116,10 @@ const response = await vault.request(
|
|
|
91
116
|
|
|
92
117
|
```typescript
|
|
93
118
|
const response = await vault.request(
|
|
94
|
-
|
|
119
|
+
connectionId,
|
|
95
120
|
HttpMethod.POST,
|
|
96
121
|
"https://api.notion.com/v1/databases/{db_id}/query",
|
|
97
122
|
{
|
|
98
|
-
user: { user_id: "alice" },
|
|
99
123
|
pathParams: { db_id: "abc123" },
|
|
100
124
|
extraHeaders: { "Notion-Version": "2022-06-28" },
|
|
101
125
|
json: { page_size: 10 },
|
|
@@ -103,6 +127,28 @@ const response = await vault.request(
|
|
|
103
127
|
);
|
|
104
128
|
```
|
|
105
129
|
|
|
130
|
+
### Using Managed Secrets
|
|
131
|
+
|
|
132
|
+
For your own APIs with API keys or service tokens (no OAuth flow needed):
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const vault = new AlterVault({
|
|
136
|
+
apiKey: "alter_key_...",
|
|
137
|
+
actorType: ActorType.BACKEND_SERVICE,
|
|
138
|
+
actorIdentifier: "my-service",
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const response = await vault.request(
|
|
142
|
+
"MANAGED_SECRET_CONNECTION_ID", // from Developer Portal
|
|
143
|
+
HttpMethod.GET,
|
|
144
|
+
"https://api.internal.com/v1/data",
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
await vault.close();
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The credential is injected automatically as the configured header type (Bearer, API Key, Basic Auth).
|
|
151
|
+
|
|
106
152
|
### Connection Management
|
|
107
153
|
|
|
108
154
|
#### List Connections
|
|
@@ -149,7 +195,6 @@ console.log(`Expires in: ${session.expiresIn}s`);
|
|
|
149
195
|
| Parameter | Type | Default | Description |
|
|
150
196
|
|-----------|------|---------|-------------|
|
|
151
197
|
| `endUser` | `{ id: string }` | *required* | End user identity |
|
|
152
|
-
| `attributes` | `Record<string, unknown>` | - | Connection attributes |
|
|
153
198
|
| `allowedProviders` | `string[]` | - | Restrict to specific providers |
|
|
154
199
|
| `returnUrl` | `string` | - | Redirect URL after OAuth flow |
|
|
155
200
|
|
|
@@ -158,9 +203,11 @@ Returns `ConnectSession` with: `sessionToken`, `connectUrl`, `expiresIn`, `expir
|
|
|
158
203
|
### AI Agent Actor Tracking
|
|
159
204
|
|
|
160
205
|
```typescript
|
|
206
|
+
import { AlterVault, ActorType, Provider, HttpMethod } from "@alter-ai/alter-sdk";
|
|
207
|
+
|
|
161
208
|
const vault = new AlterVault({
|
|
162
209
|
apiKey: "alter_key_...",
|
|
163
|
-
actorType:
|
|
210
|
+
actorType: ActorType.AI_AGENT,
|
|
164
211
|
actorIdentifier: "email-assistant-v2",
|
|
165
212
|
actorName: "Email Assistant",
|
|
166
213
|
actorVersion: "2.0.0",
|
|
@@ -168,18 +215,19 @@ const vault = new AlterVault({
|
|
|
168
215
|
});
|
|
169
216
|
|
|
170
217
|
const response = await vault.request(
|
|
171
|
-
|
|
218
|
+
connectionId,
|
|
172
219
|
HttpMethod.GET,
|
|
173
220
|
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
174
221
|
{
|
|
175
|
-
|
|
176
|
-
runId: "550e8400-e29b-41d4-a716-446655440000",
|
|
222
|
+
runId: "550e8400-e29b-41d4-a716-446655440000", // auto-generated UUID if omitted
|
|
177
223
|
threadId: "thread-xyz",
|
|
178
224
|
toolCallId: "call_abc_123",
|
|
179
225
|
},
|
|
180
226
|
);
|
|
181
227
|
```
|
|
182
228
|
|
|
229
|
+
> **Note**: `runId` is auto-generated as a UUID v4 if not provided. All sub-actions within a single `request()` call share the same `runId` for audit log grouping.
|
|
230
|
+
|
|
183
231
|
### Multi-Agent Deployments
|
|
184
232
|
|
|
185
233
|
Each agent must create its own `AlterVault` instance with a unique actor identity. Do not share a single instance across agents.
|
|
@@ -188,29 +236,28 @@ Each agent must create its own `AlterVault` instance with a unique actor identit
|
|
|
188
236
|
// Each agent gets its own vault instance
|
|
189
237
|
const emailAgent = new AlterVault({
|
|
190
238
|
apiKey: "alter_key_...",
|
|
191
|
-
actorType:
|
|
239
|
+
actorType: ActorType.AI_AGENT,
|
|
192
240
|
actorIdentifier: "email-assistant-v2",
|
|
193
241
|
actorName: "Email Assistant",
|
|
194
242
|
});
|
|
195
243
|
|
|
196
244
|
const calendarAgent = new AlterVault({
|
|
197
245
|
apiKey: "alter_key_...",
|
|
198
|
-
actorType:
|
|
246
|
+
actorType: ActorType.AI_AGENT,
|
|
199
247
|
actorIdentifier: "calendar-agent-v1",
|
|
200
248
|
actorName: "Calendar Agent",
|
|
201
249
|
});
|
|
202
250
|
|
|
203
251
|
// Audit logs and policies are tracked per agent
|
|
204
|
-
const user = { user_id: "alice" };
|
|
205
252
|
await emailAgent.request(
|
|
206
|
-
|
|
253
|
+
gmailConnectionId, // from Alter Connect
|
|
254
|
+
HttpMethod.GET,
|
|
207
255
|
"https://gmail.googleapis.com/gmail/v1/users/me/messages",
|
|
208
|
-
{ user },
|
|
209
256
|
);
|
|
210
257
|
await calendarAgent.request(
|
|
211
|
-
|
|
258
|
+
calendarConnectionId, // from Alter Connect
|
|
259
|
+
HttpMethod.GET,
|
|
212
260
|
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
213
|
-
{ user },
|
|
214
261
|
);
|
|
215
262
|
|
|
216
263
|
// Clean up each instance
|
|
@@ -221,30 +268,29 @@ await calendarAgent.close();
|
|
|
221
268
|
## Configuration
|
|
222
269
|
|
|
223
270
|
```typescript
|
|
271
|
+
import { AlterVault, ActorType } from "@alter-ai/alter-sdk";
|
|
272
|
+
|
|
224
273
|
const vault = new AlterVault({
|
|
225
274
|
apiKey: "alter_key_...", // Required: Alter Vault API key
|
|
226
|
-
|
|
275
|
+
actorType: ActorType.AI_AGENT, // Required: ActorType enum
|
|
276
|
+
actorIdentifier: "my-agent", // Required: Unique identifier
|
|
227
277
|
timeout: 30000, // Optional: HTTP timeout in ms (default: 30000)
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
actorVersion: "1.0.0", // Version string
|
|
233
|
-
framework: "langgraph", // AI framework
|
|
234
|
-
clientType: "cursor", // MCP client type
|
|
278
|
+
actorName: "My Agent", // Optional: Human-readable name
|
|
279
|
+
actorVersion: "1.0.0", // Optional: Version string
|
|
280
|
+
framework: "langgraph", // Optional: AI framework
|
|
281
|
+
clientType: "cursor", // Optional: MCP client type
|
|
235
282
|
});
|
|
236
283
|
```
|
|
237
284
|
|
|
238
285
|
## Error Handling
|
|
239
286
|
|
|
240
|
-
> **Note:** Input validation errors (invalid `apiKey`, invalid `actorType`, invalid URL scheme, missing `pathParams`) throw `AlterSDKError`.
|
|
287
|
+
> **Note:** Input validation errors (invalid `apiKey`, invalid/missing `actorType`, missing `actorIdentifier`, invalid URL scheme, missing `pathParams`) throw `AlterSDKError`.
|
|
241
288
|
|
|
242
289
|
```typescript
|
|
243
290
|
import {
|
|
244
291
|
AlterVault,
|
|
245
|
-
Provider,
|
|
246
292
|
HttpMethod,
|
|
247
|
-
AlterSDKError, // Base error (including validation: apiKey, actorType, URL scheme, pathParams)
|
|
293
|
+
AlterSDKError, // Base error (including validation: apiKey, actorType, actorIdentifier, URL scheme, pathParams)
|
|
248
294
|
PolicyViolationError,
|
|
249
295
|
ConnectionNotFoundError,
|
|
250
296
|
TokenExpiredError,
|
|
@@ -256,10 +302,9 @@ import {
|
|
|
256
302
|
|
|
257
303
|
try {
|
|
258
304
|
const response = await vault.request(
|
|
259
|
-
|
|
305
|
+
connectionId,
|
|
260
306
|
HttpMethod.GET,
|
|
261
307
|
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
262
|
-
{ user: { user_id: "alice" } },
|
|
263
308
|
);
|
|
264
309
|
} catch (error) {
|
|
265
310
|
if (error instanceof PolicyViolationError) {
|
|
@@ -282,7 +327,11 @@ try {
|
|
|
282
327
|
|
|
283
328
|
```typescript
|
|
284
329
|
// Manual cleanup (recommended)
|
|
285
|
-
const vault = new AlterVault({
|
|
330
|
+
const vault = new AlterVault({
|
|
331
|
+
apiKey: "alter_key_...",
|
|
332
|
+
actorType: ActorType.BACKEND_SERVICE,
|
|
333
|
+
actorIdentifier: "my-service",
|
|
334
|
+
});
|
|
286
335
|
try {
|
|
287
336
|
const response = await vault.request(...);
|
|
288
337
|
} finally {
|
|
@@ -295,18 +344,11 @@ try {
|
|
|
295
344
|
|
|
296
345
|
## Supported Providers
|
|
297
346
|
|
|
298
|
-
|
|
299
|
-
import { Provider } from "@alter-ai/alter-sdk";
|
|
300
|
-
|
|
301
|
-
Provider.GOOGLE // "google"
|
|
302
|
-
Provider.GITHUB // "github"
|
|
303
|
-
Provider.SLACK // "slack"
|
|
304
|
-
Provider.MICROSOFT // "microsoft"
|
|
305
|
-
Provider.SALESFORCE // "salesforce"
|
|
306
|
-
Provider.SENTRY // "sentry"
|
|
347
|
+
The SDK works with any OAuth provider configured in your Alter Vault dashboard. The first parameter to `vault.request()` is the `connection_id` (UUID) returned when a user connects via Alter Connect.
|
|
307
348
|
|
|
308
|
-
|
|
309
|
-
|
|
349
|
+
```typescript
|
|
350
|
+
// Use the connection_id from Alter Connect
|
|
351
|
+
await vault.request("550e8400-e29b-41d4-a716-446655440000", HttpMethod.GET, url);
|
|
310
352
|
```
|
|
311
353
|
|
|
312
354
|
## Requirements
|