@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/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
- stoppedAt: toIso(workspace.stoppedAt),
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 createWorkspace = (input) => run(async () => {
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
- createSandbox: createWorkspace
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 fetchImpl = options.fetch ?? fetch;
296
- const codeRes = await fetchImpl(new URL("/api/device/code", serverUrl), {
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", serverUrl), {
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
  };
@@ -0,0 +1,2 @@
1
+ export declare function normalizeServerUrl(value: string): string;
2
+ export declare function createNoRedirectFetch(fetchImpl?: typeof fetch): typeof fetch;
@@ -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.1",
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": "./src/index.d.ts",
12
- "bun": "./src/index.ts",
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 && cp src/index.d.ts dist/index.d.ts",
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"