@sealant/api-contracts-next 0.39.0-next.696 → 0.39.0-next.700
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.
|
@@ -855,7 +855,52 @@ export declare const ControlPlaneAPI: HttpApi.HttpApi<"sealantControlPlaneApi",
|
|
|
855
855
|
readonly email: import("effect/Schema").String;
|
|
856
856
|
readonly name: import("effect/Schema").String;
|
|
857
857
|
readonly createdAt: import("effect/Schema").String;
|
|
858
|
-
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<typeof import("./users.js").UserNotFoundError | typeof import("./users.js").UserInternalServerError>, never, never>, false> | import("effect/unstable/httpapi/HttpApiGroup").HttpApiGroup<"workspaces", import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"
|
|
858
|
+
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<typeof import("./users.js").UserNotFoundError | typeof import("./users.js").UserInternalServerError>, never, never>, false> | import("effect/unstable/httpapi/HttpApiGroup").HttpApiGroup<"workspaces", import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"applyWorkspaceDotfiles", "POST", "/v1/workspaces/:workspaceId/dotfiles", import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<import("effect/Schema").Struct<{
|
|
859
|
+
readonly workspaceId: import("effect/Schema").String;
|
|
860
|
+
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<never>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<import("effect/Schema").Struct<{
|
|
861
|
+
readonly ownerUserId: import("effect/Schema").String;
|
|
862
|
+
readonly onBehalfOfUserId: import("effect/Schema").String;
|
|
863
|
+
readonly user: import("effect/Schema").String;
|
|
864
|
+
readonly home: import("effect/Schema").String;
|
|
865
|
+
readonly repository: import("effect/Schema").optional<import("effect/Schema").Struct<{
|
|
866
|
+
readonly url: import("effect/Schema").String;
|
|
867
|
+
readonly ref: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
868
|
+
readonly manager: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
869
|
+
readonly bootstrap: import("effect/Schema").optional<import("effect/Schema").Boolean>;
|
|
870
|
+
readonly bootstrapCommand: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
871
|
+
}>>;
|
|
872
|
+
readonly archives: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
873
|
+
readonly data: import("effect/Schema").String;
|
|
874
|
+
readonly manager: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
875
|
+
readonly target: import("effect/Schema").optional<import("effect/Schema").Literals<readonly ["home", "config"]>>;
|
|
876
|
+
readonly bootstrap: import("effect/Schema").optional<import("effect/Schema").Boolean>;
|
|
877
|
+
readonly bootstrapCommand: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
878
|
+
}>>>;
|
|
879
|
+
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<never>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<import("effect/Schema").Struct<{
|
|
880
|
+
readonly runId: import("effect/Schema").String;
|
|
881
|
+
readonly workspaceId: import("effect/Schema").String;
|
|
882
|
+
readonly attemptId: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
883
|
+
readonly ownerUserId: import("effect/Schema").String;
|
|
884
|
+
readonly harnessId: import("effect/Schema").String;
|
|
885
|
+
readonly mode: import("effect/Schema").Literals<readonly ["one-shot", "interactive"]>;
|
|
886
|
+
readonly status: import("effect/Schema").Literals<readonly ["queued", "running", "completed", "failed", "cancelled"]>;
|
|
887
|
+
readonly prompt: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
888
|
+
readonly command: import("effect/Schema").optional<import("effect/Schema").Struct<{
|
|
889
|
+
readonly executable: import("effect/Schema").String;
|
|
890
|
+
readonly args: import("effect/Schema").$Array<import("effect/Schema").String>;
|
|
891
|
+
readonly cwd: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
892
|
+
readonly argCount: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
893
|
+
readonly argLengths: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").Number>>;
|
|
894
|
+
}>>;
|
|
895
|
+
readonly metadata: import("effect/Schema").optional<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Unknown>>;
|
|
896
|
+
readonly exitCode: import("effect/Schema").optional<import("effect/Schema").Number>;
|
|
897
|
+
readonly errorMessage: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
898
|
+
readonly startedAt: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
899
|
+
readonly finishedAt: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
900
|
+
readonly recordDeletedAt: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
901
|
+
readonly createdAt: import("effect/Schema").String;
|
|
902
|
+
readonly updatedAt: import("effect/Schema").String;
|
|
903
|
+
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<typeof import("./workspaces.js").WorkspaceBadRequestError | typeof import("./workspaces.js").WorkspaceForbiddenError | typeof import("./workspaces.js").WorkspaceNotFoundError | typeof import("./workspaces.js").WorkspaceConflictError | typeof import("./workspaces.js").WorkspaceBadGatewayError | typeof import("./workspaces.js").WorkspaceServiceUnavailableError | typeof import("./workspaces.js").WorkspaceInternalServerError>, never, never> | import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"bindWorkspace", "POST", "/v1/workspaces/:workspaceId/bind", import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<import("effect/Schema").Struct<{
|
|
859
904
|
readonly workspaceId: import("effect/Schema").String;
|
|
860
905
|
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<never>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<import("effect/Schema").Struct<{
|
|
861
906
|
readonly ownerUserId: import("effect/Schema").String;
|
|
@@ -1286,6 +1331,14 @@ export declare const ControlPlaneAPI: HttpApi.HttpApi<"sealantControlPlaneApi",
|
|
|
1286
1331
|
readonly connectedAccountId: import("effect/Schema").String;
|
|
1287
1332
|
readonly name: import("effect/Schema").String;
|
|
1288
1333
|
}>>;
|
|
1334
|
+
readonly pi: import("effect/Schema").optional<import("effect/Schema").Struct<{
|
|
1335
|
+
readonly connectedAccountId: import("effect/Schema").String;
|
|
1336
|
+
readonly name: import("effect/Schema").String;
|
|
1337
|
+
}>>;
|
|
1338
|
+
readonly opencode: import("effect/Schema").optional<import("effect/Schema").Struct<{
|
|
1339
|
+
readonly connectedAccountId: import("effect/Schema").String;
|
|
1340
|
+
readonly name: import("effect/Schema").String;
|
|
1341
|
+
}>>;
|
|
1289
1342
|
}>;
|
|
1290
1343
|
}>>;
|
|
1291
1344
|
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<typeof import("./workspaces.js").WorkspaceForbiddenError | typeof import("./workspaces.js").WorkspaceNotFoundError | typeof import("./workspaces.js").WorkspaceConflictError | typeof import("./workspaces.js").WorkspaceInternalServerError>, never, never> | import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"listWorkspaceEvents", "GET", "/v1/workspaces/:workspaceId/events", import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<import("effect/Schema").Struct<{
|
|
@@ -1360,6 +1413,9 @@ export declare const ControlPlaneAPI: HttpApi.HttpApi<"sealantControlPlaneApi",
|
|
|
1360
1413
|
readonly claude: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").String>>;
|
|
1361
1414
|
readonly codex: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").String>>;
|
|
1362
1415
|
readonly github: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").String>>;
|
|
1416
|
+
readonly pi: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").String>>;
|
|
1417
|
+
readonly opencode: import("effect/Schema").optional<import("effect/Schema").NullOr<import("effect/Schema").String>>;
|
|
1418
|
+
readonly partial: import("effect/Schema").optional<import("effect/Schema").Boolean>;
|
|
1363
1419
|
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<never>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<import("effect/Schema").Struct<{
|
|
1364
1420
|
readonly workspaceId: import("effect/Schema").String;
|
|
1365
1421
|
readonly runId: import("effect/Schema").String;
|
|
@@ -1379,8 +1435,21 @@ export declare const ControlPlaneAPI: HttpApi.HttpApi<"sealantControlPlaneApi",
|
|
|
1379
1435
|
readonly connectedAccountId: import("effect/Schema").String;
|
|
1380
1436
|
readonly name: import("effect/Schema").String;
|
|
1381
1437
|
}>>;
|
|
1438
|
+
readonly pi: import("effect/Schema").optional<import("effect/Schema").Struct<{
|
|
1439
|
+
readonly connectedAccountId: import("effect/Schema").String;
|
|
1440
|
+
readonly name: import("effect/Schema").String;
|
|
1441
|
+
}>>;
|
|
1442
|
+
readonly opencode: import("effect/Schema").optional<import("effect/Schema").Struct<{
|
|
1443
|
+
readonly connectedAccountId: import("effect/Schema").String;
|
|
1444
|
+
readonly name: import("effect/Schema").String;
|
|
1445
|
+
}>>;
|
|
1382
1446
|
}>;
|
|
1383
1447
|
}>;
|
|
1448
|
+
readonly skipped: import("effect/Schema").optional<import("effect/Schema").$Array<import("effect/Schema").Struct<{
|
|
1449
|
+
readonly provider: import("effect/Schema").Literals<readonly ["claude", "codex", "github", "pi", "opencode"]>;
|
|
1450
|
+
readonly code: import("effect/Schema").Literals<readonly ["connected-account-missing", "connected-account-invalid", "connected-account-unsupported", "login-file-unusable"]>;
|
|
1451
|
+
readonly message: import("effect/Schema").String;
|
|
1452
|
+
}>>>;
|
|
1384
1453
|
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<typeof import("./workspaces.js").WorkspaceBadRequestError | typeof import("./workspaces.js").WorkspaceForbiddenError | typeof import("./workspaces.js").WorkspaceNotFoundError | typeof import("./workspaces.js").WorkspaceConflictError | typeof import("./workspaces.js").WorkspaceBadGatewayError | typeof import("./workspaces.js").WorkspaceServiceUnavailableError | typeof import("./workspaces.js").WorkspaceInternalServerError>, never, never> | import("effect/unstable/httpapi/HttpApiEndpoint").HttpApiEndpoint<"recoverWorkspace", "POST", "/v1/workspaces/:workspaceId/recover", import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<import("effect/Schema").Struct<{
|
|
1385
1454
|
readonly workspaceId: import("effect/Schema").String;
|
|
1386
1455
|
}>>, import("effect/unstable/httpapi/HttpApiEndpoint").StringTree<never>, import("effect/unstable/httpapi/HttpApiEndpoint").Json<import("effect/Schema").Struct<{
|
|
@@ -186,6 +186,95 @@ export declare const execWorkspaceRequestSchema: Schema.Struct<{
|
|
|
186
186
|
readonly user: Schema.optional<Schema.String>;
|
|
187
187
|
}>;
|
|
188
188
|
export type ExecWorkspaceRequest = typeof execWorkspaceRequestSchema.Type;
|
|
189
|
+
/** The `harnessId` stamped on runs that apply a person's dotfiles (`applyWorkspaceDotfiles`). */
|
|
190
|
+
export declare const dotfilesRunHarnessId = "dotfiles";
|
|
191
|
+
/** How a dotfiles tree is applied: chezmoi and stow layouts are detected by `auto`. */
|
|
192
|
+
export declare const workspaceDotfilesManagerSchema: Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>;
|
|
193
|
+
/**
|
|
194
|
+
* A dotfiles repository cloned as the person (no credential reaches the workspace: a repository
|
|
195
|
+
* only the person's own identity can reach is resolved by the caller and sent as an archive).
|
|
196
|
+
*/
|
|
197
|
+
export declare const applyWorkspaceDotfilesRepositorySchema: Schema.Struct<{
|
|
198
|
+
/** An `https://` clone URL with no credential in it (no `user:token@`). */
|
|
199
|
+
readonly url: Schema.String;
|
|
200
|
+
/** Branch or tag; omitted clones the remote's default branch. */
|
|
201
|
+
readonly ref: Schema.optional<Schema.String>;
|
|
202
|
+
readonly manager: Schema.optional<Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
203
|
+
/** Run the bootstrap command after applying (when the checkout has it). Default true. */
|
|
204
|
+
readonly bootstrap: Schema.optional<Schema.Boolean>;
|
|
205
|
+
/** Relative to the checkout; default `./install.sh`. */
|
|
206
|
+
readonly bootstrapCommand: Schema.optional<Schema.String>;
|
|
207
|
+
}>;
|
|
208
|
+
/** A caller-resolved dotfiles tree, as at create (`spec.runtime.dotfilesArchives`). */
|
|
209
|
+
export declare const applyWorkspaceDotfilesArchiveSchema: Schema.Struct<{
|
|
210
|
+
/** base64 of a `.tar.gz`; at most 6 MiB of base64 (about 4 MiB decoded). */
|
|
211
|
+
readonly data: Schema.String;
|
|
212
|
+
readonly manager: Schema.optional<Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
213
|
+
/** Where the tree lands: `home` (default) or `config` (`~/.config`, copy manager only). */
|
|
214
|
+
readonly target: Schema.optional<Schema.Literals<readonly ["home", "config"]>>;
|
|
215
|
+
/** Run `./install.sh` (or `bootstrapCommand`) after applying when present. Default true. */
|
|
216
|
+
readonly bootstrap: Schema.optional<Schema.Boolean>;
|
|
217
|
+
readonly bootstrapCommand: Schema.optional<Schema.String>;
|
|
218
|
+
}>;
|
|
219
|
+
/**
|
|
220
|
+
* Apply a person's dotfiles into their home of a RUNNING workspace, as their Linux user
|
|
221
|
+
* (docs/connected-accounts-design.md §6g; Mend's ADR 0016 decision 11): the same sources as a
|
|
222
|
+
* create's dotfiles (a repository, archives, or both; the repository first, archives after in
|
|
223
|
+
* order) and the same applier (sealantd's: chezmoi, stow or copy, then each tree's bootstrap).
|
|
224
|
+
*
|
|
225
|
+
* `user` must exist and must not be root or in root's group, and `home` must be its passwd home: an
|
|
226
|
+
* existing directory of the user's, reached without a symbolic link. The clone, chezmoi, stow and the
|
|
227
|
+
* bootstrap run as the user; sealantd's archive staging and `copy` manager still run as root inside
|
|
228
|
+
* the home and follow links the person planted there, until sealantd's fix for it lands (see
|
|
229
|
+
* docs/connected-accounts-design.md §6g). `onBehalfOfUserId` names whose dotfiles they are: it is
|
|
230
|
+
* recorded on the run, and a home whose logins another person holds is refused (`home-held`). Answered `202` with a run (`harnessId`
|
|
231
|
+
* `dotfiles`) once the archives are staged: the run's first `processStarted` is the bootstrap,
|
|
232
|
+
* started once every file is applied; its output and exit are the run's. The run completes with the
|
|
233
|
+
* bootstrap's exit code (0 when no tree had one) and fails, with the daemon's words, when the apply
|
|
234
|
+
* was refused or the bootstrap ran past 30 minutes (it is stopped).
|
|
235
|
+
*/
|
|
236
|
+
export declare const applyWorkspaceDotfilesRequestSchema: Schema.Struct<{
|
|
237
|
+
/** The workspace's owner (owner scope; uniform 404 otherwise). */
|
|
238
|
+
readonly ownerUserId: Schema.String;
|
|
239
|
+
/** The Sealant user whose dotfiles these are: recorded on the run (`metadata.dotfiles`). */
|
|
240
|
+
readonly onBehalfOfUserId: Schema.String;
|
|
241
|
+
/** The Linux user to apply as (a login name or a uid); never root. */
|
|
242
|
+
readonly user: Schema.String;
|
|
243
|
+
/** The user's passwd home: absolute, normalised, never under `/workspace`. */
|
|
244
|
+
readonly home: Schema.String;
|
|
245
|
+
readonly repository: Schema.optional<Schema.Struct<{
|
|
246
|
+
/** An `https://` clone URL with no credential in it (no `user:token@`). */
|
|
247
|
+
readonly url: Schema.String;
|
|
248
|
+
/** Branch or tag; omitted clones the remote's default branch. */
|
|
249
|
+
readonly ref: Schema.optional<Schema.String>;
|
|
250
|
+
readonly manager: Schema.optional<Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
251
|
+
/** Run the bootstrap command after applying (when the checkout has it). Default true. */
|
|
252
|
+
readonly bootstrap: Schema.optional<Schema.Boolean>;
|
|
253
|
+
/** Relative to the checkout; default `./install.sh`. */
|
|
254
|
+
readonly bootstrapCommand: Schema.optional<Schema.String>;
|
|
255
|
+
}>>;
|
|
256
|
+
readonly archives: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
257
|
+
/** base64 of a `.tar.gz`; at most 6 MiB of base64 (about 4 MiB decoded). */
|
|
258
|
+
readonly data: Schema.String;
|
|
259
|
+
readonly manager: Schema.optional<Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
260
|
+
/** Where the tree lands: `home` (default) or `config` (`~/.config`, copy manager only). */
|
|
261
|
+
readonly target: Schema.optional<Schema.Literals<readonly ["home", "config"]>>;
|
|
262
|
+
/** Run `./install.sh` (or `bootstrapCommand`) after applying when present. Default true. */
|
|
263
|
+
readonly bootstrap: Schema.optional<Schema.Boolean>;
|
|
264
|
+
readonly bootstrapCommand: Schema.optional<Schema.String>;
|
|
265
|
+
}>>>;
|
|
266
|
+
}>;
|
|
267
|
+
export type ApplyWorkspaceDotfilesRequest = typeof applyWorkspaceDotfilesRequestSchema.Type;
|
|
268
|
+
/**
|
|
269
|
+
* Stable `code`s of the `WorkspaceConflictError` a dotfiles apply answers, nothing applied:
|
|
270
|
+
* `workspace-not-running` (no ready executor), `dotfiles-user-unsupported` (the workspace's
|
|
271
|
+
* sealantd cannot apply dotfiles as a user), `user-unknown` (no such user: make it first),
|
|
272
|
+
* `user-root` (the user is root or in root's group), `home-mismatch` (the home is not the user's
|
|
273
|
+
* passwd home), `home-unusable` (the home is missing, not a directory, not the user's, or reached
|
|
274
|
+
* through a symbolic link), `home-held` (another person's logins are held in the home).
|
|
275
|
+
*/
|
|
276
|
+
export declare const workspaceDotfilesConflictCodes: readonly ["workspace-not-running", "dotfiles-user-unsupported", "user-unknown", "user-root", "home-mismatch", "home-unusable", "home-held"];
|
|
277
|
+
export type WorkspaceDotfilesConflictCode = (typeof workspaceDotfilesConflictCodes)[number];
|
|
189
278
|
/**
|
|
190
279
|
* Bind a standby workspace's working directory, or a bindable extra mount, to one subdirectory of
|
|
191
280
|
* its root (sealantd ADR-0014). `mountPath` defaults to the working directory; an empty `subpath`
|
|
@@ -618,9 +707,26 @@ export declare const inspectWorkspaceImageResponseSchema: Schema.Struct<{
|
|
|
618
707
|
}>;
|
|
619
708
|
}>;
|
|
620
709
|
export type InspectWorkspaceImageResponse = typeof inspectWorkspaceImageResponseSchema.Type;
|
|
621
|
-
/**
|
|
622
|
-
|
|
710
|
+
/**
|
|
711
|
+
* Stable codes of a refused connected account, carried with the account's `provider` by the error
|
|
712
|
+
* that refuses it (a create's or a credentials put's): `connected-account-missing`
|
|
713
|
+
* (`WorkspaceNotFoundError`, 404: the person has no such account, or it is archived or someone
|
|
714
|
+
* else's) and `connected-account-invalid` (`WorkspaceConflictError`, 409: the account is marked
|
|
715
|
+
* invalid, or holds an unusable credential; reconnect it) and `connected-account-unsupported`
|
|
716
|
+
* (`WorkspaceConflictError`, 409: the account cannot serve what was asked, as a Codex API key cannot
|
|
717
|
+
* be pi's or opencode's ChatGPT login). Nothing was written either way.
|
|
718
|
+
*/
|
|
719
|
+
export declare const connectedAccountRefusalCodes: readonly ["connected-account-missing", "connected-account-invalid", "connected-account-unsupported"];
|
|
720
|
+
export type ConnectedAccountRefusalCode = (typeof connectedAccountRefusalCodes)[number];
|
|
721
|
+
/**
|
|
722
|
+
* The providers a home holds logins for (docs/connected-accounts-design.md §6c). `pi` and
|
|
723
|
+
* `opencode` are the person's ChatGPT login (a Codex connected account), written into each tool's
|
|
724
|
+
* own `auth.json`.
|
|
725
|
+
*/
|
|
726
|
+
export declare const workspaceCredentialHomeProviders: readonly ["claude", "codex", "github", "pi", "opencode"];
|
|
623
727
|
export type WorkspaceCredentialHomeProvider = (typeof workspaceCredentialHomeProviders)[number];
|
|
728
|
+
/** The connected account's provider each home provider's login is made from. */
|
|
729
|
+
export declare const workspaceCredentialHomeAccountProvider: Readonly<Record<WorkspaceCredentialHomeProvider, "claude" | "codex" | "github">>;
|
|
624
730
|
/**
|
|
625
731
|
* Put one person's logins into one home of a RUNNING workspace (docs/connected-accounts-design.md
|
|
626
732
|
* §6c). A home holds one person's logins while it is held: the first put names its person, a put
|
|
@@ -652,6 +758,25 @@ export declare const putWorkspaceCredentialsRequestSchema: Schema.Struct<{
|
|
|
652
758
|
readonly claude: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
653
759
|
readonly codex: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
654
760
|
readonly github: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
761
|
+
/**
|
|
762
|
+
* pi's ChatGPT login, made from a Codex account of `onBehalfOfUserId` (an id or a Codex account
|
|
763
|
+
* name), as the `openai-codex` entry of `<home>/.pi/agent/auth.json`. The file is merged: its
|
|
764
|
+
* other entries stay, and an `openai-codex` login the person made in pi is never replaced.
|
|
765
|
+
*/
|
|
766
|
+
readonly pi: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
767
|
+
/**
|
|
768
|
+
* opencode's ChatGPT login, made the same way, as the `openai` entry of opencode's `auth.json`
|
|
769
|
+
* (`<home>/.local/share/opencode/auth.json`, followed through links to where it really is, which
|
|
770
|
+
* must be inside the home). A login the person made in opencode is never replaced or removed.
|
|
771
|
+
*/
|
|
772
|
+
readonly opencode: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
773
|
+
/**
|
|
774
|
+
* Write what the person has connected and leave out the rest: a provider whose account is refused
|
|
775
|
+
* (`connected-account-missing`, `-invalid` or `-unsupported`) is not written, its login is removed
|
|
776
|
+
* from the home as `null` would remove it, and the answer's `skipped` says which and why, instead
|
|
777
|
+
* of the whole put failing. Every other refusal still fails the put. Default false.
|
|
778
|
+
*/
|
|
779
|
+
readonly partial: Schema.optional<Schema.Boolean>;
|
|
655
780
|
}>;
|
|
656
781
|
export type PutWorkspaceCredentialsRequest = typeof putWorkspaceCredentialsRequestSchema.Type;
|
|
657
782
|
/** One account whose copy a home holds. */
|
|
@@ -683,9 +808,33 @@ export declare const workspaceCredentialHomeSchema: Schema.Struct<{
|
|
|
683
808
|
/** The account's name under its provider, as it is now. */
|
|
684
809
|
readonly name: Schema.String;
|
|
685
810
|
}>>;
|
|
811
|
+
/** The Codex account pi's ChatGPT login is made from. */
|
|
812
|
+
readonly pi: Schema.optional<Schema.Struct<{
|
|
813
|
+
readonly connectedAccountId: Schema.String;
|
|
814
|
+
/** The account's name under its provider, as it is now. */
|
|
815
|
+
readonly name: Schema.String;
|
|
816
|
+
}>>;
|
|
817
|
+
/** The Codex account opencode's ChatGPT login is made from. */
|
|
818
|
+
readonly opencode: Schema.optional<Schema.Struct<{
|
|
819
|
+
readonly connectedAccountId: Schema.String;
|
|
820
|
+
/** The account's name under its provider, as it is now. */
|
|
821
|
+
readonly name: Schema.String;
|
|
822
|
+
}>>;
|
|
686
823
|
}>;
|
|
687
824
|
}>;
|
|
688
825
|
export type WorkspaceCredentialHome = typeof workspaceCredentialHomeSchema.Type;
|
|
826
|
+
/** A provider a partial put left out, and why (its account's refusal). */
|
|
827
|
+
export declare const workspaceCredentialSkipSchema: Schema.Struct<{
|
|
828
|
+
readonly provider: Schema.Literals<readonly ["claude", "codex", "github", "pi", "opencode"]>;
|
|
829
|
+
/**
|
|
830
|
+
* The account's refusal, or `login-file-unusable`: pi's or opencode's `auth.json` in the home
|
|
831
|
+
* cannot be written there (not a regular file, or really outside the home).
|
|
832
|
+
*/
|
|
833
|
+
readonly code: Schema.Literals<readonly ["connected-account-missing", "connected-account-invalid", "connected-account-unsupported", "login-file-unusable"]>;
|
|
834
|
+
/** The refusal's words, as a whole put would have answered them. */
|
|
835
|
+
readonly message: Schema.String;
|
|
836
|
+
}>;
|
|
837
|
+
export type WorkspaceCredentialSkip = typeof workspaceCredentialSkipSchema.Type;
|
|
689
838
|
export declare const putWorkspaceCredentialsResponseSchema: Schema.Struct<{
|
|
690
839
|
readonly workspaceId: Schema.String;
|
|
691
840
|
/** The launch attempt whose executor was written. */
|
|
@@ -712,8 +861,31 @@ export declare const putWorkspaceCredentialsResponseSchema: Schema.Struct<{
|
|
|
712
861
|
/** The account's name under its provider, as it is now. */
|
|
713
862
|
readonly name: Schema.String;
|
|
714
863
|
}>>;
|
|
864
|
+
/** The Codex account pi's ChatGPT login is made from. */
|
|
865
|
+
readonly pi: Schema.optional<Schema.Struct<{
|
|
866
|
+
readonly connectedAccountId: Schema.String;
|
|
867
|
+
/** The account's name under its provider, as it is now. */
|
|
868
|
+
readonly name: Schema.String;
|
|
869
|
+
}>>;
|
|
870
|
+
/** The Codex account opencode's ChatGPT login is made from. */
|
|
871
|
+
readonly opencode: Schema.optional<Schema.Struct<{
|
|
872
|
+
readonly connectedAccountId: Schema.String;
|
|
873
|
+
/** The account's name under its provider, as it is now. */
|
|
874
|
+
readonly name: Schema.String;
|
|
875
|
+
}>>;
|
|
715
876
|
}>;
|
|
716
877
|
}>;
|
|
878
|
+
/** A partial put's left-out providers, in the order named (empty when all were written). */
|
|
879
|
+
readonly skipped: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
880
|
+
readonly provider: Schema.Literals<readonly ["claude", "codex", "github", "pi", "opencode"]>;
|
|
881
|
+
/**
|
|
882
|
+
* The account's refusal, or `login-file-unusable`: pi's or opencode's `auth.json` in the home
|
|
883
|
+
* cannot be written there (not a regular file, or really outside the home).
|
|
884
|
+
*/
|
|
885
|
+
readonly code: Schema.Literals<readonly ["connected-account-missing", "connected-account-invalid", "connected-account-unsupported", "login-file-unusable"]>;
|
|
886
|
+
/** The refusal's words, as a whole put would have answered them. */
|
|
887
|
+
readonly message: Schema.String;
|
|
888
|
+
}>>>;
|
|
717
889
|
}>;
|
|
718
890
|
export type PutWorkspaceCredentialsResponse = typeof putWorkspaceCredentialsResponseSchema.Type;
|
|
719
891
|
/** Release one home: its login files are removed and its record deleted. */
|
|
@@ -759,6 +931,18 @@ export declare const listWorkspaceCredentialsResponseSchema: Schema.Struct<{
|
|
|
759
931
|
/** The account's name under its provider, as it is now. */
|
|
760
932
|
readonly name: Schema.String;
|
|
761
933
|
}>>;
|
|
934
|
+
/** The Codex account pi's ChatGPT login is made from. */
|
|
935
|
+
readonly pi: Schema.optional<Schema.Struct<{
|
|
936
|
+
readonly connectedAccountId: Schema.String;
|
|
937
|
+
/** The account's name under its provider, as it is now. */
|
|
938
|
+
readonly name: Schema.String;
|
|
939
|
+
}>>;
|
|
940
|
+
/** The Codex account opencode's ChatGPT login is made from. */
|
|
941
|
+
readonly opencode: Schema.optional<Schema.Struct<{
|
|
942
|
+
readonly connectedAccountId: Schema.String;
|
|
943
|
+
/** The account's name under its provider, as it is now. */
|
|
944
|
+
readonly name: Schema.String;
|
|
945
|
+
}>>;
|
|
762
946
|
}>;
|
|
763
947
|
}>>;
|
|
764
948
|
}>;
|
|
@@ -766,13 +950,15 @@ export type ListWorkspaceCredentialsResponse = typeof listWorkspaceCredentialsRe
|
|
|
766
950
|
/**
|
|
767
951
|
* Stable `code`s of the `WorkspaceConflictError` the credential routes answer:
|
|
768
952
|
* `workspace-not-running` (no ready executor), `connected-account-invalid` (a named account is
|
|
769
|
-
* marked invalid: reconnect it
|
|
953
|
+
* marked invalid or unusable: reconnect it; `provider` names its provider),
|
|
954
|
+
* `connected-account-unsupported` (a Codex account named for pi or opencode is not a ChatGPT
|
|
955
|
+
* login), `home-held` (the home holds another person's logins: release it
|
|
770
956
|
* first; `/root` while the launch's own logins are at `$HOME`, or for anyone but the workspace's
|
|
771
957
|
* owner), `home-unusable` (the home does not exist, is not a directory, is reached through a
|
|
772
958
|
* symbolic link, or a login directory in it links outside it), `home-busy` (another write into the
|
|
773
959
|
* home, or too many into this workspace, is still running: nothing was done, try again).
|
|
774
960
|
*/
|
|
775
|
-
export declare const workspaceCredentialsConflictCodes: readonly ["workspace-not-running", "connected-account-invalid", "home-held", "home-unusable", "home-busy"];
|
|
961
|
+
export declare const workspaceCredentialsConflictCodes: readonly ["workspace-not-running", "connected-account-invalid", "connected-account-unsupported", "home-held", "home-unusable", "home-busy"];
|
|
776
962
|
export type WorkspaceCredentialsConflictCode = (typeof workspaceCredentialsConflictCodes)[number];
|
|
777
963
|
export declare const expireWorkspaceRequestSchema: Schema.Struct<{
|
|
778
964
|
readonly ownerUserId: Schema.String;
|
|
@@ -1419,6 +1605,10 @@ export declare class WorkspaceForbiddenError extends WorkspaceForbiddenError_bas
|
|
|
1419
1605
|
}
|
|
1420
1606
|
declare const WorkspaceNotFoundError_base: Schema.Class<WorkspaceNotFoundError, Schema.TaggedStruct<"WorkspaceNotFoundError", {
|
|
1421
1607
|
readonly message: Schema.String;
|
|
1608
|
+
/** A stable reason, where one applies (`connected-account-missing`). */
|
|
1609
|
+
readonly code: Schema.optional<Schema.String>;
|
|
1610
|
+
/** The provider of the connected account the reason is about. */
|
|
1611
|
+
readonly provider: Schema.optional<Schema.Literals<readonly ["claude", "codex", "github"]>>;
|
|
1422
1612
|
}>, import("effect/Cause").YieldableError>;
|
|
1423
1613
|
export declare class WorkspaceNotFoundError extends WorkspaceNotFoundError_base {
|
|
1424
1614
|
}
|
|
@@ -1426,6 +1616,8 @@ declare const WorkspaceConflictError_base: Schema.Class<WorkspaceConflictError,
|
|
|
1426
1616
|
readonly message: Schema.String;
|
|
1427
1617
|
/** A stable reason, where one applies (`create-cancelled`: the create's key was cancelled). */
|
|
1428
1618
|
readonly code: Schema.optional<Schema.String>;
|
|
1619
|
+
/** The provider of the connected account the reason is about (`connected-account-invalid`). */
|
|
1620
|
+
readonly provider: Schema.optional<Schema.Literals<readonly ["claude", "codex", "github"]>>;
|
|
1429
1621
|
}>, import("effect/Cause").YieldableError>;
|
|
1430
1622
|
export declare class WorkspaceConflictError extends WorkspaceConflictError_base {
|
|
1431
1623
|
}
|
|
@@ -1444,7 +1636,63 @@ declare const WorkspaceInternalServerError_base: Schema.Class<WorkspaceInternalS
|
|
|
1444
1636
|
}>, import("effect/Cause").YieldableError>;
|
|
1445
1637
|
export declare class WorkspaceInternalServerError extends WorkspaceInternalServerError_base {
|
|
1446
1638
|
}
|
|
1447
|
-
export declare const WorkspacesGroup: HttpApiGroup.HttpApiGroup<"workspaces", HttpApiEndpoint.HttpApiEndpoint<"
|
|
1639
|
+
export declare const WorkspacesGroup: HttpApiGroup.HttpApiGroup<"workspaces", HttpApiEndpoint.HttpApiEndpoint<"applyWorkspaceDotfiles", "POST", "/:workspaceId/dotfiles", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
1640
|
+
readonly workspaceId: Schema.String;
|
|
1641
|
+
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
1642
|
+
/** The workspace's owner (owner scope; uniform 404 otherwise). */
|
|
1643
|
+
readonly ownerUserId: Schema.String;
|
|
1644
|
+
/** The Sealant user whose dotfiles these are: recorded on the run (`metadata.dotfiles`). */
|
|
1645
|
+
readonly onBehalfOfUserId: Schema.String;
|
|
1646
|
+
/** The Linux user to apply as (a login name or a uid); never root. */
|
|
1647
|
+
readonly user: Schema.String;
|
|
1648
|
+
/** The user's passwd home: absolute, normalised, never under `/workspace`. */
|
|
1649
|
+
readonly home: Schema.String;
|
|
1650
|
+
readonly repository: Schema.optional<Schema.Struct<{
|
|
1651
|
+
/** An `https://` clone URL with no credential in it (no `user:token@`). */
|
|
1652
|
+
readonly url: Schema.String;
|
|
1653
|
+
/** Branch or tag; omitted clones the remote's default branch. */
|
|
1654
|
+
readonly ref: Schema.optional<Schema.String>;
|
|
1655
|
+
readonly manager: Schema.optional<Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
1656
|
+
/** Run the bootstrap command after applying (when the checkout has it). Default true. */
|
|
1657
|
+
readonly bootstrap: Schema.optional<Schema.Boolean>;
|
|
1658
|
+
/** Relative to the checkout; default `./install.sh`. */
|
|
1659
|
+
readonly bootstrapCommand: Schema.optional<Schema.String>;
|
|
1660
|
+
}>>;
|
|
1661
|
+
readonly archives: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1662
|
+
/** base64 of a `.tar.gz`; at most 6 MiB of base64 (about 4 MiB decoded). */
|
|
1663
|
+
readonly data: Schema.String;
|
|
1664
|
+
readonly manager: Schema.optional<Schema.Literals<readonly ["auto", "chezmoi", "stow", "copy"]>>;
|
|
1665
|
+
/** Where the tree lands: `home` (default) or `config` (`~/.config`, copy manager only). */
|
|
1666
|
+
readonly target: Schema.optional<Schema.Literals<readonly ["home", "config"]>>;
|
|
1667
|
+
/** Run `./install.sh` (or `bootstrapCommand`) after applying when present. Default true. */
|
|
1668
|
+
readonly bootstrap: Schema.optional<Schema.Boolean>;
|
|
1669
|
+
readonly bootstrapCommand: Schema.optional<Schema.String>;
|
|
1670
|
+
}>>>;
|
|
1671
|
+
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
1672
|
+
readonly runId: Schema.String;
|
|
1673
|
+
readonly workspaceId: Schema.String;
|
|
1674
|
+
readonly attemptId: Schema.optional<Schema.String>;
|
|
1675
|
+
readonly ownerUserId: Schema.String;
|
|
1676
|
+
readonly harnessId: Schema.String;
|
|
1677
|
+
readonly mode: Schema.Literals<readonly ["one-shot", "interactive"]>;
|
|
1678
|
+
readonly status: Schema.Literals<readonly ["queued", "running", "completed", "failed", "cancelled"]>;
|
|
1679
|
+
readonly prompt: Schema.optional<Schema.String>;
|
|
1680
|
+
readonly command: Schema.optional<Schema.Struct<{
|
|
1681
|
+
readonly executable: Schema.String;
|
|
1682
|
+
readonly args: Schema.$Array<Schema.String>;
|
|
1683
|
+
readonly cwd: Schema.optional<Schema.String>;
|
|
1684
|
+
readonly argCount: Schema.optional<Schema.Number>;
|
|
1685
|
+
readonly argLengths: Schema.optional<Schema.$Array<Schema.Number>>;
|
|
1686
|
+
}>>;
|
|
1687
|
+
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
1688
|
+
readonly exitCode: Schema.optional<Schema.Number>;
|
|
1689
|
+
readonly errorMessage: Schema.optional<Schema.String>;
|
|
1690
|
+
readonly startedAt: Schema.optional<Schema.String>;
|
|
1691
|
+
readonly finishedAt: Schema.optional<Schema.String>;
|
|
1692
|
+
readonly recordDeletedAt: Schema.optional<Schema.String>;
|
|
1693
|
+
readonly createdAt: Schema.String;
|
|
1694
|
+
readonly updatedAt: Schema.String;
|
|
1695
|
+
}>>, HttpApiEndpoint.Json<typeof WorkspaceBadRequestError | typeof WorkspaceForbiddenError | typeof WorkspaceNotFoundError | typeof WorkspaceConflictError | typeof WorkspaceBadGatewayError | typeof WorkspaceServiceUnavailableError | typeof WorkspaceInternalServerError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"bindWorkspace", "POST", "/:workspaceId/bind", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
1448
1696
|
readonly workspaceId: Schema.String;
|
|
1449
1697
|
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
1450
1698
|
readonly ownerUserId: Schema.String;
|
|
@@ -2154,6 +2402,18 @@ export declare const WorkspacesGroup: HttpApiGroup.HttpApiGroup<"workspaces", Ht
|
|
|
2154
2402
|
/** The account's name under its provider, as it is now. */
|
|
2155
2403
|
readonly name: Schema.String;
|
|
2156
2404
|
}>>;
|
|
2405
|
+
/** The Codex account pi's ChatGPT login is made from. */
|
|
2406
|
+
readonly pi: Schema.optional<Schema.Struct<{
|
|
2407
|
+
readonly connectedAccountId: Schema.String;
|
|
2408
|
+
/** The account's name under its provider, as it is now. */
|
|
2409
|
+
readonly name: Schema.String;
|
|
2410
|
+
}>>;
|
|
2411
|
+
/** The Codex account opencode's ChatGPT login is made from. */
|
|
2412
|
+
readonly opencode: Schema.optional<Schema.Struct<{
|
|
2413
|
+
readonly connectedAccountId: Schema.String;
|
|
2414
|
+
/** The account's name under its provider, as it is now. */
|
|
2415
|
+
readonly name: Schema.String;
|
|
2416
|
+
}>>;
|
|
2157
2417
|
}>;
|
|
2158
2418
|
}>>;
|
|
2159
2419
|
}>>, HttpApiEndpoint.Json<typeof WorkspaceForbiddenError | typeof WorkspaceNotFoundError | typeof WorkspaceConflictError | typeof WorkspaceInternalServerError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"listWorkspaceEvents", "GET", "/:workspaceId/events", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
@@ -2262,6 +2522,25 @@ export declare const WorkspacesGroup: HttpApiGroup.HttpApiGroup<"workspaces", Ht
|
|
|
2262
2522
|
readonly claude: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
2263
2523
|
readonly codex: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
2264
2524
|
readonly github: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
2525
|
+
/**
|
|
2526
|
+
* pi's ChatGPT login, made from a Codex account of `onBehalfOfUserId` (an id or a Codex account
|
|
2527
|
+
* name), as the `openai-codex` entry of `<home>/.pi/agent/auth.json`. The file is merged: its
|
|
2528
|
+
* other entries stay, and an `openai-codex` login the person made in pi is never replaced.
|
|
2529
|
+
*/
|
|
2530
|
+
readonly pi: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
2531
|
+
/**
|
|
2532
|
+
* opencode's ChatGPT login, made the same way, as the `openai` entry of opencode's `auth.json`
|
|
2533
|
+
* (`<home>/.local/share/opencode/auth.json`, followed through links to where it really is, which
|
|
2534
|
+
* must be inside the home). A login the person made in opencode is never replaced or removed.
|
|
2535
|
+
*/
|
|
2536
|
+
readonly opencode: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
2537
|
+
/**
|
|
2538
|
+
* Write what the person has connected and leave out the rest: a provider whose account is refused
|
|
2539
|
+
* (`connected-account-missing`, `-invalid` or `-unsupported`) is not written, its login is removed
|
|
2540
|
+
* from the home as `null` would remove it, and the answer's `skipped` says which and why, instead
|
|
2541
|
+
* of the whole put failing. Every other refusal still fails the put. Default false.
|
|
2542
|
+
*/
|
|
2543
|
+
readonly partial: Schema.optional<Schema.Boolean>;
|
|
2265
2544
|
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
2266
2545
|
readonly workspaceId: Schema.String;
|
|
2267
2546
|
/** The launch attempt whose executor was written. */
|
|
@@ -2288,8 +2567,31 @@ export declare const WorkspacesGroup: HttpApiGroup.HttpApiGroup<"workspaces", Ht
|
|
|
2288
2567
|
/** The account's name under its provider, as it is now. */
|
|
2289
2568
|
readonly name: Schema.String;
|
|
2290
2569
|
}>>;
|
|
2570
|
+
/** The Codex account pi's ChatGPT login is made from. */
|
|
2571
|
+
readonly pi: Schema.optional<Schema.Struct<{
|
|
2572
|
+
readonly connectedAccountId: Schema.String;
|
|
2573
|
+
/** The account's name under its provider, as it is now. */
|
|
2574
|
+
readonly name: Schema.String;
|
|
2575
|
+
}>>;
|
|
2576
|
+
/** The Codex account opencode's ChatGPT login is made from. */
|
|
2577
|
+
readonly opencode: Schema.optional<Schema.Struct<{
|
|
2578
|
+
readonly connectedAccountId: Schema.String;
|
|
2579
|
+
/** The account's name under its provider, as it is now. */
|
|
2580
|
+
readonly name: Schema.String;
|
|
2581
|
+
}>>;
|
|
2291
2582
|
}>;
|
|
2292
2583
|
}>;
|
|
2584
|
+
/** A partial put's left-out providers, in the order named (empty when all were written). */
|
|
2585
|
+
readonly skipped: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
2586
|
+
readonly provider: Schema.Literals<readonly ["claude", "codex", "github", "pi", "opencode"]>;
|
|
2587
|
+
/**
|
|
2588
|
+
* The account's refusal, or `login-file-unusable`: pi's or opencode's `auth.json` in the home
|
|
2589
|
+
* cannot be written there (not a regular file, or really outside the home).
|
|
2590
|
+
*/
|
|
2591
|
+
readonly code: Schema.Literals<readonly ["connected-account-missing", "connected-account-invalid", "connected-account-unsupported", "login-file-unusable"]>;
|
|
2592
|
+
/** The refusal's words, as a whole put would have answered them. */
|
|
2593
|
+
readonly message: Schema.String;
|
|
2594
|
+
}>>>;
|
|
2293
2595
|
}>>, HttpApiEndpoint.Json<typeof WorkspaceBadRequestError | typeof WorkspaceForbiddenError | typeof WorkspaceNotFoundError | typeof WorkspaceConflictError | typeof WorkspaceBadGatewayError | typeof WorkspaceServiceUnavailableError | typeof WorkspaceInternalServerError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"recoverWorkspace", "POST", "/:workspaceId/recover", HttpApiEndpoint.StringTree<Schema.Struct<{
|
|
2294
2596
|
readonly workspaceId: Schema.String;
|
|
2295
2597
|
}>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
|
|
3
3
|
import { BudgetExceededError } from "./budgets.js";
|
|
4
|
+
import { connectedAccountProviderSchema } from "./connected-accounts.js";
|
|
4
5
|
import { runCommandSchema, runSchema } from "./runs.js";
|
|
5
6
|
import { workspaceProcessUserSchema } from "./sessions.js";
|
|
6
7
|
const NonEmptyString = Schema.String.check(Schema.isNonEmpty(), Schema.isTrimmed());
|
|
@@ -169,6 +170,82 @@ export const execWorkspaceRequestSchema = Schema.Struct({
|
|
|
169
170
|
/** Run every command as this Linux user (see `workspaceProcessUserSchema`). */
|
|
170
171
|
user: Schema.optional(workspaceProcessUserSchema),
|
|
171
172
|
});
|
|
173
|
+
/** The `harnessId` stamped on runs that apply a person's dotfiles (`applyWorkspaceDotfiles`). */
|
|
174
|
+
export const dotfilesRunHarnessId = "dotfiles";
|
|
175
|
+
/** How a dotfiles tree is applied: chezmoi and stow layouts are detected by `auto`. */
|
|
176
|
+
export const workspaceDotfilesManagerSchema = Schema.Literals(["auto", "chezmoi", "stow", "copy"]);
|
|
177
|
+
/**
|
|
178
|
+
* A dotfiles repository cloned as the person (no credential reaches the workspace: a repository
|
|
179
|
+
* only the person's own identity can reach is resolved by the caller and sent as an archive).
|
|
180
|
+
*/
|
|
181
|
+
export const applyWorkspaceDotfilesRepositorySchema = Schema.Struct({
|
|
182
|
+
/** An `https://` clone URL with no credential in it (no `user:token@`). */
|
|
183
|
+
url: NonEmptyString.check(Schema.isPattern(/^https:\/\/[^\s'"\\]+$/)),
|
|
184
|
+
/** Branch or tag; omitted clones the remote's default branch. */
|
|
185
|
+
ref: Schema.optional(NonEmptyString),
|
|
186
|
+
manager: Schema.optional(workspaceDotfilesManagerSchema),
|
|
187
|
+
/** Run the bootstrap command after applying (when the checkout has it). Default true. */
|
|
188
|
+
bootstrap: Schema.optional(Schema.Boolean),
|
|
189
|
+
/** Relative to the checkout; default `./install.sh`. */
|
|
190
|
+
bootstrapCommand: Schema.optional(NonEmptyString),
|
|
191
|
+
});
|
|
192
|
+
/** A caller-resolved dotfiles tree, as at create (`spec.runtime.dotfilesArchives`). */
|
|
193
|
+
export const applyWorkspaceDotfilesArchiveSchema = Schema.Struct({
|
|
194
|
+
/** base64 of a `.tar.gz`; at most 6 MiB of base64 (about 4 MiB decoded). */
|
|
195
|
+
data: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(6 * 1024 * 1024), Schema.isPattern(/^[A-Za-z0-9+/]+={0,2}$/)),
|
|
196
|
+
manager: Schema.optional(workspaceDotfilesManagerSchema),
|
|
197
|
+
/** Where the tree lands: `home` (default) or `config` (`~/.config`, copy manager only). */
|
|
198
|
+
target: Schema.optional(Schema.Literals(["home", "config"])),
|
|
199
|
+
/** Run `./install.sh` (or `bootstrapCommand`) after applying when present. Default true. */
|
|
200
|
+
bootstrap: Schema.optional(Schema.Boolean),
|
|
201
|
+
bootstrapCommand: Schema.optional(NonEmptyString),
|
|
202
|
+
});
|
|
203
|
+
/**
|
|
204
|
+
* Apply a person's dotfiles into their home of a RUNNING workspace, as their Linux user
|
|
205
|
+
* (docs/connected-accounts-design.md §6g; Mend's ADR 0016 decision 11): the same sources as a
|
|
206
|
+
* create's dotfiles (a repository, archives, or both; the repository first, archives after in
|
|
207
|
+
* order) and the same applier (sealantd's: chezmoi, stow or copy, then each tree's bootstrap).
|
|
208
|
+
*
|
|
209
|
+
* `user` must exist and must not be root or in root's group, and `home` must be its passwd home: an
|
|
210
|
+
* existing directory of the user's, reached without a symbolic link. The clone, chezmoi, stow and the
|
|
211
|
+
* bootstrap run as the user; sealantd's archive staging and `copy` manager still run as root inside
|
|
212
|
+
* the home and follow links the person planted there, until sealantd's fix for it lands (see
|
|
213
|
+
* docs/connected-accounts-design.md §6g). `onBehalfOfUserId` names whose dotfiles they are: it is
|
|
214
|
+
* recorded on the run, and a home whose logins another person holds is refused (`home-held`). Answered `202` with a run (`harnessId`
|
|
215
|
+
* `dotfiles`) once the archives are staged: the run's first `processStarted` is the bootstrap,
|
|
216
|
+
* started once every file is applied; its output and exit are the run's. The run completes with the
|
|
217
|
+
* bootstrap's exit code (0 when no tree had one) and fails, with the daemon's words, when the apply
|
|
218
|
+
* was refused or the bootstrap ran past 30 minutes (it is stopped).
|
|
219
|
+
*/
|
|
220
|
+
export const applyWorkspaceDotfilesRequestSchema = Schema.Struct({
|
|
221
|
+
/** The workspace's owner (owner scope; uniform 404 otherwise). */
|
|
222
|
+
ownerUserId: NonEmptyString,
|
|
223
|
+
/** The Sealant user whose dotfiles these are: recorded on the run (`metadata.dotfiles`). */
|
|
224
|
+
onBehalfOfUserId: NonEmptyString,
|
|
225
|
+
/** The Linux user to apply as (a login name or a uid); never root. */
|
|
226
|
+
user: workspaceProcessUserSchema,
|
|
227
|
+
/** The user's passwd home: absolute, normalised, never under `/workspace`. */
|
|
228
|
+
home: NonEmptyString,
|
|
229
|
+
repository: Schema.optional(applyWorkspaceDotfilesRepositorySchema),
|
|
230
|
+
archives: Schema.optional(Schema.Array(applyWorkspaceDotfilesArchiveSchema).check(Schema.isMaxLength(4))),
|
|
231
|
+
});
|
|
232
|
+
/**
|
|
233
|
+
* Stable `code`s of the `WorkspaceConflictError` a dotfiles apply answers, nothing applied:
|
|
234
|
+
* `workspace-not-running` (no ready executor), `dotfiles-user-unsupported` (the workspace's
|
|
235
|
+
* sealantd cannot apply dotfiles as a user), `user-unknown` (no such user: make it first),
|
|
236
|
+
* `user-root` (the user is root or in root's group), `home-mismatch` (the home is not the user's
|
|
237
|
+
* passwd home), `home-unusable` (the home is missing, not a directory, not the user's, or reached
|
|
238
|
+
* through a symbolic link), `home-held` (another person's logins are held in the home).
|
|
239
|
+
*/
|
|
240
|
+
export const workspaceDotfilesConflictCodes = [
|
|
241
|
+
"workspace-not-running",
|
|
242
|
+
"dotfiles-user-unsupported",
|
|
243
|
+
"user-unknown",
|
|
244
|
+
"user-root",
|
|
245
|
+
"home-mismatch",
|
|
246
|
+
"home-unusable",
|
|
247
|
+
"home-held",
|
|
248
|
+
];
|
|
172
249
|
/**
|
|
173
250
|
* Bind a standby workspace's working directory, or a bindable extra mount, to one subdirectory of
|
|
174
251
|
* its root (sealantd ADR-0014). `mountPath` defaults to the working directory; an empty `subpath`
|
|
@@ -517,8 +594,34 @@ export const inspectWorkspaceImageResponseSchema = Schema.Struct({
|
|
|
517
594
|
/** The image's per-person capability (`unknown` when none has been built yet). */
|
|
518
595
|
personLayout: workspaceImagePersonLayoutSchema,
|
|
519
596
|
});
|
|
520
|
-
/**
|
|
521
|
-
|
|
597
|
+
/**
|
|
598
|
+
* Stable codes of a refused connected account, carried with the account's `provider` by the error
|
|
599
|
+
* that refuses it (a create's or a credentials put's): `connected-account-missing`
|
|
600
|
+
* (`WorkspaceNotFoundError`, 404: the person has no such account, or it is archived or someone
|
|
601
|
+
* else's) and `connected-account-invalid` (`WorkspaceConflictError`, 409: the account is marked
|
|
602
|
+
* invalid, or holds an unusable credential; reconnect it) and `connected-account-unsupported`
|
|
603
|
+
* (`WorkspaceConflictError`, 409: the account cannot serve what was asked, as a Codex API key cannot
|
|
604
|
+
* be pi's or opencode's ChatGPT login). Nothing was written either way.
|
|
605
|
+
*/
|
|
606
|
+
export const connectedAccountRefusalCodes = [
|
|
607
|
+
"connected-account-missing",
|
|
608
|
+
"connected-account-invalid",
|
|
609
|
+
"connected-account-unsupported",
|
|
610
|
+
];
|
|
611
|
+
/**
|
|
612
|
+
* The providers a home holds logins for (docs/connected-accounts-design.md §6c). `pi` and
|
|
613
|
+
* `opencode` are the person's ChatGPT login (a Codex connected account), written into each tool's
|
|
614
|
+
* own `auth.json`.
|
|
615
|
+
*/
|
|
616
|
+
export const workspaceCredentialHomeProviders = [
|
|
617
|
+
"claude",
|
|
618
|
+
"codex",
|
|
619
|
+
"github",
|
|
620
|
+
"pi",
|
|
621
|
+
"opencode",
|
|
622
|
+
];
|
|
623
|
+
/** The connected account's provider each home provider's login is made from. */
|
|
624
|
+
export const workspaceCredentialHomeAccountProvider = { claude: "claude", codex: "codex", github: "github", pi: "codex", opencode: "codex" };
|
|
522
625
|
/**
|
|
523
626
|
* Put one person's logins into one home of a RUNNING workspace (docs/connected-accounts-design.md
|
|
524
627
|
* §6c). A home holds one person's logins while it is held: the first put names its person, a put
|
|
@@ -550,6 +653,25 @@ export const putWorkspaceCredentialsRequestSchema = Schema.Struct({
|
|
|
550
653
|
claude: Schema.optional(Schema.NullOr(NonEmptyString)),
|
|
551
654
|
codex: Schema.optional(Schema.NullOr(NonEmptyString)),
|
|
552
655
|
github: Schema.optional(Schema.NullOr(NonEmptyString)),
|
|
656
|
+
/**
|
|
657
|
+
* pi's ChatGPT login, made from a Codex account of `onBehalfOfUserId` (an id or a Codex account
|
|
658
|
+
* name), as the `openai-codex` entry of `<home>/.pi/agent/auth.json`. The file is merged: its
|
|
659
|
+
* other entries stay, and an `openai-codex` login the person made in pi is never replaced.
|
|
660
|
+
*/
|
|
661
|
+
pi: Schema.optional(Schema.NullOr(NonEmptyString)),
|
|
662
|
+
/**
|
|
663
|
+
* opencode's ChatGPT login, made the same way, as the `openai` entry of opencode's `auth.json`
|
|
664
|
+
* (`<home>/.local/share/opencode/auth.json`, followed through links to where it really is, which
|
|
665
|
+
* must be inside the home). A login the person made in opencode is never replaced or removed.
|
|
666
|
+
*/
|
|
667
|
+
opencode: Schema.optional(Schema.NullOr(NonEmptyString)),
|
|
668
|
+
/**
|
|
669
|
+
* Write what the person has connected and leave out the rest: a provider whose account is refused
|
|
670
|
+
* (`connected-account-missing`, `-invalid` or `-unsupported`) is not written, its login is removed
|
|
671
|
+
* from the home as `null` would remove it, and the answer's `skipped` says which and why, instead
|
|
672
|
+
* of the whole put failing. Every other refusal still fails the put. Default false.
|
|
673
|
+
*/
|
|
674
|
+
partial: Schema.optional(Schema.Boolean),
|
|
553
675
|
});
|
|
554
676
|
/** One account whose copy a home holds. */
|
|
555
677
|
export const workspaceHomeAccountSchema = Schema.Struct({
|
|
@@ -567,14 +689,31 @@ export const workspaceCredentialHomeSchema = Schema.Struct({
|
|
|
567
689
|
claude: Schema.optional(workspaceHomeAccountSchema),
|
|
568
690
|
codex: Schema.optional(workspaceHomeAccountSchema),
|
|
569
691
|
github: Schema.optional(workspaceHomeAccountSchema),
|
|
692
|
+
/** The Codex account pi's ChatGPT login is made from. */
|
|
693
|
+
pi: Schema.optional(workspaceHomeAccountSchema),
|
|
694
|
+
/** The Codex account opencode's ChatGPT login is made from. */
|
|
695
|
+
opencode: Schema.optional(workspaceHomeAccountSchema),
|
|
570
696
|
}),
|
|
571
697
|
});
|
|
698
|
+
/** A provider a partial put left out, and why (its account's refusal). */
|
|
699
|
+
export const workspaceCredentialSkipSchema = Schema.Struct({
|
|
700
|
+
provider: Schema.Literals(workspaceCredentialHomeProviders),
|
|
701
|
+
/**
|
|
702
|
+
* The account's refusal, or `login-file-unusable`: pi's or opencode's `auth.json` in the home
|
|
703
|
+
* cannot be written there (not a regular file, or really outside the home).
|
|
704
|
+
*/
|
|
705
|
+
code: Schema.Literals([...connectedAccountRefusalCodes, "login-file-unusable"]),
|
|
706
|
+
/** The refusal's words, as a whole put would have answered them. */
|
|
707
|
+
message: Schema.String,
|
|
708
|
+
});
|
|
572
709
|
export const putWorkspaceCredentialsResponseSchema = Schema.Struct({
|
|
573
710
|
workspaceId: NonEmptyString,
|
|
574
711
|
/** The launch attempt whose executor was written. */
|
|
575
712
|
runId: NonEmptyString,
|
|
576
713
|
/** The home as it is after the put. */
|
|
577
714
|
home: workspaceCredentialHomeSchema,
|
|
715
|
+
/** A partial put's left-out providers, in the order named (empty when all were written). */
|
|
716
|
+
skipped: Schema.optional(Schema.Array(workspaceCredentialSkipSchema)),
|
|
578
717
|
});
|
|
579
718
|
/** Release one home: its login files are removed and its record deleted. */
|
|
580
719
|
export const releaseWorkspaceCredentialsQuerySchema = Schema.Struct({
|
|
@@ -600,7 +739,9 @@ export const listWorkspaceCredentialsResponseSchema = Schema.Struct({
|
|
|
600
739
|
/**
|
|
601
740
|
* Stable `code`s of the `WorkspaceConflictError` the credential routes answer:
|
|
602
741
|
* `workspace-not-running` (no ready executor), `connected-account-invalid` (a named account is
|
|
603
|
-
* marked invalid: reconnect it
|
|
742
|
+
* marked invalid or unusable: reconnect it; `provider` names its provider),
|
|
743
|
+
* `connected-account-unsupported` (a Codex account named for pi or opencode is not a ChatGPT
|
|
744
|
+
* login), `home-held` (the home holds another person's logins: release it
|
|
604
745
|
* first; `/root` while the launch's own logins are at `$HOME`, or for anyone but the workspace's
|
|
605
746
|
* owner), `home-unusable` (the home does not exist, is not a directory, is reached through a
|
|
606
747
|
* symbolic link, or a login directory in it links outside it), `home-busy` (another write into the
|
|
@@ -609,6 +750,7 @@ export const listWorkspaceCredentialsResponseSchema = Schema.Struct({
|
|
|
609
750
|
export const workspaceCredentialsConflictCodes = [
|
|
610
751
|
"workspace-not-running",
|
|
611
752
|
"connected-account-invalid",
|
|
753
|
+
"connected-account-unsupported",
|
|
612
754
|
"home-held",
|
|
613
755
|
"home-unusable",
|
|
614
756
|
"home-busy",
|
|
@@ -907,12 +1049,18 @@ export class WorkspaceForbiddenError extends Schema.TaggedErrorClass()("Workspac
|
|
|
907
1049
|
}
|
|
908
1050
|
export class WorkspaceNotFoundError extends Schema.TaggedErrorClass()("WorkspaceNotFoundError", {
|
|
909
1051
|
message: Schema.String,
|
|
1052
|
+
/** A stable reason, where one applies (`connected-account-missing`). */
|
|
1053
|
+
code: Schema.optional(NonEmptyString),
|
|
1054
|
+
/** The provider of the connected account the reason is about. */
|
|
1055
|
+
provider: Schema.optional(connectedAccountProviderSchema),
|
|
910
1056
|
}, { httpApiStatus: 404 }) {
|
|
911
1057
|
}
|
|
912
1058
|
export class WorkspaceConflictError extends Schema.TaggedErrorClass()("WorkspaceConflictError", {
|
|
913
1059
|
message: Schema.String,
|
|
914
1060
|
/** A stable reason, where one applies (`create-cancelled`: the create's key was cancelled). */
|
|
915
1061
|
code: Schema.optional(NonEmptyString),
|
|
1062
|
+
/** The provider of the connected account the reason is about (`connected-account-invalid`). */
|
|
1063
|
+
provider: Schema.optional(connectedAccountProviderSchema),
|
|
916
1064
|
}, { httpApiStatus: 409 }) {
|
|
917
1065
|
}
|
|
918
1066
|
export class WorkspaceBadGatewayError extends Schema.TaggedErrorClass()("WorkspaceBadGatewayError", {
|
|
@@ -1041,6 +1189,27 @@ HttpApiEndpoint.post("execWorkspace", "/:workspaceId/exec", {
|
|
|
1041
1189
|
],
|
|
1042
1190
|
}))
|
|
1043
1191
|
.add(
|
|
1192
|
+
// Async like exec: 202 + the queued run once the archives are staged; poll `GET /v1/runs/:runId`.
|
|
1193
|
+
HttpApiEndpoint.post("applyWorkspaceDotfiles", "/:workspaceId/dotfiles", {
|
|
1194
|
+
params: workspaceIdParams,
|
|
1195
|
+
payload: applyWorkspaceDotfilesRequestSchema,
|
|
1196
|
+
success: runSchema.pipe(HttpApiSchema.status(202)),
|
|
1197
|
+
error: [
|
|
1198
|
+
// Root, a malformed home, a URL with a credential, or nothing to apply.
|
|
1199
|
+
WorkspaceBadRequestError,
|
|
1200
|
+
// Only a service key may apply a person's dotfiles.
|
|
1201
|
+
WorkspaceForbiddenError,
|
|
1202
|
+
WorkspaceNotFoundError,
|
|
1203
|
+
// See `workspaceDotfilesConflictCodes`.
|
|
1204
|
+
WorkspaceConflictError,
|
|
1205
|
+
// The executor did not confirm the staging.
|
|
1206
|
+
WorkspaceBadGatewayError,
|
|
1207
|
+
// Core cannot reach the executor.
|
|
1208
|
+
WorkspaceServiceUnavailableError,
|
|
1209
|
+
WorkspaceInternalServerError,
|
|
1210
|
+
],
|
|
1211
|
+
}))
|
|
1212
|
+
.add(
|
|
1044
1213
|
// Async: 202 = the stop was accepted and enqueued; the worker removes the container and the
|
|
1045
1214
|
// workspace transitions to "stopped". Idempotent — stopping a stopped workspace is a no-op 202.
|
|
1046
1215
|
HttpApiEndpoint.post("stopWorkspace", "/:workspaceId/stop", {
|
|
@@ -1106,7 +1275,7 @@ HttpApiEndpoint.post("putWorkspaceCredentials", "/:workspaceId/credentials", {
|
|
|
1106
1275
|
WorkspaceBadRequestError,
|
|
1107
1276
|
// The caller may not act for the people named (only a service key may).
|
|
1108
1277
|
WorkspaceForbiddenError,
|
|
1109
|
-
// The workspace or a named account (
|
|
1278
|
+
// The workspace, or a named account (`connected-account-missing` with its `provider`).
|
|
1110
1279
|
WorkspaceNotFoundError,
|
|
1111
1280
|
// See `workspaceCredentialsConflictCodes`.
|
|
1112
1281
|
WorkspaceConflictError,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealant/api-contracts-next",
|
|
3
|
-
"version": "0.39.0-next.
|
|
3
|
+
"version": "0.39.0-next.700",
|
|
4
4
|
"description": "Contract-first HTTP API definitions for Sealant services",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"effect": ">=4.0.0-beta.85 <5"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "78e1763231f005b670f7291cfb86917cec639598",
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
}
|