@roj-ai/client 0.1.4 → 0.1.5
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/platform/index.d.ts +1 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/methods.d.ts +34 -0
- package/dist/platform/methods.d.ts.map +1 -1
- package/dist/platform/methods.js +2 -0
- package/dist/platform/methods.js.map +1 -1
- package/dist/platform/rest-client.d.ts +25 -1
- package/dist/platform/rest-client.d.ts.map +1 -1
- package/dist/platform/rest-client.js +58 -0
- package/dist/platform/rest-client.js.map +1 -1
- package/package.json +2 -2
- package/src/platform/index.ts +1 -1
- package/src/platform/methods.ts +43 -0
- package/src/platform/rest-client.ts +91 -0
package/dist/platform/index.d.ts
CHANGED
|
@@ -20,6 +20,6 @@ export type { SandboxState } from './sandbox-state';
|
|
|
20
20
|
export { buildPreviewUrl, buildWsUrl, buildApiBaseUrl, instanceIdToHex } from './urls';
|
|
21
21
|
export type { BuildPreviewUrlOptions, BuildWsUrlOptions } from './urls';
|
|
22
22
|
export { createRojClient } from './rest-client';
|
|
23
|
-
export type { RojClient, RojClientOptions } from './rest-client';
|
|
23
|
+
export type { RojClient, RojClientOptions, SessionRpcInput } from './rest-client';
|
|
24
24
|
export { RojApiError } from './errors';
|
|
25
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/platform/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACxD,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC/G,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAG5E,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACpE,mBAAmB,WAAW,CAAA;AAE9B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC7E,mBAAmB,oBAAoB,CAAA;AAGvC,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGnD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACtF,YAAY,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAGvE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/platform/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACxD,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC/G,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAG5E,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACpE,mBAAmB,WAAW,CAAA;AAE9B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC7E,mBAAmB,oBAAoB,CAAA;AAGvC,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGnD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACtF,YAAY,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAGvE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAGjF,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -115,10 +115,22 @@ export interface CreateInstanceTokenInput {
|
|
|
115
115
|
origin?: string;
|
|
116
116
|
expiresIn?: number;
|
|
117
117
|
meta?: Record<string, unknown>;
|
|
118
|
+
/**
|
|
119
|
+
* Service codes (e.g. ['dev']) for which the platform should also build a
|
|
120
|
+
* ready-to-use preview URL with the freshly minted token baked in.
|
|
121
|
+
* Saves callers from having to know `baseDomain` or compose the URL.
|
|
122
|
+
*/
|
|
123
|
+
previewServiceCodes?: string[];
|
|
118
124
|
}
|
|
119
125
|
export interface CreateInstanceTokenOutput {
|
|
120
126
|
token: string;
|
|
121
127
|
expiresAt: string;
|
|
128
|
+
/**
|
|
129
|
+
* Preview URLs keyed by service code, populated when `previewServiceCodes`
|
|
130
|
+
* was set on the request. Each URL carries the token in `?token=` and is
|
|
131
|
+
* suitable for direct use as an iframe `src`.
|
|
132
|
+
*/
|
|
133
|
+
previewUrls?: Record<string, string>;
|
|
122
134
|
}
|
|
123
135
|
export interface ListBundlesInput {
|
|
124
136
|
limit?: number;
|
|
@@ -237,6 +249,27 @@ export interface GetServiceUrlInput {
|
|
|
237
249
|
export interface GetServiceUrlOutput {
|
|
238
250
|
url: string | null;
|
|
239
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Which file namespace inside the session to read from.
|
|
254
|
+
* - `workspace` — the user-facing workspace dir produced by session plugins (e.g. `dist/Course.zip`).
|
|
255
|
+
* - `session` — internal session storage under the SDK's `dataPath/sessions/{sessionId}`.
|
|
256
|
+
*/
|
|
257
|
+
export type SessionFileScope = 'workspace' | 'session';
|
|
258
|
+
export interface CreateSessionFileDownloadUrlInput {
|
|
259
|
+
instanceId: string;
|
|
260
|
+
sessionId: string;
|
|
261
|
+
scope: SessionFileScope;
|
|
262
|
+
/** Scope-relative path (no leading slash). Path traversal (`..`) is rejected. */
|
|
263
|
+
path: string;
|
|
264
|
+
/** TTL in seconds. Default 300, max 3600. */
|
|
265
|
+
ttlSeconds?: number;
|
|
266
|
+
}
|
|
267
|
+
export interface CreateSessionFileDownloadUrlOutput {
|
|
268
|
+
/** Signed, time-limited URL serving the file's bytes. */
|
|
269
|
+
url: string;
|
|
270
|
+
/** ISO 8601 expiry of the signed URL. */
|
|
271
|
+
expiresAt: string;
|
|
272
|
+
}
|
|
240
273
|
export declare const platformMethods: {
|
|
241
274
|
'instances.create': import("./rpc-definition").MethodDef<CreateInstanceInput, CreateInstanceOutput>;
|
|
242
275
|
'instances.get': import("./rpc-definition").MethodDef<GetInstanceInput, GetInstanceOutput>;
|
|
@@ -248,6 +281,7 @@ export declare const platformMethods: {
|
|
|
248
281
|
'sessions.publish': import("./rpc-definition").MethodDef<PublishSessionInput, PublishSessionOutput>;
|
|
249
282
|
'tokens.create': import("./rpc-definition").MethodDef<CreateInstanceTokenInput, CreateInstanceTokenOutput>;
|
|
250
283
|
'services.getUrl': import("./rpc-definition").MethodDef<GetServiceUrlInput, GetServiceUrlOutput>;
|
|
284
|
+
'sessionFiles.createDownloadUrl': import("./rpc-definition").MethodDef<CreateSessionFileDownloadUrlInput, CreateSessionFileDownloadUrlOutput>;
|
|
251
285
|
'bundles.list': import("./rpc-definition").MethodDef<ListBundlesInput, ListBundlesOutput>;
|
|
252
286
|
'bundles.delete': import("./rpc-definition").MethodDef<DeleteBundleInput, DeleteBundleOutput>;
|
|
253
287
|
'resources.create': import("./rpc-definition").MethodDef<CreateResourceInput, CreateResourceOutput>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../../src/platform/methods.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../../src/platform/methods.ts"],"names":[],"mappings":"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"}
|
package/dist/platform/methods.js
CHANGED
|
@@ -23,6 +23,8 @@ export const platformMethods = defineMethods({
|
|
|
23
23
|
'tokens.create': method(),
|
|
24
24
|
// Services
|
|
25
25
|
'services.getUrl': method(),
|
|
26
|
+
// Session files (signed-URL gateway in front of SDK's session/workspace + session/files routes)
|
|
27
|
+
'sessionFiles.createDownloadUrl': method(),
|
|
26
28
|
// Bundles
|
|
27
29
|
'bundles.list': method(),
|
|
28
30
|
'bundles.delete': method(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/platform/methods.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/platform/methods.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAoVxD,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC5C,YAAY;IACZ,kBAAkB,EAAE,MAAM,EAA6C;IACvE,eAAe,EAAE,MAAM,EAAuC;IAC9D,gBAAgB,EAAE,MAAM,EAA2C;IACnE,kBAAkB,EAAE,MAAM,EAAmD;IAC7E,mBAAmB,EAAE,MAAM,EAA+C;IAE1E,WAAW;IACX,iBAAiB,EAAE,MAAM,EAA2C;IACpE,eAAe,EAAE,MAAM,EAAyC;IAChE,kBAAkB,EAAE,MAAM,EAA6C;IAEvE,SAAS;IACT,eAAe,EAAE,MAAM,EAAuD;IAE9E,WAAW;IACX,iBAAiB,EAAE,MAAM,EAA2C;IAEpE,gGAAgG;IAChG,gCAAgC,EAAE,MAAM,EAAyE;IAEjH,UAAU;IACV,cAAc,EAAE,MAAM,EAAuC;IAC7D,gBAAgB,EAAE,MAAM,EAAyC;IAEjE,YAAY;IACZ,kBAAkB,EAAE,MAAM,EAA6C;IACvE,uBAAuB,EAAE,MAAM,EAAuD;IACtF,eAAe,EAAE,MAAM,EAAuC;IAC9D,gBAAgB,EAAE,MAAM,EAA2C;IACnE,kBAAkB,EAAE,MAAM,EAA6C;CACvE,CAAC,CAAA"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import type { CreateInstanceInput, CreateInstanceOutput, GetInstanceOutput, GetInstanceStatusOutput, ListInstancesInput, ListInstancesOutput, ArchiveInstanceOutput, CreateSessionInput, CreateSessionOutput, ListSessionsOutput, PublishSessionInput, PublishSessionOutput, CreateInstanceTokenInput, CreateInstanceTokenOutput, ListBundlesInput, ListBundlesOutput, DeleteBundleOutput, CreateResourceInput, CreateResourceOutput, AddResourceRevisionInput, AddResourceRevisionOutput, GetResourceInput, GetResourceOutput, ListResourcesInput, ListResourcesOutput, DeleteResourceOutput } from './methods';
|
|
1
|
+
import type { CreateInstanceInput, CreateInstanceOutput, GetInstanceOutput, GetInstanceStatusOutput, ListInstancesInput, ListInstancesOutput, ArchiveInstanceOutput, CreateSessionInput, CreateSessionOutput, ListSessionsOutput, PublishSessionInput, PublishSessionOutput, CreateInstanceTokenInput, CreateInstanceTokenOutput, CreateSessionFileDownloadUrlInput, CreateSessionFileDownloadUrlOutput, ListBundlesInput, ListBundlesOutput, DeleteBundleOutput, CreateResourceInput, CreateResourceOutput, AddResourceRevisionInput, AddResourceRevisionOutput, GetResourceInput, GetResourceOutput, ListResourcesInput, ListResourcesOutput, DeleteResourceOutput } from './methods';
|
|
2
2
|
export interface RojClientOptions {
|
|
3
3
|
/** Platform URL (e.g. https://roj.example.com) */
|
|
4
4
|
url: string;
|
|
5
5
|
/** Platform API key */
|
|
6
6
|
apiKey: string;
|
|
7
7
|
}
|
|
8
|
+
export interface SessionRpcInput {
|
|
9
|
+
instanceId: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
method: string;
|
|
12
|
+
input?: Record<string, unknown>;
|
|
13
|
+
}
|
|
8
14
|
export interface RojClient {
|
|
9
15
|
instances: {
|
|
10
16
|
create(input: CreateInstanceInput): Promise<CreateInstanceOutput>;
|
|
@@ -17,10 +23,28 @@ export interface RojClient {
|
|
|
17
23
|
create(input: CreateSessionInput): Promise<CreateSessionOutput>;
|
|
18
24
|
list(instanceId: string): Promise<ListSessionsOutput>;
|
|
19
25
|
publish(input: PublishSessionInput): Promise<PublishSessionOutput>;
|
|
26
|
+
/**
|
|
27
|
+
* Call a plugin/session RPC method on a running session.
|
|
28
|
+
*
|
|
29
|
+
* Auto-mints and caches an instance token; the cached token is reused until
|
|
30
|
+
* its expiry minus a small leeway. Suitable for server-to-server callers
|
|
31
|
+
* that don't have a browser cookie or pre-existing instance token.
|
|
32
|
+
*/
|
|
33
|
+
rpc<T = unknown>(input: SessionRpcInput): Promise<T>;
|
|
20
34
|
};
|
|
21
35
|
tokens: {
|
|
22
36
|
create(input: CreateInstanceTokenInput): Promise<CreateInstanceTokenOutput>;
|
|
23
37
|
};
|
|
38
|
+
sessionFiles: {
|
|
39
|
+
/**
|
|
40
|
+
* Mint a short-lived signed URL that streams the bytes of a session-bound file
|
|
41
|
+
* back to the caller. Use after a session plugin has produced an artifact
|
|
42
|
+
* (e.g. workspace `dist/Course.zip`) and the caller wants to fetch it without
|
|
43
|
+
* routing through the dev preview proxy. `scope` selects between the workspace
|
|
44
|
+
* dir and the SDK's session storage.
|
|
45
|
+
*/
|
|
46
|
+
createDownloadUrl(input: CreateSessionFileDownloadUrlInput): Promise<CreateSessionFileDownloadUrlOutput>;
|
|
47
|
+
};
|
|
24
48
|
bundles: {
|
|
25
49
|
list(input?: ListBundlesInput): Promise<ListBundlesOutput>;
|
|
26
50
|
delete(input: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-client.d.ts","sourceRoot":"","sources":["../../src/platform/rest-client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,MAAM,WAAW,CAAA;AAGlB,MAAM,WAAW,gBAAgB;IAChC,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAA;IACX,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,SAAS;IACzB,SAAS,EAAE;QACV,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACjE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;QACnD,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAA;QAC/D,IAAI,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC9D,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;KAC3D,CAAA;IACD,QAAQ,EAAE;QACT,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC/D,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;QACrD,OAAO,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"rest-client.d.ts","sourceRoot":"","sources":["../../src/platform/rest-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { createRpcClient } from './rpc-client';
|
|
2
2
|
import { RojApiError } from './errors';
|
|
3
|
+
// Re-mint instance tokens this many milliseconds before their server-stated expiry.
|
|
4
|
+
// Covers both clock skew between client and server and the latency of an in-flight
|
|
5
|
+
// session RPC that started just before expiry.
|
|
6
|
+
const TOKEN_REFRESH_LEEWAY_MS = 30000;
|
|
3
7
|
export function createRojClient(options) {
|
|
4
8
|
const rpc = createRpcClient(`${options.url}/api/v1`, {
|
|
5
9
|
headers: { Authorization: `Bearer ${options.apiKey}` },
|
|
@@ -10,6 +14,56 @@ export function createRojClient(options) {
|
|
|
10
14
|
throw new RojApiError(result.error);
|
|
11
15
|
return result.value;
|
|
12
16
|
}
|
|
17
|
+
const instanceTokenCache = new Map();
|
|
18
|
+
const inflightTokenMint = new Map();
|
|
19
|
+
async function getInstanceToken(instanceId) {
|
|
20
|
+
const cached = instanceTokenCache.get(instanceId);
|
|
21
|
+
if (cached && cached.expiresAtMs - TOKEN_REFRESH_LEEWAY_MS > Date.now()) {
|
|
22
|
+
return cached.token;
|
|
23
|
+
}
|
|
24
|
+
const inflight = inflightTokenMint.get(instanceId);
|
|
25
|
+
if (inflight)
|
|
26
|
+
return inflight;
|
|
27
|
+
const promise = (async () => {
|
|
28
|
+
try {
|
|
29
|
+
const fresh = await call('tokens.create', { instanceId });
|
|
30
|
+
instanceTokenCache.set(instanceId, {
|
|
31
|
+
token: fresh.token,
|
|
32
|
+
expiresAtMs: new Date(fresh.expiresAt).getTime(),
|
|
33
|
+
});
|
|
34
|
+
return fresh.token;
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
inflightTokenMint.delete(instanceId);
|
|
38
|
+
}
|
|
39
|
+
})();
|
|
40
|
+
inflightTokenMint.set(instanceId, promise);
|
|
41
|
+
return promise;
|
|
42
|
+
}
|
|
43
|
+
async function callSessionRpc(input, retriedAfter401 = false) {
|
|
44
|
+
const token = await getInstanceToken(input.instanceId);
|
|
45
|
+
const url = `${options.url}/api/v1/instances/${input.instanceId}/sessions/${input.sessionId}/rpc`;
|
|
46
|
+
const response = await fetch(url, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
Authorization: `Bearer ${token}`,
|
|
51
|
+
},
|
|
52
|
+
body: JSON.stringify({ method: input.method, input: input.input ?? {} }),
|
|
53
|
+
});
|
|
54
|
+
// Token may have been revoked or rotated server-side before its stated `expiresAt`.
|
|
55
|
+
// Evict the cache and retry once with a freshly minted token.
|
|
56
|
+
if (response.status === 401 && !retriedAfter401) {
|
|
57
|
+
instanceTokenCache.delete(input.instanceId);
|
|
58
|
+
return callSessionRpc(input, true);
|
|
59
|
+
}
|
|
60
|
+
const body = await response.json().catch(() => null);
|
|
61
|
+
if (!response.ok || !body || body.ok === false) {
|
|
62
|
+
const error = body?.error ?? { type: 'transport_error', message: `HTTP ${response.status}` };
|
|
63
|
+
throw new RojApiError(error);
|
|
64
|
+
}
|
|
65
|
+
return body.value;
|
|
66
|
+
}
|
|
13
67
|
return {
|
|
14
68
|
instances: {
|
|
15
69
|
create: (input) => call('instances.create', input),
|
|
@@ -22,10 +76,14 @@ export function createRojClient(options) {
|
|
|
22
76
|
create: (input) => call('sessions.create', input),
|
|
23
77
|
list: (instanceId) => call('sessions.list', { instanceId }),
|
|
24
78
|
publish: (input) => call('sessions.publish', input),
|
|
79
|
+
rpc: (input) => callSessionRpc(input),
|
|
25
80
|
},
|
|
26
81
|
tokens: {
|
|
27
82
|
create: (input) => call('tokens.create', input),
|
|
28
83
|
},
|
|
84
|
+
sessionFiles: {
|
|
85
|
+
createDownloadUrl: (input) => call('sessionFiles.createDownloadUrl', input),
|
|
86
|
+
},
|
|
29
87
|
bundles: {
|
|
30
88
|
list: (input) => call('bundles.list', input ?? {}),
|
|
31
89
|
delete: (input) => call('bundles.delete', input),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-client.js","sourceRoot":"","sources":["../../src/platform/rest-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"rest-client.js","sourceRoot":"","sources":["../../src/platform/rest-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roj-ai/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"type-check": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@roj-ai/shared": "^0.1.
|
|
43
|
+
"@roj-ai/shared": "^0.1.5"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"typescript": "5.9.3"
|
package/src/platform/index.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type { BuildPreviewUrlOptions, BuildWsUrlOptions } from './urls'
|
|
|
31
31
|
|
|
32
32
|
// REST client
|
|
33
33
|
export { createRojClient } from './rest-client'
|
|
34
|
-
export type { RojClient, RojClientOptions } from './rest-client'
|
|
34
|
+
export type { RojClient, RojClientOptions, SessionRpcInput } from './rest-client'
|
|
35
35
|
|
|
36
36
|
// Errors
|
|
37
37
|
export { RojApiError } from './errors'
|
package/src/platform/methods.ts
CHANGED
|
@@ -151,11 +151,23 @@ export interface CreateInstanceTokenInput {
|
|
|
151
151
|
origin?: string
|
|
152
152
|
expiresIn?: number // token TTL in seconds (default 24h, max 7d)
|
|
153
153
|
meta?: Record<string, unknown> // custom claims propagated to plugin method caller context
|
|
154
|
+
/**
|
|
155
|
+
* Service codes (e.g. ['dev']) for which the platform should also build a
|
|
156
|
+
* ready-to-use preview URL with the freshly minted token baked in.
|
|
157
|
+
* Saves callers from having to know `baseDomain` or compose the URL.
|
|
158
|
+
*/
|
|
159
|
+
previewServiceCodes?: string[]
|
|
154
160
|
}
|
|
155
161
|
|
|
156
162
|
export interface CreateInstanceTokenOutput {
|
|
157
163
|
token: string
|
|
158
164
|
expiresAt: string
|
|
165
|
+
/**
|
|
166
|
+
* Preview URLs keyed by service code, populated when `previewServiceCodes`
|
|
167
|
+
* was set on the request. Each URL carries the token in `?token=` and is
|
|
168
|
+
* suitable for direct use as an iframe `src`.
|
|
169
|
+
*/
|
|
170
|
+
previewUrls?: Record<string, string>
|
|
159
171
|
}
|
|
160
172
|
|
|
161
173
|
// ============================================================================
|
|
@@ -304,6 +316,34 @@ export interface GetServiceUrlOutput {
|
|
|
304
316
|
url: string | null
|
|
305
317
|
}
|
|
306
318
|
|
|
319
|
+
// ============================================================================
|
|
320
|
+
// Session files
|
|
321
|
+
// ============================================================================
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Which file namespace inside the session to read from.
|
|
325
|
+
* - `workspace` — the user-facing workspace dir produced by session plugins (e.g. `dist/Course.zip`).
|
|
326
|
+
* - `session` — internal session storage under the SDK's `dataPath/sessions/{sessionId}`.
|
|
327
|
+
*/
|
|
328
|
+
export type SessionFileScope = 'workspace' | 'session'
|
|
329
|
+
|
|
330
|
+
export interface CreateSessionFileDownloadUrlInput {
|
|
331
|
+
instanceId: string
|
|
332
|
+
sessionId: string
|
|
333
|
+
scope: SessionFileScope
|
|
334
|
+
/** Scope-relative path (no leading slash). Path traversal (`..`) is rejected. */
|
|
335
|
+
path: string
|
|
336
|
+
/** TTL in seconds. Default 300, max 3600. */
|
|
337
|
+
ttlSeconds?: number
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export interface CreateSessionFileDownloadUrlOutput {
|
|
341
|
+
/** Signed, time-limited URL serving the file's bytes. */
|
|
342
|
+
url: string
|
|
343
|
+
/** ISO 8601 expiry of the signed URL. */
|
|
344
|
+
expiresAt: string
|
|
345
|
+
}
|
|
346
|
+
|
|
307
347
|
// ============================================================================
|
|
308
348
|
// Method registry
|
|
309
349
|
// ============================================================================
|
|
@@ -327,6 +367,9 @@ export const platformMethods = defineMethods({
|
|
|
327
367
|
// Services
|
|
328
368
|
'services.getUrl': method<GetServiceUrlInput, GetServiceUrlOutput>(),
|
|
329
369
|
|
|
370
|
+
// Session files (signed-URL gateway in front of SDK's session/workspace + session/files routes)
|
|
371
|
+
'sessionFiles.createDownloadUrl': method<CreateSessionFileDownloadUrlInput, CreateSessionFileDownloadUrlOutput>(),
|
|
372
|
+
|
|
330
373
|
// Bundles
|
|
331
374
|
'bundles.list': method<ListBundlesInput, ListBundlesOutput>(),
|
|
332
375
|
'bundles.delete': method<DeleteBundleInput, DeleteBundleOutput>(),
|
|
@@ -16,6 +16,8 @@ import type {
|
|
|
16
16
|
PublishSessionOutput,
|
|
17
17
|
CreateInstanceTokenInput,
|
|
18
18
|
CreateInstanceTokenOutput,
|
|
19
|
+
CreateSessionFileDownloadUrlInput,
|
|
20
|
+
CreateSessionFileDownloadUrlOutput,
|
|
19
21
|
ListBundlesInput,
|
|
20
22
|
ListBundlesOutput,
|
|
21
23
|
DeleteBundleOutput,
|
|
@@ -38,6 +40,13 @@ export interface RojClientOptions {
|
|
|
38
40
|
apiKey: string
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
export interface SessionRpcInput {
|
|
44
|
+
instanceId: string
|
|
45
|
+
sessionId: string
|
|
46
|
+
method: string
|
|
47
|
+
input?: Record<string, unknown>
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
export interface RojClient {
|
|
42
51
|
instances: {
|
|
43
52
|
create(input: CreateInstanceInput): Promise<CreateInstanceOutput>
|
|
@@ -50,10 +59,28 @@ export interface RojClient {
|
|
|
50
59
|
create(input: CreateSessionInput): Promise<CreateSessionOutput>
|
|
51
60
|
list(instanceId: string): Promise<ListSessionsOutput>
|
|
52
61
|
publish(input: PublishSessionInput): Promise<PublishSessionOutput>
|
|
62
|
+
/**
|
|
63
|
+
* Call a plugin/session RPC method on a running session.
|
|
64
|
+
*
|
|
65
|
+
* Auto-mints and caches an instance token; the cached token is reused until
|
|
66
|
+
* its expiry minus a small leeway. Suitable for server-to-server callers
|
|
67
|
+
* that don't have a browser cookie or pre-existing instance token.
|
|
68
|
+
*/
|
|
69
|
+
rpc<T = unknown>(input: SessionRpcInput): Promise<T>
|
|
53
70
|
}
|
|
54
71
|
tokens: {
|
|
55
72
|
create(input: CreateInstanceTokenInput): Promise<CreateInstanceTokenOutput>
|
|
56
73
|
}
|
|
74
|
+
sessionFiles: {
|
|
75
|
+
/**
|
|
76
|
+
* Mint a short-lived signed URL that streams the bytes of a session-bound file
|
|
77
|
+
* back to the caller. Use after a session plugin has produced an artifact
|
|
78
|
+
* (e.g. workspace `dist/Course.zip`) and the caller wants to fetch it without
|
|
79
|
+
* routing through the dev preview proxy. `scope` selects between the workspace
|
|
80
|
+
* dir and the SDK's session storage.
|
|
81
|
+
*/
|
|
82
|
+
createDownloadUrl(input: CreateSessionFileDownloadUrlInput): Promise<CreateSessionFileDownloadUrlOutput>
|
|
83
|
+
}
|
|
57
84
|
bundles: {
|
|
58
85
|
list(input?: ListBundlesInput): Promise<ListBundlesOutput>
|
|
59
86
|
delete(input: { bundleId?: string; bundleSlug?: string }): Promise<DeleteBundleOutput>
|
|
@@ -70,6 +97,16 @@ export interface RojClient {
|
|
|
70
97
|
}
|
|
71
98
|
}
|
|
72
99
|
|
|
100
|
+
// Re-mint instance tokens this many milliseconds before their server-stated expiry.
|
|
101
|
+
// Covers both clock skew between client and server and the latency of an in-flight
|
|
102
|
+
// session RPC that started just before expiry.
|
|
103
|
+
const TOKEN_REFRESH_LEEWAY_MS = 30_000
|
|
104
|
+
|
|
105
|
+
interface CachedToken {
|
|
106
|
+
token: string
|
|
107
|
+
expiresAtMs: number
|
|
108
|
+
}
|
|
109
|
+
|
|
73
110
|
export function createRojClient(options: RojClientOptions): RojClient {
|
|
74
111
|
const rpc = createRpcClient<PlatformMethods>(`${options.url}/api/v1`, {
|
|
75
112
|
headers: { Authorization: `Bearer ${options.apiKey}` },
|
|
@@ -84,6 +121,56 @@ export function createRojClient(options: RojClientOptions): RojClient {
|
|
|
84
121
|
return result.value
|
|
85
122
|
}
|
|
86
123
|
|
|
124
|
+
const instanceTokenCache = new Map<string, CachedToken>()
|
|
125
|
+
const inflightTokenMint = new Map<string, Promise<string>>()
|
|
126
|
+
async function getInstanceToken(instanceId: string): Promise<string> {
|
|
127
|
+
const cached = instanceTokenCache.get(instanceId)
|
|
128
|
+
if (cached && cached.expiresAtMs - TOKEN_REFRESH_LEEWAY_MS > Date.now()) {
|
|
129
|
+
return cached.token
|
|
130
|
+
}
|
|
131
|
+
const inflight = inflightTokenMint.get(instanceId)
|
|
132
|
+
if (inflight) return inflight
|
|
133
|
+
const promise = (async () => {
|
|
134
|
+
try {
|
|
135
|
+
const fresh = await call('tokens.create', { instanceId })
|
|
136
|
+
instanceTokenCache.set(instanceId, {
|
|
137
|
+
token: fresh.token,
|
|
138
|
+
expiresAtMs: new Date(fresh.expiresAt).getTime(),
|
|
139
|
+
})
|
|
140
|
+
return fresh.token
|
|
141
|
+
} finally {
|
|
142
|
+
inflightTokenMint.delete(instanceId)
|
|
143
|
+
}
|
|
144
|
+
})()
|
|
145
|
+
inflightTokenMint.set(instanceId, promise)
|
|
146
|
+
return promise
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function callSessionRpc<T>(input: SessionRpcInput, retriedAfter401 = false): Promise<T> {
|
|
150
|
+
const token = await getInstanceToken(input.instanceId)
|
|
151
|
+
const url = `${options.url}/api/v1/instances/${input.instanceId}/sessions/${input.sessionId}/rpc`
|
|
152
|
+
const response = await fetch(url, {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
headers: {
|
|
155
|
+
'Content-Type': 'application/json',
|
|
156
|
+
Authorization: `Bearer ${token}`,
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify({ method: input.method, input: input.input ?? {} }),
|
|
159
|
+
})
|
|
160
|
+
// Token may have been revoked or rotated server-side before its stated `expiresAt`.
|
|
161
|
+
// Evict the cache and retry once with a freshly minted token.
|
|
162
|
+
if (response.status === 401 && !retriedAfter401) {
|
|
163
|
+
instanceTokenCache.delete(input.instanceId)
|
|
164
|
+
return callSessionRpc<T>(input, true)
|
|
165
|
+
}
|
|
166
|
+
const body = await response.json().catch(() => null) as { ok?: boolean; value?: unknown; error?: { type: string; message: string } } | null
|
|
167
|
+
if (!response.ok || !body || body.ok === false) {
|
|
168
|
+
const error = body?.error ?? { type: 'transport_error', message: `HTTP ${response.status}` }
|
|
169
|
+
throw new RojApiError(error)
|
|
170
|
+
}
|
|
171
|
+
return body.value as T
|
|
172
|
+
}
|
|
173
|
+
|
|
87
174
|
return {
|
|
88
175
|
instances: {
|
|
89
176
|
create: (input) => call('instances.create', input),
|
|
@@ -96,10 +183,14 @@ export function createRojClient(options: RojClientOptions): RojClient {
|
|
|
96
183
|
create: (input) => call('sessions.create', input),
|
|
97
184
|
list: (instanceId) => call('sessions.list', { instanceId }),
|
|
98
185
|
publish: (input) => call('sessions.publish', input),
|
|
186
|
+
rpc: (input) => callSessionRpc(input),
|
|
99
187
|
},
|
|
100
188
|
tokens: {
|
|
101
189
|
create: (input) => call('tokens.create', input),
|
|
102
190
|
},
|
|
191
|
+
sessionFiles: {
|
|
192
|
+
createDownloadUrl: (input) => call('sessionFiles.createDownloadUrl', input),
|
|
193
|
+
},
|
|
103
194
|
bundles: {
|
|
104
195
|
list: (input) => call('bundles.list', input ?? {}),
|
|
105
196
|
delete: (input) => call('bundles.delete', input),
|