@roj-ai/client 0.0.2
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/api/client.d.ts +18 -0
- package/dist/api/unwrap.d.ts +2 -0
- package/dist/index.d.ts +9 -0
- package/dist/platform/errors.d.ts +6 -0
- package/dist/platform/index.d.ts +24 -0
- package/dist/platform/instance-methods.d.ts +94 -0
- package/dist/platform/methods.d.ts +260 -0
- package/dist/platform/rest-client.d.ts +49 -0
- package/dist/platform/rpc-client.d.ts +26 -0
- package/dist/platform/rpc-definition.d.ts +39 -0
- package/dist/platform/rpc-server.d.ts +21 -0
- package/dist/platform/sandbox-state.d.ts +1 -0
- package/dist/platform/urls.d.ts +34 -0
- package/dist/src/entities.d.ts +297 -0
- package/dist/src/enums.d.ts +6 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/names.d.ts +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +40 -0
- package/src/api/client.ts +75 -0
- package/src/api/unwrap.ts +7 -0
- package/src/index.ts +19 -0
- package/src/platform/errors.ts +11 -0
- package/src/platform/index.ts +37 -0
- package/src/platform/instance-methods.ts +153 -0
- package/src/platform/methods.ts +343 -0
- package/src/platform/rest-client.ts +131 -0
- package/src/platform/rpc-client.ts +67 -0
- package/src/platform/rpc-definition.ts +57 -0
- package/src/platform/rpc-server.ts +60 -0
- package/src/platform/sandbox-state.ts +1 -0
- package/src/platform/urls.ts +62 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instance-scoped RPC method definitions.
|
|
3
|
+
*
|
|
4
|
+
* These methods are called from the SPA via POST /api/v1/instances/:id/rpc
|
|
5
|
+
* with instance token or cookie auth. The instance is already resolved by the route,
|
|
6
|
+
* so inputs do NOT contain instanceId.
|
|
7
|
+
*
|
|
8
|
+
* Shared between worker (server) and client SDK.
|
|
9
|
+
*/
|
|
10
|
+
import { defineMethods, method } from './rpc-definition'
|
|
11
|
+
import type { PublishSessionOutput, GetAgentLogsOutput } from './methods'
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Sandbox methods
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
export type InstanceCreateSandboxInput = {}
|
|
18
|
+
export interface InstanceCreateSandboxOutput {
|
|
19
|
+
sandboxId: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface InstancePauseSandboxInput {
|
|
23
|
+
sandboxId: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type InstanceResumeSandboxInput = {}
|
|
27
|
+
|
|
28
|
+
export interface InstanceTerminateSandboxInput {
|
|
29
|
+
sandboxId: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface InstanceRestartAgentInput {
|
|
33
|
+
sandboxId: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface InstanceGetAgentLogsInput {
|
|
37
|
+
sandboxId: string
|
|
38
|
+
lines?: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface InstanceExecInSandboxInput {
|
|
42
|
+
command: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface InstanceExecInSandboxOutput {
|
|
46
|
+
stdout: string
|
|
47
|
+
stderr: string
|
|
48
|
+
success: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface InstanceValidateSandboxTokenInput {
|
|
52
|
+
sandboxId: string
|
|
53
|
+
token: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface InstanceValidateSandboxTokenOutput {
|
|
57
|
+
value: boolean
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Session methods
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
export interface InstanceCreateSessionInput {
|
|
65
|
+
presetId: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface InstanceCreateSessionOutput {
|
|
69
|
+
sessionId: string
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type InstanceListSessionsInput = {}
|
|
73
|
+
export interface InstanceListSessionsOutput {
|
|
74
|
+
sessions: Array<{
|
|
75
|
+
id: string
|
|
76
|
+
presetId: string | null
|
|
77
|
+
status: string
|
|
78
|
+
createdAt: number
|
|
79
|
+
}>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface InstancePublishSessionInput {
|
|
83
|
+
sessionId: string
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// Service methods
|
|
88
|
+
// ============================================================================
|
|
89
|
+
|
|
90
|
+
export interface InstanceGetServiceUrlInput {
|
|
91
|
+
sessionId: string
|
|
92
|
+
serviceType: string
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface InstanceGetServiceUrlOutput {
|
|
96
|
+
url: string | null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface InstanceGetServiceUrlsInput {
|
|
100
|
+
sessionId: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface InstanceGetServiceUrlsOutput {
|
|
104
|
+
services: Array<{
|
|
105
|
+
serviceType: string
|
|
106
|
+
code: string
|
|
107
|
+
port: number
|
|
108
|
+
}>
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface InstanceEnsureSandboxOutput {
|
|
112
|
+
sandboxId: string
|
|
113
|
+
state: string
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Shared output for void actions
|
|
118
|
+
// ============================================================================
|
|
119
|
+
|
|
120
|
+
export interface InstanceOkOutput {
|
|
121
|
+
ok: boolean
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Method registry
|
|
126
|
+
// ============================================================================
|
|
127
|
+
|
|
128
|
+
export const instanceMethods = defineMethods({
|
|
129
|
+
// Sandbox
|
|
130
|
+
createSandbox: method<InstanceCreateSandboxInput, InstanceCreateSandboxOutput>(),
|
|
131
|
+
pauseSandbox: method<InstancePauseSandboxInput, InstanceOkOutput>(),
|
|
132
|
+
resumeSandbox: method<InstanceResumeSandboxInput, InstanceOkOutput>(),
|
|
133
|
+
terminateSandbox: method<InstanceTerminateSandboxInput, InstanceOkOutput>(),
|
|
134
|
+
restartAgent: method<InstanceRestartAgentInput, InstanceOkOutput>(),
|
|
135
|
+
getAgentLogs: method<InstanceGetAgentLogsInput, GetAgentLogsOutput>(),
|
|
136
|
+
execInSandbox: method<InstanceExecInSandboxInput, InstanceExecInSandboxOutput>(),
|
|
137
|
+
validateSandboxToken: method<InstanceValidateSandboxTokenInput, InstanceValidateSandboxTokenOutput>(),
|
|
138
|
+
|
|
139
|
+
// Sessions
|
|
140
|
+
createSession: method<InstanceCreateSessionInput, InstanceCreateSessionOutput>(),
|
|
141
|
+
listSessions: method<InstanceListSessionsInput, InstanceListSessionsOutput>(),
|
|
142
|
+
publishSession: method<InstancePublishSessionInput, PublishSessionOutput>(),
|
|
143
|
+
|
|
144
|
+
// Services
|
|
145
|
+
getServiceUrl: method<InstanceGetServiceUrlInput, InstanceGetServiceUrlOutput>(),
|
|
146
|
+
getServiceUrls: method<InstanceGetServiceUrlsInput, InstanceGetServiceUrlsOutput>(),
|
|
147
|
+
|
|
148
|
+
// Idempotent sandbox access
|
|
149
|
+
ensureSandbox: method<{}, InstanceEnsureSandboxOutput>(),
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
export type InstanceMethods = typeof instanceMethods
|
|
153
|
+
export type InstanceMethodName = keyof InstanceMethods
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform RPC method definitions.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for all platform API method types.
|
|
5
|
+
* Shared between worker (server) and client SDK.
|
|
6
|
+
*/
|
|
7
|
+
import { defineMethods, method } from './rpc-definition'
|
|
8
|
+
import type { SandboxState } from './sandbox-state'
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Instance methods
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export interface CreateInstanceInput {
|
|
15
|
+
templateSlug: string
|
|
16
|
+
bundleSlug?: string
|
|
17
|
+
bundleRevisionId?: string
|
|
18
|
+
name: string
|
|
19
|
+
vcsType?: 'github' | 'gitLocal' | 'none'
|
|
20
|
+
metadata?: Record<string, unknown>
|
|
21
|
+
autoCreateSession?: {
|
|
22
|
+
presetId: string
|
|
23
|
+
blocking?: boolean
|
|
24
|
+
initialPrompt?: string
|
|
25
|
+
resourceIds?: string[]
|
|
26
|
+
fileIds?: string[]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CreateInstanceOutput {
|
|
31
|
+
instanceId: string
|
|
32
|
+
status: 'created' | 'initializing' | 'ready'
|
|
33
|
+
sessionId?: string
|
|
34
|
+
wsToken?: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface GetInstanceInput {
|
|
38
|
+
instanceId: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface GetInstanceOutput {
|
|
42
|
+
instanceId: string
|
|
43
|
+
name: string
|
|
44
|
+
status: string
|
|
45
|
+
templateSlug: string
|
|
46
|
+
bundleSlug: string
|
|
47
|
+
bundleRevisionId: string
|
|
48
|
+
vcsType: string
|
|
49
|
+
metadata: Record<string, unknown> | null
|
|
50
|
+
createdAt: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface GetInstanceStatusInput {
|
|
54
|
+
instanceId: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface GetInstanceStatusOutput {
|
|
58
|
+
instanceId: string
|
|
59
|
+
status: string
|
|
60
|
+
sandbox: {
|
|
61
|
+
state: SandboxState
|
|
62
|
+
e2bId?: string
|
|
63
|
+
lastActivityAt?: string
|
|
64
|
+
} | null
|
|
65
|
+
sessions: Array<{
|
|
66
|
+
id: string
|
|
67
|
+
presetId: string | null
|
|
68
|
+
status: string
|
|
69
|
+
createdAt: string
|
|
70
|
+
}>
|
|
71
|
+
lifecycleEvents: Array<{
|
|
72
|
+
event: string
|
|
73
|
+
detail?: string
|
|
74
|
+
createdAt: string
|
|
75
|
+
}>
|
|
76
|
+
serviceUrls: Array<{
|
|
77
|
+
code: string
|
|
78
|
+
sessionId: string | null
|
|
79
|
+
serviceType: string | null
|
|
80
|
+
port: number
|
|
81
|
+
}>
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ArchiveInstanceInput {
|
|
85
|
+
instanceId: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ArchiveInstanceOutput {
|
|
89
|
+
ok: boolean
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ListInstancesInput {
|
|
93
|
+
limit?: number
|
|
94
|
+
offset?: number
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface ListInstancesOutput {
|
|
98
|
+
instances: GetInstanceOutput[]
|
|
99
|
+
total: number
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Session methods
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
export interface CreateSessionInput {
|
|
107
|
+
instanceId: string
|
|
108
|
+
presetId: string
|
|
109
|
+
blocking?: boolean
|
|
110
|
+
origin?: string
|
|
111
|
+
expiresIn?: number // token TTL in seconds (default 24h, max 7d)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface CreateSessionOutput {
|
|
115
|
+
sessionId: string
|
|
116
|
+
status: 'creating' | 'active'
|
|
117
|
+
wsToken?: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface ListSessionsInput {
|
|
121
|
+
instanceId: string
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface ListSessionsOutput {
|
|
125
|
+
sessions: Array<{
|
|
126
|
+
id: string
|
|
127
|
+
presetId: string | null
|
|
128
|
+
status: string
|
|
129
|
+
createdAt: string
|
|
130
|
+
}>
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface PublishSessionInput {
|
|
134
|
+
instanceId: string
|
|
135
|
+
sessionId: string
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface PublishSessionOutput {
|
|
139
|
+
ok: boolean
|
|
140
|
+
pushed: boolean
|
|
141
|
+
commitSha?: string
|
|
142
|
+
error?: string
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ============================================================================
|
|
146
|
+
// Token methods
|
|
147
|
+
// ============================================================================
|
|
148
|
+
|
|
149
|
+
export interface CreateInstanceTokenInput {
|
|
150
|
+
instanceId: string
|
|
151
|
+
origin?: string
|
|
152
|
+
expiresIn?: number // token TTL in seconds (default 24h, max 7d)
|
|
153
|
+
meta?: Record<string, unknown> // custom claims propagated to plugin method caller context
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface CreateInstanceTokenOutput {
|
|
157
|
+
token: string
|
|
158
|
+
expiresAt: string
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Bundle methods
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
export interface ListBundlesInput {
|
|
166
|
+
limit?: number
|
|
167
|
+
offset?: number
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface ListBundlesOutput {
|
|
171
|
+
bundles: Array<{
|
|
172
|
+
id: string
|
|
173
|
+
slug: string
|
|
174
|
+
name: string | null
|
|
175
|
+
description: string | null
|
|
176
|
+
latestRevision: { id: string; version: string | null; r2Key: string; createdAt: string } | null
|
|
177
|
+
createdAt: string
|
|
178
|
+
}>
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface DeleteBundleInput {
|
|
182
|
+
bundleId?: string
|
|
183
|
+
bundleSlug?: string
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface DeleteBundleOutput {
|
|
187
|
+
ok: boolean
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ============================================================================
|
|
191
|
+
// Resource methods
|
|
192
|
+
// ============================================================================
|
|
193
|
+
|
|
194
|
+
export interface CreateResourceInput {
|
|
195
|
+
slug: string
|
|
196
|
+
name?: string
|
|
197
|
+
description?: string
|
|
198
|
+
fileId: string
|
|
199
|
+
label?: string
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface CreateResourceOutput {
|
|
203
|
+
resourceId: string
|
|
204
|
+
revisionId: string
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface AddResourceRevisionInput {
|
|
208
|
+
resourceId?: string
|
|
209
|
+
resourceSlug?: string
|
|
210
|
+
fileId: string
|
|
211
|
+
label?: string
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export interface AddResourceRevisionOutput {
|
|
215
|
+
revisionId: string
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface GetResourceInput {
|
|
219
|
+
resourceId?: string
|
|
220
|
+
resourceSlug?: string
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface GetResourceOutput {
|
|
224
|
+
id: string
|
|
225
|
+
slug: string
|
|
226
|
+
name: string | null
|
|
227
|
+
description: string | null
|
|
228
|
+
latestRevision: {
|
|
229
|
+
id: string
|
|
230
|
+
label: string | null
|
|
231
|
+
file: { id: string; filename: string; mimeType: string; size: number }
|
|
232
|
+
createdAt: string
|
|
233
|
+
} | null
|
|
234
|
+
createdAt: string
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface ListResourcesInput {
|
|
238
|
+
limit?: number
|
|
239
|
+
offset?: number
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface ListResourcesOutput {
|
|
243
|
+
resources: GetResourceOutput[]
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export interface DeleteResourceInput {
|
|
247
|
+
resourceId: string
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface DeleteResourceOutput {
|
|
251
|
+
ok: boolean
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ============================================================================
|
|
255
|
+
// Sandbox methods (admin/debug)
|
|
256
|
+
// ============================================================================
|
|
257
|
+
|
|
258
|
+
export interface PauseSandboxInput {
|
|
259
|
+
instanceId: string
|
|
260
|
+
sandboxId: string
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface ResumeSandboxInput {
|
|
264
|
+
instanceId: string
|
|
265
|
+
sandboxId: string
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface TerminateSandboxInput {
|
|
269
|
+
instanceId: string
|
|
270
|
+
sandboxId: string
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface RestartAgentInput {
|
|
274
|
+
instanceId: string
|
|
275
|
+
sandboxId: string
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export interface GetAgentLogsInput {
|
|
279
|
+
instanceId: string
|
|
280
|
+
sandboxId: string
|
|
281
|
+
lines?: number
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export interface GetAgentLogsOutput {
|
|
285
|
+
logs: string
|
|
286
|
+
truncated: boolean
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export interface SandboxActionOutput {
|
|
290
|
+
ok: boolean
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// Services
|
|
295
|
+
// ============================================================================
|
|
296
|
+
|
|
297
|
+
export interface GetServiceUrlInput {
|
|
298
|
+
instanceId: string
|
|
299
|
+
sessionId: string
|
|
300
|
+
serviceType: string
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export interface GetServiceUrlOutput {
|
|
304
|
+
url: string | null
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ============================================================================
|
|
308
|
+
// Method registry
|
|
309
|
+
// ============================================================================
|
|
310
|
+
|
|
311
|
+
export const platformMethods = defineMethods({
|
|
312
|
+
// Instances
|
|
313
|
+
'instances.create': method<CreateInstanceInput, CreateInstanceOutput>(),
|
|
314
|
+
'instances.get': method<GetInstanceInput, GetInstanceOutput>(),
|
|
315
|
+
'instances.list': method<ListInstancesInput, ListInstancesOutput>(),
|
|
316
|
+
'instances.status': method<GetInstanceStatusInput, GetInstanceStatusOutput>(),
|
|
317
|
+
'instances.archive': method<ArchiveInstanceInput, ArchiveInstanceOutput>(),
|
|
318
|
+
|
|
319
|
+
// Sessions
|
|
320
|
+
'sessions.create': method<CreateSessionInput, CreateSessionOutput>(),
|
|
321
|
+
'sessions.list': method<ListSessionsInput, ListSessionsOutput>(),
|
|
322
|
+
'sessions.publish': method<PublishSessionInput, PublishSessionOutput>(),
|
|
323
|
+
|
|
324
|
+
// Tokens
|
|
325
|
+
'tokens.create': method<CreateInstanceTokenInput, CreateInstanceTokenOutput>(),
|
|
326
|
+
|
|
327
|
+
// Services
|
|
328
|
+
'services.getUrl': method<GetServiceUrlInput, GetServiceUrlOutput>(),
|
|
329
|
+
|
|
330
|
+
// Bundles
|
|
331
|
+
'bundles.list': method<ListBundlesInput, ListBundlesOutput>(),
|
|
332
|
+
'bundles.delete': method<DeleteBundleInput, DeleteBundleOutput>(),
|
|
333
|
+
|
|
334
|
+
// Resources
|
|
335
|
+
'resources.create': method<CreateResourceInput, CreateResourceOutput>(),
|
|
336
|
+
'resources.addRevision': method<AddResourceRevisionInput, AddResourceRevisionOutput>(),
|
|
337
|
+
'resources.get': method<GetResourceInput, GetResourceOutput>(),
|
|
338
|
+
'resources.list': method<ListResourcesInput, ListResourcesOutput>(),
|
|
339
|
+
'resources.delete': method<DeleteResourceInput, DeleteResourceOutput>(),
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
export type PlatformMethods = typeof platformMethods
|
|
343
|
+
export type PlatformMethodName = keyof PlatformMethods
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { createRpcClient } from './rpc-client'
|
|
2
|
+
import type { MethodInput, MethodOutput } from './rpc-definition'
|
|
3
|
+
import type { PlatformMethods, PlatformMethodName } from './methods'
|
|
4
|
+
import type {
|
|
5
|
+
CreateInstanceInput,
|
|
6
|
+
CreateInstanceOutput,
|
|
7
|
+
GetInstanceOutput,
|
|
8
|
+
GetInstanceStatusOutput,
|
|
9
|
+
ListInstancesInput,
|
|
10
|
+
ListInstancesOutput,
|
|
11
|
+
ArchiveInstanceOutput,
|
|
12
|
+
CreateSessionInput,
|
|
13
|
+
CreateSessionOutput,
|
|
14
|
+
ListSessionsOutput,
|
|
15
|
+
PublishSessionInput,
|
|
16
|
+
PublishSessionOutput,
|
|
17
|
+
CreateInstanceTokenInput,
|
|
18
|
+
CreateInstanceTokenOutput,
|
|
19
|
+
ListBundlesInput,
|
|
20
|
+
ListBundlesOutput,
|
|
21
|
+
DeleteBundleOutput,
|
|
22
|
+
CreateResourceInput,
|
|
23
|
+
CreateResourceOutput,
|
|
24
|
+
AddResourceRevisionInput,
|
|
25
|
+
AddResourceRevisionOutput,
|
|
26
|
+
GetResourceInput,
|
|
27
|
+
GetResourceOutput,
|
|
28
|
+
ListResourcesInput,
|
|
29
|
+
ListResourcesOutput,
|
|
30
|
+
DeleteResourceOutput,
|
|
31
|
+
} from './methods'
|
|
32
|
+
import { RojApiError } from './errors'
|
|
33
|
+
|
|
34
|
+
export interface RojClientOptions {
|
|
35
|
+
/** Platform URL (e.g. https://roj.example.com) */
|
|
36
|
+
url: string
|
|
37
|
+
/** Platform API key */
|
|
38
|
+
apiKey: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface RojClient {
|
|
42
|
+
instances: {
|
|
43
|
+
create(input: CreateInstanceInput): Promise<CreateInstanceOutput>
|
|
44
|
+
get(instanceId: string): Promise<GetInstanceOutput>
|
|
45
|
+
getStatus(instanceId: string): Promise<GetInstanceStatusOutput>
|
|
46
|
+
list(input?: ListInstancesInput): Promise<ListInstancesOutput>
|
|
47
|
+
archive(instanceId: string): Promise<ArchiveInstanceOutput>
|
|
48
|
+
}
|
|
49
|
+
sessions: {
|
|
50
|
+
create(input: CreateSessionInput): Promise<CreateSessionOutput>
|
|
51
|
+
list(instanceId: string): Promise<ListSessionsOutput>
|
|
52
|
+
publish(input: PublishSessionInput): Promise<PublishSessionOutput>
|
|
53
|
+
}
|
|
54
|
+
tokens: {
|
|
55
|
+
create(input: CreateInstanceTokenInput): Promise<CreateInstanceTokenOutput>
|
|
56
|
+
}
|
|
57
|
+
bundles: {
|
|
58
|
+
list(input?: ListBundlesInput): Promise<ListBundlesOutput>
|
|
59
|
+
delete(input: { bundleId?: string; bundleSlug?: string }): Promise<DeleteBundleOutput>
|
|
60
|
+
}
|
|
61
|
+
files: {
|
|
62
|
+
upload(file: File | Blob, filename?: string): Promise<{ ok: true; fileId: string; filename: string; mimeType: string; size: number; r2Key: string }>
|
|
63
|
+
}
|
|
64
|
+
resources: {
|
|
65
|
+
create(input: CreateResourceInput): Promise<CreateResourceOutput>
|
|
66
|
+
addRevision(input: AddResourceRevisionInput): Promise<AddResourceRevisionOutput>
|
|
67
|
+
get(input: GetResourceInput): Promise<GetResourceOutput>
|
|
68
|
+
list(input?: ListResourcesInput): Promise<ListResourcesOutput>
|
|
69
|
+
delete(resourceId: string): Promise<DeleteResourceOutput>
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function createRojClient(options: RojClientOptions): RojClient {
|
|
74
|
+
const rpc = createRpcClient<PlatformMethods>(`${options.url}/api/v1`, {
|
|
75
|
+
headers: { Authorization: `Bearer ${options.apiKey}` },
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
async function call<M extends PlatformMethodName>(
|
|
79
|
+
method: M,
|
|
80
|
+
input: MethodInput<PlatformMethods, M>,
|
|
81
|
+
): Promise<MethodOutput<PlatformMethods, M>> {
|
|
82
|
+
const result = await rpc.call(method, input)
|
|
83
|
+
if (!result.ok) throw new RojApiError(result.error)
|
|
84
|
+
return result.value
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
instances: {
|
|
89
|
+
create: (input) => call('instances.create', input),
|
|
90
|
+
get: (instanceId) => call('instances.get', { instanceId }),
|
|
91
|
+
getStatus: (instanceId) => call('instances.status', { instanceId }),
|
|
92
|
+
list: (input) => call('instances.list', input ?? {}),
|
|
93
|
+
archive: (instanceId) => call('instances.archive', { instanceId }),
|
|
94
|
+
},
|
|
95
|
+
sessions: {
|
|
96
|
+
create: (input) => call('sessions.create', input),
|
|
97
|
+
list: (instanceId) => call('sessions.list', { instanceId }),
|
|
98
|
+
publish: (input) => call('sessions.publish', input),
|
|
99
|
+
},
|
|
100
|
+
tokens: {
|
|
101
|
+
create: (input) => call('tokens.create', input),
|
|
102
|
+
},
|
|
103
|
+
bundles: {
|
|
104
|
+
list: (input) => call('bundles.list', input ?? {}),
|
|
105
|
+
delete: (input) => call('bundles.delete', input),
|
|
106
|
+
},
|
|
107
|
+
files: {
|
|
108
|
+
upload: async (file, filename) => {
|
|
109
|
+
const formData = new FormData()
|
|
110
|
+
formData.append('file', file, filename)
|
|
111
|
+
const response = await fetch(`${options.url}/api/v1/files/upload`, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: { Authorization: `Bearer ${options.apiKey}` },
|
|
114
|
+
body: formData,
|
|
115
|
+
})
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
const body = await response.json().catch(() => ({ message: response.statusText }))
|
|
118
|
+
throw new RojApiError({ type: 'http_error', message: body.error ?? body.message ?? response.statusText })
|
|
119
|
+
}
|
|
120
|
+
return response.json()
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
resources: {
|
|
124
|
+
create: (input) => call('resources.create', input),
|
|
125
|
+
addRevision: (input) => call('resources.addRevision', input),
|
|
126
|
+
get: (input) => call('resources.get', input),
|
|
127
|
+
list: (input) => call('resources.list', input ?? {}),
|
|
128
|
+
delete: (resourceId) => call('resources.delete', { resourceId }),
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe RPC client.
|
|
3
|
+
* Mirrors the method definitions for compile-time safety.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* const client = createRpcClient<PlatformMethods>('https://api.roj.cloud/rpc', {
|
|
7
|
+
* headers: { Authorization: `Bearer ${apiKey}` },
|
|
8
|
+
* })
|
|
9
|
+
* const result = await client.call('instances.create', { ... })
|
|
10
|
+
*/
|
|
11
|
+
import type { MethodDef, MethodInput, MethodOutput, RpcError, RpcResponse } from './rpc-definition'
|
|
12
|
+
|
|
13
|
+
export interface RpcClientOptions {
|
|
14
|
+
headers?: Record<string, string>
|
|
15
|
+
credentials?: RequestCredentials
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RpcClient<Methods extends Record<string, MethodDef>> {
|
|
19
|
+
call<M extends string & keyof Methods>(
|
|
20
|
+
method: M,
|
|
21
|
+
input: MethodInput<Methods, M>,
|
|
22
|
+
): Promise<RpcResult<MethodOutput<Methods, M>>>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type RpcResult<T> =
|
|
26
|
+
| { ok: true; value: T }
|
|
27
|
+
| { ok: false; error: RpcError }
|
|
28
|
+
|
|
29
|
+
export function createRpcClient<Methods extends Record<string, MethodDef>>(
|
|
30
|
+
baseUrl: string,
|
|
31
|
+
options?: RpcClientOptions,
|
|
32
|
+
): RpcClient<Methods> {
|
|
33
|
+
return {
|
|
34
|
+
async call<M extends string & keyof Methods>(
|
|
35
|
+
method: M,
|
|
36
|
+
input: MethodInput<Methods, M>,
|
|
37
|
+
): Promise<RpcResult<MethodOutput<Methods, M>>> {
|
|
38
|
+
const response = await fetch(`${baseUrl}/rpc`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
...options?.headers,
|
|
43
|
+
},
|
|
44
|
+
credentials: options?.credentials,
|
|
45
|
+
body: JSON.stringify({ method, input }),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const data = (await response.json()) as RpcResponse
|
|
49
|
+
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
error: data.error ?? { type: 'transport_error', message: `HTTP ${response.status}` },
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (data.ok) {
|
|
58
|
+
return { ok: true, value: data.value as MethodOutput<Methods, M> }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
error: data.error ?? { type: 'unknown_error', message: 'Unknown error' },
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
}
|