@gitterm/sdk 0.8.0 → 0.10.0
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 +28 -17
- package/dist/client.d.ts +25 -1
- package/dist/direct/index.js +4 -4
- package/dist/errors.d.ts +4 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +48 -19
- package/dist/types.d.ts +93 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,8 +12,8 @@ bun add @gitterm/sdk
|
|
|
12
12
|
npm install @gitterm/sdk
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Requires Node 22.12+ or Bun. Create an API token in the dashboard
|
|
16
|
-
|
|
15
|
+
Requires Node 22.12+ or Bun. Create an API token under **API tokens** in the dashboard, or with
|
|
16
|
+
`gitterm login`.
|
|
17
17
|
|
|
18
18
|
## Quick start
|
|
19
19
|
|
|
@@ -23,12 +23,10 @@ Create a workspace, run a prompt, and get the final result:
|
|
|
23
23
|
import { createGittermClient } from "@gitterm/sdk";
|
|
24
24
|
|
|
25
25
|
const client = createGittermClient({ token: process.env.GITTERM_API_TOKEN });
|
|
26
|
-
const [github] = await client.integrations.connections.list({ integration: "github" });
|
|
27
|
-
if (!github) throw new Error("Connect GitHub in the Gitterm dashboard first");
|
|
28
26
|
|
|
29
27
|
const { workspace } = await client.workspaces.create({
|
|
30
28
|
repo: "https://github.com/acme/product",
|
|
31
|
-
connections: [github
|
|
29
|
+
connections: ["github"], // the GitHub connection that covers acme
|
|
32
30
|
autoTerminateAfterMs: 2 * 60 * 60 * 1000,
|
|
33
31
|
});
|
|
34
32
|
|
|
@@ -48,19 +46,24 @@ try {
|
|
|
48
46
|
```
|
|
49
47
|
|
|
50
48
|
Every integration you can attach, personal or admin-provided, is a **connection** with one shape.
|
|
51
|
-
|
|
49
|
+
Reference each one the way you remember it:
|
|
52
50
|
|
|
53
51
|
```ts
|
|
54
|
-
const connections = await client.integrations.connections.list();
|
|
55
|
-
const github = connections.find((c) => c.integration === "github");
|
|
56
|
-
const google = connections.find((c) => c.integration === "google");
|
|
57
|
-
|
|
58
52
|
await client.workspaces.create({
|
|
59
53
|
repo: "https://github.com/acme/product",
|
|
60
|
-
connections: [
|
|
54
|
+
connections: [
|
|
55
|
+
"github", // integration key: the GitHub connection that covers acme, or the shared one
|
|
56
|
+
"Linear", // a connection name, as shown under Integrations (case-insensitive)
|
|
57
|
+
"3f7d0c2e-…", // or an id from connections.list()
|
|
58
|
+
],
|
|
61
59
|
});
|
|
62
60
|
```
|
|
63
61
|
|
|
62
|
+
An integration key works when it is unambiguous: `github` picks by the repository's owner;
|
|
63
|
+
`google`, `mcp`, and `executor` need exactly one connection of that kind. Names are not unique, so
|
|
64
|
+
a name shared by two connections is rejected with both ids; use the id or rename one. At most one
|
|
65
|
+
GitHub and one Google connection can be attached; MCP and Executor connections are unlimited.
|
|
66
|
+
|
|
64
67
|
GitHub tokens and Google workload credentials are issued inside the workspace; the SDK caller does
|
|
65
68
|
not receive or forward them.
|
|
66
69
|
|
|
@@ -168,6 +171,7 @@ client.credentials.listProviders();
|
|
|
168
171
|
client.integrations.catalog(); // integrations the admin enabled: key, category, personal/shared
|
|
169
172
|
client.integrations.connections.list(filter?); // what you can attach; personal + shared, one shape
|
|
170
173
|
client.integrations.connections.get(id);
|
|
174
|
+
client.integrations.connections.resolve(references, { repo }); // what ids/keys/names attach
|
|
171
175
|
client.integrations.connections.create(input); // integrations:write; may return a browser step
|
|
172
176
|
client.integrations.connections.remove(id);
|
|
173
177
|
client.integrations.connections.waitFor({ integration, since }); // after a `pending` create
|
|
@@ -300,6 +304,11 @@ running `gh auth login`:
|
|
|
300
304
|
- Without repository credentials or an integration, GitTerm leaves CLI authentication
|
|
301
305
|
to the environment or the CLI's existing configuration.
|
|
302
306
|
|
|
307
|
+
Commit attribution is separate from these push credentials. By default the workspace owner
|
|
308
|
+
is the author (their GitHub noreply address when GitHub is linked) and GitTerm is the
|
|
309
|
+
committer: the GitHub App's bot account when the deployment uses an app. **Settings →
|
|
310
|
+
Account → Commit attribution** makes the owner both instead, for new workspaces.
|
|
311
|
+
|
|
303
312
|
GitTerm supplies `GH_TOKEN` only to the invoked CLI process, so there is no stale
|
|
304
313
|
installation token exported into the agent's long-running environment. Explicit
|
|
305
314
|
`GH_TOKEN` or `GITHUB_TOKEN` environment variables override this CLI authentication;
|
|
@@ -482,8 +491,10 @@ await client.workspaces.create({
|
|
|
482
491
|
|
|
483
492
|
`provider` is a discriminated union, so TypeScript only offers `region` for providers
|
|
484
493
|
where GitTerm supports caller-selected placement. Machine keys are configured by admins
|
|
485
|
-
and returned by `client.catalog.workspaceOptions()
|
|
486
|
-
provider account configuration are never supplied by SDK
|
|
494
|
+
and returned by `client.catalog.workspaceOptions()` with their `vcpus` and `memoryGb`;
|
|
495
|
+
raw CPU, memory, credentials, and provider account configuration are never supplied by SDK
|
|
496
|
+
callers. The catalog lists only the sizes you may use: an admin can pin a provider to its
|
|
497
|
+
default size, and on managed GitTerm the Free plan gets each provider's smallest size.
|
|
487
498
|
|
|
488
499
|
This makes release automation a normal workspace task: create an OpenCode workspace,
|
|
489
500
|
run UI review or browser capture tools in the sandbox, upload the resulting media, update
|
|
@@ -502,7 +513,7 @@ A workspace has one of four statuses:
|
|
|
502
513
|
| `terminated` | Gone for good. |
|
|
503
514
|
|
|
504
515
|
Whether `create()` returns `running` or `pending` depends on the provider. Sandbox providers
|
|
505
|
-
(E2B, Daytona, Vercel,
|
|
516
|
+
(E2B, Daytona, Vercel, boat, exe.dev, Cloudflare) settle immediately and return `running`.
|
|
506
517
|
Railway settles by webhook and returns `pending` until its deployment reports success, usually
|
|
507
518
|
within a minute. Code that only ever ran against a sandbox provider will see `pending` for the
|
|
508
519
|
first time when it moves to Railway.
|
|
@@ -726,7 +737,7 @@ const { workspace } = await client.workspaces.create({
|
|
|
726
737
|
|
|
727
738
|
const run = await client.runs.create({
|
|
728
739
|
workspace,
|
|
729
|
-
model: "anthropic/claude-sonnet-
|
|
740
|
+
model: "anthropic/claude-sonnet-5-5",
|
|
730
741
|
prompt: "Record before/after videos of the changes in PR #42",
|
|
731
742
|
});
|
|
732
743
|
```
|
|
@@ -840,7 +851,7 @@ await saveConfig({
|
|
|
840
851
|
```
|
|
841
852
|
|
|
842
853
|
Device-code logins produce the same revocable `gt_...` API token as the dashboard;
|
|
843
|
-
they appear
|
|
854
|
+
they appear under **API tokens** in the dashboard and can be revoked there.
|
|
844
855
|
|
|
845
856
|
## Direct provider mode
|
|
846
857
|
|
|
@@ -853,7 +864,7 @@ All built-in compute providers use the same provisioning plan and workspace/run
|
|
|
853
864
|
| E2B | OpenCode-compatible template | Yes | Yes |
|
|
854
865
|
| Daytona | Public Gitterm OpenCode server image by default | Yes | Yes |
|
|
855
866
|
| Vercel | Vercel Sandbox project | Yes | Yes |
|
|
856
|
-
|
|
|
867
|
+
| boat | boat API key (provider type `ascii`) | Yes | Yes |
|
|
857
868
|
| exe.dev | Lifecycle token, or an existing VM with `ls,ssh,share,ssh-key` | Yes | No |
|
|
858
869
|
| Railway | Project/environment and public service domains | With a volume | No |
|
|
859
870
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentType, AgentRun, AgentRunCreateInput, AgentRunListOptions, AgentRunListResult, AgentRunMessage, AgentRunReply, AuthStatus, CloudProvider, RunRef, RunWaitOptions, RunWatchOptions, WaitOptions, Workspace, WorkspaceCreateInput, WorkspaceCreateResult, WorkspaceEnsureRunningResult, WorkspaceListOptions, WorkspaceListResult, WorkspaceRef, WorkspaceRestartResult, WorkspaceRuntimeAccess, WorkspacePauseResult, WorkspaceTerminateResult, WorkspaceCatalog, WorkspaceSetupStatus, ModelCredential, ModelProviderInfo, Integration, IntegrationKey, Connection, ConnectionKind, CreateConnectionInput, CreateConnectionResult, GitHubRepository, GitHubBranch, GoogleSetup } from "./types.js";
|
|
1
|
+
import type { AgentType, AgentRun, AgentRunCreateInput, AgentRunListOptions, AgentRunListResult, AgentRunMessage, AgentRunReply, AuthStatus, CloudProvider, RunRef, RunWaitOptions, RunWatchOptions, WaitOptions, Workspace, WorkspaceCreateInput, WorkspaceCreateResult, WorkspaceEnsureRunningResult, WorkspaceListOptions, WorkspaceListResult, WorkspaceRef, WorkspaceRestartResult, WorkspaceRuntimeAccess, WorkspacePauseResult, WorkspaceTerminateResult, WorkspaceCatalog, WorkspaceSetupStatus, ModelCredential, ModelProviderInfo, Integration, IntegrationKey, Connection, SavedBot, ConnectionKind, CreateConnectionInput, CreateConnectionResult, GitHubRepository, GitHubBranch, GoogleSetup, McpConnectionTestResult, UpdateMcpConnectionInput } from "./types.js";
|
|
2
2
|
import type { AgentRunEvent, AgentRunResult, RunResultOptions, WorkspaceModelAccess } from "./types.js";
|
|
3
3
|
export type GittermClientOptions = {
|
|
4
4
|
serverUrl?: string;
|
|
@@ -69,6 +69,17 @@ export type GittermClient = {
|
|
|
69
69
|
list(): Promise<ModelCredential[]>;
|
|
70
70
|
listProviders(): Promise<ModelProviderInfo[]>;
|
|
71
71
|
};
|
|
72
|
+
bots: {
|
|
73
|
+
/** Claims (or renews) the right to run this saved bot; one process at a time. */
|
|
74
|
+
acquireLease(leaseId: string): Promise<{
|
|
75
|
+
success: true;
|
|
76
|
+
}>;
|
|
77
|
+
releaseLease(leaseId: string): Promise<{
|
|
78
|
+
success: true;
|
|
79
|
+
}>;
|
|
80
|
+
/** The settings saved for this client's token in the dashboard; null if it isn't a bot's. */
|
|
81
|
+
self(): Promise<SavedBot | null>;
|
|
82
|
+
};
|
|
72
83
|
integrations: {
|
|
73
84
|
/** Integrations the admin has enabled for this deployment. */
|
|
74
85
|
catalog(): Promise<Integration[]>;
|
|
@@ -79,6 +90,14 @@ export type GittermClient = {
|
|
|
79
90
|
kind?: ConnectionKind;
|
|
80
91
|
}): Promise<Connection[]>;
|
|
81
92
|
get(id: string): Promise<Connection>;
|
|
93
|
+
/**
|
|
94
|
+
* The connections `workspaces.create({ connections })` would attach for these references
|
|
95
|
+
* (ids, integration keys, or names), without creating anything. Rejects with the same
|
|
96
|
+
* message creation would, e.g. for an ambiguous name. Pass `repo` to resolve `"github"`.
|
|
97
|
+
*/
|
|
98
|
+
resolve(references: string[], options?: {
|
|
99
|
+
repo?: string;
|
|
100
|
+
}): Promise<Connection[]>;
|
|
82
101
|
/** Requires the `integrations:write` scope. */
|
|
83
102
|
create(input: CreateConnectionInput): Promise<CreateConnectionResult>;
|
|
84
103
|
/** Removes a personal connection. Shared connections are managed by the admin. */
|
|
@@ -92,6 +111,7 @@ export type GittermClient = {
|
|
|
92
111
|
since?: Date | string;
|
|
93
112
|
timeoutMs?: number;
|
|
94
113
|
intervalMs?: number;
|
|
114
|
+
connectionId?: string;
|
|
95
115
|
}): Promise<Connection>;
|
|
96
116
|
};
|
|
97
117
|
github: {
|
|
@@ -103,6 +123,10 @@ export type GittermClient = {
|
|
|
103
123
|
/** Issuer and attribute mapping to configure the Google provider before connecting. */
|
|
104
124
|
setup(): Promise<GoogleSetup>;
|
|
105
125
|
};
|
|
126
|
+
mcp: {
|
|
127
|
+
test(id: string): Promise<McpConnectionTestResult>;
|
|
128
|
+
update(input: UpdateMcpConnectionInput): Promise<Connection>;
|
|
129
|
+
};
|
|
106
130
|
};
|
|
107
131
|
};
|
|
108
132
|
export declare function createGittermClient(options?: GittermClientOptions): GittermClient;
|
package/dist/direct/index.js
CHANGED
|
@@ -2177,12 +2177,12 @@ var WORKSPACE_LIFECYCLE_ERROR_CODES = [
|
|
|
2177
2177
|
|
|
2178
2178
|
class GittermError extends Error {
|
|
2179
2179
|
code;
|
|
2180
|
-
|
|
2180
|
+
status;
|
|
2181
2181
|
constructor(code, message, options = {}) {
|
|
2182
|
-
super(message);
|
|
2182
|
+
super(message, "cause" in options ? { cause: options.cause } : undefined);
|
|
2183
2183
|
this.name = "GittermError";
|
|
2184
2184
|
this.code = code;
|
|
2185
|
-
this.
|
|
2185
|
+
this.status = options.status;
|
|
2186
2186
|
}
|
|
2187
2187
|
}
|
|
2188
2188
|
|
|
@@ -3341,7 +3341,7 @@ function createAsciiDirectProvider(config) {
|
|
|
3341
3341
|
async function deleteBox(boxId) {
|
|
3342
3342
|
const response = await fetch(`https://ascii.dev/api/box/v1/boxes/${boxId}`, {
|
|
3343
3343
|
method: "DELETE",
|
|
3344
|
-
headers: { Authorization: `Bearer ${config.apiKey}
|
|
3344
|
+
headers: { Authorization: `Bearer ${config.apiKey}`, "X-Ascii-Confirm-Delete": boxId }
|
|
3345
3345
|
});
|
|
3346
3346
|
if (!response.ok && response.status !== 404) {
|
|
3347
3347
|
throw new Error(`Ascii Box deletion failed (${response.status})`);
|
package/dist/errors.d.ts
CHANGED
|
@@ -5,15 +5,18 @@ export type WorkspaceLifecycleErrorCode = "WORKSPACE_NOT_RUNNING" | "WORKSPACE_T
|
|
|
5
5
|
export declare const WORKSPACE_LIFECYCLE_ERROR_CODES: readonly WorkspaceLifecycleErrorCode[];
|
|
6
6
|
export declare class GittermError extends Error {
|
|
7
7
|
readonly code: GittermErrorCode;
|
|
8
|
-
|
|
8
|
+
/** HTTP status of the API response; undefined when the server never answered. */
|
|
9
|
+
readonly status: number | undefined;
|
|
9
10
|
constructor(code: GittermErrorCode, message: string, options?: {
|
|
10
11
|
cause?: unknown;
|
|
12
|
+
status?: number;
|
|
11
13
|
});
|
|
12
14
|
}
|
|
13
15
|
export declare class WorkspaceLifecycleError extends GittermError {
|
|
14
16
|
readonly code: WorkspaceLifecycleErrorCode;
|
|
15
17
|
constructor(code: WorkspaceLifecycleErrorCode, message: string, options?: {
|
|
16
18
|
cause?: unknown;
|
|
19
|
+
status?: number;
|
|
17
20
|
});
|
|
18
21
|
}
|
|
19
22
|
/** result() could not produce a successful result. The run remains inspectable. */
|
package/dist/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export type { DeviceCodeInfo, LoginWithDeviceCodeOptions } from "./device-login.
|
|
|
6
6
|
export { AgentRunError, GittermError, WorkspaceLifecycleError } from "./errors.js";
|
|
7
7
|
export { createGittermWorkspaceClient, getWorkspaceEnvironment, type GittermWorkspaceClient, type WorkspaceClientOptions, type WorkspaceEnvironment, type WorkspacePort, type WorkspacePortVisibility, type WorkspaceSelf, } from "./workspace-client.js";
|
|
8
8
|
export type { CredentialErrorCode, GittermErrorCode, WorkspaceLifecycleErrorCode, } from "./errors.js";
|
|
9
|
-
export type { AgentPermissionRequest, AgentQuestion, AgentQuestionOption, AgentQuestionRequest, AgentRun, AgentRunAttachment, AgentRunCreateInput, AgentRunInputRequest, AgentRunMessage, AgentRunMessagePart, AgentRunReply, AgentRunStatus, AgentRunEvent, AgentRunResult, AgentRunReplyPermission, AgentRunReplyQuestion, RunResultOptions, RunRef, RunWaitOptions, RunWatchOptions, AgentType, AgentKey, AuthStatus, BuiltInAgentKey, CloudProvider, ProviderKey, Workspace, WorkspaceCreateInput, WorkspaceCreateResult, WorkspaceCatalog, WorkspaceEnsureRunningResult, WorkspaceHostingType, WorkspaceListOptions, WorkspaceListResult, WorkspaceRestartResult, WorkspaceRuntimeAccess, WorkspaceStatus, WorkspaceSetupStatus, ModelCredential, ModelProviderInfo, ModelCredentialSource, WorkspaceModelsInput, WorkspaceModelAccess, WorkspacePauseResult, WorkspaceTerminateResult, WorkspaceProviderSelection, Integration, IntegrationKey, IntegrationCategory, Connection, ConnectionKind, ConnectionStatus, ConnectionDetails, GitHubConnectionDetails, GoogleConnectionDetails, CreateConnectionInput, CreateConnectionResult, GitHubRepository, GitHubBranch, GoogleSetup, } from "./types.js";
|
|
9
|
+
export type { AgentPermissionRequest, AgentQuestion, AgentQuestionOption, AgentQuestionRequest, AgentRun, AgentRunAttachment, AgentRunCreateInput, AgentRunInputRequest, AgentRunMessage, AgentRunMessagePart, AgentRunReply, AgentRunStatus, AgentRunEvent, AgentRunResult, AgentRunReplyPermission, AgentRunReplyQuestion, RunResultOptions, RunRef, RunWaitOptions, RunWatchOptions, AgentType, AgentKey, AuthStatus, BuiltInAgentKey, CloudProvider, ProviderKey, Workspace, WorkspaceCreateInput, WorkspaceCreateResult, WorkspaceCatalog, WorkspaceEnsureRunningResult, WorkspaceHostingType, WorkspaceListOptions, WorkspaceListResult, WorkspaceRestartResult, WorkspaceRuntimeAccess, WorkspaceStatus, WorkspaceSetupStatus, ModelCredential, ModelProviderInfo, ModelCredentialSource, WorkspaceModelsInput, WorkspaceModelAccess, WorkspacePauseResult, WorkspaceTerminateResult, WorkspaceProviderSelection, Integration, IntegrationKey, IntegrationCategory, Connection, SavedBot, ConnectionKind, ConnectionStatus, ConnectionDetails, GitHubConnectionDetails, GoogleConnectionDetails, McpConnectionDetails, McpAuthentication, CreateMcpConnectionInput, UpdateMcpConnectionInput, McpConnectionTestResult, CreateConnectionInput, CreateConnectionResult, GitHubRepository, GitHubBranch, GoogleSetup, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -68,12 +68,12 @@ var WORKSPACE_LIFECYCLE_ERROR_CODES = [
|
|
|
68
68
|
|
|
69
69
|
class GittermError extends Error {
|
|
70
70
|
code;
|
|
71
|
-
|
|
71
|
+
status;
|
|
72
72
|
constructor(code, message, options = {}) {
|
|
73
|
-
super(message);
|
|
73
|
+
super(message, "cause" in options ? { cause: options.cause } : undefined);
|
|
74
74
|
this.name = "GittermError";
|
|
75
75
|
this.code = code;
|
|
76
|
-
this.
|
|
76
|
+
this.status = options.status;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -288,7 +288,12 @@ function runHelpers(operations) {
|
|
|
288
288
|
|
|
289
289
|
// src/client.ts
|
|
290
290
|
function toConnection(connection) {
|
|
291
|
-
|
|
291
|
+
const details = connection.details;
|
|
292
|
+
return {
|
|
293
|
+
...connection,
|
|
294
|
+
connectedAt: toIso(connection.connectedAt),
|
|
295
|
+
details: "lastCheckedAt" in details ? { ...details, lastCheckedAt: toIso(details.lastCheckedAt) } : details
|
|
296
|
+
};
|
|
292
297
|
}
|
|
293
298
|
function envValue(name) {
|
|
294
299
|
const value = typeof process !== "undefined" ? process.env[name] : undefined;
|
|
@@ -421,27 +426,26 @@ function toGittermError(serverUrl, error) {
|
|
|
421
426
|
return error;
|
|
422
427
|
if (error instanceof TRPCClientError) {
|
|
423
428
|
const data = error.data;
|
|
424
|
-
|
|
425
|
-
if (!error.data) {
|
|
429
|
+
if (!data) {
|
|
426
430
|
return new GittermError("NETWORK", `Could not reach the GitTerm server at ${serverUrl}`, {
|
|
427
|
-
cause: error
|
|
431
|
+
cause: error.cause ?? error
|
|
428
432
|
});
|
|
429
433
|
}
|
|
430
|
-
const
|
|
431
|
-
const structuredLifecycleCode = WORKSPACE_LIFECYCLE_ERROR_CODES.find((candidate) => candidate === data
|
|
434
|
+
const status = { status: data.httpStatus };
|
|
435
|
+
const structuredLifecycleCode = WORKSPACE_LIFECYCLE_ERROR_CODES.find((candidate) => candidate === data.workspaceLifecycleCode);
|
|
432
436
|
if (structuredLifecycleCode) {
|
|
433
|
-
return new WorkspaceLifecycleError(structuredLifecycleCode, error.message,
|
|
437
|
+
return new WorkspaceLifecycleError(structuredLifecycleCode, error.message, status);
|
|
434
438
|
}
|
|
435
439
|
if (error.message.startsWith("INPUT_NOT_PENDING:"))
|
|
436
|
-
return new GittermError("INPUT_NOT_PENDING", error.message,
|
|
440
|
+
return new GittermError("INPUT_NOT_PENDING", error.message, status);
|
|
437
441
|
const credentialCode = credentialErrorCode(error.message);
|
|
438
442
|
if (credentialCode)
|
|
439
|
-
return new GittermError(credentialCode, error.message,
|
|
443
|
+
return new GittermError(credentialCode, error.message, status);
|
|
440
444
|
const lifecycleCode = WORKSPACE_LIFECYCLE_ERROR_CODES.find((candidate) => error.message.startsWith(`${candidate}:`));
|
|
441
|
-
if (lifecycleCode)
|
|
442
|
-
return new WorkspaceLifecycleError(lifecycleCode, error.message,
|
|
443
|
-
|
|
444
|
-
return new GittermError(code, code === "UNAUTHORIZED" ?
|
|
445
|
+
if (lifecycleCode)
|
|
446
|
+
return new WorkspaceLifecycleError(lifecycleCode, error.message, status);
|
|
447
|
+
const code = mapTrpcCode(data.code);
|
|
448
|
+
return new GittermError(code, code === "UNAUTHORIZED" ? `${error.message}. Check your GitTerm API token, or create a new one in the dashboard.` : error.message, status);
|
|
445
449
|
}
|
|
446
450
|
return new GittermError("NETWORK", error instanceof Error ? error.message : "Network request failed", { cause: error });
|
|
447
451
|
}
|
|
@@ -698,14 +702,27 @@ ${log}` : ""}`);
|
|
|
698
702
|
return result.map(toConnection);
|
|
699
703
|
}),
|
|
700
704
|
get: (id) => run(async () => toConnection(await trpc.integrations.connections.get.query({ id }))),
|
|
705
|
+
resolve: (references, options) => run(async () => {
|
|
706
|
+
const result = await trpc.integrations.connections.resolve.query({
|
|
707
|
+
references,
|
|
708
|
+
...options?.repo ? { repo: options.repo } : {}
|
|
709
|
+
});
|
|
710
|
+
return result.map(toConnection);
|
|
711
|
+
}),
|
|
701
712
|
create: (input) => run(async () => {
|
|
702
713
|
const result = await trpc.integrations.connections.create.mutate(input);
|
|
703
|
-
return result.status
|
|
714
|
+
return result.status !== "pending" ? { ...result, connection: toConnection(result.connection) } : result;
|
|
704
715
|
}),
|
|
705
716
|
remove: (id) => run(async () => {
|
|
706
717
|
await trpc.integrations.connections.remove.mutate({ id });
|
|
707
718
|
}),
|
|
708
|
-
waitFor: ({
|
|
719
|
+
waitFor: ({
|
|
720
|
+
integration,
|
|
721
|
+
since,
|
|
722
|
+
connectionId,
|
|
723
|
+
timeoutMs = 5 * 60000,
|
|
724
|
+
intervalMs = 3000
|
|
725
|
+
}) => run(async () => {
|
|
709
726
|
const sinceMs = since ? new Date(since).getTime() : 0;
|
|
710
727
|
const deadline = Date.now() + timeoutMs;
|
|
711
728
|
while (Date.now() < deadline) {
|
|
@@ -713,7 +730,7 @@ ${log}` : ""}`);
|
|
|
713
730
|
integration,
|
|
714
731
|
kind: "personal"
|
|
715
732
|
});
|
|
716
|
-
const match = result.map(toConnection).filter((c) => c.status === "connected" && new Date(c.connectedAt).getTime() >= sinceMs).sort((a, b) => b.connectedAt.localeCompare(a.connectedAt))[0];
|
|
733
|
+
const match = result.map(toConnection).filter((c) => c.status === "connected" && (connectionId ? c.id === connectionId : new Date(c.connectedAt).getTime() >= sinceMs)).sort((a, b) => b.connectedAt.localeCompare(a.connectedAt))[0];
|
|
717
734
|
if (match)
|
|
718
735
|
return match;
|
|
719
736
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
@@ -727,8 +744,20 @@ ${log}` : ""}`);
|
|
|
727
744
|
},
|
|
728
745
|
google: {
|
|
729
746
|
setup: () => run(async () => trpc.integrations.google.setup.query())
|
|
747
|
+
},
|
|
748
|
+
mcp: {
|
|
749
|
+
test: (id) => run(async () => {
|
|
750
|
+
const result = await trpc.integrations.mcp.test.mutate({ id });
|
|
751
|
+
return { ...result, connection: toConnection(result.connection) };
|
|
752
|
+
}),
|
|
753
|
+
update: (input) => run(async () => toConnection(await trpc.integrations.mcp.update.mutate(input)))
|
|
730
754
|
}
|
|
731
755
|
},
|
|
756
|
+
bots: {
|
|
757
|
+
acquireLease: (leaseId) => run(() => trpc.bots.acquireLease.mutate({ leaseId })),
|
|
758
|
+
releaseLease: (leaseId) => run(() => trpc.bots.releaseLease.mutate({ leaseId })),
|
|
759
|
+
self: () => run(async () => trpc.bots.self.query())
|
|
760
|
+
},
|
|
732
761
|
credentials: {
|
|
733
762
|
list: () => run(async () => {
|
|
734
763
|
const result = await trpc.modelCredentials.listMyCredentials.query();
|
package/dist/types.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ export type RunRef = {
|
|
|
62
62
|
id: string;
|
|
63
63
|
};
|
|
64
64
|
export type WaitOptions = {
|
|
65
|
+
/** For `ensureRunning` the server maximum is 240000 (4 minutes). */
|
|
65
66
|
timeoutMs?: number;
|
|
66
67
|
pollIntervalMs?: number;
|
|
67
68
|
/** Abort the wait early; the promise rejects with code `ABORTED`. */
|
|
@@ -106,50 +107,12 @@ export type ProviderKey = "railway" | "aws" | "e2b" | "daytona" | "cloudflare" |
|
|
|
106
107
|
type ProviderSelectionBase = {
|
|
107
108
|
/** Select a specific provider installation. Usually omitted. */
|
|
108
109
|
providerId?: string;
|
|
109
|
-
/** An admin-defined
|
|
110
|
+
/** An admin-defined machine size, by key. */
|
|
110
111
|
machine?: {
|
|
111
112
|
type: "profile";
|
|
112
113
|
key: string;
|
|
113
114
|
};
|
|
114
115
|
};
|
|
115
|
-
type FlexibleMachine<T> = {
|
|
116
|
-
type: "profile";
|
|
117
|
-
key: string;
|
|
118
|
-
} | {
|
|
119
|
-
type: "custom";
|
|
120
|
-
resources: T;
|
|
121
|
-
};
|
|
122
|
-
type AwsResources = {
|
|
123
|
-
cpu?: number;
|
|
124
|
-
memory?: number;
|
|
125
|
-
ephemeralStorageGiB?: number;
|
|
126
|
-
architecture?: "X86_64" | "ARM64";
|
|
127
|
-
};
|
|
128
|
-
type DaytonaResources = {
|
|
129
|
-
resources?: {
|
|
130
|
-
cpu?: number;
|
|
131
|
-
memory?: number;
|
|
132
|
-
disk?: number;
|
|
133
|
-
};
|
|
134
|
-
editorResources?: {
|
|
135
|
-
cpu?: number;
|
|
136
|
-
memory?: number;
|
|
137
|
-
disk?: number;
|
|
138
|
-
};
|
|
139
|
-
};
|
|
140
|
-
type VercelResources = {
|
|
141
|
-
vcpus?: number;
|
|
142
|
-
};
|
|
143
|
-
type ExeDevResources = {
|
|
144
|
-
cpu?: number;
|
|
145
|
-
memory?: string;
|
|
146
|
-
disk?: string;
|
|
147
|
-
};
|
|
148
|
-
/** E2B fixes CPU/RAM per template, so resources select a template build. */
|
|
149
|
-
type E2bResources = {
|
|
150
|
-
templateId?: string;
|
|
151
|
-
sshTemplateId?: string;
|
|
152
|
-
};
|
|
153
116
|
export type WorkspaceProviderSelection = {
|
|
154
117
|
type: "railway";
|
|
155
118
|
providerId?: string;
|
|
@@ -158,26 +121,8 @@ export type WorkspaceProviderSelection = {
|
|
|
158
121
|
type: "aws";
|
|
159
122
|
region?: string;
|
|
160
123
|
accessProfile?: string;
|
|
161
|
-
} &
|
|
162
|
-
|
|
163
|
-
}) | ({
|
|
164
|
-
type: "daytona";
|
|
165
|
-
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
166
|
-
machine?: FlexibleMachine<DaytonaResources>;
|
|
167
|
-
}) | ({
|
|
168
|
-
type: "vercel";
|
|
169
|
-
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
170
|
-
machine?: FlexibleMachine<VercelResources>;
|
|
171
|
-
}) | ({
|
|
172
|
-
type: "exedev";
|
|
173
|
-
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
174
|
-
machine?: FlexibleMachine<ExeDevResources>;
|
|
175
|
-
}) | ({
|
|
176
|
-
type: "e2b";
|
|
177
|
-
} & Omit<ProviderSelectionBase, "machine"> & {
|
|
178
|
-
machine?: FlexibleMachine<E2bResources>;
|
|
179
|
-
}) | ({
|
|
180
|
-
type: "ascii";
|
|
124
|
+
} & ProviderSelectionBase) | ({
|
|
125
|
+
type: "daytona" | "vercel" | "exedev" | "e2b" | "ascii";
|
|
181
126
|
} & ProviderSelectionBase) | {
|
|
182
127
|
type: "cloudflare";
|
|
183
128
|
providerId?: string;
|
|
@@ -185,6 +130,7 @@ export type WorkspaceProviderSelection = {
|
|
|
185
130
|
export type BuiltInAgentKey = "opencode-ttyd" | "opencode" | "t3code";
|
|
186
131
|
export type AgentKey = BuiltInAgentKey | (string & {});
|
|
187
132
|
export type WorkspaceCreateInput = {
|
|
133
|
+
provisioningProfile?: "personal" | "bot";
|
|
188
134
|
idempotencyKey?: string;
|
|
189
135
|
name?: string;
|
|
190
136
|
/**
|
|
@@ -225,13 +171,21 @@ export type WorkspaceCreateInput = {
|
|
|
225
171
|
token: string;
|
|
226
172
|
};
|
|
227
173
|
/**
|
|
228
|
-
*
|
|
229
|
-
* integration
|
|
230
|
-
*
|
|
174
|
+
* Connections to attach. Each is a connection id from `client.integrations.connections.list()`,
|
|
175
|
+
* an integration key, or a connection name (case-insensitive; ambiguous names are rejected).
|
|
176
|
+
* `"github"` attaches the connection that covers the repository's owner, or the deployment's
|
|
177
|
+
* shared one. At most one GitHub and one Google connection; any number of MCP/Executor ones.
|
|
178
|
+
* A GitHub connection renews Git/gh credentials automatically; a Google connection injects
|
|
179
|
+
* keyless ADC/gcloud auth. Cannot be combined with `repositoryCredentials` for GitHub.
|
|
231
180
|
*/
|
|
232
181
|
connections?: string[];
|
|
233
182
|
/** Defaults from the selected provider. */
|
|
234
183
|
persistent?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Keep the workspace running while idle instead of pausing it. On managed
|
|
186
|
+
* GitTerm this needs a paid plan, and spending limits still pause it.
|
|
187
|
+
*/
|
|
188
|
+
alwaysOn?: boolean;
|
|
235
189
|
workspaceProfile?: "standard" | "ssh-enabled";
|
|
236
190
|
/** Omit to use dashboard defaults. An explicit block inherits nothing unless requested. */
|
|
237
191
|
models?: WorkspaceModelsInput;
|
|
@@ -283,7 +237,7 @@ export type Integration = {
|
|
|
283
237
|
allowShared: boolean;
|
|
284
238
|
};
|
|
285
239
|
export type ConnectionKind = "personal" | "shared";
|
|
286
|
-
export type ConnectionStatus = "connected" | "suspended";
|
|
240
|
+
export type ConnectionStatus = "connected" | "suspended" | "untested" | "needs_auth" | "error";
|
|
287
241
|
export type GitHubConnectionDetails = {
|
|
288
242
|
integration: "github";
|
|
289
243
|
mode: "app" | "pat";
|
|
@@ -305,7 +259,42 @@ export type GoogleConnectionDetails = {
|
|
|
305
259
|
attributeMapping: Record<string, string>;
|
|
306
260
|
};
|
|
307
261
|
};
|
|
308
|
-
export type
|
|
262
|
+
export type McpConnectionDetails = {
|
|
263
|
+
revision?: number;
|
|
264
|
+
integration: "mcp" | "executor";
|
|
265
|
+
url: string;
|
|
266
|
+
authType: "none" | "bearer" | "headers";
|
|
267
|
+
codemode: boolean;
|
|
268
|
+
toolCount: number | null;
|
|
269
|
+
serverInfo: {
|
|
270
|
+
name: string;
|
|
271
|
+
version: string;
|
|
272
|
+
} | null;
|
|
273
|
+
lastCheckedAt: string | null;
|
|
274
|
+
};
|
|
275
|
+
export type McpAuthentication = {
|
|
276
|
+
type: "none";
|
|
277
|
+
} | {
|
|
278
|
+
type: "headers";
|
|
279
|
+
headers: Record<string, string>;
|
|
280
|
+
};
|
|
281
|
+
export type CreateMcpConnectionInput = {
|
|
282
|
+
integration: "mcp" | "executor";
|
|
283
|
+
name: string;
|
|
284
|
+
url: string;
|
|
285
|
+
authentication: McpAuthentication;
|
|
286
|
+
codemode?: boolean;
|
|
287
|
+
};
|
|
288
|
+
export type UpdateMcpConnectionInput = Omit<CreateMcpConnectionInput, "integration" | "authentication"> & {
|
|
289
|
+
id: string;
|
|
290
|
+
authentication?: McpAuthentication;
|
|
291
|
+
};
|
|
292
|
+
export type McpConnectionTestResult = {
|
|
293
|
+
status: "connected" | "needs_auth" | "error";
|
|
294
|
+
message: string;
|
|
295
|
+
connection: Connection;
|
|
296
|
+
};
|
|
297
|
+
export type ConnectionDetails = GitHubConnectionDetails | GoogleConnectionDetails | McpConnectionDetails;
|
|
309
298
|
/**
|
|
310
299
|
* Something you can attach to a workspace via `connections: [id]`. Personal connections are
|
|
311
300
|
* owned by you; shared ones are provided by the admin and have stable ids like `github:shared`.
|
|
@@ -328,15 +317,16 @@ export type CreateConnectionInput = {
|
|
|
328
317
|
serviceAccountEmail: string;
|
|
329
318
|
} | {
|
|
330
319
|
integration: "github";
|
|
331
|
-
};
|
|
320
|
+
} | CreateMcpConnectionInput;
|
|
332
321
|
export type CreateConnectionResult = {
|
|
333
|
-
status: "connected";
|
|
322
|
+
status: "connected" | "saved";
|
|
334
323
|
connection: Connection;
|
|
335
324
|
/** Commands you still need to run outside GitTerm, e.g. the Google IAM binding. */
|
|
336
325
|
nextSteps: Array<{
|
|
337
326
|
label: string;
|
|
338
327
|
command: string;
|
|
339
328
|
}>;
|
|
329
|
+
message?: string;
|
|
340
330
|
} | {
|
|
341
331
|
/** Finish in a browser at `authorizeUrl`, then `connections.waitFor()` the new connection. */
|
|
342
332
|
status: "pending";
|
|
@@ -440,6 +430,8 @@ export type AgentRunReply = {
|
|
|
440
430
|
reject: true;
|
|
441
431
|
};
|
|
442
432
|
export type AgentRun = {
|
|
433
|
+
/** A runtime snapshot was read successfully, even if it contained no final text. */
|
|
434
|
+
outputAvailable?: boolean;
|
|
443
435
|
id: string;
|
|
444
436
|
workspaceId: string;
|
|
445
437
|
title: string;
|
|
@@ -488,6 +480,8 @@ export type AgentRunAttachment = {
|
|
|
488
480
|
data: string;
|
|
489
481
|
};
|
|
490
482
|
export type AgentRunCreateInput = {
|
|
483
|
+
/** Absolute execution deadline enforced by the server, even if the client disconnects. */
|
|
484
|
+
deadlineAt?: string;
|
|
491
485
|
workspace: WorkspaceRef;
|
|
492
486
|
/**
|
|
493
487
|
* Stable key used to return the same run when a request is retried.
|
|
@@ -730,11 +724,18 @@ export type WorkspaceCatalog = {
|
|
|
730
724
|
description: string;
|
|
731
725
|
roleArn: string;
|
|
732
726
|
}>;
|
|
727
|
+
/** Where the provider runs workspaces (e.g. "EU", "US"); null when not set. */
|
|
728
|
+
location: string | null;
|
|
729
|
+
/** Sizes you may pick on this provider; `isDefault` is used when none is requested. */
|
|
733
730
|
machines: Array<{
|
|
734
731
|
id: string;
|
|
735
732
|
key: string;
|
|
736
733
|
name: string;
|
|
737
734
|
description: string | null;
|
|
735
|
+
vcpus: number | null;
|
|
736
|
+
memoryGb: number | null;
|
|
737
|
+
/** Hourly price in millionths of a dollar on managed GitTerm; null when unpriced. */
|
|
738
|
+
priceMicrosPerHour: number | null;
|
|
738
739
|
isDefault: boolean;
|
|
739
740
|
}>;
|
|
740
741
|
agentKeys: string[];
|
|
@@ -748,4 +749,30 @@ export type WorkspaceCatalog = {
|
|
|
748
749
|
workspaceApiAccess: boolean;
|
|
749
750
|
}>;
|
|
750
751
|
};
|
|
752
|
+
/** A chat bot's settings, saved in the dashboard (Bots). Secrets stay in the bot's .env. */
|
|
753
|
+
export type SavedBot = {
|
|
754
|
+
id: string;
|
|
755
|
+
name: string;
|
|
756
|
+
platform: "slack" | "discord";
|
|
757
|
+
/** Repository URL, with `#branch` when one is picked. */
|
|
758
|
+
repo: string;
|
|
759
|
+
/** OpenCode `provider/model`. */
|
|
760
|
+
model: string;
|
|
761
|
+
/** Saved credential label; null uses the provider's default credential. */
|
|
762
|
+
credential: string | null;
|
|
763
|
+
/** Tool connection references besides GitHub. */
|
|
764
|
+
connections: string[];
|
|
765
|
+
/** Compute provider key; null uses your default. */
|
|
766
|
+
provider: string | null;
|
|
767
|
+
/** "token": the bot brings its own GITTERM_BOT_GITHUB_TOKEN. */
|
|
768
|
+
githubAccess: "connection" | "token";
|
|
769
|
+
/** Channel ids it answers in; empty answers in every channel it's in. */
|
|
770
|
+
channels: string[];
|
|
771
|
+
/** User ids allowed to use it; empty allows everyone in the channel. */
|
|
772
|
+
allowedUsers: string[];
|
|
773
|
+
allowGuests: boolean;
|
|
774
|
+
instructions: string | null;
|
|
775
|
+
/** A command run in the checkout before the agent starts in a new sandbox. */
|
|
776
|
+
setup: string | null;
|
|
777
|
+
};
|
|
751
778
|
export {};
|