@gitterm/sdk 0.0.8 → 0.1.1

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.
@@ -0,0 +1,39 @@
1
+ import type { DirectProviderWorkspaceInput, DirectProvisioningPlan, DirectModelCredential, DirectWorkspaceCreateInput, DirectWorkspaceRuntime } from "./types.js";
2
+ export declare const DIRECT_OPENCODE_PORT = 4096;
3
+ export declare const DIRECT_OPENCODE_COMMAND = "opencode serve --hostname 0.0.0.0 --port 4096";
4
+ export declare const DIRECT_OPENCODE_SERVER_IMAGE = "opeoginni/gitterm-opencode-server:latest";
5
+ export declare const DIRECT_E2B_TEMPLATES: {
6
+ readonly standard: "gitterm-opencode-server";
7
+ readonly large: "gitterm-opencode-server-lg";
8
+ };
9
+ export declare const DIRECT_GITTERM_INSTRUCTIONS = "You are running in a direct Gitterm workspace. Follow the user's instructions and verify outcomes before reporting success.";
10
+ export declare function resolveDirectImage(image?: string): string;
11
+ export declare function directModelAuth(credential: DirectModelCredential): {
12
+ enterpriseUrl?: string | undefined;
13
+ accountId?: string | undefined;
14
+ type: "oauth";
15
+ refresh: string;
16
+ access: string;
17
+ expires: number;
18
+ } | {
19
+ metadata?: Record<string, string> | undefined;
20
+ type: "api";
21
+ key: string;
22
+ };
23
+ export declare function validateDirectFilePath(path: string): string;
24
+ export declare function validateDirectFileMode(mode?: number): number;
25
+ export declare function buildDirectGittermInstructions(additional?: string): string;
26
+ export declare function repositoryName(url: string): string;
27
+ export declare function buildDirectProvisioningPlan(input: DirectWorkspaceCreateInput & {
28
+ id: string;
29
+ lifecycle: DirectProviderWorkspaceInput["lifecycle"];
30
+ password: string;
31
+ }): DirectProvisioningPlan;
32
+ export declare function railwayContainerEnvironment(plan: DirectProvisioningPlan): Record<string, string>;
33
+ export declare function setupCommandScript(commands: string[]): string;
34
+ export declare function shellQuote(value: string): string;
35
+ export declare function shellPath(path: string): string;
36
+ export declare function cloneRepositoryScript(repository: NonNullable<DirectProvisioningPlan["repository"]>, directory: string): string;
37
+ export declare function pinFloatingDockerImage(image: string): Promise<string>;
38
+ export declare function basicAuthHeader(password: string): string;
39
+ export declare function waitForDirectRuntime(runtime: DirectWorkspaceRuntime, timeoutMs?: number): Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { DirectProviderAdapter, RailwayDirectProviderConfig } from "./types.js";
2
+ export declare function createRailwayDirectProvider(config: RailwayDirectProviderConfig): DirectProviderAdapter;
@@ -0,0 +1,319 @@
1
+ export type DirectWorkspaceLifecycle = "ephemeral" | "persistent";
2
+ export type DirectWorkspaceStatus = "pending" | "running" | "paused" | "failed" | "terminated" | "unknown";
3
+ export type DirectProviderCapabilities = {
4
+ persistence: "supported" | "unsupported";
5
+ recommendedLifecycle: DirectWorkspaceLifecycle;
6
+ supportsPause: boolean;
7
+ /** Whether manually pausing an ephemeral workspace preserves its filesystem/session. */
8
+ ephemeralPause: "stateful" | "state-losing" | "unsupported";
9
+ supportsKeepAlive: boolean;
10
+ };
11
+ export type DirectApiModelCredential = {
12
+ providerName: string;
13
+ type?: "api";
14
+ apiKey: string;
15
+ metadata?: Record<string, string>;
16
+ };
17
+ export type DirectOAuthModelCredential = {
18
+ providerName: string;
19
+ type: "oauth";
20
+ refreshToken: string;
21
+ /** May be omitted when OpenCode should refresh immediately. */
22
+ accessToken?: string;
23
+ /** Unix epoch time in milliseconds. Defaults to expired when omitted. */
24
+ expiresAt?: number;
25
+ accountId?: string;
26
+ enterpriseUrl?: string;
27
+ };
28
+ export type DirectModelCredential = DirectApiModelCredential | DirectOAuthModelCredential;
29
+ export type DirectAuthPrompt = {
30
+ type: "text";
31
+ key: string;
32
+ message: string;
33
+ placeholder?: string;
34
+ when?: {
35
+ key: string;
36
+ op: "eq" | "neq";
37
+ value: string;
38
+ };
39
+ } | {
40
+ type: "select";
41
+ key: string;
42
+ message: string;
43
+ options: Array<{
44
+ label: string;
45
+ value: string;
46
+ hint?: string;
47
+ }>;
48
+ when?: {
49
+ key: string;
50
+ op: "eq" | "neq";
51
+ value: string;
52
+ };
53
+ };
54
+ export type DirectAuthMethod = {
55
+ type: "oauth";
56
+ id: string;
57
+ label: string;
58
+ prompts?: DirectAuthPrompt[];
59
+ } | {
60
+ type: "key";
61
+ label?: string;
62
+ } | {
63
+ type: "env";
64
+ names: string[];
65
+ };
66
+ export type DirectAuthIntegration = {
67
+ id: string;
68
+ name: string;
69
+ methods: DirectAuthMethod[];
70
+ connections: Array<{
71
+ type: "credential";
72
+ id: string;
73
+ label: string;
74
+ } | {
75
+ type: "env";
76
+ name: string;
77
+ }>;
78
+ };
79
+ export type DirectAuthAttempt = {
80
+ id: string;
81
+ workspaceId: string;
82
+ integrationId: string;
83
+ url: string;
84
+ instructions: string;
85
+ mode: "auto" | "code";
86
+ createdAt: number;
87
+ expiresAt: number;
88
+ };
89
+ export type DirectAuthAttemptStatus = {
90
+ status: "pending";
91
+ createdAt: number;
92
+ expiresAt: number;
93
+ } | {
94
+ status: "complete";
95
+ createdAt: number;
96
+ expiresAt: number;
97
+ } | {
98
+ status: "failed";
99
+ message: string;
100
+ createdAt: number;
101
+ expiresAt: number;
102
+ } | {
103
+ status: "expired";
104
+ createdAt: number;
105
+ expiresAt: number;
106
+ };
107
+ export type DirectAuthWaitOptions = {
108
+ timeoutMs?: number;
109
+ pollIntervalMs?: number;
110
+ };
111
+ export type DirectSecretFile = {
112
+ /** Absolute path or a path below the workspace user's home (`~/...`). */
113
+ path: string;
114
+ content: string;
115
+ /** Unix permission bits. Defaults to owner read/write (0600). */
116
+ mode?: number;
117
+ };
118
+ export type DirectWorkspaceSetup = {
119
+ beforeAgent?: string[];
120
+ afterAgent?: string[];
121
+ };
122
+ export type DirectWorkspaceCreateInput = {
123
+ id?: string;
124
+ repo?: string;
125
+ branch?: string;
126
+ baseCommit?: string;
127
+ checkoutRef?: string;
128
+ repositoryCredentials?: {
129
+ username?: string;
130
+ token: string;
131
+ };
132
+ lifecycle?: DirectWorkspaceLifecycle;
133
+ environmentVariables?: Record<string, string>;
134
+ modelCredentials?: DirectModelCredential[];
135
+ setup?: DirectWorkspaceSetup;
136
+ secretFiles?: DirectSecretFile[];
137
+ /** Provider-specific attachment settings. */
138
+ exedev?: {
139
+ existingVmName: string;
140
+ };
141
+ /** Trusted integration context appended to the generated global AGENTS.md. */
142
+ additionalAgentInstructions?: string;
143
+ opencode?: {
144
+ config?: Record<string, unknown>;
145
+ plugins?: string[];
146
+ skills?: Array<{
147
+ name: string;
148
+ content: string;
149
+ }>;
150
+ };
151
+ };
152
+ export type DirectWorkspaceRuntime = {
153
+ url: string;
154
+ directory: string;
155
+ headers?: Record<string, string>;
156
+ password?: string;
157
+ };
158
+ export type DirectWorkspace = {
159
+ id: string;
160
+ provider: string;
161
+ externalId: string;
162
+ status: DirectWorkspaceStatus;
163
+ lifecycle: DirectWorkspaceLifecycle;
164
+ runtime: DirectWorkspaceRuntime;
165
+ setup: "not_requested" | "before_agent_complete" | "after_agent";
166
+ createdAt: string;
167
+ };
168
+ export type DirectWorkspaceSetupStatus = {
169
+ status: "not_requested" | "waiting" | "running" | "succeeded" | "failed";
170
+ exitCode: number | null;
171
+ startedAt: string | null;
172
+ finishedAt: string | null;
173
+ log: string | null;
174
+ };
175
+ export type DirectWorkspaceSetupWaitOptions = {
176
+ timeoutMs?: number;
177
+ pollIntervalMs?: number;
178
+ };
179
+ export type DirectProviderWorkspaceInput = DirectWorkspaceCreateInput & {
180
+ id: string;
181
+ lifecycle: DirectWorkspaceLifecycle;
182
+ password: string;
183
+ provisioning: DirectProvisioningPlan;
184
+ };
185
+ export type DirectAgentFile = {
186
+ path: string;
187
+ contentBase64: string;
188
+ mode?: number;
189
+ };
190
+ export type DirectProvisioningPlan = {
191
+ workspaceId: string;
192
+ lifecycle: DirectWorkspaceLifecycle;
193
+ repository?: {
194
+ url: string;
195
+ name: string;
196
+ branch?: string;
197
+ checkoutRef?: string;
198
+ baseCommit?: string;
199
+ authUsername?: string;
200
+ authToken?: string;
201
+ };
202
+ agent: {
203
+ files: DirectAgentFile[];
204
+ environmentVariables: Record<string, string>;
205
+ command: string;
206
+ port: number;
207
+ };
208
+ setup: {
209
+ beforeAgent: string[];
210
+ afterAgent: string[];
211
+ };
212
+ };
213
+ export interface DirectProviderAdapter {
214
+ readonly name: string;
215
+ readonly capabilities: DirectProviderCapabilities;
216
+ create(input: DirectProviderWorkspaceInput): Promise<{
217
+ externalId: string;
218
+ runtime: DirectWorkspaceRuntime;
219
+ }>;
220
+ status(workspace: DirectWorkspace): Promise<DirectWorkspaceStatus>;
221
+ pause?(workspace: DirectWorkspace): Promise<void>;
222
+ resume?(workspace: DirectWorkspace): Promise<Partial<DirectWorkspaceRuntime> | void>;
223
+ terminate(workspace: DirectWorkspace): Promise<void>;
224
+ keepAlive?(workspace: DirectWorkspace, timeoutMs: number): Promise<void>;
225
+ }
226
+ export type E2BDirectProviderConfig = {
227
+ type: "e2b";
228
+ apiKey: string;
229
+ /** Optional. Defaults to standard. */
230
+ size?: "standard" | "large";
231
+ /** Optional. Overrides size with a specific E2B template. */
232
+ templateId?: string;
233
+ timeoutMs?: number;
234
+ };
235
+ export type DaytonaDirectProviderConfig = {
236
+ type: "daytona";
237
+ apiKey: string;
238
+ target: "us" | "eu";
239
+ /** Optional. Defaults to the public Gitterm OpenCode server image. Floating tags are pinned to a digest. */
240
+ image?: string;
241
+ cpu?: number;
242
+ memory?: number;
243
+ disk?: number;
244
+ };
245
+ export type VercelDirectProviderConfig = {
246
+ type: "vercel";
247
+ apiToken: string;
248
+ teamId: string;
249
+ projectId: string;
250
+ /** Optional VCR image. When omitted, the configured Node runtime is used. */
251
+ image?: string;
252
+ runtime?: "node26" | "node24" | "node22" | "python3.13";
253
+ runtimeSetupCommands?: string[];
254
+ vcpus?: number;
255
+ timeoutMs?: number;
256
+ };
257
+ export type AsciiDirectProviderConfig = {
258
+ type: "ascii";
259
+ apiKey: string;
260
+ size?: "small" | "default" | "large";
261
+ runtimeSetupCommands?: string[];
262
+ timeoutMs?: number | null;
263
+ };
264
+ export type ExeDevDirectProviderConfig = {
265
+ type: "exedev";
266
+ /**
267
+ * Token `cmds` must include `new`, `ls`, `ssh`, `share`, `ssh-key`, `pause`, `resume`, and `rm`.
268
+ * Default tokens cannot provision or clean up a Gitterm workspace.
269
+ */
270
+ apiToken: string;
271
+ /** Optional. Defaults to the public Gitterm OpenCode server image. */
272
+ image?: string;
273
+ cpu?: number;
274
+ memory?: string;
275
+ disk?: string;
276
+ runtimeSetupCommands?: string[];
277
+ };
278
+ export type RailwayDirectProviderConfig = {
279
+ type: "railway";
280
+ apiToken: string;
281
+ apiUrl?: string;
282
+ projectId: string;
283
+ environmentId: string;
284
+ region?: string;
285
+ /** Optional. Defaults to the public Gitterm OpenCode server image. */
286
+ image?: string;
287
+ runtimePort?: number;
288
+ };
289
+ export type DirectProviderConfig = E2BDirectProviderConfig | DaytonaDirectProviderConfig | VercelDirectProviderConfig | AsciiDirectProviderConfig | ExeDevDirectProviderConfig | RailwayDirectProviderConfig;
290
+ export type DirectRunCreateInput = {
291
+ workspace: DirectWorkspace;
292
+ prompt: string;
293
+ title?: string;
294
+ agent?: string;
295
+ model?: string;
296
+ /** Reuse this native OpenCode session for conversational context. */
297
+ sessionId?: string;
298
+ };
299
+ export type DirectRun = {
300
+ id: string;
301
+ workspaceId: string;
302
+ sessionId: string;
303
+ messageId: string;
304
+ title: string;
305
+ status: "running" | "retrying" | "completed" | "failed" | "cancelled";
306
+ error: string | null;
307
+ finalText: string | null;
308
+ submittedAt: string;
309
+ };
310
+ export type DirectRunMessage = {
311
+ id: string;
312
+ role: "user" | "assistant";
313
+ text: string;
314
+ error: string | null;
315
+ };
316
+ export type DirectRunWaitOptions = {
317
+ timeoutMs?: number;
318
+ pollIntervalMs?: number;
319
+ };
@@ -0,0 +1,2 @@
1
+ import type { DirectProviderAdapter, VercelDirectProviderConfig } from "./types.js";
2
+ export declare function createVercelDirectProvider(config: VercelDirectProviderConfig): DirectProviderAdapter;
package/dist/index.js CHANGED
@@ -236,7 +236,7 @@ async function runWithServer(serverUrl, operation) {
236
236
  cause: error
237
237
  });
