@rayrun/sdk 0.4.0 → 0.5.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 +36 -0
- package/index.d.ts +130 -0
- package/index.js +18 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,42 @@ await rayrun.clients.setAccessProfile(clientUid, profile.uid, clientToolPolicyVe
|
|
|
50
50
|
The effective policy is always the intersection of the workspace, profile, and client rules. A
|
|
51
51
|
profile can narrow access but cannot grant something blocked by the workspace or client.
|
|
52
52
|
|
|
53
|
+
## Manage hosted tool hooks
|
|
54
|
+
|
|
55
|
+
Hooks are versioned TypeScript adapters hosted and sandboxed by Rayrun. Pull the generated types and
|
|
56
|
+
draft, test it without a live upstream call, then create an immutable shadow or active revision.
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
const { hook } = await rayrun.hooks.get(connectionUid, toolUid);
|
|
60
|
+
|
|
61
|
+
const tested = await rayrun.hooks.test(connectionUid, toolUid, {
|
|
62
|
+
source: hook.draftSource,
|
|
63
|
+
config: hook.draftConfig,
|
|
64
|
+
arguments: { query: 'release' },
|
|
65
|
+
mockResult: { items: [] },
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const saved = await rayrun.hooks.saveDraft(connectionUid, toolUid, {
|
|
69
|
+
source: hook.draftSource,
|
|
70
|
+
config: hook.draftConfig,
|
|
71
|
+
expectedVersion: hook.version,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await rayrun.hooks.deploy(connectionUid, toolUid, {
|
|
75
|
+
expectedVersion: saved.hook.version,
|
|
76
|
+
mode: 'shadow',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const runs = await rayrun.hooks.listRuns(connectionUid, toolUid, { limit: 25 });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`setDeployment` moves an active or shadow pointer to an existing compatible revision, or deactivates
|
|
83
|
+
it with `revisionUid: null`. Every mutation uses `expectedVersion`; fetch and reconcile instead of
|
|
84
|
+
blindly retrying a `version_conflict`. Use a full-control API key for hook writes. Read-only keys can
|
|
85
|
+
inspect source, generated declarations, revision history, and deployed-run metadata; captured logs
|
|
86
|
+
and errors require `hooks:write`. `RayrunApiError.diagnostics` carries compiler line and column
|
|
87
|
+
details for editor and CI output.
|
|
88
|
+
|
|
53
89
|
## Stream code run-ahead
|
|
54
90
|
|
|
55
91
|
A model harness that receives `execute_code` arguments incrementally can let Rayrun start eligible
|
package/index.d.ts
CHANGED
|
@@ -51,6 +51,89 @@ export type Tool = {
|
|
|
51
51
|
inputSchema: Record<string, unknown>;
|
|
52
52
|
title: string | null;
|
|
53
53
|
};
|
|
54
|
+
export type ToolHookPublicContract = {
|
|
55
|
+
description?: string;
|
|
56
|
+
inputSchema?: Record<string, unknown>;
|
|
57
|
+
outputSchema?: Record<string, unknown>;
|
|
58
|
+
};
|
|
59
|
+
export type ToolHookRevision = {
|
|
60
|
+
config: Record<string, JsonValue>;
|
|
61
|
+
createdAt: string;
|
|
62
|
+
publicContract: ToolHookPublicContract | null;
|
|
63
|
+
revisionNumber: number;
|
|
64
|
+
source: string;
|
|
65
|
+
sourceHash: string;
|
|
66
|
+
uid: string;
|
|
67
|
+
upstreamDefinitionHash: string;
|
|
68
|
+
};
|
|
69
|
+
export type ToolHook = {
|
|
70
|
+
activeRevisionStale: boolean;
|
|
71
|
+
activeRevisionUid: string | null;
|
|
72
|
+
draftConfig: Record<string, JsonValue>;
|
|
73
|
+
draftSource: string;
|
|
74
|
+
hookUid: string | null;
|
|
75
|
+
revisions: ToolHookRevision[];
|
|
76
|
+
shadowRevisionStale: boolean;
|
|
77
|
+
shadowRevisionUid: string | null;
|
|
78
|
+
target: {
|
|
79
|
+
definitionHash: string | null;
|
|
80
|
+
inputSchema: Record<string, unknown>;
|
|
81
|
+
name: string;
|
|
82
|
+
outputSchema: Record<string, unknown> | null;
|
|
83
|
+
toolUid: string;
|
|
84
|
+
};
|
|
85
|
+
types: string;
|
|
86
|
+
version: number;
|
|
87
|
+
};
|
|
88
|
+
export type ToolHookLogEntry = {
|
|
89
|
+
data?: JsonValue;
|
|
90
|
+
level: 'debug' | 'error' | 'info' | 'warn';
|
|
91
|
+
message: string;
|
|
92
|
+
};
|
|
93
|
+
export type ToolHookTestFailure = {
|
|
94
|
+
durationMs: number;
|
|
95
|
+
error: {
|
|
96
|
+
code: 'invalid_arguments' | 'invalid_outcome' | 'invalid_output' | 'runtime_error' | 'timeout';
|
|
97
|
+
message: string;
|
|
98
|
+
};
|
|
99
|
+
logs: ToolHookLogEntry[];
|
|
100
|
+
status: 'failed';
|
|
101
|
+
};
|
|
102
|
+
export type ToolHookBeforeTestResult =
|
|
103
|
+
| {
|
|
104
|
+
durationMs: number;
|
|
105
|
+
logs: ToolHookLogEntry[];
|
|
106
|
+
outcome:
|
|
107
|
+
| { action: 'continue'; arguments: JsonValue }
|
|
108
|
+
| { action: 'reject'; message: string; reason: string }
|
|
109
|
+
| { action: 'require_approval'; arguments: JsonValue; reason: string };
|
|
110
|
+
status: 'completed';
|
|
111
|
+
}
|
|
112
|
+
| ToolHookTestFailure;
|
|
113
|
+
export type ToolHookAfterTestResult =
|
|
114
|
+
| {
|
|
115
|
+
durationMs: number;
|
|
116
|
+
logs: ToolHookLogEntry[];
|
|
117
|
+
outcome:
|
|
118
|
+
| { action: 'return'; result: JsonValue }
|
|
119
|
+
| { action: 'fail'; message: string; reason: string };
|
|
120
|
+
status: 'completed';
|
|
121
|
+
}
|
|
122
|
+
| ToolHookTestFailure;
|
|
123
|
+
export type ToolHookRun = {
|
|
124
|
+
createdAt: string;
|
|
125
|
+
differsFromActive: boolean | null;
|
|
126
|
+
durationMs: number;
|
|
127
|
+
errorMessage: string | null;
|
|
128
|
+
id: string;
|
|
129
|
+
logs: ToolHookLogEntry[] | null;
|
|
130
|
+
outcome: 'approval-required' | 'continued' | 'failed' | 'rejected' | 'returned';
|
|
131
|
+
requestId: string;
|
|
132
|
+
revisionUid: string;
|
|
133
|
+
shadow: boolean;
|
|
134
|
+
stage: 'after' | 'before';
|
|
135
|
+
uid: string;
|
|
136
|
+
};
|
|
54
137
|
export type Client = {
|
|
55
138
|
accessProfile: Pick<AccessProfile, 'name' | 'uid'> | null;
|
|
56
139
|
clientName: string;
|
|
@@ -243,6 +326,7 @@ export const CODE_RUN_AHEAD_META_KEY: 'io.rayrun/run-ahead-session';
|
|
|
243
326
|
|
|
244
327
|
export class RayrunApiError extends Error {
|
|
245
328
|
code: string;
|
|
329
|
+
diagnostics: Array<{ column?: number; line?: number; message: string }>;
|
|
246
330
|
requestId: string | null;
|
|
247
331
|
status: number;
|
|
248
332
|
}
|
|
@@ -291,6 +375,52 @@ export class Rayrun {
|
|
|
291
375
|
body: { decision: ToolDecision | null; riskConfirmed?: boolean; riskOverride?: Risk | null },
|
|
292
376
|
): Promise<void>;
|
|
293
377
|
};
|
|
378
|
+
hooks: {
|
|
379
|
+
deploy(
|
|
380
|
+
connectionUid: string,
|
|
381
|
+
toolUid: string,
|
|
382
|
+
body: { expectedVersion: number; mode: 'active' | 'shadow' },
|
|
383
|
+
): Promise<{ hook: ToolHook }>;
|
|
384
|
+
get(connectionUid: string, toolUid: string): Promise<{ hook: ToolHook }>;
|
|
385
|
+
listRuns(
|
|
386
|
+
connectionUid: string,
|
|
387
|
+
toolUid: string,
|
|
388
|
+
query?: PageQuery,
|
|
389
|
+
): Promise<CursorPage<ToolHookRun>>;
|
|
390
|
+
saveDraft(
|
|
391
|
+
connectionUid: string,
|
|
392
|
+
toolUid: string,
|
|
393
|
+
body: {
|
|
394
|
+
config?: Record<string, JsonValue>;
|
|
395
|
+
expectedVersion: number;
|
|
396
|
+
source: string;
|
|
397
|
+
},
|
|
398
|
+
): Promise<{ hook: ToolHook }>;
|
|
399
|
+
setDeployment(
|
|
400
|
+
connectionUid: string,
|
|
401
|
+
toolUid: string,
|
|
402
|
+
body: {
|
|
403
|
+
expectedVersion: number;
|
|
404
|
+
mode: 'active' | 'shadow';
|
|
405
|
+
revisionUid: string | null;
|
|
406
|
+
},
|
|
407
|
+
): Promise<{ hook: ToolHook }>;
|
|
408
|
+
test(
|
|
409
|
+
connectionUid: string,
|
|
410
|
+
toolUid: string,
|
|
411
|
+
body: {
|
|
412
|
+
arguments: JsonValue;
|
|
413
|
+
config?: Record<string, JsonValue>;
|
|
414
|
+
mockResult?: JsonValue;
|
|
415
|
+
source: string;
|
|
416
|
+
},
|
|
417
|
+
): Promise<{
|
|
418
|
+
after?: ToolHookAfterTestResult;
|
|
419
|
+
before: ToolHookBeforeTestResult;
|
|
420
|
+
publicContract: ToolHookPublicContract | null;
|
|
421
|
+
sourceHash: string;
|
|
422
|
+
}>;
|
|
423
|
+
};
|
|
294
424
|
clients: {
|
|
295
425
|
list(query?: PageQuery): Promise<CursorPage<Client>>;
|
|
296
426
|
listTools(uid: string, query?: PageQuery & { query?: string }): Promise<CursorPage<ClientTool>>;
|
package/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
2
2
|
|
|
3
3
|
export class RayrunApiError extends Error {
|
|
4
|
-
constructor(message, { code, requestId, status }) {
|
|
4
|
+
constructor(message, { code, diagnostics = [], requestId, status }) {
|
|
5
5
|
super(message);
|
|
6
6
|
this.name = 'RayrunApiError';
|
|
7
7
|
this.code = code;
|
|
8
|
+
this.diagnostics = diagnostics;
|
|
8
9
|
this.requestId = requestId;
|
|
9
10
|
this.status = status;
|
|
10
11
|
}
|
|
@@ -112,6 +113,21 @@ export class Rayrun {
|
|
|
112
113
|
setPolicy: (connectionUid, toolUid, body) =>
|
|
113
114
|
this.request('PATCH', `/connections/${connectionUid}/tools/${toolUid}/policy`, { body }),
|
|
114
115
|
};
|
|
116
|
+
const toolHookPath = (connectionUid, toolUid) =>
|
|
117
|
+
`/connections/${connectionUid}/tools/${toolUid}/hook`;
|
|
118
|
+
this.hooks = {
|
|
119
|
+
deploy: (connectionUid, toolUid, body) =>
|
|
120
|
+
this.request('POST', `${toolHookPath(connectionUid, toolUid)}/deploy`, { body }),
|
|
121
|
+
get: (connectionUid, toolUid) => this.request('GET', toolHookPath(connectionUid, toolUid)),
|
|
122
|
+
listRuns: (connectionUid, toolUid, query) =>
|
|
123
|
+
this.request('GET', `${toolHookPath(connectionUid, toolUid)}/runs`, { query }),
|
|
124
|
+
saveDraft: (connectionUid, toolUid, body) =>
|
|
125
|
+
this.request('PUT', toolHookPath(connectionUid, toolUid), { body }),
|
|
126
|
+
setDeployment: (connectionUid, toolUid, body) =>
|
|
127
|
+
this.request('POST', `${toolHookPath(connectionUid, toolUid)}/deployment`, { body }),
|
|
128
|
+
test: (connectionUid, toolUid, body) =>
|
|
129
|
+
this.request('POST', `${toolHookPath(connectionUid, toolUid)}/test`, { body }),
|
|
130
|
+
};
|
|
115
131
|
this.clients = {
|
|
116
132
|
list: (query) => this.request('GET', '/clients', { query }),
|
|
117
133
|
listTools: (uid, query) => this.request('GET', `/clients/${uid}/tools`, { query }),
|
|
@@ -189,6 +205,7 @@ export class Rayrun {
|
|
|
189
205
|
problem?.error?.message ?? `Rayrun API request failed with HTTP ${response.status}.`,
|
|
190
206
|
{
|
|
191
207
|
code: problem?.error?.code ?? 'request_failed',
|
|
208
|
+
diagnostics: Array.isArray(problem?.diagnostics) ? problem.diagnostics : [],
|
|
192
209
|
requestId: problem?.error?.requestId ?? response.headers.get('rayrun-request-id'),
|
|
193
210
|
status: response.status,
|
|
194
211
|
},
|