@sealant/sdk 0.5.0 → 0.5.2
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/effect/api-client.d.ts +92 -10
- package/dist/effect/operations.d.ts +27 -4
- package/dist/effect/operations.js +3 -0
- package/dist/facade/workspace.js +50 -5
- package/dist/internal/blueprint.d.ts +1 -0
- package/dist/internal/blueprint.js +4 -1
- package/dist/internal/duration.d.ts +6 -0
- package/dist/internal/duration.js +34 -0
- package/dist/types.d.ts +15 -6
- package/package.json +2 -2
|
@@ -756,12 +756,13 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
756
756
|
readonly github?: string | undefined;
|
|
757
757
|
} | undefined;
|
|
758
758
|
readonly spec: unknown;
|
|
759
|
+
readonly ttlSeconds?: number | undefined;
|
|
759
760
|
};
|
|
760
761
|
readonly responseMode?: Mode;
|
|
761
762
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
762
763
|
readonly workspaceId: string;
|
|
763
764
|
readonly name: string;
|
|
764
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
765
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
765
766
|
readonly registryId: string;
|
|
766
767
|
readonly repository: string;
|
|
767
768
|
readonly tag: string;
|
|
@@ -795,6 +796,19 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
795
796
|
readonly createdAt: string;
|
|
796
797
|
readonly updatedAt: string;
|
|
797
798
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
799
|
+
readonly expireWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
800
|
+
readonly params: {
|
|
801
|
+
readonly workspaceId: string;
|
|
802
|
+
};
|
|
803
|
+
readonly payload: {
|
|
804
|
+
readonly ownerUserId: string;
|
|
805
|
+
readonly ttlSeconds?: number | null | undefined;
|
|
806
|
+
};
|
|
807
|
+
readonly responseMode?: Mode;
|
|
808
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
809
|
+
readonly workspaceId: string;
|
|
810
|
+
readonly expiresAt: string | null;
|
|
811
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
798
812
|
readonly getWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
799
813
|
readonly params: {
|
|
800
814
|
readonly workspaceId: string;
|
|
@@ -804,7 +818,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
804
818
|
readonly workspaceId: string;
|
|
805
819
|
readonly name: string;
|
|
806
820
|
readonly ownerUserId: string;
|
|
807
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
821
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
808
822
|
readonly registryId?: string | undefined;
|
|
809
823
|
readonly repository?: string | undefined;
|
|
810
824
|
readonly tag?: string | undefined;
|
|
@@ -828,6 +842,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
828
842
|
readonly updatedAt: string;
|
|
829
843
|
readonly startedAt?: string | undefined;
|
|
830
844
|
readonly finishedAt?: string | undefined;
|
|
845
|
+
readonly expiresAt?: string | undefined;
|
|
831
846
|
readonly spec?: unknown;
|
|
832
847
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
833
848
|
readonly getWorkspaceSshTarget: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
@@ -862,7 +877,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
862
877
|
readonly items: readonly {
|
|
863
878
|
readonly attemptId: string;
|
|
864
879
|
readonly relation: "launch" | "rebuild" | "resume" | "retry";
|
|
865
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
880
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
866
881
|
readonly triggerType: "api" | "manual" | "retry" | "schedule";
|
|
867
882
|
readonly triggerRef?: string | undefined;
|
|
868
883
|
readonly runtime?: {
|
|
@@ -913,7 +928,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
913
928
|
readonly listWorkspaces: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
914
929
|
readonly query: {
|
|
915
930
|
readonly ownerUserId: string;
|
|
916
|
-
readonly status?: "cancelled" | "failed" | "queued" | "ready" | "running" | undefined;
|
|
931
|
+
readonly status?: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped" | undefined;
|
|
917
932
|
readonly limit?: string | undefined;
|
|
918
933
|
};
|
|
919
934
|
readonly responseMode?: Mode;
|
|
@@ -922,7 +937,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
922
937
|
readonly workspaceId: string;
|
|
923
938
|
readonly name: string;
|
|
924
939
|
readonly ownerUserId: string;
|
|
925
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
940
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
926
941
|
readonly registryId?: string | undefined;
|
|
927
942
|
readonly repository?: string | undefined;
|
|
928
943
|
readonly tag?: string | undefined;
|
|
@@ -946,6 +961,7 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
946
961
|
readonly updatedAt: string;
|
|
947
962
|
readonly startedAt?: string | undefined;
|
|
948
963
|
readonly finishedAt?: string | undefined;
|
|
964
|
+
readonly expiresAt?: string | undefined;
|
|
949
965
|
}[];
|
|
950
966
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError), [Mode] extends ["response-only"] ? never : never>;
|
|
951
967
|
readonly renameWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
@@ -961,6 +977,31 @@ declare const buildControlPlaneClient: (config: SealantInternalConfig) => Effect
|
|
|
961
977
|
readonly name: string;
|
|
962
978
|
readonly updatedAt: string;
|
|
963
979
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
980
|
+
readonly restartWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
981
|
+
readonly params: {
|
|
982
|
+
readonly workspaceId: string;
|
|
983
|
+
};
|
|
984
|
+
readonly payload: {
|
|
985
|
+
readonly ownerUserId: string;
|
|
986
|
+
};
|
|
987
|
+
readonly responseMode?: Mode;
|
|
988
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
989
|
+
readonly workspaceId: string;
|
|
990
|
+
readonly runId: string;
|
|
991
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
992
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
993
|
+
readonly stopWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
994
|
+
readonly params: {
|
|
995
|
+
readonly workspaceId: string;
|
|
996
|
+
};
|
|
997
|
+
readonly payload: {
|
|
998
|
+
readonly ownerUserId: string;
|
|
999
|
+
};
|
|
1000
|
+
readonly responseMode?: Mode;
|
|
1001
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1002
|
+
readonly workspaceId: string;
|
|
1003
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
1004
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
964
1005
|
};
|
|
965
1006
|
}, never, HttpClient.HttpClient>;
|
|
966
1007
|
/** The fully-typed control-plane client, derived from the `@sealant/api-contracts` HttpApi. */
|
|
@@ -1718,12 +1759,13 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1718
1759
|
readonly github?: string | undefined;
|
|
1719
1760
|
} | undefined;
|
|
1720
1761
|
readonly spec: unknown;
|
|
1762
|
+
readonly ttlSeconds?: number | undefined;
|
|
1721
1763
|
};
|
|
1722
1764
|
readonly responseMode?: Mode;
|
|
1723
1765
|
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1724
1766
|
readonly workspaceId: string;
|
|
1725
1767
|
readonly name: string;
|
|
1726
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
1768
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
1727
1769
|
readonly registryId: string;
|
|
1728
1770
|
readonly repository: string;
|
|
1729
1771
|
readonly tag: string;
|
|
@@ -1757,6 +1799,19 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1757
1799
|
readonly createdAt: string;
|
|
1758
1800
|
readonly updatedAt: string;
|
|
1759
1801
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1802
|
+
readonly expireWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1803
|
+
readonly params: {
|
|
1804
|
+
readonly workspaceId: string;
|
|
1805
|
+
};
|
|
1806
|
+
readonly payload: {
|
|
1807
|
+
readonly ownerUserId: string;
|
|
1808
|
+
readonly ttlSeconds?: number | null | undefined;
|
|
1809
|
+
};
|
|
1810
|
+
readonly responseMode?: Mode;
|
|
1811
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1812
|
+
readonly workspaceId: string;
|
|
1813
|
+
readonly expiresAt: string | null;
|
|
1814
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1760
1815
|
readonly getWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1761
1816
|
readonly params: {
|
|
1762
1817
|
readonly workspaceId: string;
|
|
@@ -1766,7 +1821,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1766
1821
|
readonly workspaceId: string;
|
|
1767
1822
|
readonly name: string;
|
|
1768
1823
|
readonly ownerUserId: string;
|
|
1769
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
1824
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
1770
1825
|
readonly registryId?: string | undefined;
|
|
1771
1826
|
readonly repository?: string | undefined;
|
|
1772
1827
|
readonly tag?: string | undefined;
|
|
@@ -1790,6 +1845,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1790
1845
|
readonly updatedAt: string;
|
|
1791
1846
|
readonly startedAt?: string | undefined;
|
|
1792
1847
|
readonly finishedAt?: string | undefined;
|
|
1848
|
+
readonly expiresAt?: string | undefined;
|
|
1793
1849
|
readonly spec?: unknown;
|
|
1794
1850
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1795
1851
|
readonly getWorkspaceSshTarget: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
@@ -1824,7 +1880,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1824
1880
|
readonly items: readonly {
|
|
1825
1881
|
readonly attemptId: string;
|
|
1826
1882
|
readonly relation: "launch" | "rebuild" | "resume" | "retry";
|
|
1827
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
1883
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
1828
1884
|
readonly triggerType: "api" | "manual" | "retry" | "schedule";
|
|
1829
1885
|
readonly triggerRef?: string | undefined;
|
|
1830
1886
|
readonly runtime?: {
|
|
@@ -1875,7 +1931,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1875
1931
|
readonly listWorkspaces: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1876
1932
|
readonly query: {
|
|
1877
1933
|
readonly ownerUserId: string;
|
|
1878
|
-
readonly status?: "cancelled" | "failed" | "queued" | "ready" | "running" | undefined;
|
|
1934
|
+
readonly status?: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped" | undefined;
|
|
1879
1935
|
readonly limit?: string | undefined;
|
|
1880
1936
|
};
|
|
1881
1937
|
readonly responseMode?: Mode;
|
|
@@ -1884,7 +1940,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1884
1940
|
readonly workspaceId: string;
|
|
1885
1941
|
readonly name: string;
|
|
1886
1942
|
readonly ownerUserId: string;
|
|
1887
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
1943
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
1888
1944
|
readonly registryId?: string | undefined;
|
|
1889
1945
|
readonly repository?: string | undefined;
|
|
1890
1946
|
readonly tag?: string | undefined;
|
|
@@ -1908,6 +1964,7 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1908
1964
|
readonly updatedAt: string;
|
|
1909
1965
|
readonly startedAt?: string | undefined;
|
|
1910
1966
|
readonly finishedAt?: string | undefined;
|
|
1967
|
+
readonly expiresAt?: string | undefined;
|
|
1911
1968
|
}[];
|
|
1912
1969
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError), [Mode] extends ["response-only"] ? never : never>;
|
|
1913
1970
|
readonly renameWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
@@ -1923,6 +1980,31 @@ declare const SealantApiClient_base: Context.ServiceClass<SealantApiClient, "@se
|
|
|
1923
1980
|
readonly name: string;
|
|
1924
1981
|
readonly updatedAt: string;
|
|
1925
1982
|
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1983
|
+
readonly restartWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1984
|
+
readonly params: {
|
|
1985
|
+
readonly workspaceId: string;
|
|
1986
|
+
};
|
|
1987
|
+
readonly payload: {
|
|
1988
|
+
readonly ownerUserId: string;
|
|
1989
|
+
};
|
|
1990
|
+
readonly responseMode?: Mode;
|
|
1991
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
1992
|
+
readonly workspaceId: string;
|
|
1993
|
+
readonly runId: string;
|
|
1994
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
1995
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1996
|
+
readonly stopWorkspace: <Mode extends import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode = import("effect/unstable/httpapi/HttpApiEndpoint").ClientResponseMode>(request: {
|
|
1997
|
+
readonly params: {
|
|
1998
|
+
readonly workspaceId: string;
|
|
1999
|
+
};
|
|
2000
|
+
readonly payload: {
|
|
2001
|
+
readonly ownerUserId: string;
|
|
2002
|
+
};
|
|
2003
|
+
readonly responseMode?: Mode;
|
|
2004
|
+
}) => Effect.Effect<HttpApiClient.Client.Response<{
|
|
2005
|
+
readonly workspaceId: string;
|
|
2006
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
2007
|
+
}, Mode>, import("effect/unstable/http/HttpClientError").HttpClientError | ([Mode] extends ["response-only"] ? never : import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadGatewayError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError), [Mode] extends ["response-only"] ? never : never>;
|
|
1926
2008
|
};
|
|
1927
2009
|
}>;
|
|
1928
2010
|
export declare class SealantApiClient extends SealantApiClient_base {
|
|
@@ -25,10 +25,11 @@ export declare const createWorkspaceOp: (payload: {
|
|
|
25
25
|
readonly github?: string | undefined;
|
|
26
26
|
} | undefined;
|
|
27
27
|
readonly spec: unknown;
|
|
28
|
+
readonly ttlSeconds?: number | undefined;
|
|
28
29
|
}, idempotencyKey?: string | undefined) => Effect.Effect<{
|
|
29
30
|
readonly workspaceId: string;
|
|
30
31
|
readonly name: string;
|
|
31
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
32
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
32
33
|
readonly registryId: string;
|
|
33
34
|
readonly repository: string;
|
|
34
35
|
readonly tag: string;
|
|
@@ -37,7 +38,7 @@ export declare const getWorkspaceOp: (workspaceId: string) => Effect.Effect<{
|
|
|
37
38
|
readonly workspaceId: string;
|
|
38
39
|
readonly name: string;
|
|
39
40
|
readonly ownerUserId: string;
|
|
40
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
41
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
41
42
|
readonly registryId?: string | undefined;
|
|
42
43
|
readonly repository?: string | undefined;
|
|
43
44
|
readonly tag?: string | undefined;
|
|
@@ -61,18 +62,19 @@ export declare const getWorkspaceOp: (workspaceId: string) => Effect.Effect<{
|
|
|
61
62
|
readonly updatedAt: string;
|
|
62
63
|
readonly startedAt?: string | undefined;
|
|
63
64
|
readonly finishedAt?: string | undefined;
|
|
65
|
+
readonly expiresAt?: string | undefined;
|
|
64
66
|
readonly spec?: unknown;
|
|
65
67
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
66
68
|
export declare const listWorkspacesOp: (query: {
|
|
67
69
|
readonly ownerUserId: string;
|
|
68
|
-
readonly status?: "cancelled" | "failed" | "queued" | "ready" | "running" | undefined;
|
|
70
|
+
readonly status?: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped" | undefined;
|
|
69
71
|
readonly limit?: string | undefined;
|
|
70
72
|
}) => Effect.Effect<{
|
|
71
73
|
readonly items: readonly {
|
|
72
74
|
readonly workspaceId: string;
|
|
73
75
|
readonly name: string;
|
|
74
76
|
readonly ownerUserId: string;
|
|
75
|
-
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running";
|
|
77
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
76
78
|
readonly registryId?: string | undefined;
|
|
77
79
|
readonly repository?: string | undefined;
|
|
78
80
|
readonly tag?: string | undefined;
|
|
@@ -96,6 +98,7 @@ export declare const listWorkspacesOp: (query: {
|
|
|
96
98
|
readonly updatedAt: string;
|
|
97
99
|
readonly startedAt?: string | undefined;
|
|
98
100
|
readonly finishedAt?: string | undefined;
|
|
101
|
+
readonly expiresAt?: string | undefined;
|
|
99
102
|
}[];
|
|
100
103
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError, SealantApiClient>;
|
|
101
104
|
export declare const execWorkspaceOp: (workspaceId: string, payload: {
|
|
@@ -121,6 +124,26 @@ export declare const execWorkspaceOp: (workspaceId: string, payload: {
|
|
|
121
124
|
readonly createdAt: string;
|
|
122
125
|
readonly updatedAt: string;
|
|
123
126
|
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceConflictError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
127
|
+
export declare const stopWorkspaceOp: (workspaceId: string, payload: {
|
|
128
|
+
readonly ownerUserId: string;
|
|
129
|
+
}) => Effect.Effect<{
|
|
130
|
+
readonly workspaceId: string;
|
|
131
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
132
|
+
}, 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").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
133
|
+
export declare const restartWorkspaceOp: (workspaceId: string, payload: {
|
|
134
|
+
readonly ownerUserId: string;
|
|
135
|
+
}) => Effect.Effect<{
|
|
136
|
+
readonly workspaceId: string;
|
|
137
|
+
readonly runId: string;
|
|
138
|
+
readonly status: "cancelled" | "failed" | "queued" | "ready" | "running" | "stopped";
|
|
139
|
+
}, 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").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
140
|
+
export declare const expireWorkspaceOp: (workspaceId: string, payload: {
|
|
141
|
+
readonly ownerUserId: string;
|
|
142
|
+
readonly ttlSeconds?: number | null | undefined;
|
|
143
|
+
}) => Effect.Effect<{
|
|
144
|
+
readonly workspaceId: string;
|
|
145
|
+
readonly expiresAt: string | null;
|
|
146
|
+
}, import("effect/unstable/http/HttpClientError").HttpClientError | import("effect/Schema").SchemaError | import("@sealant/api-contracts").WorkspaceBadRequestError | import("@sealant/api-contracts").WorkspaceInternalServerError | import("@sealant/api-contracts").WorkspaceNotFoundError, SealantApiClient>;
|
|
124
147
|
export declare const createRunOp: (payload: {
|
|
125
148
|
readonly workspaceId: string;
|
|
126
149
|
readonly harnessId: string;
|
|
@@ -8,6 +8,9 @@ export const createWorkspaceOp = (payload, idempotencyKey) => Effect.flatMap(Sea
|
|
|
8
8
|
export const getWorkspaceOp = (workspaceId) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.getWorkspace({ params: { workspaceId } }));
|
|
9
9
|
export const listWorkspacesOp = (query) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.listWorkspaces({ query }));
|
|
10
10
|
export const execWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.execWorkspace({ params: { workspaceId }, payload }));
|
|
11
|
+
export const stopWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.stopWorkspace({ params: { workspaceId }, payload }));
|
|
12
|
+
export const restartWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.restartWorkspace({ params: { workspaceId }, payload }));
|
|
13
|
+
export const expireWorkspaceOp = (workspaceId, payload) => Effect.flatMap(SealantApiClient, (client) => client.workspaces.expireWorkspace({ params: { workspaceId }, payload }));
|
|
11
14
|
// ---- runs ----
|
|
12
15
|
export const createRunOp = (payload) => Effect.flatMap(SealantApiClient, (client) => client.runs.createRun({ payload }));
|
|
13
16
|
export const getRunOp = (runId) => Effect.flatMap(SealantApiClient, (client) => client.runs.getRun({ params: { runId } }));
|
package/dist/facade/workspace.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { execWorkspace } from "../effect/exec-workspace.js";
|
|
2
|
-
import { getWorkspaceOp } from "../effect/operations.js";
|
|
2
|
+
import { expireWorkspaceOp, getWorkspaceOp, restartWorkspaceOp, stopWorkspaceOp, } from "../effect/operations.js";
|
|
3
3
|
import { SealantError, SealantNotImplementedError } from "../errors.js";
|
|
4
|
-
|
|
4
|
+
import { parseTtlSeconds } from "../internal/duration.js";
|
|
5
|
+
// Terminal statuses a workspace can never leave: ready()/events() fail fast (or end the stream)
|
|
6
|
+
// on these instead of polling out their deadline. "stopped" is terminal too — a TTL expiry or a
|
|
7
|
+
// concurrent stop while ready() polls must surface immediately, not as a 10-minute timeout.
|
|
8
|
+
const FAILED_STATUSES = new Set(["failed", "cancelled", "stopped"]);
|
|
5
9
|
const READY_POLL_INTERVAL_MS = 2_000;
|
|
6
10
|
const READY_TIMEOUT_MS = 10 * 60 * 1_000;
|
|
11
|
+
const STOP_POLL_INTERVAL_MS = 1_000;
|
|
12
|
+
const STOP_TIMEOUT_MS = 60 * 1_000;
|
|
7
13
|
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8
14
|
let harnessExecutors;
|
|
9
15
|
export const registerHarnessExecutors = (executors) => {
|
|
@@ -83,9 +89,48 @@ export const makeWorkspace = (ctx, init) => {
|
|
|
83
89
|
}
|
|
84
90
|
return iterate();
|
|
85
91
|
},
|
|
86
|
-
stop:
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
// BLOCKING stop: the control plane accepts the stop (202) and the worker tears the container
|
|
93
|
+
// down; resolve only once the workspace reports the terminal "stopped" status, so callers can
|
|
94
|
+
// trust the container is gone when this settles.
|
|
95
|
+
stop: async () => {
|
|
96
|
+
const ownerUserId = ctx.config.hostLocal.ownerUserId;
|
|
97
|
+
await ctx.runtime.run(stopWorkspaceOp(init.id, { ownerUserId }));
|
|
98
|
+
const deadline = Date.now() + STOP_TIMEOUT_MS;
|
|
99
|
+
for (;;) {
|
|
100
|
+
const details = await ctx.runtime.run(getWorkspaceOp(init.id));
|
|
101
|
+
if (details.status === "stopped") {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (Date.now() > deadline) {
|
|
105
|
+
throw new SealantError(`Timed out waiting for workspace ${init.id} to stop.`, {
|
|
106
|
+
code: "workspace_stop_timeout",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
await delay(STOP_POLL_INTERVAL_MS);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
// Restart drives a fresh launch (new attempt, new container, same resolved spec) and returns a
|
|
113
|
+
// handle that resolves readiness against the NEW runtime via the usual ready() gate.
|
|
114
|
+
restart: async () => {
|
|
115
|
+
const ownerUserId = ctx.config.hostLocal.ownerUserId;
|
|
116
|
+
await ctx.runtime.run(restartWorkspaceOp(init.id, { ownerUserId }));
|
|
117
|
+
return makeWorkspace(ctx, {
|
|
118
|
+
id: init.id,
|
|
119
|
+
name: init.name,
|
|
120
|
+
status: "queued",
|
|
121
|
+
...(init.harness === undefined ? {} : { harness: init.harness }),
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
// expire({in: "2h"}) sets the TTL, expire() expires now (the platform reaper stops it on its
|
|
125
|
+
// next tick), expire({in: null}) clears the TTL. Resolves once the expiry is recorded.
|
|
126
|
+
expire: async (options) => {
|
|
127
|
+
const ownerUserId = ctx.config.hostLocal.ownerUserId;
|
|
128
|
+
const ttl = options?.in;
|
|
129
|
+
await ctx.runtime.run(expireWorkspaceOp(init.id, {
|
|
130
|
+
ownerUserId,
|
|
131
|
+
...(ttl === undefined ? {} : { ttlSeconds: ttl === null ? null : parseTtlSeconds(ttl) }),
|
|
132
|
+
}));
|
|
133
|
+
},
|
|
89
134
|
};
|
|
90
135
|
return workspace;
|
|
91
136
|
};
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { randomUUID } from "node:crypto";
|
|
14
14
|
import { mapWorkspaceCredentials } from "./credentials.js";
|
|
15
|
+
import { parseTtlSeconds } from "./duration.js";
|
|
15
16
|
const sanitizeRepoSlug = (value) => {
|
|
16
17
|
const slug = value
|
|
17
18
|
.toLowerCase()
|
|
@@ -39,7 +40,8 @@ export const buildCreateWorkspaceRequest = (options, config) => {
|
|
|
39
40
|
kind: "git",
|
|
40
41
|
provider: "generic",
|
|
41
42
|
url: toGitUrl(options.repository),
|
|
42
|
-
|
|
43
|
+
// Omitted ref = the repository's default branch, resolved by the clone itself.
|
|
44
|
+
...(options.ref === undefined ? {} : { ref: options.ref }),
|
|
43
45
|
},
|
|
44
46
|
},
|
|
45
47
|
harness: { id: options.harness.id },
|
|
@@ -63,6 +65,7 @@ export const buildCreateWorkspaceRequest = (options, config) => {
|
|
|
63
65
|
repository: sanitizeRepoSlug(tail),
|
|
64
66
|
tag: `sdk-${randomUUID().slice(0, 8)}`,
|
|
65
67
|
...(options.name === undefined ? {} : { name: options.name }),
|
|
68
|
+
...(options.ttl === undefined ? {} : { ttlSeconds: parseTtlSeconds(options.ttl) }),
|
|
66
69
|
spec,
|
|
67
70
|
},
|
|
68
71
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a human TTL like `"90m"`, `"2h"`, `"45s"`, `"1d"` into whole seconds (milliseconds round
|
|
3
|
+
* up to at least 1s — the wire TTL is second-granular). Throws a typed `SealantError` on anything
|
|
4
|
+
* else so a typo'd TTL fails at the call site instead of silently never expiring.
|
|
5
|
+
*/
|
|
6
|
+
export declare const parseTtlSeconds: (ttl: string) => number;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SealantError } from "../errors.js";
|
|
2
|
+
const DURATION_PATTERN = /^(\d+)(ms|s|m|h|d)$/;
|
|
3
|
+
const UNIT_SECONDS = {
|
|
4
|
+
s: 1,
|
|
5
|
+
m: 60,
|
|
6
|
+
h: 3600,
|
|
7
|
+
d: 86400,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Parse a human TTL like `"90m"`, `"2h"`, `"45s"`, `"1d"` into whole seconds (milliseconds round
|
|
11
|
+
* up to at least 1s — the wire TTL is second-granular). Throws a typed `SealantError` on anything
|
|
12
|
+
* else so a typo'd TTL fails at the call site instead of silently never expiring.
|
|
13
|
+
*/
|
|
14
|
+
export const parseTtlSeconds = (ttl) => {
|
|
15
|
+
const match = DURATION_PATTERN.exec(ttl.trim());
|
|
16
|
+
if (match === null) {
|
|
17
|
+
throw new SealantError(`Invalid TTL duration "${ttl}". Use a positive integer with a unit: e.g. "45s", "90m", "2h", "1d".`, { code: "invalid_ttl" });
|
|
18
|
+
}
|
|
19
|
+
const value = Number.parseInt(match[1] ?? "", 10);
|
|
20
|
+
const unit = match[2] ?? "";
|
|
21
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
22
|
+
throw new SealantError(`Invalid TTL duration "${ttl}". The value must be a positive integer.`, {
|
|
23
|
+
code: "invalid_ttl",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (unit === "ms") {
|
|
27
|
+
return Math.max(1, Math.ceil(value / 1000));
|
|
28
|
+
}
|
|
29
|
+
const multiplier = UNIT_SECONDS[unit];
|
|
30
|
+
if (multiplier === undefined) {
|
|
31
|
+
throw new SealantError(`Invalid TTL duration "${ttl}".`, { code: "invalid_ttl" });
|
|
32
|
+
}
|
|
33
|
+
return value * multiplier;
|
|
34
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -56,8 +56,8 @@ export interface Harness {
|
|
|
56
56
|
/** Optional launch command for an interactive session (defaults to the executable). */
|
|
57
57
|
readonly launchCommand?: string;
|
|
58
58
|
}
|
|
59
|
-
/** Lifecycle status of a workspace.
|
|
60
|
-
export type WorkspaceStatus = "queued" | "running" | "ready" | "failed" | "cancelled";
|
|
59
|
+
/** Lifecycle status of a workspace. */
|
|
60
|
+
export type WorkspaceStatus = "queued" | "running" | "ready" | "failed" | "cancelled" | "stopped";
|
|
61
61
|
/** A coarse lifecycle event observed while a workspace is being provisioned. */
|
|
62
62
|
export interface WorkspaceEvent {
|
|
63
63
|
readonly type: string;
|
|
@@ -109,6 +109,12 @@ export interface CreateOptions {
|
|
|
109
109
|
readonly onEvent?: (event: WorkspaceEvent) => void;
|
|
110
110
|
/** Connected-account credentials to attach to the workspace (see `WorkspaceCredentialsOptions`). */
|
|
111
111
|
readonly credentials?: WorkspaceCredentialsOptions;
|
|
112
|
+
/**
|
|
113
|
+
* Time-to-live for the workspace, e.g. `"90m"`, `"2h"` (also `"45s"`, `"1d"`). Once it elapses
|
|
114
|
+
* the platform stops the workspace and removes its container. Omitted = the server default TTL
|
|
115
|
+
* (if the install configures one).
|
|
116
|
+
*/
|
|
117
|
+
readonly ttl?: string;
|
|
112
118
|
}
|
|
113
119
|
export interface ListOptions {
|
|
114
120
|
readonly status?: WorkspaceStatus;
|
|
@@ -152,13 +158,16 @@ export interface Workspace {
|
|
|
152
158
|
exec(argv: readonly string[], options?: WorkspaceExecOptions): Promise<WorkspaceExecResult>;
|
|
153
159
|
/** Lifecycle events as an async stream. */
|
|
154
160
|
events(): AsyncIterable<WorkspaceEvent>;
|
|
155
|
-
/** Stop the workspace
|
|
161
|
+
/** Stop the workspace: remove its container and settle it in the terminal "stopped" status. */
|
|
156
162
|
stop(): Promise<void>;
|
|
157
|
-
/** Restart the workspace into a fresh runtime
|
|
163
|
+
/** Restart the workspace into a fresh runtime — a new container, no filesystem carry-over. */
|
|
158
164
|
restart(): Promise<Workspace>;
|
|
159
|
-
/**
|
|
165
|
+
/**
|
|
166
|
+
* Schedule the workspace to expire: `expire({ in: "2h" })` sets the TTL, `expire()` expires it
|
|
167
|
+
* now (the platform reaper stops it shortly), `expire({ in: null })` clears the TTL.
|
|
168
|
+
*/
|
|
160
169
|
expire(options?: {
|
|
161
|
-
readonly in?: string;
|
|
170
|
+
readonly in?: string | null;
|
|
162
171
|
}): Promise<void>;
|
|
163
172
|
}
|
|
164
173
|
export interface RunOptions {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealant/sdk",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
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": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"effect": "^4.0.0-beta.85",
|
|
30
|
-
"@sealant/api-contracts": "^0.5.
|
|
30
|
+
"@sealant/api-contracts": "^0.5.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@effect/vitest": "^4.0.0-beta.85",
|