238
238
  }
239
- throw new GittermError(code, code === "UNAUTHORIZED" ? "Not logged in or token expired. Run: gitterm login" : error.message, { cause: error });
239
+ throw new GittermError(code, code === "UNAUTHORIZED" ? `Authentication failed: ${error.message}. Check that the API token is valid and has not expired.` : error.message, { cause: error });
240
240
  }
241
241
  throw new GittermError("NETWORK", error instanceof Error ? error.message : "Network request failed", { cause: error });
242
242
  }
@@ -525,16 +525,16 @@ function createGittermWorkspaceClient(options = {}) {
525
525
  };
526
526
  }
527
527
  export {
528
- saveConfig,
529
- loginWithDeviceCode,
530
- loadConfigSync,
531
- loadConfig,
532
- getWorkspaceEnvironment,
533
- getConfigPath,
534
- deleteConfig,
535
- createGittermWorkspaceClient,
536
- createGittermClient,
537
- WorkspaceLifecycleError,
528
+ DEFAULT_GITTERM_SERVER_URL,
538
529
  GittermError,
539
- DEFAULT_GITTERM_SERVER_URL
530
+ WorkspaceLifecycleError,
531
+ createGittermClient,
532
+ createGittermWorkspaceClient,
533
+ deleteConfig,
534
+ getConfigPath,
535
+ getWorkspaceEnvironment,
536
+ loadConfig,
537
+ loadConfigSync,
538
+ loginWithDeviceCode,
539
+ saveConfig
540
540
  };
