@sealant/sdk 0.20.2 → 0.22.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/dist/client.d.ts +5 -1
- package/dist/client.js +57 -15
- package/dist/effect/api-client.d.ts +98 -0
- package/dist/effect/exec-workspace.js +2 -2
- package/dist/effect/index.d.ts +1 -1
- package/dist/effect/index.js +1 -1
- package/dist/effect/operations.d.ts +80 -4
- package/dist/effect/operations.js +18 -4
- package/dist/effect/run-harness.js +3 -3
- package/dist/facade/record.js +20 -7
- package/dist/facade/run.js +3 -2
- package/dist/facade/session.d.ts +1 -0
- package/dist/facade/session.js +1 -0
- package/dist/facade/workspace.js +6 -5
- package/dist/internal/config.d.ts +3 -3
- package/dist/internal/config.js +1 -1
- package/dist/types.d.ts +88 -4
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccessTokensNamespace, CreateOptions, InferenceNamespace, ListOptions, Run, Workspace, SealantConfig } from "./types.js";
|
|
1
|
+
import type { AccessTokensNamespace, ConnectedAccountsNamespace, CreateOptions, InferenceNamespace, ListOptions, Run, Workspace, SealantConfig, UsersNamespace } from "./types.js";
|
|
2
2
|
export declare class Sealant {
|
|
3
3
|
#private;
|
|
4
4
|
constructor(config: SealantConfig);
|
|
@@ -21,6 +21,10 @@ export declare class Sealant {
|
|
|
21
21
|
* the session endpoints enforce exactly those scopes (a read-stream token can stream but is
|
|
22
22
|
* rejected for input and exec).
|
|
23
23
|
*/
|
|
24
|
+
/** Identity rows for products that own their own login (one client per user afterwards). */
|
|
25
|
+
readonly users: UsersNamespace;
|
|
26
|
+
/** This client's owner's Claude / Codex / GitHub accounts. Secrets go in; none come out. */
|
|
27
|
+
readonly connectedAccounts: ConnectedAccountsNamespace;
|
|
24
28
|
readonly accessTokens: AccessTokensNamespace;
|
|
25
29
|
/** Runs by id — so a record can be replayed long after its workspace is gone. */
|
|
26
30
|
readonly runs: {
|
package/dist/client.js
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* `Sealant` — the public client and the import users reach for.
|
|
3
|
-
*
|
|
4
|
-
* import { Sealant, opencode } from "@sealant/sdk"
|
|
5
|
-
* const sealant = new Sealant({ baseUrl: "http://localhost:8080" })
|
|
6
|
-
*
|
|
7
|
-
* This is the plain-Promise facade over the Effect core: an app `Layer` built once in the
|
|
8
|
-
* constructor providing the wire client derived from `@sealant/api-contracts`. Everything is a plain
|
|
9
|
-
* HTTP call to `baseUrl`. Operations whose endpoints have not landed yet stay TYPED against the
|
|
10
|
-
* stable surface and reject with `SealantNotImplementedError` so callers can compile and wire
|
|
11
|
-
* against the final shape today.
|
|
12
|
-
*/
|
|
13
|
-
import { createAccessTokenOp, createWorkspaceOp, getRunOp, getWorkspaceOp, inferenceRespondOp, listWorkspacesOp, } from "./effect/operations.js";
|
|
1
|
+
import { archiveConnectedAccountOp, createAccessTokenOp, createConnectedAccountOp, createWorkspaceOp, ensureUserOp, getRunOp, getUserOp, getWorkspaceOp, inferenceRespondOp, listConnectedAccountsOp, listWorkspacesOp, } from "./effect/operations.js";
|
|
14
2
|
import { runHarness, startHarness } from "./effect/run-harness.js";
|
|
15
3
|
import { makeSdkRuntime } from "./effect/runtime.js";
|
|
16
4
|
import { SealantError } from "./errors.js";
|
|
@@ -20,6 +8,19 @@ import { buildCreateWorkspaceRequest } from "./internal/blueprint.js";
|
|
|
20
8
|
import { resolveInternalConfig } from "./internal/config.js";
|
|
21
9
|
import { parseTtlSeconds } from "./internal/duration.js";
|
|
22
10
|
import { buildInferenceRespondRequest, mapInferenceResponse } from "./internal/inference.js";
|
|
11
|
+
const mapConnectedAccount = (wire) => ({
|
|
12
|
+
connectedAccountId: wire.connectedAccountId,
|
|
13
|
+
ownerUserId: wire.ownerUserId,
|
|
14
|
+
provider: wire.provider,
|
|
15
|
+
name: wire.name,
|
|
16
|
+
kind: wire.kind,
|
|
17
|
+
status: wire.status,
|
|
18
|
+
metadata: wire.metadata,
|
|
19
|
+
connectedAt: wire.connectedAt,
|
|
20
|
+
updatedAt: wire.updatedAt,
|
|
21
|
+
lastUsedAt: wire.lastUsedAt,
|
|
22
|
+
lastSyncedAt: wire.lastSyncedAt,
|
|
23
|
+
});
|
|
23
24
|
// Wire the run-execution implementations into the Workspace facade (the injection point exists to
|
|
24
25
|
// break the workspace <-> run-harness import cycle; the client is the composition root).
|
|
25
26
|
registerHarnessExecutors({ run: runHarness, start: startHarness });
|
|
@@ -72,7 +73,7 @@ export class Sealant {
|
|
|
72
73
|
return workspace.ready();
|
|
73
74
|
},
|
|
74
75
|
get: async (id) => {
|
|
75
|
-
const details = await this.#runtime.run(getWorkspaceOp(id));
|
|
76
|
+
const details = await this.#runtime.run(getWorkspaceOp(id, this.#ctx.config.hostLocal.ownerUserId));
|
|
76
77
|
return makeWorkspace(this.#ctx, {
|
|
77
78
|
id: details.workspaceId,
|
|
78
79
|
name: details.name,
|
|
@@ -109,6 +110,47 @@ export class Sealant {
|
|
|
109
110
|
* the session endpoints enforce exactly those scopes (a read-stream token can stream but is
|
|
110
111
|
* rejected for input and exec).
|
|
111
112
|
*/
|
|
113
|
+
/** Identity rows for products that own their own login (one client per user afterwards). */
|
|
114
|
+
users = {
|
|
115
|
+
ensure: async (options) => {
|
|
116
|
+
const wire = await this.#runtime.run(ensureUserOp({
|
|
117
|
+
email: options.email,
|
|
118
|
+
name: options.name,
|
|
119
|
+
...(options.userId === undefined ? {} : { userId: options.userId }),
|
|
120
|
+
}));
|
|
121
|
+
return {
|
|
122
|
+
userId: wire.userId,
|
|
123
|
+
email: wire.email,
|
|
124
|
+
name: wire.name,
|
|
125
|
+
createdAt: wire.createdAt,
|
|
126
|
+
created: wire.created,
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
get: async (userId) => {
|
|
130
|
+
const wire = await this.#runtime.run(getUserOp(userId));
|
|
131
|
+
return { userId: wire.userId, email: wire.email, name: wire.name, createdAt: wire.createdAt };
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
/** This client's owner's Claude / Codex / GitHub accounts. Secrets go in; none come out. */
|
|
135
|
+
connectedAccounts = {
|
|
136
|
+
list: async () => {
|
|
137
|
+
const wire = await this.#runtime.run(listConnectedAccountsOp(this.#ctx.config.hostLocal.ownerUserId));
|
|
138
|
+
return wire.items.map(mapConnectedAccount);
|
|
139
|
+
},
|
|
140
|
+
connect: async (options) => {
|
|
141
|
+
const wire = await this.#runtime.run(createConnectedAccountOp({
|
|
142
|
+
ownerUserId: this.#ctx.config.hostLocal.ownerUserId,
|
|
143
|
+
provider: options.provider,
|
|
144
|
+
secret: options.secret,
|
|
145
|
+
...(options.name === undefined ? {} : { name: options.name }),
|
|
146
|
+
}));
|
|
147
|
+
return mapConnectedAccount(wire);
|
|
148
|
+
},
|
|
149
|
+
disconnect: async (connectedAccountId) => {
|
|
150
|
+
const wire = await this.#runtime.run(archiveConnectedAccountOp(connectedAccountId, this.#ctx.config.hostLocal.ownerUserId));
|
|
151
|
+
return mapConnectedAccount(wire);
|
|
152
|
+
},
|
|
153
|
+
};
|
|
112
154
|
accessTokens = {
|
|
113
155
|
create: async (options) => {
|
|
114
156
|
const wire = await this.#runtime.run(createAccessTokenOp({
|
|
@@ -130,7 +172,7 @@ export class Sealant {
|
|
|
130
172
|
/** Runs by id — so a record can be replayed long after its workspace is gone. */
|
|
131
173
|
runs = {
|
|
132
174
|
get: async (runId) => {
|
|
133
|
-
const wire = await this.#runtime.run(getRunOp(runId));
|
|
175
|
+
const wire = await this.#runtime.run(getRunOp(runId, this.#ctx.config.hostLocal.ownerUserId));
|
|
134
176
|
return makeRun(this.#ctx, { wire });
|
|
135
177
|
},
|
|
136
178
|
};
|
|
@@ -537,6 +537,9 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
537
537
|
readonly params: {
|
|
538
538
|
readonly runId: string;
|
|
539
539
|
};
|
|
540
|
+
readonly query: {
|
|
541
|
+
readonly ownerUserId?: string | undefined;
|
|
542
|
+
};
|
|
540
543
|
readonly responseMode?: Mode;
|
|
541
544
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
542
545
|
readonly runId: string;
|
|
@@ -566,6 +569,9 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
566
569
|
readonly params: {
|
|
567
570
|
readonly runId: string;
|
|
568
571
|
};
|
|
572
|
+
readonly query: {
|
|
573
|
+
readonly ownerUserId?: string | undefined;
|
|
574
|
+
};
|
|
569
575
|
readonly responseMode?: Mode;
|
|
570
576
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
571
577
|
readonly files: readonly {
|
|
@@ -580,6 +586,9 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
580
586
|
readonly runId: string;
|
|
581
587
|
readonly sequence: string;
|
|
582
588
|
};
|
|
589
|
+
readonly query: {
|
|
590
|
+
readonly ownerUserId?: string | undefined;
|
|
591
|
+
};
|
|
583
592
|
readonly responseMode?: Mode;
|
|
584
593
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
585
594
|
readonly eventId: string;
|
|
@@ -603,6 +612,9 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
603
612
|
readonly params: {
|
|
604
613
|
readonly runId: string;
|
|
605
614
|
};
|
|
615
|
+
readonly query: {
|
|
616
|
+
readonly ownerUserId?: string | undefined;
|
|
617
|
+
};
|
|
606
618
|
readonly responseMode?: Mode;
|
|
607
619
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
608
620
|
readonly runId: string;
|
|
@@ -624,6 +636,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
624
636
|
readonly runId: string;
|
|
625
637
|
};
|
|
626
638
|
readonly query: {
|
|
639
|
+
readonly ownerUserId?: string | undefined;
|
|
627
640
|
readonly processId: string;
|
|
628
641
|
readonly stream: "pty" | "stderr" | "stdout";
|
|
629
642
|
readonly atSequence?: string | undefined;
|
|
@@ -642,6 +655,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
642
655
|
readonly runId: string;
|
|
643
656
|
};
|
|
644
657
|
readonly query: {
|
|
658
|
+
readonly ownerUserId?: string | undefined;
|
|
645
659
|
readonly fromSequence?: string | undefined;
|
|
646
660
|
readonly toSequence?: string | undefined;
|
|
647
661
|
readonly limit?: string | undefined;
|
|
@@ -758,6 +772,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
758
772
|
readonly cwd?: string | undefined;
|
|
759
773
|
readonly cols: number;
|
|
760
774
|
readonly rows: number;
|
|
775
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
761
776
|
readonly exitCode?: number | undefined;
|
|
762
777
|
readonly exitSignal?: number | undefined;
|
|
763
778
|
readonly errorMessage?: string | undefined;
|
|
@@ -783,6 +798,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
783
798
|
readonly cols?: number | undefined;
|
|
784
799
|
readonly rows?: number | undefined;
|
|
785
800
|
readonly term?: string | undefined;
|
|
801
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
786
802
|
readonly metadata?: {
|
|
787
803
|
readonly [x: string]: unknown;
|
|
788
804
|
} | undefined;
|
|
@@ -798,6 +814,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
798
814
|
readonly cwd?: string | undefined;
|
|
799
815
|
readonly cols: number;
|
|
800
816
|
readonly rows: number;
|
|
817
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
801
818
|
readonly exitCode?: number | undefined;
|
|
802
819
|
readonly exitSignal?: number | undefined;
|
|
803
820
|
readonly errorMessage?: string | undefined;
|
|
@@ -829,6 +846,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
829
846
|
readonly cwd?: string | undefined;
|
|
830
847
|
readonly cols: number;
|
|
831
848
|
readonly rows: number;
|
|
849
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
832
850
|
readonly exitCode?: number | undefined;
|
|
833
851
|
readonly exitSignal?: number | undefined;
|
|
834
852
|
readonly errorMessage?: string | undefined;
|
|
@@ -883,6 +901,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
883
901
|
readonly cwd?: string | undefined;
|
|
884
902
|
readonly cols: number;
|
|
885
903
|
readonly rows: number;
|
|
904
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
886
905
|
readonly exitCode?: number | undefined;
|
|
887
906
|
readonly exitSignal?: number | undefined;
|
|
888
907
|
readonly errorMessage?: string | undefined;
|
|
@@ -1033,6 +1052,33 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1033
1052
|
readonly status: "ok";
|
|
1034
1053
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError), [Mode] extends ["response-only"] ? never : never>;
|
|
1035
1054
|
};
|
|
1055
|
+
readonly users: {
|
|
1056
|
+
readonly ensureUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1057
|
+
readonly payload: {
|
|
1058
|
+
readonly email: string;
|
|
1059
|
+
readonly name: string;
|
|
1060
|
+
readonly userId?: string | undefined;
|
|
1061
|
+
};
|
|
1062
|
+
readonly responseMode?: Mode;
|
|
1063
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1064
|
+
readonly userId: string;
|
|
1065
|
+
readonly email: string;
|
|
1066
|
+
readonly name: string;
|
|
1067
|
+
readonly createdAt: string;
|
|
1068
|
+
readonly created: boolean;
|
|
1069
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError), [Mode] extends ["response-only"] ? never : never>;
|
|
1070
|
+
readonly getUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1071
|
+
readonly params: {
|
|
1072
|
+
readonly userId: string;
|
|
1073
|
+
};
|
|
1074
|
+
readonly responseMode?: Mode;
|
|
1075
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1076
|
+
readonly userId: string;
|
|
1077
|
+
readonly email: string;
|
|
1078
|
+
readonly name: string;
|
|
1079
|
+
readonly createdAt: string;
|
|
1080
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserInternalServerError | import("@sealant/api-contracts").UserNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1081
|
+
};
|
|
1036
1082
|
readonly workspaces: {
|
|
1037
1083
|
readonly createWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1038
1084
|
readonly headers: {
|
|
@@ -1131,6 +1177,9 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
1131
1177
|
readonly params: {
|
|
1132
1178
|
readonly workspaceId: string;
|
|
1133
1179
|
};
|
|
1180
|
+
readonly query: {
|
|
1181
|
+
readonly ownerUserId?: string | undefined;
|
|
1182
|
+
};
|
|
1134
1183
|
readonly responseMode?: Mode;
|
|
1135
1184
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1136
1185
|
readonly workspaceId: string;
|
|
@@ -1858,6 +1907,9 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1858
1907
|
readonly params: {
|
|
1859
1908
|
readonly runId: string;
|
|
1860
1909
|
};
|
|
1910
|
+
readonly query: {
|
|
1911
|
+
readonly ownerUserId?: string | undefined;
|
|
1912
|
+
};
|
|
1861
1913
|
readonly responseMode?: Mode;
|
|
1862
1914
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1863
1915
|
readonly runId: string;
|
|
@@ -1887,6 +1939,9 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1887
1939
|
readonly params: {
|
|
1888
1940
|
readonly runId: string;
|
|
1889
1941
|
};
|
|
1942
|
+
readonly query: {
|
|
1943
|
+
readonly ownerUserId?: string | undefined;
|
|
1944
|
+
};
|
|
1890
1945
|
readonly responseMode?: Mode;
|
|
1891
1946
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1892
1947
|
readonly files: readonly {
|
|
@@ -1901,6 +1956,9 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1901
1956
|
readonly runId: string;
|
|
1902
1957
|
readonly sequence: string;
|
|
1903
1958
|
};
|
|
1959
|
+
readonly query: {
|
|
1960
|
+
readonly ownerUserId?: string | undefined;
|
|
1961
|
+
};
|
|
1904
1962
|
readonly responseMode?: Mode;
|
|
1905
1963
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1906
1964
|
readonly eventId: string;
|
|
@@ -1924,6 +1982,9 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1924
1982
|
readonly params: {
|
|
1925
1983
|
readonly runId: string;
|
|
1926
1984
|
};
|
|
1985
|
+
readonly query: {
|
|
1986
|
+
readonly ownerUserId?: string | undefined;
|
|
1987
|
+
};
|
|
1927
1988
|
readonly responseMode?: Mode;
|
|
1928
1989
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1929
1990
|
readonly runId: string;
|
|
@@ -1945,6 +2006,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1945
2006
|
readonly runId: string;
|
|
1946
2007
|
};
|
|
1947
2008
|
readonly query: {
|
|
2009
|
+
readonly ownerUserId?: string | undefined;
|
|
1948
2010
|
readonly processId: string;
|
|
1949
2011
|
readonly stream: "pty" | "stderr" | "stdout";
|
|
1950
2012
|
readonly atSequence?: string | undefined;
|
|
@@ -1963,6 +2025,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1963
2025
|
readonly runId: string;
|
|
1964
2026
|
};
|
|
1965
2027
|
readonly query: {
|
|
2028
|
+
readonly ownerUserId?: string | undefined;
|
|
1966
2029
|
readonly fromSequence?: string | undefined;
|
|
1967
2030
|
readonly toSequence?: string | undefined;
|
|
1968
2031
|
readonly limit?: string | undefined;
|
|
@@ -2079,6 +2142,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2079
2142
|
readonly cwd?: string | undefined;
|
|
2080
2143
|
readonly cols: number;
|
|
2081
2144
|
readonly rows: number;
|
|
2145
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
2082
2146
|
readonly exitCode?: number | undefined;
|
|
2083
2147
|
readonly exitSignal?: number | undefined;
|
|
2084
2148
|
readonly errorMessage?: string | undefined;
|
|
@@ -2104,6 +2168,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2104
2168
|
readonly cols?: number | undefined;
|
|
2105
2169
|
readonly rows?: number | undefined;
|
|
2106
2170
|
readonly term?: string | undefined;
|
|
2171
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
2107
2172
|
readonly metadata?: {
|
|
2108
2173
|
readonly [x: string]: unknown;
|
|
2109
2174
|
} | undefined;
|
|
@@ -2119,6 +2184,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2119
2184
|
readonly cwd?: string | undefined;
|
|
2120
2185
|
readonly cols: number;
|
|
2121
2186
|
readonly rows: number;
|
|
2187
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
2122
2188
|
readonly exitCode?: number | undefined;
|
|
2123
2189
|
readonly exitSignal?: number | undefined;
|
|
2124
2190
|
readonly errorMessage?: string | undefined;
|
|
@@ -2150,6 +2216,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2150
2216
|
readonly cwd?: string | undefined;
|
|
2151
2217
|
readonly cols: number;
|
|
2152
2218
|
readonly rows: number;
|
|
2219
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
2153
2220
|
readonly exitCode?: number | undefined;
|
|
2154
2221
|
readonly exitSignal?: number | undefined;
|
|
2155
2222
|
readonly errorMessage?: string | undefined;
|
|
@@ -2204,6 +2271,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2204
2271
|
readonly cwd?: string | undefined;
|
|
2205
2272
|
readonly cols: number;
|
|
2206
2273
|
readonly rows: number;
|
|
2274
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
2207
2275
|
readonly exitCode?: number | undefined;
|
|
2208
2276
|
readonly exitSignal?: number | undefined;
|
|
2209
2277
|
readonly errorMessage?: string | undefined;
|
|
@@ -2354,6 +2422,33 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2354
2422
|
readonly status: "ok";
|
|
2355
2423
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError), [Mode] extends ["response-only"] ? never : never>;
|
|
2356
2424
|
};
|
|
2425
|
+
readonly users: {
|
|
2426
|
+
readonly ensureUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
2427
|
+
readonly payload: {
|
|
2428
|
+
readonly email: string;
|
|
2429
|
+
readonly name: string;
|
|
2430
|
+
readonly userId?: string | undefined;
|
|
2431
|
+
};
|
|
2432
|
+
readonly responseMode?: Mode;
|
|
2433
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
2434
|
+
readonly userId: string;
|
|
2435
|
+
readonly email: string;
|
|
2436
|
+
readonly name: string;
|
|
2437
|
+
readonly createdAt: string;
|
|
2438
|
+
readonly created: boolean;
|
|
2439
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError), [Mode] extends ["response-only"] ? never : never>;
|
|
2440
|
+
readonly getUser: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
2441
|
+
readonly params: {
|
|
2442
|
+
readonly userId: string;
|
|
2443
|
+
};
|
|
2444
|
+
readonly responseMode?: Mode;
|
|
2445
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
2446
|
+
readonly userId: string;
|
|
2447
|
+
readonly email: string;
|
|
2448
|
+
readonly name: string;
|
|
2449
|
+
readonly createdAt: string;
|
|
2450
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserInternalServerError | import("@sealant/api-contracts").UserNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
2451
|
+
};
|
|
2357
2452
|
readonly workspaces: {
|
|
2358
2453
|
readonly createWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
2359
2454
|
readonly headers: {
|
|
@@ -2452,6 +2547,9 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
2452
2547
|
readonly params: {
|
|
2453
2548
|
readonly workspaceId: string;
|
|
2454
2549
|
};
|
|
2550
|
+
readonly query: {
|
|
2551
|
+
readonly ownerUserId?: string | undefined;
|
|
2552
|
+
};
|
|
2455
2553
|
readonly responseMode?: Mode;
|
|
2456
2554
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
2457
2555
|
readonly workspaceId: string;
|
|
@@ -37,7 +37,7 @@ const execWorkspaceEffect = (ctx, init, argv, options) => Effect.gen(function* (
|
|
|
37
37
|
}));
|
|
38
38
|
}
|
|
39
39
|
yield* Effect.sleep(POLL_INTERVAL);
|
|
40
|
-
wire = yield* getRunOp(runId);
|
|
40
|
+
wire = yield* getRunOp(runId, ctx.config.hostLocal.ownerUserId);
|
|
41
41
|
}
|
|
42
42
|
// Exec framing: "completed" means every command executed and was recorded — anything else means
|
|
43
43
|
// the machinery broke and the exit code cannot be trusted, which IS the error case.
|
|
@@ -48,7 +48,7 @@ const execWorkspaceEffect = (ctx, init, argv, options) => Effect.gen(function* (
|
|
|
48
48
|
const processId = findCommandProcessId(started, executable);
|
|
49
49
|
const stdout = processId === undefined ? "" : yield* readScrollback(runId, processId, "stdout");
|
|
50
50
|
const stderr = processId === undefined ? "" : yield* readScrollback(runId, processId, "stderr");
|
|
51
|
-
const changes = toRunChangesData(yield* getRunChangesOp(runId));
|
|
51
|
+
const changes = toRunChangesData(yield* getRunChangesOp(runId, ctx.config.hostLocal.ownerUserId));
|
|
52
52
|
return {
|
|
53
53
|
exitCode: wire.exitCode ?? -1,
|
|
54
54
|
stdout,
|
package/dist/effect/index.d.ts
CHANGED
|
@@ -24,4 +24,4 @@ export { makeSdkRuntime } from "./runtime.js";
|
|
|
24
24
|
export type { SdkRuntime, SdkServices } from "./runtime.js";
|
|
25
25
|
export { resolveInternalConfig } from "../internal/config.js";
|
|
26
26
|
export type { SealantHostLocalConfig, SealantInternalConfig } from "../internal/config.js";
|
|
27
|
-
export { InferenceBadRequestError, InferenceConflictError, InferenceInternalServerError, InferenceNotFoundError, InferenceUnavailableError, RunBadRequestError, RunInternalServerError, RunNotFoundError, WorkspaceBadGatewayError, WorkspaceBadRequestError, WorkspaceConflictError, WorkspaceForbiddenError, WorkspaceInternalServerError, WorkspaceNotFoundError, WorkspaceServiceUnavailableError, WorkspaceUnauthorizedError, } from "@sealant/api-contracts";
|
|
27
|
+
export { ConnectedAccountBadRequestError, ConnectedAccountConflictError, ConnectedAccountInternalServerError, ConnectedAccountNotFoundError, ConnectedAccountServiceUnavailableError, InferenceBadRequestError, InferenceConflictError, InferenceInternalServerError, InferenceNotFoundError, InferenceUnavailableError, RunBadRequestError, RunInternalServerError, RunNotFoundError, UserBadRequestError, UserInternalServerError, UserNotFoundError, WorkspaceBadGatewayError, WorkspaceBadRequestError, WorkspaceConflictError, WorkspaceForbiddenError, WorkspaceInternalServerError, WorkspaceNotFoundError, WorkspaceServiceUnavailableError, WorkspaceUnauthorizedError, } from "@sealant/api-contracts";
|
package/dist/effect/index.js
CHANGED
|
@@ -28,4 +28,4 @@ export { resolveInternalConfig } from "../internal/config.js";
|
|
|
28
28
|
// The typed contract errors carried on the client's failure channel (workspaces + runs +
|
|
29
29
|
// inference — the groups the operations above call). Re-exported so Effect consumers don't need to
|
|
30
30
|
// depend on the contracts package directly to `Effect.catchTag` a failure.
|
|
31
|
-
export { InferenceBadRequestError, InferenceConflictError, InferenceInternalServerError, InferenceNotFoundError, InferenceUnavailableError, RunBadRequestError, RunInternalServerError, RunNotFoundError, WorkspaceBadGatewayError, WorkspaceBadRequestError, WorkspaceConflictError, WorkspaceForbiddenError, WorkspaceInternalServerError, WorkspaceNotFoundError, WorkspaceServiceUnavailableError, WorkspaceUnauthorizedError, } from "@sealant/api-contracts";
|
|
31
|
+
export { ConnectedAccountBadRequestError, ConnectedAccountConflictError, ConnectedAccountInternalServerError, ConnectedAccountNotFoundError, ConnectedAccountServiceUnavailableError, InferenceBadRequestError, InferenceConflictError, InferenceInternalServerError, InferenceNotFoundError, InferenceUnavailableError, RunBadRequestError, RunInternalServerError, RunNotFoundError, UserBadRequestError, UserInternalServerError, UserNotFoundError, WorkspaceBadGatewayError, WorkspaceBadRequestError, WorkspaceConflictError, WorkspaceForbiddenError, WorkspaceInternalServerError, WorkspaceNotFoundError, WorkspaceServiceUnavailableError, WorkspaceUnauthorizedError, } from "@sealant/api-contracts";
|
|
@@ -37,7 +37,7 @@ export declare const createWorkspaceOp: (payload: {
|
|
|
37
37
|
readonly repository: string;
|
|
38
38
|
readonly tag: string;
|
|
39
39
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceForbiddenError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError | import("@sealant/api-contracts").WorkspaceServiceUnavailableError, SealantApiClient>;
|
|
40
|
-
export declare const getWorkspaceOp: (workspaceId: string) => Effect.Effect<{
|
|
40
|
+
export declare const getWorkspaceOp: (workspaceId: string, ownerUserId?: string | undefined) => Effect.Effect<{
|
|
41
41
|
readonly workspaceId: string;
|
|
42
42
|
readonly name: string;
|
|
43
43
|
readonly ownerUserId: string;
|
|
@@ -194,7 +194,7 @@ export declare const createRunOp: (payload: {
|
|
|
194
194
|
readonly createdAt: string;
|
|
195
195
|
readonly updatedAt: string;
|
|
196
196
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RunBadRequestError | import("@sealant/api-contracts").RunInternalServerError | import("@sealant/api-contracts").RunNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
197
|
-
export declare const getRunOp: (runId: string) => Effect.Effect<{
|
|
197
|
+
export declare const getRunOp: (runId: string, ownerUserId?: string | undefined) => Effect.Effect<{
|
|
198
198
|
readonly runId: string;
|
|
199
199
|
readonly workspaceId: string;
|
|
200
200
|
readonly attemptId?: string | undefined;
|
|
@@ -284,6 +284,7 @@ export declare const updateRunOp: (runId: string, payload: {
|
|
|
284
284
|
readonly updatedAt: string;
|
|
285
285
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RunBadRequestError | import("@sealant/api-contracts").RunInternalServerError | import("@sealant/api-contracts").RunNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
286
286
|
export declare const getRunTimelineOp: (runId: string, query: {
|
|
287
|
+
readonly ownerUserId?: string | undefined;
|
|
287
288
|
readonly fromSequence?: string | undefined;
|
|
288
289
|
readonly toSequence?: string | undefined;
|
|
289
290
|
readonly limit?: string | undefined;
|
|
@@ -300,6 +301,7 @@ export declare const getRunTimelineOp: (runId: string, query: {
|
|
|
300
301
|
readonly confidence: number;
|
|
301
302
|
}[], import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RunBadRequestError | import("@sealant/api-contracts").RunInternalServerError | import("@sealant/api-contracts").RunNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
302
303
|
export declare const getRunScrollbackOp: (runId: string, query: {
|
|
304
|
+
readonly ownerUserId?: string | undefined;
|
|
303
305
|
readonly processId: string;
|
|
304
306
|
readonly stream: "pty" | "stderr" | "stdout";
|
|
305
307
|
readonly atSequence?: string | undefined;
|
|
@@ -311,7 +313,7 @@ export declare const getRunScrollbackOp: (runId: string, query: {
|
|
|
311
313
|
readonly byteCount: number;
|
|
312
314
|
readonly contentBase64: string;
|
|
313
315
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RunBadRequestError | import("@sealant/api-contracts").RunInternalServerError | import("@sealant/api-contracts").RunNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
314
|
-
export declare const getRunLossOp: (runId: string) => Effect.Effect<{
|
|
316
|
+
export declare const getRunLossOp: (runId: string, ownerUserId?: string | undefined) => Effect.Effect<{
|
|
315
317
|
readonly runId: string;
|
|
316
318
|
readonly droppedEventCount: string;
|
|
317
319
|
readonly sequenceGapCount: number;
|
|
@@ -326,7 +328,7 @@ export declare const getRunLossOp: (runId: string) => Effect.Effect<{
|
|
|
326
328
|
readonly reason?: string | undefined;
|
|
327
329
|
}[];
|
|
328
330
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("@sealant/api-contracts").RunInternalServerError | import("@sealant/api-contracts").RunNotFoundError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
329
|
-
export declare const getRunChangesOp: (runId: string) => Effect.Effect<{
|
|
331
|
+
export declare const getRunChangesOp: (runId: string, ownerUserId?: string | undefined) => Effect.Effect<{
|
|
330
332
|
readonly files: readonly {
|
|
331
333
|
readonly path: string;
|
|
332
334
|
readonly change: "added" | "deleted" | "modified" | "renamed";
|
|
@@ -345,6 +347,7 @@ export declare const createSessionOp: (payload: {
|
|
|
345
347
|
readonly cols?: number | undefined;
|
|
346
348
|
readonly rows?: number | undefined;
|
|
347
349
|
readonly term?: string | undefined;
|
|
350
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
348
351
|
readonly metadata?: {
|
|
349
352
|
readonly [x: string]: unknown;
|
|
350
353
|
} | undefined;
|
|
@@ -358,6 +361,7 @@ export declare const createSessionOp: (payload: {
|
|
|
358
361
|
readonly cwd?: string | undefined;
|
|
359
362
|
readonly cols: number;
|
|
360
363
|
readonly rows: number;
|
|
364
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
361
365
|
readonly exitCode?: number | undefined;
|
|
362
366
|
readonly exitSignal?: number | undefined;
|
|
363
367
|
readonly errorMessage?: string | undefined;
|
|
@@ -378,6 +382,7 @@ export declare const getSessionOp: (sessionId: string, ownerUserId?: string | un
|
|
|
378
382
|
readonly cwd?: string | undefined;
|
|
379
383
|
readonly cols: number;
|
|
380
384
|
readonly rows: number;
|
|
385
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
381
386
|
readonly exitCode?: number | undefined;
|
|
382
387
|
readonly exitSignal?: number | undefined;
|
|
383
388
|
readonly errorMessage?: string | undefined;
|
|
@@ -404,6 +409,7 @@ export declare const listSessionsOp: (query: {
|
|
|
404
409
|
readonly cwd?: string | undefined;
|
|
405
410
|
readonly cols: number;
|
|
406
411
|
readonly rows: number;
|
|
412
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
407
413
|
readonly exitCode?: number | undefined;
|
|
408
414
|
readonly exitSignal?: number | undefined;
|
|
409
415
|
readonly errorMessage?: string | undefined;
|
|
@@ -459,6 +465,7 @@ export declare const closeSessionOp: (sessionId: string, payload: {
|
|
|
459
465
|
readonly cwd?: string | undefined;
|
|
460
466
|
readonly cols: number;
|
|
461
467
|
readonly rows: number;
|
|
468
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
462
469
|
readonly exitCode?: number | undefined;
|
|
463
470
|
readonly exitSignal?: number | undefined;
|
|
464
471
|
readonly errorMessage?: string | undefined;
|
|
@@ -486,6 +493,75 @@ export declare const createAccessTokenOp: (payload: {
|
|
|
486
493
|
readonly createdAt: string;
|
|
487
494
|
readonly token: string;
|
|
488
495
|
}, import("@sealant/api-contracts").AccessTokenBadRequestError | import("@sealant/api-contracts").AccessTokenInternalServerError | import("@sealant/api-contracts").AccessTokenNotFoundError | import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
496
|
+
export declare const ensureUserOp: (payload: {
|
|
497
|
+
readonly email: string;
|
|
498
|
+
readonly name: string;
|
|
499
|
+
readonly userId?: string | undefined;
|
|
500
|
+
}) => Effect.Effect<{
|
|
501
|
+
readonly userId: string;
|
|
502
|
+
readonly email: string;
|
|
503
|
+
readonly name: string;
|
|
504
|
+
readonly createdAt: string;
|
|
505
|
+
readonly created: boolean;
|
|
506
|
+
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserBadRequestError | import("@sealant/api-contracts").UserInternalServerError, SealantApiClient>;
|
|
507
|
+
export declare const getUserOp: (userId: string) => Effect.Effect<{
|
|
508
|
+
readonly userId: string;
|
|
509
|
+
readonly email: string;
|
|
510
|
+
readonly name: string;
|
|
511
|
+
readonly createdAt: string;
|
|
512
|
+
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").UserInternalServerError | import("@sealant/api-contracts").UserNotFoundError, SealantApiClient>;
|
|
513
|
+
export declare const listConnectedAccountsOp: (ownerUserId: string) => Effect.Effect<{
|
|
514
|
+
readonly items: readonly {
|
|
515
|
+
readonly connectedAccountId: string;
|
|
516
|
+
readonly ownerUserId: string;
|
|
517
|
+
readonly provider: "claude" | "codex" | "github";
|
|
518
|
+
readonly name: string;
|
|
519
|
+
readonly kind: string;
|
|
520
|
+
readonly status: "active" | "archived" | "invalid";
|
|
521
|
+
readonly metadata: {
|
|
522
|
+
readonly [x: string]: unknown;
|
|
523
|
+
};
|
|
524
|
+
readonly connectedAt: string;
|
|
525
|
+
readonly updatedAt: string;
|
|
526
|
+
readonly lastUsedAt: string | null;
|
|
527
|
+
readonly lastSyncedAt: string | null;
|
|
528
|
+
}[];
|
|
529
|
+
}, import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
530
|
+
export declare const createConnectedAccountOp: (payload: {
|
|
531
|
+
readonly ownerUserId: string;
|
|
532
|
+
readonly provider: "claude" | "codex" | "github";
|
|
533
|
+
readonly name?: string | undefined;
|
|
534
|
+
readonly secret: string;
|
|
535
|
+
}) => Effect.Effect<{
|
|
536
|
+
readonly connectedAccountId: string;
|
|
537
|
+
readonly ownerUserId: string;
|
|
538
|
+
readonly provider: "claude" | "codex" | "github";
|
|
539
|
+
readonly name: string;
|
|
540
|
+
readonly kind: string;
|
|
541
|
+
readonly status: "active" | "archived" | "invalid";
|
|
542
|
+
readonly metadata: {
|
|
543
|
+
readonly [x: string]: unknown;
|
|
544
|
+
};
|
|
545
|
+
readonly connectedAt: string;
|
|
546
|
+
readonly updatedAt: string;
|
|
547
|
+
readonly lastUsedAt: string | null;
|
|
548
|
+
readonly lastSyncedAt: string | null;
|
|
549
|
+
}, import("@sealant/api-contracts").ConnectedAccountBadRequestError | import("@sealant/api-contracts").ConnectedAccountConflictError | import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("@sealant/api-contracts").ConnectedAccountNotFoundError | import("@sealant/api-contracts").ConnectedAccountServiceUnavailableError | import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
550
|
+
export declare const archiveConnectedAccountOp: (connectedAccountId: string, ownerUserId: string) => Effect.Effect<{
|
|
551
|
+
readonly connectedAccountId: string;
|
|
552
|
+
readonly ownerUserId: string;
|
|
553
|
+
readonly provider: "claude" | "codex" | "github";
|
|
554
|
+
readonly name: string;
|
|
555
|
+
readonly kind: string;
|
|
556
|
+
readonly status: "active" | "archived" | "invalid";
|
|
557
|
+
readonly metadata: {
|
|
558
|
+
readonly [x: string]: unknown;
|
|
559
|
+
};
|
|
560
|
+
readonly connectedAt: string;
|
|
561
|
+
readonly updatedAt: string;
|
|
562
|
+
readonly lastUsedAt: string | null;
|
|
563
|
+
readonly lastSyncedAt: string | null;
|
|
564
|
+
}, import("@sealant/api-contracts").ConnectedAccountInternalServerError | import("@sealant/api-contracts").ConnectedAccountNotFoundError | import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError, SealantApiClient>;
|
|
489
565
|
export declare const inferenceRespondOp: (payload: {
|
|
490
566
|
readonly ownerUserId: string;
|
|
491
567
|
readonly credentials?: {
|
|
@@ -5,7 +5,10 @@ export const createWorkspaceOp = (payload, idempotencyKey) => Effect.flatMap(Sea
|
|
|
5
5
|
payload,
|
|
6
6
|
headers: idempotencyKey === undefined ? {} : { "idempotency-key": idempotencyKey },
|
|
7
7
|
}));
|
|
8
|
-
export const getWorkspaceOp = (workspaceId) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.getWorkspace({
|
|
8
|
+
export const getWorkspaceOp = (workspaceId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.getWorkspace({
|
|
9
|
+
params: { workspaceId },
|
|
10
|
+
query: ownerUserId === undefined ? {} : { ownerUserId },
|
|
11
|
+
}));
|
|
9
12
|
export const listWorkspacesOp = (query) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.listWorkspaces({ query }));
|
|
10
13
|
export const execWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.execWorkspace({ params: { workspaceId }, payload }));
|
|
11
14
|
export const stopWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.stopWorkspace({ params: { workspaceId }, payload }));
|
|
@@ -13,13 +16,14 @@ export const restartWorkspaceOp = (workspaceId, payload) => Effect.flatMap(Seala
|
|
|
13
16
|
export const expireWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.expireWorkspace({ params: { workspaceId }, payload }));
|
|
14
17
|
// ---- runs ----
|
|
15
18
|
export const createRunOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.runs.createRun({ payload }));
|
|
16
|
-
|
|
19
|
+
const ownerQuery = (ownerUserId) => ownerUserId === undefined ? {} : { ownerUserId };
|
|
20
|
+
export const getRunOp = (runId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRun({ params: { runId }, query: ownerQuery(ownerUserId) }));
|
|
17
21
|
export const listRunsOp = (query) => Effect.flatMap(SealantApiClient, (client) => client.runs.listRuns({ query }));
|
|
18
22
|
export const updateRunOp = (runId, payload) => Effect.flatMap(SealantApiClient, (client) => client.runs.updateRun({ params: { runId }, payload }));
|
|
19
23
|
export const getRunTimelineOp = (runId, query) => Effect.flatMap(SealantApiClient, (client) => Effect.map(client.runs.getRunTimeline({ params: { runId }, query }), (r) => r.items));
|
|
20
24
|
export const getRunScrollbackOp = (runId, query) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRunScrollback({ params: { runId }, query }));
|
|
21
|
-
export const getRunLossOp = (runId) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRunLoss({ params: { runId } }));
|
|
22
|
-
export const getRunChangesOp = (runId) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRunChanges({ params: { runId } }));
|
|
25
|
+
export const getRunLossOp = (runId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRunLoss({ params: { runId }, query: ownerQuery(ownerUserId) }));
|
|
26
|
+
export const getRunChangesOp = (runId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRunChanges({ params: { runId }, query: ownerQuery(ownerUserId) }));
|
|
23
27
|
// ---- sessions ----
|
|
24
28
|
export const createSessionOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.sessions.createSession({ payload, headers: {} }));
|
|
25
29
|
export const getSessionOp = (sessionId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.sessions.getSession({
|
|
@@ -35,5 +39,15 @@ export const signalSessionOp = (sessionId, payload) => Effect.flatMap(SealantApi
|
|
|
35
39
|
export const closeSessionOp = (sessionId, payload) => Effect.flatMap(SealantApiClient, (client) => client.sessions.closeSession({ params: { sessionId }, headers: {}, payload }));
|
|
36
40
|
// ---- access tokens ----
|
|
37
41
|
export const createAccessTokenOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.accessTokens.createAccessToken({ payload }));
|
|
42
|
+
// ---- users ----
|
|
43
|
+
export const ensureUserOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.users.ensureUser({ payload }));
|
|
44
|
+
export const getUserOp = (userId) => Effect.flatMap(SealantApiClient, (client) => client.users.getUser({ params: { userId } }));
|
|
45
|
+
// ---- connected accounts ----
|
|
46
|
+
export const listConnectedAccountsOp = (ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.connectedAccounts.listConnectedAccounts({ query: { ownerUserId } }));
|
|
47
|
+
export const createConnectedAccountOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.connectedAccounts.createConnectedAccount({ payload }));
|
|
48
|
+
export const archiveConnectedAccountOp = (connectedAccountId, ownerUserId) => Effect.flatMap(SealantApiClient, (client) => client.connectedAccounts.archiveConnectedAccount({
|
|
49
|
+
params: { connectedAccountId },
|
|
50
|
+
query: { ownerUserId },
|
|
51
|
+
}));
|
|
38
52
|
// ---- inference ----
|
|
39
53
|
export const inferenceRespondOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.inference.respond({ payload }));
|
|
@@ -38,7 +38,7 @@ const createHarnessRunEffect = (ctx, init, prompt, options) => Effect.gen(functi
|
|
|
38
38
|
...metadata,
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
const details = yield* getWorkspaceOp(init.id);
|
|
41
|
+
const details = yield* getWorkspaceOp(init.id, ctx.config.hostLocal.ownerUserId);
|
|
42
42
|
const spec = details.spec;
|
|
43
43
|
const harnessId = spec?.harness?.id;
|
|
44
44
|
if (harnessId === undefined) {
|
|
@@ -66,10 +66,10 @@ const runHarnessEffect = (ctx, init, prompt, options) => Effect.gen(function* ()
|
|
|
66
66
|
}));
|
|
67
67
|
}
|
|
68
68
|
yield* Effect.sleep(POLL_INTERVAL);
|
|
69
|
-
wire = yield* getRunOp(runId);
|
|
69
|
+
wire = yield* getRunOp(runId, ctx.config.hostLocal.ownerUserId);
|
|
70
70
|
}
|
|
71
71
|
// Read the changes the run produced (captured server-side).
|
|
72
|
-
const changes = toRunChangesData(yield* getRunChangesOp(runId));
|
|
72
|
+
const changes = toRunChangesData(yield* getRunChangesOp(runId, ctx.config.hostLocal.ownerUserId));
|
|
73
73
|
return makeRun(ctx, { wire, changes });
|
|
74
74
|
});
|
|
75
75
|
/** The BLOCKING `harness.run()` implementation, registered into the Workspace facade by the client. */
|
package/dist/facade/record.js
CHANGED
|
@@ -135,7 +135,10 @@ export const renderTranscript = (commands) => {
|
|
|
135
135
|
return `${blocks.join("\n\n")}\n`;
|
|
136
136
|
};
|
|
137
137
|
export const makeRunRecord = (ctx, runId) => {
|
|
138
|
-
const fetchTimeline = (from) => ctx.runtime.run(getRunTimelineOp(runId,
|
|
138
|
+
const fetchTimeline = (from) => ctx.runtime.run(getRunTimelineOp(runId, {
|
|
139
|
+
ownerUserId: ctx.config.hostLocal.ownerUserId,
|
|
140
|
+
...(from === undefined ? {} : { fromSequence: from.toString() }),
|
|
141
|
+
}));
|
|
139
142
|
return {
|
|
140
143
|
runId,
|
|
141
144
|
replay: async (options) => {
|
|
@@ -171,7 +174,10 @@ export const makeRunRecord = (ctx, runId) => {
|
|
|
171
174
|
let from = options?.from;
|
|
172
175
|
const deadline = Date.now() + STREAM_TIMEOUT_MS;
|
|
173
176
|
for (;;) {
|
|
174
|
-
const wire = await ctxRun.run(getRunTimelineOp(runId,
|
|
177
|
+
const wire = await ctxRun.run(getRunTimelineOp(runId, {
|
|
178
|
+
ownerUserId: ctx.config.hostLocal.ownerUserId,
|
|
179
|
+
...(from === undefined ? {} : { fromSequence: from.toString() }),
|
|
180
|
+
}));
|
|
175
181
|
for (const entry of wire) {
|
|
176
182
|
const mapped = toTimelineEntry(entry);
|
|
177
183
|
yield mapped;
|
|
@@ -179,9 +185,12 @@ export const makeRunRecord = (ctx, runId) => {
|
|
|
179
185
|
}
|
|
180
186
|
// Stop once the run is terminal — with one final drain to catch entries written between the
|
|
181
187
|
// last timeline fetch and the status check.
|
|
182
|
-
const run = await ctxRun.run(getRunOp(runId));
|
|
188
|
+
const run = await ctxRun.run(getRunOp(runId, ctx.config.hostLocal.ownerUserId));
|
|
183
189
|
if (TERMINAL_RUN_STATUSES.has(run.status)) {
|
|
184
|
-
const tail = await ctxRun.run(getRunTimelineOp(runId,
|
|
190
|
+
const tail = await ctxRun.run(getRunTimelineOp(runId, {
|
|
191
|
+
ownerUserId: ctx.config.hostLocal.ownerUserId,
|
|
192
|
+
...(from === undefined ? {} : { fromSequence: from.toString() }),
|
|
193
|
+
}));
|
|
185
194
|
for (const entry of tail) {
|
|
186
195
|
yield toTimelineEntry(entry);
|
|
187
196
|
}
|
|
@@ -208,7 +217,11 @@ export const makeRunRecord = (ctx, runId) => {
|
|
|
208
217
|
scrollback: (processId, stream) => {
|
|
209
218
|
const run = ctx.runtime;
|
|
210
219
|
async function* iterate() {
|
|
211
|
-
const response = await run.run(getRunScrollbackOp(runId, {
|
|
220
|
+
const response = await run.run(getRunScrollbackOp(runId, {
|
|
221
|
+
ownerUserId: ctx.config.hostLocal.ownerUserId,
|
|
222
|
+
processId,
|
|
223
|
+
stream,
|
|
224
|
+
}));
|
|
212
225
|
const bytes = Buffer.from(response.contentBase64, "base64");
|
|
213
226
|
if (bytes.byteLength > 0) {
|
|
214
227
|
yield new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
@@ -216,9 +229,9 @@ export const makeRunRecord = (ctx, runId) => {
|
|
|
216
229
|
}
|
|
217
230
|
return iterate();
|
|
218
231
|
},
|
|
219
|
-
loss: async () => toLossReport(await ctx.runtime.run(getRunLossOp(runId))),
|
|
232
|
+
loss: async () => toLossReport(await ctx.runtime.run(getRunLossOp(runId, ctx.config.hostLocal.ownerUserId))),
|
|
220
233
|
summary: async () => {
|
|
221
|
-
const run = await ctx.runtime.run(getRunOp(runId));
|
|
234
|
+
const run = await ctx.runtime.run(getRunOp(runId, ctx.config.hostLocal.ownerUserId));
|
|
222
235
|
const timeline = await fetchTimeline();
|
|
223
236
|
const durationMs = run.startedAt !== undefined && run.finishedAt !== undefined
|
|
224
237
|
? new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime()
|
package/dist/facade/run.js
CHANGED
|
@@ -46,11 +46,12 @@ export const makeRun = (ctx, init) => {
|
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
await delay(WAIT_POLL_INTERVAL_MS);
|
|
49
|
-
current = await ctx.runtime.run(getRunOp(runId));
|
|
49
|
+
current = await ctx.runtime.run(getRunOp(runId, ctx.config.hostLocal.ownerUserId));
|
|
50
50
|
}
|
|
51
51
|
// Settle the changes: a handle from `harness.start()` or `runs.get()` has none captured yet,
|
|
52
52
|
// so read the server-side capture now that the run is terminal.
|
|
53
|
-
const settledChanges = changesData ??
|
|
53
|
+
const settledChanges = changesData ??
|
|
54
|
+
toRunChangesData(await ctx.runtime.run(getRunChangesOp(runId, ctx.config.hostLocal.ownerUserId)));
|
|
54
55
|
return makeRun(ctx, { wire: current, changes: settledChanges });
|
|
55
56
|
},
|
|
56
57
|
};
|
package/dist/facade/session.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const makeInteractiveSession: (ctx: SdkContext, wire: {
|
|
|
10
10
|
readonly cwd?: string | undefined;
|
|
11
11
|
readonly cols: number;
|
|
12
12
|
readonly rows: number;
|
|
13
|
+
readonly mode?: "pipe" | "pty" | undefined;
|
|
13
14
|
readonly exitCode?: number | undefined;
|
|
14
15
|
readonly exitSignal?: number | undefined;
|
|
15
16
|
readonly errorMessage?: string | undefined;
|
package/dist/facade/session.js
CHANGED
|
@@ -202,6 +202,7 @@ export const makeInteractiveSession = (ctx, wire) => {
|
|
|
202
202
|
id: sessionId,
|
|
203
203
|
workspaceId: wire.workspaceId,
|
|
204
204
|
runId: wire.runId,
|
|
205
|
+
mode: wire.mode ?? "pty",
|
|
205
206
|
send: async (input) => {
|
|
206
207
|
const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
|
|
207
208
|
await ctx.runtime.run(sendSessionInputOp(sessionId, {
|
package/dist/facade/workspace.js
CHANGED
|
@@ -34,6 +34,7 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
34
34
|
...(options?.cols === undefined ? {} : { cols: options.cols }),
|
|
35
35
|
...(options?.rows === undefined ? {} : { rows: options.rows }),
|
|
36
36
|
...(options?.term === undefined ? {} : { term: options.term }),
|
|
37
|
+
...(options?.mode === undefined ? {} : { mode: options.mode }),
|
|
37
38
|
...(options?.metadata === undefined ? {} : { metadata: { ...options.metadata } }),
|
|
38
39
|
}));
|
|
39
40
|
return makeInteractiveSession(ctx, created);
|
|
@@ -62,7 +63,7 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
62
63
|
if (init.harness !== undefined) {
|
|
63
64
|
return [init.harness.launchCommand ?? init.harness.id];
|
|
64
65
|
}
|
|
65
|
-
const details = await ctx.runtime.run(getWorkspaceOp(init.id));
|
|
66
|
+
const details = await ctx.runtime.run(getWorkspaceOp(init.id, ctx.config.hostLocal.ownerUserId));
|
|
66
67
|
const spec = details.spec;
|
|
67
68
|
const harnessId = spec?.harness?.id;
|
|
68
69
|
if (harnessId === undefined) {
|
|
@@ -92,13 +93,13 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
92
93
|
id: init.id,
|
|
93
94
|
name: init.name,
|
|
94
95
|
status: async () => {
|
|
95
|
-
const details = await ctx.runtime.run(getWorkspaceOp(init.id));
|
|
96
|
+
const details = await ctx.runtime.run(getWorkspaceOp(init.id, ctx.config.hostLocal.ownerUserId));
|
|
96
97
|
return details.status;
|
|
97
98
|
},
|
|
98
99
|
ready: async () => {
|
|
99
100
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
100
101
|
for (;;) {
|
|
101
|
-
const details = await ctx.runtime.run(getWorkspaceOp(init.id));
|
|
102
|
+
const details = await ctx.runtime.run(getWorkspaceOp(init.id, ctx.config.hostLocal.ownerUserId));
|
|
102
103
|
// Gate on the coarse "ready" status, which the control plane now emits ONLY after the
|
|
103
104
|
// in-workspace daemon's control socket is accepting (readiness probe in the launch path).
|
|
104
105
|
// This is honest: when ready() resolves, harness.run() can connect without racing the socket.
|
|
@@ -127,7 +128,7 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
127
128
|
let lastStatus;
|
|
128
129
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
129
130
|
for (;;) {
|
|
130
|
-
const details = await ctxRun.run(getWorkspaceOp(init.id));
|
|
131
|
+
const details = await ctxRun.run(getWorkspaceOp(init.id, ctx.config.hostLocal.ownerUserId));
|
|
131
132
|
if (details.status !== lastStatus) {
|
|
132
133
|
lastStatus = details.status;
|
|
133
134
|
yield {
|
|
@@ -155,7 +156,7 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
155
156
|
await ctx.runtime.run(stopWorkspaceOp(init.id, { ownerUserId }));
|
|
156
157
|
const deadline = Date.now() + STOP_TIMEOUT_MS;
|
|
157
158
|
for (;;) {
|
|
158
|
-
const details = await ctx.runtime.run(getWorkspaceOp(init.id));
|
|
159
|
+
const details = await ctx.runtime.run(getWorkspaceOp(init.id, ctx.config.hostLocal.ownerUserId));
|
|
159
160
|
if (details.status === "stopped") {
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The PUBLIC surface (`SealantConfig` in `../types.ts`) is intentionally minimal: `{ baseUrl, apiKey }`.
|
|
5
5
|
* The SDK is now a thin HTTP client (run execution + telemetry moved server-side), so the only
|
|
6
|
-
* host-local concerns left are
|
|
7
|
-
* payloads.
|
|
8
|
-
*
|
|
6
|
+
* host-local concerns left are the owner principal and the registry id used on create/run
|
|
7
|
+
* payloads. The owner comes from `SealantConfig.ownerUserId` when a product acts on behalf of a
|
|
8
|
+
* specific user (one client per user), else from the environment with docker-compose defaults.
|
|
9
9
|
*/
|
|
10
10
|
import type { SealantConfig } from "../types.js";
|
|
11
11
|
export interface SealantHostLocalConfig {
|
package/dist/internal/config.js
CHANGED
|
@@ -11,7 +11,7 @@ export const resolveInternalConfig = (config) => ({
|
|
|
11
11
|
apiKey: config.apiKey,
|
|
12
12
|
fetch: config.fetch,
|
|
13
13
|
hostLocal: {
|
|
14
|
-
ownerUserId: env("SEALANT_OWNER_USER_ID") ?? DEFAULT_OWNER_USER_ID,
|
|
14
|
+
ownerUserId: config.ownerUserId ?? env("SEALANT_OWNER_USER_ID") ?? DEFAULT_OWNER_USER_ID,
|
|
15
15
|
registryId: env("SEALANT_REGISTRY_ID") ?? DEFAULT_REGISTRY_ID,
|
|
16
16
|
},
|
|
17
17
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -23,8 +23,18 @@
|
|
|
23
23
|
export interface SealantConfig {
|
|
24
24
|
/** Base URL of the Sealant control-plane API (e.g. `http://localhost:8080`). */
|
|
25
25
|
readonly baseUrl: string;
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Bearer secret for authenticated deployments: a SERVICE KEY (`SEALANT_SERVICE_KEYS` on the
|
|
28
|
+
* control plane — lets this client act on behalf of any `ownerUserId`) or a scoped user access
|
|
29
|
+
* token (session surface only). Optional for a localhost demo with no auth.
|
|
30
|
+
*/
|
|
27
31
|
readonly apiKey?: string;
|
|
32
|
+
/**
|
|
33
|
+
* The user every call is attributed to. A product that owns its own login builds ONE client per
|
|
34
|
+
* user with that user's Sealant id (see `users.ensure`). Defaults to `SEALANT_OWNER_USER_ID`,
|
|
35
|
+
* then `usr_local`.
|
|
36
|
+
*/
|
|
37
|
+
readonly ownerUserId?: string;
|
|
28
38
|
/** Override the `fetch` implementation (tests, custom agents, proxies). */
|
|
29
39
|
readonly fetch?: typeof fetch;
|
|
30
40
|
}
|
|
@@ -367,14 +377,24 @@ export interface RunOptions {
|
|
|
367
377
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
368
378
|
}
|
|
369
379
|
/** Options for opening an interactive PTY session. */
|
|
380
|
+
/**
|
|
381
|
+
* How a session's leader is wired. `pty` (default) allocates a pseudoterminal — interactive
|
|
382
|
+
* shells and TUIs. `pipe` gives the leader plain stdio pipes and no tty — the shape for processes
|
|
383
|
+
* that speak a byte protocol over stdin/stdout (JSON-RPC / NDJSON servers such as
|
|
384
|
+
* `codex app-server`): `send` feeds stdin, `output`/`attach` carry stdout byte-exact, stderr is
|
|
385
|
+
* recorded as diagnostics only, and `resize` is rejected.
|
|
386
|
+
*/
|
|
387
|
+
export type SessionMode = "pty" | "pipe";
|
|
370
388
|
export interface SessionOptions {
|
|
371
389
|
/** Working directory inside the workspace (defaults to the repository root). */
|
|
372
390
|
readonly cwd?: string;
|
|
373
|
-
/** Extra environment for the
|
|
391
|
+
/** Extra environment for the session process (not for secrets — use `credentials`). */
|
|
374
392
|
readonly env?: Readonly<Record<string, string>>;
|
|
375
393
|
readonly cols?: number;
|
|
376
394
|
readonly rows?: number;
|
|
377
395
|
readonly term?: string;
|
|
396
|
+
/** Leader wiring; defaults to `pty`. `cols`/`rows`/`term` are ignored for `pipe`. */
|
|
397
|
+
readonly mode?: SessionMode;
|
|
378
398
|
/** Opaque correlation bag, stored verbatim and echoed on reads. */
|
|
379
399
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
380
400
|
}
|
|
@@ -705,7 +725,9 @@ export interface InteractiveSession {
|
|
|
705
725
|
readonly workspaceId: string;
|
|
706
726
|
/** The run recording this session — its record is the durable, replayable evidence. */
|
|
707
727
|
readonly runId: string;
|
|
708
|
-
/**
|
|
728
|
+
/** Leader wiring: a pseudoterminal or plain stdio pipes. */
|
|
729
|
+
readonly mode: SessionMode;
|
|
730
|
+
/** Send input: keystrokes to a PTY, bytes to a pipe leader's stdin. Strings are UTF-8-encoded. */
|
|
709
731
|
send(input: string | Uint8Array): Promise<void>;
|
|
710
732
|
/**
|
|
711
733
|
* Byte-exact output as a RESUMABLE stream: recorded history from `from` (inclusive; default the
|
|
@@ -716,7 +738,7 @@ export interface InteractiveSession {
|
|
|
716
738
|
readonly from?: bigint;
|
|
717
739
|
readonly signal?: AbortSignal;
|
|
718
740
|
}): AsyncIterable<SessionOutputChunk>;
|
|
719
|
-
/** Resize the PTY. */
|
|
741
|
+
/** Resize the PTY. Rejected for `pipe` sessions, which have no terminal. */
|
|
720
742
|
resize(cols: number, rows: number): Promise<void>;
|
|
721
743
|
/** Deliver a POSIX signal to the session's process (e.g. 2 = SIGINT). */
|
|
722
744
|
signal(signal: number): Promise<void>;
|
|
@@ -881,3 +903,65 @@ export interface InferenceContinueOptions {
|
|
|
881
903
|
export interface InferenceNamespace {
|
|
882
904
|
respond(options: InferenceRespondOptions | InferenceContinueOptions): Promise<InferenceResponse>;
|
|
883
905
|
}
|
|
906
|
+
export interface SealantUser {
|
|
907
|
+
readonly userId: string;
|
|
908
|
+
readonly email: string;
|
|
909
|
+
readonly name: string;
|
|
910
|
+
readonly createdAt: string;
|
|
911
|
+
}
|
|
912
|
+
export interface EnsureUserOptions {
|
|
913
|
+
readonly email: string;
|
|
914
|
+
readonly name: string;
|
|
915
|
+
/** Caller-chosen id for a NEW user; ignored when the email already exists. */
|
|
916
|
+
readonly userId?: string;
|
|
917
|
+
}
|
|
918
|
+
export interface EnsuredUser extends SealantUser {
|
|
919
|
+
/** True when this call created the user. */
|
|
920
|
+
readonly created: boolean;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Identity rows for products that own their own login. `ensure` is idempotent on email: call it on
|
|
924
|
+
* every sign-in and build the per-user client with the returned `userId` as `ownerUserId`.
|
|
925
|
+
*/
|
|
926
|
+
export interface UsersNamespace {
|
|
927
|
+
ensure(options: EnsureUserOptions): Promise<EnsuredUser>;
|
|
928
|
+
get(userId: string): Promise<SealantUser>;
|
|
929
|
+
}
|
|
930
|
+
export type ConnectedAccountProvider = "claude" | "codex" | "github";
|
|
931
|
+
export type ConnectedAccountStatus = "active" | "invalid" | "archived";
|
|
932
|
+
/** A connected account as every surface sees it — NEVER carries secret material. */
|
|
933
|
+
export interface ConnectedAccount {
|
|
934
|
+
readonly connectedAccountId: string;
|
|
935
|
+
readonly ownerUserId: string;
|
|
936
|
+
readonly provider: ConnectedAccountProvider;
|
|
937
|
+
readonly name: string;
|
|
938
|
+
/** Provider-shaped payload kind: oauth-token | credentials-json | auth-json | gh-cli-token. */
|
|
939
|
+
readonly kind: string;
|
|
940
|
+
readonly status: ConnectedAccountStatus;
|
|
941
|
+
/** Non-secret display data (token suffix, codex account email, github login + scopes). */
|
|
942
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
943
|
+
readonly connectedAt: string;
|
|
944
|
+
readonly updatedAt: string;
|
|
945
|
+
readonly lastUsedAt: string | null;
|
|
946
|
+
readonly lastSyncedAt: string | null;
|
|
947
|
+
}
|
|
948
|
+
export interface ConnectConnectedAccountOptions {
|
|
949
|
+
readonly provider: ConnectedAccountProvider;
|
|
950
|
+
/**
|
|
951
|
+
* Provider-shaped plaintext, passed through and sealed server-side: a Claude setup token or
|
|
952
|
+
* verbatim `.credentials.json`, verbatim Codex `auth.json`, or a GitHub token. Never logged.
|
|
953
|
+
*/
|
|
954
|
+
readonly secret: string;
|
|
955
|
+
/** Account name under the provider; defaults to `default` (the one `credentials: { x: true }` picks). */
|
|
956
|
+
readonly name?: string;
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* The owner's connected provider accounts. `connect` upserts on (provider, name), so reconnecting
|
|
960
|
+
* swaps the sealed credential in place. Secrets flow one way — in; no call returns them.
|
|
961
|
+
*/
|
|
962
|
+
export interface ConnectedAccountsNamespace {
|
|
963
|
+
list(): Promise<readonly ConnectedAccount[]>;
|
|
964
|
+
connect(options: ConnectConnectedAccountOptions): Promise<ConnectedAccount>;
|
|
965
|
+
/** Soft-archives the account; uniform not-found for "does not exist" and "not yours". */
|
|
966
|
+
disconnect(connectedAccountId: string): Promise<ConnectedAccount>;
|
|
967
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealant/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "The fluent public SDK for Sealant — create a workspace, run a harness, replay the record.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@sealant/api-contracts": "^0.
|
|
29
|
+
"@sealant/api-contracts": "^0.22.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@effect/vitest": "4.0.0-beta.85",
|