@gitterm/sdk 0.0.1 → 0.0.4
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 +177 -14
- package/dist/client.d.ts +56 -0
- package/dist/config.d.ts +11 -0
- package/dist/device-login.d.ts +15 -0
- package/dist/errors.d.ts +15 -0
- package/dist/index.d.ts +9 -213
- package/dist/index.js +177 -11
- package/dist/transport.d.ts +2 -0
- package/dist/types.d.ts +297 -0
- package/dist/workspace-client.d.ts +44 -0
- package/package.json +5 -7
- package/src/index.d.ts +0 -213
package/dist/index.js
CHANGED
|
@@ -62,6 +62,43 @@ class GittermError extends Error {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
class WorkspaceLifecycleError extends GittermError {
|
|
66
|
+
constructor(code, message, options = {}) {
|
|
67
|
+
super(code, message, options);
|
|
68
|
+
this.name = "WorkspaceLifecycleError";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/transport.ts
|
|
73
|
+
var LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
74
|
+
function normalizeServerUrl(value) {
|
|
75
|
+
let url;
|
|
76
|
+
try {
|
|
77
|
+
url = new URL(value);
|
|
78
|
+
} catch {
|
|
79
|
+
throw new Error(`Invalid GitTerm server URL: ${value}`);
|
|
80
|
+
}
|
|
81
|
+
if (url.username || url.password) {
|
|
82
|
+
throw new Error("GitTerm server URL must not contain credentials");
|
|
83
|
+
}
|
|
84
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname))) {
|
|
85
|
+
throw new Error("GitTerm server URL must use HTTPS (HTTP is allowed only for loopback)");
|
|
86
|
+
}
|
|
87
|
+
url.hash = "";
|
|
88
|
+
url.search = "";
|
|
89
|
+
return url.toString().replace(/\/$/, "");
|
|
90
|
+
}
|
|
91
|
+
function createNoRedirectFetch(fetchImpl = fetch) {
|
|
92
|
+
return async (input, init) => {
|
|
93
|
+
const response = await fetchImpl(input, { ...init, redirect: "manual" });
|
|
94
|
+
if (response.status >= 300 && response.status < 400) {
|
|
95
|
+
const location = response.headers.get("location");
|
|
96
|
+
throw new Error(location ? `GitTerm server redirects are not allowed: ${location}` : "GitTerm server redirects are not allowed");
|
|
97
|
+
}
|
|
98
|
+
return response;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
65
102
|
// src/client.ts
|
|
66
103
|
function envValue(name) {
|
|
67
104
|
const value = typeof process !== "undefined" ? process.env[name] : undefined;
|
|
@@ -69,12 +106,12 @@ function envValue(name) {
|
|
|
69
106
|
}
|
|
70
107
|
function resolveCredentials(options) {
|
|
71
108
|
const config = !options.serverUrl || !options.token ? loadConfigSync(options.configPath) : null;
|
|
72
|
-
const serverUrl = options.serverUrl ?? envValue("GITTERM_SERVER_URL") ?? config?.serverUrl;
|
|
109
|
+
const serverUrl = options.serverUrl ?? envValue("GITTERM_SERVER_URL") ?? config?.serverUrl ?? DEFAULT_GITTERM_SERVER_URL;
|
|
73
110
|
const token = options.token ?? envValue("GITTERM_API_TOKEN") ?? config?.token;
|
|
74
111
|
if (!serverUrl || !token) {
|
|
75
112
|
throw new GittermError("NOT_LOGGED_IN", "Not logged in. Run: gitterm login");
|
|
76
113
|
}
|
|
77
|
-
return { serverUrl, token };
|
|
114
|
+
return { serverUrl: normalizeServerUrl(serverUrl), token };
|
|
78
115
|
}
|
|
79
116
|
function toTrpcUrl(serverUrl) {
|
|
80
117
|
return new URL("/trpc", serverUrl).toString();
|
|
@@ -121,7 +158,7 @@ function normalizeWorkspace(workspace) {
|
|
|
121
158
|
imageId: workspace.image.imageId
|
|
122
159
|
} : null,
|
|
123
160
|
startedAt: toIso(workspace.startedAt),
|
|
124
|
-
|
|
161
|
+
pausedAt: toIso(workspace.pausedAt),
|
|
125
162
|
terminatedAt: toIso(workspace.terminatedAt),
|
|
126
163
|
lastActiveAt: toIso(workspace.lastActiveAt),
|
|
127
164
|
updatedAt: toIso(workspace.updatedAt)
|
|
@@ -154,6 +191,8 @@ function mapTrpcCode(code) {
|
|
|
154
191
|
return "FORBIDDEN";
|
|
155
192
|
case "BAD_REQUEST":
|
|
156
193
|
return "BAD_REQUEST";
|
|
194
|
+
case "CONFLICT":
|
|
195
|
+
return "CONFLICT";
|
|
157
196
|
default:
|
|
158
197
|
return "SERVER_ERROR";
|
|
159
198
|
}
|
|
@@ -172,6 +211,24 @@ async function runWithServer(serverUrl, operation) {
|
|
|
172
211
|
});
|
|
173
212
|
}
|
|
174
213
|
const code = mapTrpcCode(trpcCode);
|
|
214
|
+
if (/WORKSPACE_TERMINATED/.test(error.message)) {
|
|
215
|
+
throw new WorkspaceLifecycleError("WORKSPACE_TERMINATED", error.message, { cause: error });
|
|
216
|
+
}
|
|
217
|
+
if (/WORKSPACE_NON_RECOVERABLE/.test(error.message)) {
|
|
218
|
+
throw new WorkspaceLifecycleError("WORKSPACE_NON_RECOVERABLE", error.message, {
|
|
219
|
+
cause: error
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (/WORKSPACE_START_TIMEOUT/.test(error.message)) {
|
|
223
|
+
throw new WorkspaceLifecycleError("WORKSPACE_START_TIMEOUT", error.message, {
|
|
224
|
+
cause: error
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (/WORKSPACE_RESTART_FAILED/.test(error.message)) {
|
|
228
|
+
throw new WorkspaceLifecycleError("WORKSPACE_RESTART_FAILED", error.message, {
|
|
229
|
+
cause: error
|
|
230
|
+
});
|
|
231
|
+
}
|
|
175
232
|
throw new GittermError(code, code === "UNAUTHORIZED" ? "Not logged in or token expired. Run: gitterm login" : error.message, { cause: error });
|
|
176
233
|
}
|
|
177
234
|
throw new GittermError("NETWORK", error instanceof Error ? error.message : "Network request failed", { cause: error });
|
|
@@ -183,14 +240,13 @@ function createGittermClient(options = {}) {
|
|
|
183
240
|
links: [
|
|
184
241
|
httpBatchLink({
|
|
185
242
|
url: toTrpcUrl(credentials.serverUrl),
|
|
186
|
-
fetch: options.fetch,
|
|
243
|
+
fetch: createNoRedirectFetch(options.fetch),
|
|
187
244
|
headers: () => ({ authorization: `Bearer ${credentials.token}` })
|
|
188
245
|
})
|
|
189
246
|
]
|
|
190
247
|
});
|
|
191
248
|
const run = (operation) => runWithServer(credentials.serverUrl, operation);
|
|
192
|
-
const
|
|
193
|
-
const result = await trpc.workspace.createWorkspace.mutate(input);
|
|
249
|
+
const normalizeCreateResult = (result) => {
|
|
194
250
|
const workspace = normalizeWorkspace(result.workspace);
|
|
195
251
|
if (!workspace)
|
|
196
252
|
throw new GittermError("SERVER_ERROR", "Workspace creation failed");
|
|
@@ -208,7 +264,30 @@ function createGittermClient(options = {}) {
|
|
|
208
264
|
providerKey: null
|
|
209
265
|
};
|
|
210
266
|
return { workspace, runtime };
|
|
267
|
+
};
|
|
268
|
+
const createWorkspace = (input) => run(async () => {
|
|
269
|
+
const result = await trpc.workspace.createWorkspace.mutate(input);
|
|
270
|
+
return normalizeCreateResult(result);
|
|
211
271
|
});
|
|
272
|
+
const waitForWorkspaceSetup = async (workspaceId, waitOptions) => {
|
|
273
|
+
const timeoutMs = waitOptions?.timeoutMs ?? 10 * 60000;
|
|
274
|
+
const pollIntervalMs = waitOptions?.pollIntervalMs ?? 2000;
|
|
275
|
+
const deadline = Date.now() + timeoutMs;
|
|
276
|
+
while (true) {
|
|
277
|
+
const result = await trpc.workspace.getSetupStatus.query({ workspaceId });
|
|
278
|
+
if (result.status === "not_requested" || result.status === "succeeded")
|
|
279
|
+
return result;
|
|
280
|
+
if (result.status === "failed") {
|
|
281
|
+
const log = result.log?.trim();
|
|
282
|
+
throw new GittermError("BAD_REQUEST", `Workspace setup failed${result.exitCode === null ? "" : ` with exit code ${result.exitCode}`}${log ? `
|
|
283
|
+
${log}` : ""}`);
|
|
284
|
+
}
|
|
285
|
+
if (Date.now() >= deadline) {
|
|
286
|
+
throw new GittermError("NETWORK", `Timed out waiting for workspace ${workspaceId} setup`);
|
|
287
|
+
}
|
|
288
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
289
|
+
}
|
|
290
|
+
};
|
|
212
291
|
return {
|
|
213
292
|
serverUrl: credentials.serverUrl,
|
|
214
293
|
auth: {
|
|
@@ -273,7 +352,28 @@ function createGittermClient(options = {}) {
|
|
|
273
352
|
};
|
|
274
353
|
}),
|
|
275
354
|
create: createWorkspace,
|
|
276
|
-
|
|
355
|
+
setupStatus: (workspaceId) => run(async () => trpc.workspace.getSetupStatus.query({ workspaceId })),
|
|
356
|
+
waitForSetup: (workspaceId, waitOptions) => run(() => waitForWorkspaceSetup(workspaceId, waitOptions))
|
|
357
|
+
},
|
|
358
|
+
runs: {
|
|
359
|
+
create: (input) => run(async () => trpc.run.create.mutate(input)),
|
|
360
|
+
get: (workspaceId, runId) => run(async () => trpc.run.get.query({ workspaceId, runId })),
|
|
361
|
+
messages: (workspaceId, runId) => run(async () => trpc.run.messages.query({ workspaceId, runId })),
|
|
362
|
+
cancel: (workspaceId, runId) => run(async () => trpc.run.cancel.mutate({ workspaceId, runId })),
|
|
363
|
+
wait: (workspaceId, runId, waitOptions) => run(async () => {
|
|
364
|
+
const timeoutMs = waitOptions?.timeoutMs ?? 30 * 60000;
|
|
365
|
+
const pollIntervalMs = waitOptions?.pollIntervalMs ?? 2000;
|
|
366
|
+
const deadline = Date.now() + timeoutMs;
|
|
367
|
+
while (true) {
|
|
368
|
+
const result = await trpc.run.get.query({ workspaceId, runId });
|
|
369
|
+
if (result.status !== "pending" && result.status !== "running" && result.status !== "retrying")
|
|
370
|
+
return result;
|
|
371
|
+
if (Date.now() >= deadline) {
|
|
372
|
+
throw new GittermError("NETWORK", `Timed out waiting for run ${runId}`);
|
|
373
|
+
}
|
|
374
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
375
|
+
}
|
|
376
|
+
})
|
|
277
377
|
},
|
|
278
378
|
catalog: {
|
|
279
379
|
agentTypes: (input) => run(async () => {
|
|
@@ -283,7 +383,8 @@ function createGittermClient(options = {}) {
|
|
|
283
383
|
cloudProviders: (input) => run(async () => {
|
|
284
384
|
const result = await trpc.workspace.listCloudProviders.query(input);
|
|
285
385
|
return result.cloudProviders;
|
|
286
|
-
})
|
|
386
|
+
}),
|
|
387
|
+
workspaceOptions: () => run(async () => trpc.workspace.getWorkspaceCatalog.query())
|
|
287
388
|
}
|
|
288
389
|
};
|
|
289
390
|
}
|
|
@@ -292,8 +393,9 @@ function sleep(ms) {
|
|
|
292
393
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
293
394
|
}
|
|
294
395
|
async function loginWithDeviceCode(serverUrl, options = {}) {
|
|
295
|
-
const
|
|
296
|
-
const
|
|
396
|
+
const normalizedServerUrl = normalizeServerUrl(serverUrl);
|
|
397
|
+
const fetchImpl = createNoRedirectFetch(options.fetch);
|
|
398
|
+
const codeRes = await fetchImpl(new URL("/api/device/code", normalizedServerUrl), {
|
|
297
399
|
method: "POST",
|
|
298
400
|
headers: { "content-type": "application/json" },
|
|
299
401
|
body: JSON.stringify({ clientName: options.clientName ?? "gitterm" })
|
|
@@ -309,7 +411,7 @@ async function loginWithDeviceCode(serverUrl, options = {}) {
|
|
|
309
411
|
});
|
|
310
412
|
const deadline = Date.now() + codeJson.expiresInSeconds * 1000;
|
|
311
413
|
while (Date.now() < deadline) {
|
|
312
|
-
const tokenRes = await fetchImpl(new URL("/api/device/token",
|
|
414
|
+
const tokenRes = await fetchImpl(new URL("/api/device/token", normalizedServerUrl), {
|
|
313
415
|
method: "POST",
|
|
314
416
|
headers: { "content-type": "application/json" },
|
|
315
417
|
body: JSON.stringify({ deviceCode: codeJson.deviceCode })
|
|
@@ -326,14 +428,78 @@ async function loginWithDeviceCode(serverUrl, options = {}) {
|
|
|
326
428
|
}
|
|
327
429
|
throw new Error("Device code expired; try again.");
|
|
328
430
|
}
|
|
431
|
+
// src/workspace-client.ts
|
|
432
|
+
import { TRPCClientError as TRPCClientError2, createTRPCClient as createTRPCClient2, httpBatchLink as httpBatchLink2 } from "@trpc/client";
|
|
433
|
+
function getWorkspaceEnvironment(environment) {
|
|
434
|
+
environment ??= typeof process === "undefined" ? {} : process.env;
|
|
435
|
+
const serverUrl = environment.WORKSPACE_API_URL;
|
|
436
|
+
const token = environment.WORKSPACE_AUTH_TOKEN;
|
|
437
|
+
const workspaceId = environment.WORKSPACE_ID;
|
|
438
|
+
const workspaceEnvironmentPresent = Boolean(serverUrl || token || workspaceId);
|
|
439
|
+
if (!workspaceEnvironmentPresent)
|
|
440
|
+
return null;
|
|
441
|
+
if (!serverUrl || !token || !workspaceId) {
|
|
442
|
+
throw new GittermError("UNAUTHORIZED", "Incomplete GitTerm workspace environment: WORKSPACE_API_URL, WORKSPACE_AUTH_TOKEN, and WORKSPACE_ID are required");
|
|
443
|
+
}
|
|
444
|
+
return { serverUrl: normalizeServerUrl(serverUrl), token, workspaceId };
|
|
445
|
+
}
|
|
446
|
+
function errorCode(code) {
|
|
447
|
+
if (code === "UNAUTHORIZED" || code === "NOT_FOUND" || code === "FORBIDDEN")
|
|
448
|
+
return code;
|
|
449
|
+
if (code === "BAD_REQUEST")
|
|
450
|
+
return code;
|
|
451
|
+
return "SERVER_ERROR";
|
|
452
|
+
}
|
|
453
|
+
function createGittermWorkspaceClient(options = {}) {
|
|
454
|
+
const detected = options.serverUrl && options.token && options.workspaceId ? null : getWorkspaceEnvironment();
|
|
455
|
+
const rawServerUrl = options.serverUrl ?? detected?.serverUrl;
|
|
456
|
+
const token = options.token ?? detected?.token;
|
|
457
|
+
const workspaceId = options.workspaceId ?? detected?.workspaceId;
|
|
458
|
+
if (!rawServerUrl || !token || !workspaceId) {
|
|
459
|
+
throw new GittermError("UNAUTHORIZED", "This command must run inside a GitTerm workspace");
|
|
460
|
+
}
|
|
461
|
+
const serverUrl = normalizeServerUrl(rawServerUrl);
|
|
462
|
+
const trpc = createTRPCClient2({
|
|
463
|
+
links: [
|
|
464
|
+
httpBatchLink2({
|
|
465
|
+
url: new URL("/trpc", serverUrl).toString(),
|
|
466
|
+
fetch: createNoRedirectFetch(options.fetch),
|
|
467
|
+
headers: () => ({ authorization: `Bearer ${token}` })
|
|
468
|
+
})
|
|
469
|
+
]
|
|
470
|
+
});
|
|
471
|
+
async function run(operation) {
|
|
472
|
+
try {
|
|
473
|
+
return await operation();
|
|
474
|
+
} catch (error) {
|
|
475
|
+
if (error instanceof TRPCClientError2) {
|
|
476
|
+
throw new GittermError(errorCode(error.data?.code), error.message, { cause: error });
|
|
477
|
+
}
|
|
478
|
+
throw new GittermError("NETWORK", error instanceof Error ? error.message : "Network request failed", { cause: error });
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
workspaceId,
|
|
483
|
+
serverUrl,
|
|
484
|
+
self: { get: () => run(() => trpc.workspaceOps.getSelf.query()) },
|
|
485
|
+
ports: {
|
|
486
|
+
list: () => run(() => trpc.workspaceOps.listPorts.query()),
|
|
487
|
+
open: (port, input) => run(() => trpc.workspaceOps.openPort.mutate({ port, ...input })),
|
|
488
|
+
close: (port) => run(() => trpc.workspaceOps.closePort.mutate({ port }))
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
}
|
|
329
492
|
export {
|
|
330
493
|
saveConfig,
|
|
331
494
|
loginWithDeviceCode,
|
|
332
495
|
loadConfigSync,
|
|
333
496
|
loadConfig,
|
|
497
|
+
getWorkspaceEnvironment,
|
|
334
498
|
getConfigPath,
|
|
335
499
|
deleteConfig,
|
|
500
|
+
createGittermWorkspaceClient,
|
|
336
501
|
createGittermClient,
|
|
502
|
+
WorkspaceLifecycleError,
|
|
337
503
|
GittermError,
|
|
338
504
|
DEFAULT_GITTERM_SERVER_URL
|
|
339
505
|
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
export type AuthStatus = {
|
|
2
|
+
loggedIn: true;
|
|
3
|
+
userId: string;
|
|
4
|
+
email: string;
|
|
5
|
+
name: string;
|
|
6
|
+
plan: string;
|
|
7
|
+
authMethod: "session" | "apiToken";
|
|
8
|
+
};
|
|
9
|
+
export type WorkspaceStatus = "pending" | "running" | "paused" | "terminated";
|
|
10
|
+
export type WorkspaceHostingType = "cloud" | "local";
|
|
11
|
+
export type Workspace = {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string | null;
|
|
14
|
+
status: WorkspaceStatus;
|
|
15
|
+
repositoryUrl: string | null;
|
|
16
|
+
repositoryBranch: string | null;
|
|
17
|
+
baseCommit: string | null;
|
|
18
|
+
checkoutRef: string | null;
|
|
19
|
+
domain: string;
|
|
20
|
+
subdomain: string | null;
|
|
21
|
+
persistent: boolean;
|
|
22
|
+
hostingType: WorkspaceHostingType;
|
|
23
|
+
serverOnly: boolean;
|
|
24
|
+
workspaceProfile: string;
|
|
25
|
+
cloudProviderId: string;
|
|
26
|
+
agentType: {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
description: string | null;
|
|
30
|
+
} | null;
|
|
31
|
+
image: {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
imageId: string;
|
|
35
|
+
} | null;
|
|
36
|
+
startedAt: string | null;
|
|
37
|
+
pausedAt: string | null;
|
|
38
|
+
terminatedAt: string | null;
|
|
39
|
+
lastActiveAt: string | null;
|
|
40
|
+
updatedAt: string | null;
|
|
41
|
+
};
|
|
42
|
+
export type WorkspaceRuntimeAccess = {
|
|
43
|
+
workspaceId: string;
|
|
44
|
+
status: WorkspaceStatus;
|
|
45
|
+
url: string | null;
|
|
46
|
+
headers?: Record<string, string>;
|
|
47
|
+
password?: string;
|
|
48
|
+
directory: string;
|
|
49
|
+
repo: string | null;
|
|
50
|
+
branch: string | null;
|
|
51
|
+
baseCommit: string | null;
|
|
52
|
+
checkoutRef: string | null;
|
|
53
|
+
persistent: boolean;
|
|
54
|
+
recoverable: boolean;
|
|
55
|
+
providerKey: string | null;
|
|
56
|
+
};
|
|
57
|
+
export type WorkspaceCreateResult = {
|
|
58
|
+
workspace: Workspace;
|
|
59
|
+
runtime: WorkspaceRuntimeAccess;
|
|
60
|
+
};
|
|
61
|
+
export type WorkspaceListOptions = {
|
|
62
|
+
limit?: number;
|
|
63
|
+
offset?: number;
|
|
64
|
+
status?: "all" | "active" | "terminated";
|
|
65
|
+
};
|
|
66
|
+
export type WorkspaceListResult = {
|
|
67
|
+
workspaces: Workspace[];
|
|
68
|
+
pagination: {
|
|
69
|
+
total: number;
|
|
70
|
+
limit: number;
|
|
71
|
+
offset: number;
|
|
72
|
+
hasMore: boolean;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
export type ProviderKey = "railway" | "aws" | "e2b" | "daytona" | "cloudflare" | "vercel" | "ascii" | "exedev";
|
|
76
|
+
type ProviderSelectionBase = {
|
|
77
|
+
/** Select a specific provider installation. Usually omitted. */
|
|
78
|
+
providerId?: string;
|
|
79
|
+
/** An admin-defined profile or flexible resources within the provider's allowed limits. */
|
|
80
|
+
machine?: {
|
|
81
|
+
type: "profile";
|
|
82
|
+
key: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
type FlexibleMachine<T> = {
|
|
86
|
+
type: "profile";
|
|
87
|
+
key: string;
|
|
88
|
+
} | {
|
|
89
|
+
type: "custom";
|
|
90
|
+
resources: T;
|
|
91
|
+
};
|
|
92
|
+
type AwsResources = {
|
|
93
|
+
cpu?: number;
|
|
94
|
+
memory?: number;
|
|
95
|
+
ephemeralStorageGiB?: number;
|
|
96
|
+
architecture?: "X86_64" | "ARM64";
|
|
97
|
+
};
|
|
98
|
+
type DaytonaResources = {
|
|
99
|
+
resources?: {
|
|
100
|
+
cpu?: number;
|
|
101
|
+
memory?: number;
|
|
102
|
+
disk?: number;
|
|
103
|
+
};
|
|
104
|
+
editorResources?: {
|
|
105
|
+
cpu?: number;
|
|
106
|
+
memory?: number;
|
|
107
|
+
disk?: number;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
type VercelResources = {
|
|
111
|
+
vcpus?: number;
|
|
112
|
+
};
|
|
113
|
+
type ExeDevResources = {
|
|
114
|
+
cpu?: number;
|
|
115
|
+
memory?: string;
|
|
116
|
+
disk?: string;
|
|
117
|
+
};
|
|
118
|
+
export type WorkspaceProviderSelection = {
|
|
119
|
+
type: "railway";
|
|
120
|
+
providerId?: string;
|
|
121
|
+
region?: string;
|
|
122
|
+
} | ({
|
|
123
|
+
type: "aws";
|
|
124
|
+
region?: string;
|
|
125
|
+
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
126
|
+
machine?: FlexibleMachine<AwsResources>;
|
|
127
|
+
}) | ({
|
|
128
|
+
type: "daytona";
|
|
129
|
+
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
130
|
+
machine?: FlexibleMachine<DaytonaResources>;
|
|
131
|
+
}) | ({
|
|
132
|
+
type: "vercel";
|
|
133
|
+
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
134
|
+
machine?: FlexibleMachine<VercelResources>;
|
|
135
|
+
}) | ({
|
|
136
|
+
type: "exedev";
|
|
137
|
+
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
138
|
+
machine?: FlexibleMachine<ExeDevResources>;
|
|
139
|
+
}) | ({
|
|
140
|
+
type: "e2b" | "ascii";
|
|
141
|
+
} & ProviderSelectionBase) | {
|
|
142
|
+
type: "cloudflare";
|
|
143
|
+
providerId?: string;
|
|
144
|
+
};
|
|
145
|
+
export type BuiltInAgentKey = "opencode-ttyd" | "opencode" | "t3code";
|
|
146
|
+
export type AgentKey = BuiltInAgentKey | (string & {});
|
|
147
|
+
export type WorkspaceCreateInput = {
|
|
148
|
+
idempotencyKey?: string;
|
|
149
|
+
name?: string;
|
|
150
|
+
repo: string;
|
|
151
|
+
branch?: string;
|
|
152
|
+
baseCommit?: string;
|
|
153
|
+
checkoutRef?: string;
|
|
154
|
+
subdomain?: string;
|
|
155
|
+
/** Stable agent key. Defaults to `opencode`. */
|
|
156
|
+
agent?: AgentKey;
|
|
157
|
+
/** Provider intent. Defaults to the user's or deployment's preferred provider. */
|
|
158
|
+
provider?: WorkspaceProviderSelection;
|
|
159
|
+
gitIntegrationId?: string;
|
|
160
|
+
/** Defaults from the selected provider. */
|
|
161
|
+
persistent?: boolean;
|
|
162
|
+
workspaceProfile?: "standard" | "ssh-enabled";
|
|
163
|
+
modelCredentialIds?: string[];
|
|
164
|
+
/**
|
|
165
|
+
* Ordered commands launched in the repository after the agent server starts.
|
|
166
|
+
* They do not block workspace readiness; inspect ~/.gitterm/setup for status
|
|
167
|
+
* and logs through workspaces.setupStatus()/waitForSetup().
|
|
168
|
+
*/
|
|
169
|
+
setupCommands?: string[];
|
|
170
|
+
/** OpenCode capabilities materialized only in this workspace. */
|
|
171
|
+
opencode?: {
|
|
172
|
+
skills?: Array<{
|
|
173
|
+
name: string;
|
|
174
|
+
content: string;
|
|
175
|
+
}>;
|
|
176
|
+
/** NPM package specs or plugin paths accepted by OpenCode. Pin versions for repeatable runs. */
|
|
177
|
+
plugins?: string[];
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
export type WorkspaceRestartResult = {
|
|
181
|
+
status: WorkspaceStatus;
|
|
182
|
+
};
|
|
183
|
+
export type WorkspacePauseResult = {
|
|
184
|
+
durationMinutes: number;
|
|
185
|
+
};
|
|
186
|
+
export type WorkspaceTerminateResult = {
|
|
187
|
+
workspace: Workspace | null;
|
|
188
|
+
cleanupInBackground: boolean;
|
|
189
|
+
};
|
|
190
|
+
export type WorkspaceEnsureRunningResult = {
|
|
191
|
+
workspace: Workspace;
|
|
192
|
+
runtime: WorkspaceRuntimeAccess;
|
|
193
|
+
};
|
|
194
|
+
export type AgentRunStatus = "pending" | "running" | "retrying" | "completed" | "failed" | "cancelled";
|
|
195
|
+
export type AgentRun = {
|
|
196
|
+
id: string;
|
|
197
|
+
workspaceId: string;
|
|
198
|
+
title: string;
|
|
199
|
+
status: AgentRunStatus;
|
|
200
|
+
error: string | null;
|
|
201
|
+
finalText: string | null;
|
|
202
|
+
context: {
|
|
203
|
+
type: "isolated";
|
|
204
|
+
} | {
|
|
205
|
+
type: "continued";
|
|
206
|
+
runId: string;
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
export type AgentRunCreateInput = {
|
|
210
|
+
workspaceId: string;
|
|
211
|
+
/** Stable key used to return the same run when a request is retried. */
|
|
212
|
+
idempotencyKey: string;
|
|
213
|
+
prompt: string;
|
|
214
|
+
title?: string;
|
|
215
|
+
agent?: string;
|
|
216
|
+
/** OpenCode model in provider/model format. */
|
|
217
|
+
model?: string;
|
|
218
|
+
/** Start with fresh context (default), or continue a terminal run's context. */
|
|
219
|
+
context?: {
|
|
220
|
+
type: "isolated";
|
|
221
|
+
} | {
|
|
222
|
+
type: "continue";
|
|
223
|
+
runId: string;
|
|
224
|
+
};
|
|
225
|
+
/** Wait for workspace setup commands before submitting the prompt. */
|
|
226
|
+
waitForSetup?: boolean;
|
|
227
|
+
setupTimeoutMs?: number;
|
|
228
|
+
};
|
|
229
|
+
export type AgentRunMessage = {
|
|
230
|
+
id: string;
|
|
231
|
+
role: "user" | "assistant";
|
|
232
|
+
createdAt: string;
|
|
233
|
+
completedAt: string | null;
|
|
234
|
+
text: string;
|
|
235
|
+
error: string | null;
|
|
236
|
+
};
|
|
237
|
+
export type WorkspaceSetupStatus = {
|
|
238
|
+
status: "not_requested" | "waiting" | "running" | "succeeded" | "failed";
|
|
239
|
+
exitCode: number | null;
|
|
240
|
+
startedAt: string | null;
|
|
241
|
+
finishedAt: string | null;
|
|
242
|
+
log: string | null;
|
|
243
|
+
};
|
|
244
|
+
export type AgentType = {
|
|
245
|
+
id: string;
|
|
246
|
+
key: string;
|
|
247
|
+
name: string;
|
|
248
|
+
description: string | null;
|
|
249
|
+
serverOnly: boolean;
|
|
250
|
+
isEnabled: boolean;
|
|
251
|
+
createdAt: Date | string;
|
|
252
|
+
updatedAt: Date | string;
|
|
253
|
+
};
|
|
254
|
+
export type CloudProvider = {
|
|
255
|
+
id: string;
|
|
256
|
+
name: string;
|
|
257
|
+
providerKey: ProviderKey | string;
|
|
258
|
+
regions?: Array<{
|
|
259
|
+
id: string;
|
|
260
|
+
name: string;
|
|
261
|
+
location: string;
|
|
262
|
+
externalRegionIdentifier: string;
|
|
263
|
+
}>;
|
|
264
|
+
};
|
|
265
|
+
export type WorkspaceCatalog = {
|
|
266
|
+
agents: Array<{
|
|
267
|
+
id: string;
|
|
268
|
+
key: string;
|
|
269
|
+
name: string;
|
|
270
|
+
description: string | null;
|
|
271
|
+
serverOnly: boolean;
|
|
272
|
+
}>;
|
|
273
|
+
providers: Array<{
|
|
274
|
+
id: string;
|
|
275
|
+
type: ProviderKey;
|
|
276
|
+
name: string;
|
|
277
|
+
isDefault: boolean;
|
|
278
|
+
persistence: "required" | "optional" | "unsupported";
|
|
279
|
+
regionSelection: "none" | "user" | "admin";
|
|
280
|
+
regions: Array<{
|
|
281
|
+
id: string;
|
|
282
|
+
key: string;
|
|
283
|
+
name: string;
|
|
284
|
+
location: string;
|
|
285
|
+
}>;
|
|
286
|
+
machines: Array<{
|
|
287
|
+
id: string;
|
|
288
|
+
key: string;
|
|
289
|
+
name: string;
|
|
290
|
+
description: string | null;
|
|
291
|
+
isDefault: boolean;
|
|
292
|
+
}>;
|
|
293
|
+
agentKeys: string[];
|
|
294
|
+
ssh: boolean;
|
|
295
|
+
}>;
|
|
296
|
+
};
|
|
297
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type WorkspaceEnvironment = {
|
|
2
|
+
serverUrl: string;
|
|
3
|
+
token: string;
|
|
4
|
+
workspaceId: string;
|
|
5
|
+
};
|
|
6
|
+
export type WorkspaceSelf = {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string | null;
|
|
9
|
+
status: "pending" | "running" | "paused" | "terminated";
|
|
10
|
+
repositoryUrl: string | null;
|
|
11
|
+
repositoryBranch: string | null;
|
|
12
|
+
baseCommit: string | null;
|
|
13
|
+
checkoutRef: string | null;
|
|
14
|
+
providerKey: string | null;
|
|
15
|
+
url: string | null;
|
|
16
|
+
ports: WorkspacePort[];
|
|
17
|
+
};
|
|
18
|
+
export type WorkspacePort = {
|
|
19
|
+
port: number;
|
|
20
|
+
name: string | null;
|
|
21
|
+
url: string | null;
|
|
22
|
+
};
|
|
23
|
+
export type WorkspaceClientOptions = Partial<WorkspaceEnvironment> & {
|
|
24
|
+
fetch?: typeof globalThis.fetch;
|
|
25
|
+
};
|
|
26
|
+
export type GittermWorkspaceClient = {
|
|
27
|
+
workspaceId: string;
|
|
28
|
+
serverUrl: string;
|
|
29
|
+
self: {
|
|
30
|
+
get(): Promise<WorkspaceSelf>;
|
|
31
|
+
};
|
|
32
|
+
ports: {
|
|
33
|
+
list(): Promise<WorkspacePort[]>;
|
|
34
|
+
open(port: number, options?: {
|
|
35
|
+
name?: string;
|
|
36
|
+
}): Promise<WorkspacePort>;
|
|
37
|
+
close(port: number): Promise<{
|
|
38
|
+
port: number;
|
|
39
|
+
closed: boolean;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare function getWorkspaceEnvironment(environment?: Record<string, string | undefined>): WorkspaceEnvironment | null;
|
|
44
|
+
export declare function createGittermWorkspaceClient(options?: WorkspaceClientOptions): GittermWorkspaceClient;
|
package/package.json
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitterm/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"files": [
|
|
5
|
-
"dist"
|
|
6
|
-
"src/index.d.ts"
|
|
5
|
+
"dist"
|
|
7
6
|
],
|
|
8
7
|
"type": "module",
|
|
9
8
|
"exports": {
|
|
10
9
|
".": {
|
|
11
|
-
"types": "./
|
|
12
|
-
"bun": "./
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"bun": "./dist/index.js",
|
|
13
12
|
"import": "./dist/index.js",
|
|
14
13
|
"default": "./dist/index.js"
|
|
15
14
|
}
|
|
@@ -18,7 +17,7 @@
|
|
|
18
17
|
"access": "public"
|
|
19
18
|
},
|
|
20
19
|
"scripts": {
|
|
21
|
-
"build": "bun build src/index.ts --outdir dist --target node --format esm --external @trpc/client &&
|
|
20
|
+
"build": "rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --external @trpc/client && tsc -p tsconfig.build.json",
|
|
22
21
|
"prepublishOnly": "bun run check-types && bun run build",
|
|
23
22
|
"check-types": "tsc --noEmit"
|
|
24
23
|
},
|
|
@@ -27,7 +26,6 @@
|
|
|
27
26
|
},
|
|
28
27
|
"devDependencies": {
|
|
29
28
|
"@gitterm/api": "workspace:*",
|
|
30
|
-
"@gitterm/config": "workspace:*",
|
|
31
29
|
"@trpc/server": "catalog:",
|
|
32
30
|
"@types/bun": "^1.2.6",
|
|
33
31
|
"typescript": "^5.8.2"
|