package/dist/types.d.ts CHANGED
@@ -180,12 +180,25 @@ export type WorkspaceCreateInput = {
180
180
  * inline; connect those in the dashboard.
181
181
  */
182
182
  modelCredentials?: WorkspaceModelCredentialInput[];
183
+ /** Ephemeral environment variables injected into this workspace only. */
184
+ environmentVariables?: Record<string, string>;
183
185
  /**
184
- * Ordered commands launched in the repository after the agent server starts.
185
- * They do not block workspace readiness; inspect ~/.gitterm/setup for status
186
- * and logs through workspaces.setupStatus()/waitForSetup().
186
+ * Setup phases run in order. `beforeAgent` blocks agent startup and fails
187
+ * create() when it exits non-zero; `afterAgent` starts after the agent is
188
+ * reachable and is observable with setupStatus()/waitForSetup().
187
189
  */
188
- setupCommands?: string[];
190
+ setup?: {
191
+ beforeAgent?: string[];
192
+ afterAgent?: string[];
193
+ };
194
+ /** Secret files written relative to the repository and excluded from git. Rotate by recreating the workspace. */
195
+ secretFiles?: Array<{
196
+ path: string;
197
+ content: string;
198
+ mode?: "0400" | "0600";
199
+ }>;
200
+ /** Trusted integration context appended to the workspace's global AGENTS.md. */
201
+ additionalAgentInstructions?: string;
189
202
  /** OpenCode capabilities materialized only in this workspace. */
190
203
  opencode?: {
191
204
  skills?: Array<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitterm/sdk",
3
- "version": "0.0.8",
3
+ "version": "0.1.1",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -11,18 +11,29 @@
11
11
  "bun": "./dist/index.js",
12
12
  "import": "./dist/index.js",
13
13
  "default": "./dist/index.js"
14
+ },
15
+ "./direct": {
16
+ "types": "./dist/direct/index.d.ts",
17
+ "bun": "./dist/direct/index.js",
18
+ "import": "./dist/direct/index.js",
19
+ "default": "./dist/direct/index.js"
14
20
  }
15
21
  },
