Skip to content
Source
Sign inSign up

providerSetup.ts

241 lines8.4 KB

1import * as Schema from "effect/Schema";
2​
3import {
4 EnvironmentId,
5 ForwardCompatibleArray,
6 ForwardCompatibleOptional,
7 IsoDateTime,
8 TrimmedNonEmptyString,
9} from "./baseSchemas.ts";
10import { ProviderDriverKind, ProviderInstanceId } from "./providerInstance.ts";
11​
12export const ProviderSetupInput = Schema.Struct({
13 instanceId: ProviderInstanceId,
14});
15export type ProviderSetupInput = typeof ProviderSetupInput.Type;
16​
17const SetupOperationId = TrimmedNonEmptyString.check(Schema.isMaxLength(128));
18​
19export const ProviderAuthMethod = Schema.Struct({
20 id: SetupOperationId,
21 accountEmail: Schema.optional(TrimmedNonEmptyString),
22 canRemove: Schema.optionalKey(Schema.Boolean),
23 name: TrimmedNonEmptyString,
24 description: Schema.NullOr(Schema.String),
25 type: Schema.Literals(["agent", "terminal", "credentials"]),
26});
27export type ProviderAuthMethod = typeof ProviderAuthMethod.Type;
28​
29export const ProviderAuthInteraction = Schema.Union([
30 Schema.Struct({
31 type: Schema.Literal("browser"),
32 id: SetupOperationId,
33 url: TrimmedNonEmptyString.check(Schema.isMaxLength(16_384)),
34 requiresConsent: Schema.Boolean,
35 acceptsCallback: Schema.optionalKey(Schema.Boolean),
36 }),
37 Schema.Struct({
38 type: Schema.Literal("deviceCode"),
39 id: SetupOperationId,
40 url: TrimmedNonEmptyString.check(Schema.isMaxLength(16_384)),
41 userCode: TrimmedNonEmptyString.check(Schema.isMaxLength(256)),
42 }),
43 Schema.Struct({
44 type: Schema.Literal("terminal"),
45 id: SetupOperationId,
46 output: Schema.String.check(Schema.isMaxLength(16_384)),
47 outputOffset: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
48 }),
49 Schema.Struct({
50 type: Schema.Literal("credentials"),
51 id: SetupOperationId,
52 fields: Schema.Array(
53 Schema.Struct({
54 name: SetupOperationId,
55 label: TrimmedNonEmptyString,
56 secret: Schema.Boolean,
57 }),
58 ).check(Schema.isMaxLength(16)),
59 }),
60]);
61export type ProviderAuthInteraction = typeof ProviderAuthInteraction.Type;
62​
63export const ProviderAuthResponse = Schema.Union([
64 Schema.Struct({
65 type: Schema.Literal("browser"),
66 action: Schema.Literals(["accept", "decline"]),
67 }),
68 Schema.Struct({
69 type: Schema.Literal("terminal"),
70 data: Schema.String.check(Schema.isMaxLength(4_096)),
71 size: Schema.optionalKey(
72 Schema.Struct({
73 cols: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 500 })),
74 rows: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 200 })),
75 }),
76 ),
77 }),
78 Schema.Struct({
79 type: Schema.Literal("credentials"),
80 values: Schema.Record(SetupOperationId, Schema.String.check(Schema.isMaxLength(16_384))).check(
81 Schema.isMaxProperties(16),
82 ),
83 }),
84]);
85export type ProviderAuthResponse = typeof ProviderAuthResponse.Type;
86​
87export const ProviderAuthStartInput = Schema.Struct({
88 instanceId: ProviderInstanceId,
89 methodId: Schema.optionalKey(SetupOperationId),
90 returnUrl: Schema.optionalKey(Schema.String),
91 callbackMode: Schema.optionalKey(Schema.Literals(["server", "client"])),
92});
93export type ProviderAuthStartInput = typeof ProviderAuthStartInput.Type;
94​
95export const ProviderAuthRemoveMethodInput = Schema.Struct({
96 instanceId: ProviderInstanceId,
97 methodId: SetupOperationId,
98});
99​
100export const ProviderAuthRespondInput = Schema.Struct({
101 instanceId: ProviderInstanceId,
102 flowId: SetupOperationId,
103 interactionId: SetupOperationId,
104 response: ProviderAuthResponse,
105});
106export type ProviderAuthRespondInput = typeof ProviderAuthRespondInput.Type;
107​
108export const ProviderAuthState = Schema.Struct({
109 instanceId: ProviderInstanceId,
110 phase: Schema.Literals([
111 "idle",
112 "starting",
113 "waiting",
114 "verifying",
115 "succeeded",
116 "failed",
117 "cancelled",
118 ]),
119 flowId: Schema.NullOr(SetupOperationId),
120 authorizationUrl: Schema.NullOr(Schema.String),
121 expiresAt: Schema.NullOr(IsoDateTime),
122 message: Schema.NullOr(Schema.String),
123 // Drop unknown auth methods rather than rejecting the entire state.
124 methods: Schema.optionalKey(
125 ForwardCompatibleArray(ProviderAuthMethod).check(Schema.isMaxLength(32)),
126 ),
127 interaction: ForwardCompatibleOptional(Schema.NullOr(ProviderAuthInteraction)),
128 credentialOwner: ForwardCompatibleOptional(Schema.Literals(["provider", "t3"])),
129});
130export type ProviderAuthState = typeof ProviderAuthState.Type;
131​
132export const ProviderAuthCompleteInput = Schema.Struct({
133 instanceId: ProviderInstanceId,
134 flowId: SetupOperationId,
135 callbackUrl: TrimmedNonEmptyString.check(Schema.isMaxLength(16_384)),
136});
137export type ProviderAuthCompleteInput = typeof ProviderAuthCompleteInput.Type;
138​
139export const ProviderAuthCancelInput = Schema.Struct({
140 instanceId: ProviderInstanceId,
141 flowId: SetupOperationId,
142});
143export type ProviderAuthCancelInput = typeof ProviderAuthCancelInput.Type;
144​
145const ByteCount = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
146​
147export const ProviderInstallState = Schema.Struct({
148 driver: ProviderDriverKind,
149 operationId: Schema.NullOr(SetupOperationId),
150 phase: Schema.Literals([
151 "idle",
152 "downloading",
153 "extracting",
154 "verifying",
155 "succeeded",
156 "failed",
157 "cancelled",
158 ]),
159 downloadedBytes: ByteCount,
160 totalBytes: Schema.NullOr(ByteCount),
161 version: Schema.NullOr(TrimmedNonEmptyString),
162 installedVersion: Schema.NullOr(TrimmedNonEmptyString),
163 executablePath: Schema.optionalKey(Schema.NullOr(TrimmedNonEmptyString)),
164 source: Schema.optionalKey(Schema.NullOr(Schema.Literals(["managed", "local"]))),
165 canRemove: Schema.Boolean,
166 message: Schema.NullOr(Schema.String),
167});
168export type ProviderInstallState = typeof ProviderInstallState.Type;
169​
170export const ProviderInstallCancelInput = Schema.Struct({
171 instanceId: ProviderInstanceId,
172 operationId: SetupOperationId,
173});
174export type ProviderInstallCancelInput = typeof ProviderInstallCancelInput.Type;
175​
176/** Safe setup failure text. Never include OAuth codes, URLs, or native token data. */
177export class ProviderSetupError extends Schema.TaggedError<ProviderSetupError>()(
178 "ProviderSetupError",
179 {
180 instanceId: ProviderInstanceId,
181 operation: Schema.String,
182 detail: Schema.String,
183 cause: Schema.optional(Schema.Defect()),
184 },
185) {
186 override get message(): string {
187 return this.detail;
188 }
190​
191export const ChatGptReconnectProfile = Schema.Struct({
192 clientId: Schema.String.check(Schema.isPattern(/^oaiapp_[\w-]+$/u)),
193 subject: Schema.optionalKey(Schema.String),
194 email: Schema.optionalKey(Schema.NullOr(Schema.String)),
195 redirectUri: Schema.optionalKey(
196 Schema.String.check(
197 Schema.isPattern(/^http:\/\/(?:127\.0\.0\.1|localhost):[1-9]\d{0,4}\/auth\/callback$/u),
198 ),
199 ),
200 connectionLabel: Schema.optionalKey(Schema.String),
201 sharingEnabled: Schema.optionalKey(Schema.Boolean),
202 idTokenHint: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(16_384))),
203});
204export type ChatGptReconnectProfile = typeof ChatGptReconnectProfile.Type;
205export const ChatGptTransferredProfile = Schema.Struct({
206 registration: ChatGptReconnectProfile,
207 credentials: Schema.Struct({
208 clientId: Schema.String,
209 accessToken: Schema.NonEmptyString.check(Schema.isMaxLength(16_384)),
210 refreshToken: Schema.NullOr(Schema.String.check(Schema.isMaxLength(16_384))),
211 idToken: Schema.NonEmptyString.check(Schema.isMaxLength(16_384)),
212 issuer: Schema.String,
213 expiresAt: Schema.Finite,
214 earliestRefreshAt: Schema.NullOr(Schema.Finite),
215 scopes: Schema.Array(Schema.String),
216 subject: Schema.String,
217 email: Schema.NullOr(Schema.String),
218 }),
219});
220export type ChatGptTransferredProfile = typeof ChatGptTransferredProfile.Type;
221export const ChatGptReconnectProfileInput = Schema.Struct({
222 instanceId: ProviderInstanceId,
223 methodId: Schema.String,
224});
225export const ChatGptImportProfileInput = Schema.Struct({
226 instanceId: ProviderInstanceId,
227 profile: ChatGptTransferredProfile,
228});
229export const ChatGptHandoffInput = Schema.Struct({
230 instanceId: ProviderInstanceId,
231 environmentId: EnvironmentId,
232 attemptId: Schema.String.check(Schema.isMaxLength(128)),
233 returnUrl: Schema.String.check(Schema.isMaxLength(4_096)),
234 profile: Schema.NullOr(ChatGptReconnectProfile),
235});
236export type ChatGptHandoffInput = typeof ChatGptHandoffInput.Type;
237export const ChatGptHandoffState = Schema.Union([
238 Schema.Struct({ phase: Schema.Literal("auth"), state: ProviderAuthState }),
239 Schema.Struct({ phase: Schema.Literal("finished"), profile: ChatGptTransferredProfile }),
240]);
241export type ChatGptHandoffState = typeof ChatGptHandoffState.Type;