@rayrun/sdk 0.2.1 → 0.4.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 +40 -4
- package/index.d.ts +97 -4
- package/index.js +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,13 +9,46 @@ import { Rayrun } from '@rayrun/sdk';
|
|
|
9
9
|
|
|
10
10
|
const rayrun = new Rayrun({ apiKey: process.env.RAYRUN_API_KEY });
|
|
11
11
|
const { items: connections } = await rayrun.connections.list();
|
|
12
|
+
const { items: matchingTools } = await rayrun.tools.list({ query: 'create issue' });
|
|
12
13
|
```
|
|
13
14
|
|
|
14
15
|
Create keys in **Dashboard → Settings → API keys**. The plaintext is shown once.
|
|
15
16
|
|
|
16
17
|
The client covers catalog search, connection and credential setup, OAuth links, indexing, tool and
|
|
17
|
-
client policies, activity, review queues, and webhooks. Safe reads retry
|
|
18
|
-
and transient network failures; writes do not retry automatically.
|
|
18
|
+
client policies, reusable access profiles, activity, review queues, and webhooks. Safe reads retry
|
|
19
|
+
rate limits, server errors, and transient network failures; writes do not retry automatically.
|
|
20
|
+
|
|
21
|
+
Inspect the effective policy applied to one connected client without reproducing policy logic in
|
|
22
|
+
your application:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
const { items: effectivePolicy } = await rayrun.clients.listTools(clientUid, {
|
|
26
|
+
query: 'create issue',
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Each result includes the effective decision and the workspace, access-profile, or client layer that
|
|
31
|
+
restricted it.
|
|
32
|
+
|
|
33
|
+
## Reuse one access ceiling across clients
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
const { profile } = await rayrun.accessProfiles.create({
|
|
37
|
+
name: 'Support agents',
|
|
38
|
+
description: 'Read by default; sensitive tools stay blocked.',
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await rayrun.accessProfiles.setPolicy(profile.uid, 'read-only', profile.toolPolicyVersion);
|
|
42
|
+
await rayrun.accessProfiles.update(profile.uid, {
|
|
43
|
+
description: 'Read by default; sensitive tools stay blocked.',
|
|
44
|
+
expectedVersion: profile.toolPolicyVersion + 1,
|
|
45
|
+
name: 'Support agents',
|
|
46
|
+
});
|
|
47
|
+
await rayrun.clients.setAccessProfile(clientUid, profile.uid, clientToolPolicyVersion);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The effective policy is always the intersection of the workspace, profile, and client rules. A
|
|
51
|
+
profile can narrow access but cannot grant something blocked by the workspace or client.
|
|
19
52
|
|
|
20
53
|
## Stream code run-ahead
|
|
21
54
|
|
|
@@ -72,10 +105,13 @@ const valid = verifyWebhookSignature({
|
|
|
72
105
|
```
|
|
73
106
|
|
|
74
107
|
After verification, parse the body as `WebhookPayload`. Every event has a stable `id`, `type`, and
|
|
75
|
-
`occurredAt`; its `data` shape is narrowed by `type`.
|
|
108
|
+
`occurredAt`; its `data` shape is narrowed by `type`. Delivery is at least once, so make processing
|
|
109
|
+
idempotent and deduplicate on `id`.
|
|
76
110
|
For `activity.call`, `arguments` and `result` contain the captured tool payloads, or `null` when
|
|
77
111
|
capture was disabled for that connection, the webhook did not opt in with
|
|
78
|
-
`forwardToolPayloads: true`, or no result existed.
|
|
112
|
+
`forwardToolPayloads: true`, or no result existed. `payloadCaptured` distinguishes a metadata-only
|
|
113
|
+
webhook from a call where capture was disabled. Rayrun observes MCP tool arguments and results; it
|
|
114
|
+
does not receive the host's full Claude or GPT prompt, assistant response, or surrounding chat.
|
|
79
115
|
|
|
80
116
|
```ts
|
|
81
117
|
import type { WebhookPayload } from '@rayrun/sdk';
|
package/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type JsonValue =
|
|
|
10
10
|
export type PageQuery = { cursor?: string; limit?: number };
|
|
11
11
|
export type ToolDecision = 'allow' | 'ask' | 'block';
|
|
12
12
|
export type ToolAccessMode = 'read-only' | 'ask-before-changes' | 'allow-all' | 'custom';
|
|
13
|
+
export type AccessProfileMode = 'read-only' | 'ask-before-changes' | 'allow-all' | 'block-all';
|
|
13
14
|
export type Risk = 'read' | 'change' | 'destructive' | 'unknown';
|
|
14
15
|
export type Connection = {
|
|
15
16
|
authorizedAt: string | null;
|
|
@@ -24,6 +25,7 @@ export type Connection = {
|
|
|
24
25
|
slug: string;
|
|
25
26
|
status: 'connected' | 'disabled' | 'error' | 'indexing' | 'needs-authorization' | 'new';
|
|
26
27
|
toolAccessMode: ToolAccessMode;
|
|
28
|
+
toolPolicyVersion: number;
|
|
27
29
|
};
|
|
28
30
|
export type CatalogEntry = {
|
|
29
31
|
authType: Connection['authType'];
|
|
@@ -50,15 +52,54 @@ export type Tool = {
|
|
|
50
52
|
title: string | null;
|
|
51
53
|
};
|
|
52
54
|
export type Client = {
|
|
55
|
+
accessProfile: Pick<AccessProfile, 'name' | 'uid'> | null;
|
|
53
56
|
clientName: string;
|
|
54
57
|
grantedAt: string;
|
|
55
58
|
lastUsedAt: string | null;
|
|
56
59
|
redirectHost: string;
|
|
57
60
|
revokedAt: string | null;
|
|
58
61
|
toolAccessMode: ToolAccessMode;
|
|
62
|
+
toolPolicyVersion: number;
|
|
59
63
|
uid: string;
|
|
60
64
|
userName: string;
|
|
61
65
|
};
|
|
66
|
+
export type ClientTool = {
|
|
67
|
+
approved: boolean;
|
|
68
|
+
clientDecision: ToolDecision | null;
|
|
69
|
+
effectiveDecision: ToolDecision;
|
|
70
|
+
effectiveReason:
|
|
71
|
+
| 'definition-unapproved'
|
|
72
|
+
| 'workspace-tool-rule'
|
|
73
|
+
| 'workspace-default'
|
|
74
|
+
| 'client-profile-tool-rule'
|
|
75
|
+
| 'client-profile-default'
|
|
76
|
+
| 'client-tool-rule'
|
|
77
|
+
| 'client-default'
|
|
78
|
+
| 'multiple-layers'
|
|
79
|
+
| 'workspace-and-client';
|
|
80
|
+
name: string;
|
|
81
|
+
riskLevel: Risk;
|
|
82
|
+
riskReason: string;
|
|
83
|
+
serviceName: string;
|
|
84
|
+
uid: string;
|
|
85
|
+
workspaceDecision: ToolDecision | null;
|
|
86
|
+
};
|
|
87
|
+
export type AccessProfile = {
|
|
88
|
+
assignedClientCount: number;
|
|
89
|
+
description: string;
|
|
90
|
+
name: string;
|
|
91
|
+
toolAccessMode: AccessProfileMode;
|
|
92
|
+
toolPolicyVersion: number;
|
|
93
|
+
uid: string;
|
|
94
|
+
};
|
|
95
|
+
export type AccessProfileTool = {
|
|
96
|
+
available: boolean;
|
|
97
|
+
decision: ToolDecision | null;
|
|
98
|
+
name: string;
|
|
99
|
+
riskLevel: Risk;
|
|
100
|
+
serviceName: string;
|
|
101
|
+
uid: string;
|
|
102
|
+
};
|
|
62
103
|
export type Activity = {
|
|
63
104
|
calledAt: string;
|
|
64
105
|
clientName: string | null;
|
|
@@ -111,7 +152,17 @@ export type WebhookEvent =
|
|
|
111
152
|
| 'review.changed'
|
|
112
153
|
| 'tool.definition-changed'
|
|
113
154
|
| 'tool.policy-changed';
|
|
114
|
-
export type
|
|
155
|
+
export type WebhookDeliveryEvent = Exclude<WebhookEvent, '*'> | 'webhook.test';
|
|
156
|
+
export type ToolPolicyEventType =
|
|
157
|
+
| 'access-profile-archived'
|
|
158
|
+
| 'access-profile-assigned'
|
|
159
|
+
| 'access-profile-changed'
|
|
160
|
+
| 'access-profile-created'
|
|
161
|
+
| 'client-mode-changed'
|
|
162
|
+
| 'client-tool-rule-changed'
|
|
163
|
+
| 'workspace-mode-changed'
|
|
164
|
+
| 'workspace-tool-rule-changed';
|
|
165
|
+
export type WebhookEnvelope<T extends WebhookDeliveryEvent, D> = {
|
|
115
166
|
data: D;
|
|
116
167
|
id: string;
|
|
117
168
|
occurredAt: string;
|
|
@@ -124,12 +175,23 @@ export type WebhookPayload =
|
|
|
124
175
|
activityId: string;
|
|
125
176
|
arguments: JsonValue;
|
|
126
177
|
calledAt: string;
|
|
178
|
+
clientUid: string | null;
|
|
127
179
|
connectionUid: string | null;
|
|
128
180
|
errorCode: string | null;
|
|
181
|
+
payloadCaptured: boolean;
|
|
129
182
|
policyDecision: ToolDecision | null;
|
|
130
183
|
result: JsonValue;
|
|
184
|
+
sessionUid: string;
|
|
131
185
|
succeeded: boolean | null;
|
|
132
186
|
toolName: string;
|
|
187
|
+
userUid: string | null;
|
|
188
|
+
}
|
|
189
|
+
>
|
|
190
|
+
| WebhookEnvelope<
|
|
191
|
+
'webhook.test',
|
|
192
|
+
{
|
|
193
|
+
endpointUid: string;
|
|
194
|
+
message: string;
|
|
133
195
|
}
|
|
134
196
|
>
|
|
135
197
|
| WebhookEnvelope<
|
|
@@ -169,7 +231,10 @@ export type WebhookPayload =
|
|
|
169
231
|
{
|
|
170
232
|
connectionUid: string | null;
|
|
171
233
|
decision: ToolDecision | null;
|
|
172
|
-
eventType:
|
|
234
|
+
eventType: ToolPolicyEventType;
|
|
235
|
+
metadata: Record<string, JsonValue>;
|
|
236
|
+
oauthClientConsentUid: string | null;
|
|
237
|
+
oauthClientName: string | null;
|
|
173
238
|
toolUid: string | null;
|
|
174
239
|
}
|
|
175
240
|
>;
|
|
@@ -208,7 +273,7 @@ export class Rayrun {
|
|
|
208
273
|
| { kind: 'openapi'; specificationUrl: string; baseUrl?: string; name?: string },
|
|
209
274
|
): Promise<{ connection: { uid: string } }>;
|
|
210
275
|
createOAuthLink(uid: string): Promise<{ authorizationUrl: string }>;
|
|
211
|
-
delete(uid: string): Promise<void>;
|
|
276
|
+
delete(uid: string, expectedVersion: number): Promise<void>;
|
|
212
277
|
index(uid: string): Promise<{ enqueued: boolean }>;
|
|
213
278
|
list(query?: PageQuery): Promise<CursorPage<Connection>>;
|
|
214
279
|
setCredential(uid: string, body: Credential): Promise<{ enqueued: boolean }>;
|
|
@@ -219,7 +284,7 @@ export class Rayrun {
|
|
|
219
284
|
setPolicy(uid: string, mode: ToolAccessMode): Promise<void>;
|
|
220
285
|
};
|
|
221
286
|
tools: {
|
|
222
|
-
list(query?: PageQuery & { connectionUid?: string }): Promise<CursorPage<Tool>>;
|
|
287
|
+
list(query?: PageQuery & { connectionUid?: string; query?: string }): Promise<CursorPage<Tool>>;
|
|
223
288
|
setPolicy(
|
|
224
289
|
connectionUid: string,
|
|
225
290
|
toolUid: string,
|
|
@@ -228,6 +293,12 @@ export class Rayrun {
|
|
|
228
293
|
};
|
|
229
294
|
clients: {
|
|
230
295
|
list(query?: PageQuery): Promise<CursorPage<Client>>;
|
|
296
|
+
listTools(uid: string, query?: PageQuery & { query?: string }): Promise<CursorPage<ClientTool>>;
|
|
297
|
+
setAccessProfile(
|
|
298
|
+
uid: string,
|
|
299
|
+
profileUid: string | null,
|
|
300
|
+
expectedVersion: number,
|
|
301
|
+
): Promise<void>;
|
|
231
302
|
setPolicy(uid: string, mode: Exclude<ToolAccessMode, 'custom'>): Promise<void>;
|
|
232
303
|
setToolPolicy(
|
|
233
304
|
uid: string,
|
|
@@ -235,6 +306,28 @@ export class Rayrun {
|
|
|
235
306
|
body: { decision: ToolDecision | null; riskConfirmed?: boolean },
|
|
236
307
|
): Promise<void>;
|
|
237
308
|
};
|
|
309
|
+
accessProfiles: {
|
|
310
|
+
archive(uid: string, expectedVersion: number): Promise<void>;
|
|
311
|
+
create(body: { description: string; name: string }): Promise<{ profile: AccessProfile }>;
|
|
312
|
+
/** @deprecated Use archive. */
|
|
313
|
+
delete(uid: string, expectedVersion: number): Promise<void>;
|
|
314
|
+
list(query?: PageQuery): Promise<CursorPage<AccessProfile>>;
|
|
315
|
+
listTools(uid: string, query?: PageQuery): Promise<CursorPage<AccessProfileTool>>;
|
|
316
|
+
setPolicy(uid: string, mode: AccessProfileMode, expectedVersion: number): Promise<void>;
|
|
317
|
+
setToolPolicy(
|
|
318
|
+
uid: string,
|
|
319
|
+
toolUid: string,
|
|
320
|
+
body: {
|
|
321
|
+
decision: ToolDecision | null;
|
|
322
|
+
expectedVersion: number;
|
|
323
|
+
riskConfirmed?: boolean;
|
|
324
|
+
},
|
|
325
|
+
): Promise<void>;
|
|
326
|
+
update(
|
|
327
|
+
uid: string,
|
|
328
|
+
body: { description: string; expectedVersion: number; name: string },
|
|
329
|
+
): Promise<void>;
|
|
330
|
+
};
|
|
238
331
|
activity: { list(query?: PageQuery): Promise<CursorPage<Activity>> };
|
|
239
332
|
reviews: { list(query?: PageQuery): Promise<CursorPage<Review>> };
|
|
240
333
|
webhooks: {
|
package/index.js
CHANGED
|
@@ -114,10 +114,31 @@ export class Rayrun {
|
|
|
114
114
|
};
|
|
115
115
|
this.clients = {
|
|
116
116
|
list: (query) => this.request('GET', '/clients', { query }),
|
|
117
|
+
listTools: (uid, query) => this.request('GET', `/clients/${uid}/tools`, { query }),
|
|
118
|
+
setAccessProfile: (uid, profileUid, expectedVersion) =>
|
|
119
|
+
this.request('PATCH', `/clients/${uid}/access-profile`, {
|
|
120
|
+
body: { expectedVersion, profileUid },
|
|
121
|
+
}),
|
|
117
122
|
setPolicy: (uid, mode) => this.request('PATCH', `/clients/${uid}/policy`, { body: { mode } }),
|
|
118
123
|
setToolPolicy: (uid, toolUid, body) =>
|
|
119
124
|
this.request('PATCH', `/clients/${uid}/tools/${toolUid}/policy`, { body }),
|
|
120
125
|
};
|
|
126
|
+
const archiveAccessProfile = (uid, expectedVersion) =>
|
|
127
|
+
this.request('DELETE', `/access-profiles/${uid}`, { query: { expectedVersion } });
|
|
128
|
+
this.accessProfiles = {
|
|
129
|
+
archive: archiveAccessProfile,
|
|
130
|
+
create: (body) => this.request('POST', '/access-profiles', { body }),
|
|
131
|
+
delete: archiveAccessProfile,
|
|
132
|
+
list: (query) => this.request('GET', '/access-profiles', { query }),
|
|
133
|
+
listTools: (uid, query) => this.request('GET', `/access-profiles/${uid}/tools`, { query }),
|
|
134
|
+
setPolicy: (uid, mode, expectedVersion) =>
|
|
135
|
+
this.request('PATCH', `/access-profiles/${uid}/policy`, {
|
|
136
|
+
body: { expectedVersion, mode },
|
|
137
|
+
}),
|
|
138
|
+
setToolPolicy: (uid, toolUid, body) =>
|
|
139
|
+
this.request('PATCH', `/access-profiles/${uid}/tools/${toolUid}/policy`, { body }),
|
|
140
|
+
update: (uid, body) => this.request('PATCH', `/access-profiles/${uid}`, { body }),
|
|
141
|
+
};
|
|
121
142
|
this.activity = { list: (query) => this.request('GET', '/activity', { query }) };
|
|
122
143
|
this.reviews = { list: (query) => this.request('GET', '/reviews', { query }) };
|
|
123
144
|
this.webhooks = {
|