16
22
  "publishConfig": {
17
23
  "access": "public"
18
24
  },
19
25
  "scripts": {
20
- "build": "rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --external @trpc/client && tsc -p tsconfig.build.json",
26
+ "build": "rm -rf dist && bun build src/index.ts src/direct/index.ts --outdir dist --target node --format esm --external @trpc/client --external @opencode-ai/sdk --external @opencode-ai/sdk/v2 --external e2b --external @asciidev/box-sdk --external @daytonaio/sdk --external @vercel/sandbox && tsc -p tsconfig.build.json",
21
27
  "prepublishOnly": "bun run check-types && bun run build",
22
28
  "check-types": "tsc --noEmit"
23
29
  },
24
30
  "dependencies": {
25
- "@trpc/client": "^11.8.1"
31
+ "@asciidev/box-sdk": "^0.0.34",
32
+ "@daytonaio/sdk": "^0.207.0",
33
+ "@opencode-ai/sdk": "^1.18.25",
34
+ "@trpc/client": "^11.8.1",
35
+ "@vercel/sandbox": "^3.2.1",
36
+ "e2b": "^2.46.1"
26
37
  },
27
38
  "devDependencies": {
28
39
  "@gitterm/api": "workspace:*",
@@ -31,6 +42,6 @@
31
42
  "typescript": "^5.8.2"
32
43
  },
33
44
  "engines": {
34
- "node": ">=18"
45
+ "node": ">=20.18.1"
35
46
  }
36
47
  }