Open History to see the last commit
1import * as Effect from "effect/Effect";
2import * as Schema from "effect/Schema";
3import { AcpRegistryUrlAuthAction } from "./acpRegistry.ts";
4import {
5 type EnvironmentMachineKind,
6 ExecutionEnvironmentDescriptor,
7 ServerSelfUpdateMethod,
8} from "./environment.ts";
9import { AuthClientPresentationMetadata, ServerAuthDescriptor } from "./auth.ts";
10import {
11 ForwardCompatibleArray,
12 IsoDateTime,
13 NonNegativeInt,
14 PositiveInt,
15 ProjectId,
16 ThreadId,
17 TrimmedNonEmptyString,
18} from "./baseSchemas.ts";
19import {
20 KeybindingCommand,
21 KeybindingValue,
22 KeybindingWhen,
23 ResolvedKeybindingsConfig,
24} from "./keybindings.ts";
25import { EditorId, FileManagerRevealKind, RemoteOpenTarget } from "./editor.ts";
26import { ManagedPolicySummary } from "./managedPolicy.ts";
27import { ModelCapabilities, ProviderOptionDescriptor } from "./model.ts";
28import { RuntimeMode } from "./providerPolicy.ts";
29import { ProviderDriverKind, ProviderInstanceId } from "./providerInstance.ts";
30import { ServerProviderUsageLimits, UsageLimitSourceSnapshots } from "./providerUsageLimits.ts";
31import { ServerSettings } from "./settings.ts";
32import { DesktopUpdateChannelSchema } from "./ipc.ts";
33
34const KeybindingsMalformedConfigIssue = Schema.Struct({
35 kind: Schema.Literal("keybindings.malformed-config"),
36 message: TrimmedNonEmptyString,
37});
38
39const KeybindingsInvalidEntryIssue = Schema.Struct({
40 kind: Schema.Literal("keybindings.invalid-entry"),
41 message: TrimmedNonEmptyString,
42 index: Schema.Number,
43});
44
45export const ServerConfigIssue = Schema.Union([
46 KeybindingsMalformedConfigIssue,
47 KeybindingsInvalidEntryIssue,
48]);
49export type ServerConfigIssue = typeof ServerConfigIssue.Type;
50
51const ServerConfigIssues = ForwardCompatibleArray(ServerConfigIssue);
52
53export const ServerProviderState = Schema.Literals(["ready", "warning", "error", "disabled"]);
54export type ServerProviderState = typeof ServerProviderState.Type;
55
56export const ServerProviderAuthStatus = Schema.Literals([
57 "authenticated",
58 "unauthenticated",
59 "unknown",
60]);
61export type ServerProviderAuthStatus = typeof ServerProviderAuthStatus.Type;
62
63export const ServerProviderAuth = Schema.Struct({
64 status: ServerProviderAuthStatus,
65 type: Schema.optional(TrimmedNonEmptyString),
66 label: Schema.optional(TrimmedNonEmptyString),
67 email: Schema.optional(TrimmedNonEmptyString),
68 action: Schema.optional(AcpRegistryUrlAuthAction),
69 canLogout: Schema.optional(Schema.Boolean),
70 subscriptionSharing: Schema.optional(Schema.Boolean),
71 profileId: Schema.optional(TrimmedNonEmptyString),
72 workspaceId: Schema.optional(TrimmedNonEmptyString),
73});
74export type ServerProviderAuth = typeof ServerProviderAuth.Type;
75
76export const ServerProviderModel = Schema.Struct({
77 slug: TrimmedNonEmptyString,
78 name: TrimmedNonEmptyString,
79 shortName: Schema.optional(TrimmedNonEmptyString),
80 subProvider: Schema.optional(TrimmedNonEmptyString),
81 aliases: Schema.optional(Schema.Array(TrimmedNonEmptyString)),
82 badge: Schema.optional(Schema.Literal("new")),
83 isCustom: Schema.Boolean,
84 isDefault: Schema.optional(Schema.Boolean),
85 isLegacy: Schema.optional(Schema.Boolean),
86 // False when the provider can run this model in sessions but not for
87 // application text generation. Absent means supported.
88 supportsTextGeneration: Schema.optional(Schema.Boolean),
89 capabilities: Schema.NullOr(ModelCapabilities),
90});
91export type ServerProviderModel = typeof ServerProviderModel.Type;
92
93export const ServerProviderUpdateRequiredModel = Schema.Struct({
94 slug: TrimmedNonEmptyString,
95 name: TrimmedNonEmptyString,
96 badge: Schema.optional(Schema.Literal("new")),
97 minVersion: TrimmedNonEmptyString,
98});
99export type ServerProviderUpdateRequiredModel = typeof ServerProviderUpdateRequiredModel.Type;
100
101export const ServerProviderSlashCommandInput = Schema.Struct({
102 hint: TrimmedNonEmptyString,
103});
104export type ServerProviderSlashCommandInput = typeof ServerProviderSlashCommandInput.Type;
105
106export const ServerProviderSlashCommand = Schema.Struct({
107 name: TrimmedNonEmptyString,
108 description: Schema.optional(TrimmedNonEmptyString),
109 input: Schema.optional(ServerProviderSlashCommandInput),
110});
111export type ServerProviderSlashCommand = typeof ServerProviderSlashCommand.Type;
112
113export const ServerProviderSkill = Schema.Struct({
114 name: TrimmedNonEmptyString,
115 description: Schema.optional(TrimmedNonEmptyString),
116 path: TrimmedNonEmptyString,
117 scope: Schema.optional(TrimmedNonEmptyString),
118 enabled: Schema.Boolean,
119 displayName: Schema.optional(TrimmedNonEmptyString),
120 shortDescription: Schema.optional(TrimmedNonEmptyString),
121 /** Claude disable-model-invocation: only users can invoke; composers must offer a slash command. */
122 userInvocationOnly: Schema.optional(Schema.Boolean),
123 /** Claude user-invocable:false: only agents can invoke; composers must hide the slash command. */
124 userInvocable: Schema.optional(Schema.Boolean),
125});
126export type ServerProviderSkill = typeof ServerProviderSkill.Type;
127
128export const ServerProviderWorkspaceSnapshot = Schema.Struct({
129 cwd: TrimmedNonEmptyString,
130 checkedAt: IsoDateTime,
131 slashCommands: Schema.Array(ServerProviderSlashCommand),
132 slashCommandsPending: Schema.optional(Schema.Boolean),
133 skills: Schema.Array(ServerProviderSkill),
134 optionDescriptors: Schema.optional(Schema.Array(ProviderOptionDescriptor)),
135 // Absent means the provider's machine `models`, which keeps most snapshots small.
136 models: Schema.optional(Schema.Array(ServerProviderModel)),
137 modelsPending: Schema.optional(Schema.Boolean),
138});
139export type ServerProviderWorkspaceSnapshot = typeof ServerProviderWorkspaceSnapshot.Type;
140
141export const PROVIDER_WORKSPACE_SNAPSHOT_TTL_MS = 5 * 60_000;
142
143export function isProviderWorkspaceSnapshotCurrent(
144 snapshot: Pick<ServerProviderWorkspaceSnapshot, "checkedAt">,
145 nowMs: number,
146): boolean {
147 return nowMs - Date.parse(snapshot.checkedAt) < PROVIDER_WORKSPACE_SNAPSHOT_TTL_MS;
148}
149
150/** A pending snapshot keeps what it found before and is rescanned before its TTL. */
151export function isProviderWorkspaceSnapshotPending(
152 snapshot: Pick<ServerProviderWorkspaceSnapshot, "slashCommandsPending" | "modelsPending">,
153): boolean {
154 return snapshot.slashCommandsPending === true || snapshot.modelsPending === true;
155}
156
157/** Unavailable snapshots must set installed and enabled false. */
158export const ServerProviderAvailability = Schema.Literals(["available", "unavailable"]);
159export type ServerProviderAvailability = typeof ServerProviderAvailability.Type;
160
161export const ServerProviderContinuation = Schema.Struct({
162 groupKey: TrimmedNonEmptyString,
163});
164export type ServerProviderContinuation = typeof ServerProviderContinuation.Type;
165
166export const ServerProviderCompatibilityStatus = Schema.Literals([
167 "unknown",
168 "supported",
169 "graceful",
170 "unsupported",
171 "broken",
172]);
173export const ServerProviderCompatibilityAdvisory = Schema.Struct({
174 status: ServerProviderCompatibilityStatus,
175 latestVersionStatus: Schema.optionalKey(ServerProviderCompatibilityStatus),
176 message: Schema.NullOr(TrimmedNonEmptyString),
177 recommendedVersion: Schema.NullOr(TrimmedNonEmptyString),
178 recommendedRange: Schema.NullOr(TrimmedNonEmptyString),
179});
180export type ServerProviderCompatibilityAdvisory = typeof ServerProviderCompatibilityAdvisory.Type;
181
182export const ServerProviderVersionAdvisoryStatus = Schema.Literals([
183 "unknown",
184 "current",
185 "behind_latest",
186]);
187export type ServerProviderVersionAdvisoryStatus = typeof ServerProviderVersionAdvisoryStatus.Type;
188
189export const ServerProviderVersionAdvisory = Schema.Struct({
190 status: ServerProviderVersionAdvisoryStatus,
191 currentVersion: Schema.NullOr(TrimmedNonEmptyString),
192 latestVersion: Schema.NullOr(TrimmedNonEmptyString),
193 updateCommand: Schema.NullOr(TrimmedNonEmptyString),
194 canUpdate: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
195 canInstallVersion: Schema.optionalKey(Schema.Boolean),
196 checkedAt: Schema.NullOr(IsoDateTime),
197 message: Schema.NullOr(TrimmedNonEmptyString),
198});
199export type ServerProviderVersionAdvisory = typeof ServerProviderVersionAdvisory.Type;
200
201export const ServerProviderUpdateStatus = Schema.Literals([
202 "idle",
203 "queued",
204 "running",
205 "succeeded",
206 "failed",
207 "unchanged",
208]);
209export type ServerProviderUpdateStatus = typeof ServerProviderUpdateStatus.Type;
210
211export const ServerProviderUpdateState = Schema.Struct({
212 status: ServerProviderUpdateStatus,
213 startedAt: Schema.NullOr(IsoDateTime),
214 finishedAt: Schema.NullOr(IsoDateTime),
215 message: Schema.NullOr(TrimmedNonEmptyString),
216 output: Schema.NullOr(Schema.String.check(Schema.isMaxLength(10_000))),
217});
218export type ServerProviderUpdateState = typeof ServerProviderUpdateState.Type;
219
220export const ServerProvider = Schema.Struct({
221 // Only instanceId is stable enough for provider routing.
222 instanceId: ProviderInstanceId,
223 driver: ProviderDriverKind,
224 displayName: Schema.optional(TrimmedNonEmptyString),
225 accentColor: Schema.optional(TrimmedNonEmptyString),
226 // Validate driver-supplied remote icons against the driver's trusted origin.
227 iconUrl: Schema.optional(TrimmedNonEmptyString.check(Schema.isMaxLength(2_048))),
228 badgeLabel: Schema.optional(TrimmedNonEmptyString),
229 continuation: Schema.optional(ServerProviderContinuation),
230 showInteractionModeToggle: Schema.optional(Schema.Boolean),
231 reportsContextWindow: Schema.optional(Schema.Boolean),
232 supportedRuntimeModes: Schema.optional(ForwardCompatibleArray(RuntimeMode)),
233 supportsConversationRollback: Schema.optional(Schema.Boolean),
234 supportsTextGeneration: Schema.optional(Schema.Boolean),
235 setup: Schema.optional(
236 Schema.Struct({
237 canAuthenticate: Schema.Boolean,
238 canInstall: Schema.Boolean,
239 documentationUrl: Schema.optionalKey(TrimmedNonEmptyString.check(Schema.isMaxLength(2_048))),
240 }),
241 ),
242 nativeSessions: Schema.optional(
243 Schema.Struct({
244 canList: Schema.Boolean,
245 canLoad: Schema.Boolean,
246 canResume: Schema.Boolean,
247 canDelete: Schema.optional(Schema.Boolean),
248 }),
249 ),
250 configurableProviders: Schema.optional(Schema.Boolean),
251 runtimePaths: Schema.optionalKey(
252 Schema.Struct({
253 homePath: TrimmedNonEmptyString,
254 shadowHomePath: Schema.NullOr(TrimmedNonEmptyString),
255 }),
256 ),
257 enabled: Schema.Boolean,
258 installed: Schema.Boolean,
259 version: Schema.NullOr(TrimmedNonEmptyString),
260 // Version reported by the installed CLI for a local provider with a separate
261 // server. Null means unknown; absence keeps legacy snapshots on `version`.
262 installedVersion: Schema.optionalKey(Schema.NullOr(TrimmedNonEmptyString)),
263 status: ServerProviderState,
264 auth: ServerProviderAuth,
265 checkedAt: IsoDateTime,
266 message: Schema.optional(TrimmedNonEmptyString),
267 availability: Schema.optional(ServerProviderAvailability),
268 unavailableReason: Schema.optional(TrimmedNonEmptyString),
269 models: Schema.Array(ServerProviderModel),
270 // Kept apart from `models` so clients that predate it never offer them.
271 updateRequiredModels: Schema.optionalKey(Schema.Array(ServerProviderUpdateRequiredModel)),
272 slashCommands: Schema.Array(ServerProviderSlashCommand).pipe(
273 Schema.withDecodingDefault(Effect.succeed([])),
274 ),
275 skills: Schema.Array(ServerProviderSkill).pipe(Schema.withDecodingDefault(Effect.succeed([]))),
276 workspaceSnapshots: Schema.optionalKey(Schema.Array(ServerProviderWorkspaceSnapshot)),
277 usageLimits: Schema.optional(ServerProviderUsageLimits),
278 versionAdvisory: Schema.optionalKey(ServerProviderVersionAdvisory),
279 compatibilityAdvisory: Schema.optionalKey(ServerProviderCompatibilityAdvisory),
280 updateState: Schema.optionalKey(ServerProviderUpdateState),
281 /**
282 * Stands for the machine slash commands and skills, which are then left out. Sent to clients
283 * that ask for catalog digests; they load both lists with their next cwd snapshot.
284 */
285 catalogDigest: Schema.optionalKey(TrimmedNonEmptyString),
286 /** Set by the client, never sent: the `catalogDigest` its slash commands and skills belong to. */
287 loadedCatalogDigest: Schema.optionalKey(TrimmedNonEmptyString),
288});
289export type ServerProvider = typeof ServerProvider.Type;
290
291/** A provider without the lists that equal the ones its reader already holds. */
292export const ServerProviderDelta = ServerProvider.mapFields((fields) => ({
293 ...fields,
294 models: Schema.optionalKey(fields.models),
295 // Declared again without the decoding default, which would read as a change to an empty list.
296 slashCommands: Schema.optionalKey(Schema.Array(ServerProviderSlashCommand)),
297 skills: Schema.optionalKey(Schema.Array(ServerProviderSkill)),
298}));
299export type ServerProviderDelta = typeof ServerProviderDelta.Type;
300
301const sameJson = (left: unknown, right: unknown) =>
302 left === right || JSON.stringify(left) === JSON.stringify(right);
303
304/** Leaves each provider's models, slash commands, and skills out when `previous` has the same. */
305export function serverProviderDeltas(
306 previous: ReadonlyArray<ServerProvider>,
307 next: ReadonlyArray<ServerProvider>,
308): ServerProviderDelta[] {
309 const held = new Map(previous.map((provider) => [provider.instanceId, provider]));
310 return next.map((provider) => {
311 const base = held.get(provider.instanceId);
312 if (base === undefined) return provider;
313 const { models, slashCommands, skills, ...rest } = provider;
314 return {
315 ...rest,
316 ...(sameJson(base.models, models) ? {} : { models }),
317 ...(sameJson(base.slashCommands, slashCommands) ? {} : { slashCommands }),
318 ...(sameJson(base.skills, skills) ? {} : { skills }),
319 };
320 });
321}
322
323/** Rebuilds the provider list `serverProviderDeltas` was made from. */
324export function applyServerProviderDeltas(
325 previous: ReadonlyArray<ServerProvider>,
326 deltas: ReadonlyArray<ServerProviderDelta>,
327): ServerProvider[] {
328 const held = new Map(previous.map((provider) => [provider.instanceId, provider]));
329 return deltas.flatMap((delta) => {
330 const base = held.get(delta.instanceId);
331 const models = delta.models ?? base?.models;
332 const slashCommands = delta.slashCommands ?? base?.slashCommands;
333 const skills = delta.skills ?? base?.skills;
334 // A list this reader never held cannot be rebuilt; drop the provider like an unreadable one.
335 return models && slashCommands && skills ? [{ ...delta, models, slashCommands, skills }] : [];
336 });
337}
338
339export const ServerProviders = ForwardCompatibleArray(ServerProvider);
340export type ServerProviders = typeof ServerProviders.Type;
341
342export const isProviderAvailable = (snapshot: ServerProvider): boolean =>
343 snapshot.availability !== "unavailable";
344
345/** Legacy producers omit this field and support text generation. */
346export const isProviderTextGenerationCapable = (snapshot: ServerProvider): boolean =>
347 snapshot.supportsTextGeneration !== false;
348
349export const OtlpEndpointSource = Schema.Literals(["environment", "bootstrap", "settings"]);
350export type OtlpEndpointSource = typeof OtlpEndpointSource.Type;
351
352export const ServerObservability = Schema.Struct({
353 logsDirectoryPath: TrimmedNonEmptyString,
354 localTracingEnabled: Schema.Boolean,
355 otlpTracesUrl: Schema.optional(TrimmedNonEmptyString),
356 otlpTracesSource: Schema.optional(OtlpEndpointSource),
357 otlpTracesVariable: Schema.optional(TrimmedNonEmptyString),
358 otlpTracesEnabled: Schema.Boolean,
359 otlpMetricsUrl: Schema.optional(TrimmedNonEmptyString),
360 otlpMetricsSource: Schema.optional(OtlpEndpointSource),
361 otlpMetricsVariable: Schema.optional(TrimmedNonEmptyString),
362 otlpMetricsEnabled: Schema.Boolean,
363 otlpLogsUrl: Schema.optional(TrimmedNonEmptyString),
364 otlpLogsSource: Schema.optional(OtlpEndpointSource),
365 otlpLogsVariable: Schema.optional(TrimmedNonEmptyString),
366 otlpLogsEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
367});
368export type ServerObservability = typeof ServerObservability.Type;
369
370export const OtlpSignal = Schema.Literals(["traces", "metrics", "logs"]);
371export type OtlpSignal = typeof OtlpSignal.Type;
372
373export const OtlpEndpointCheckInput = Schema.Struct({
374 signal: OtlpSignal,
375 url: TrimmedNonEmptyString.check(Schema.isPattern(/^https?:\/\/./i)),
376});
377export type OtlpEndpointCheckInput = typeof OtlpEndpointCheckInput.Type;
378
379export const OtlpEndpointCheckResult = Schema.Union([
380 Schema.TaggedStruct("Accepted", { latencyMs: Schema.Number }),
381 Schema.TaggedStruct("Rejected", { status: Schema.Number }),
382 Schema.TaggedStruct("Unreachable", { timedOut: Schema.Boolean }),
383]);
384export type OtlpEndpointCheckResult = typeof OtlpEndpointCheckResult.Type;
385
386/** The client tells the server what it is, so the triage context can name it. */
387export const ServerPrepareTriageInput = Schema.Struct({
388 client: AuthClientPresentationMetadata,
389});
390export type ServerPrepareTriageInput = typeof ServerPrepareTriageInput.Type;
391
392export const ServerPrepareTriageResult = Schema.Struct({
393 /** Composer text that links the session's prompt file. */
394 prompt: Schema.String,
395});
396export type ServerPrepareTriageResult = typeof ServerPrepareTriageResult.Type;
397
398/**
399 * The prompt file links as a chip in the user's message; clients spot a triage
400 * draft by it.
401 */
402export const TRIAGE_PROMPT_FILE_NAME = "triage-playbook.md";
403
404export class ServerPrepareTriageError extends Schema.TaggedError<ServerPrepareTriageError>()(
405 "ServerPrepareTriageError",
406 { cause: Schema.optional(Schema.Defect()) },
407) {
408 override get message(): string {
409 return "Could not write the triage session files.";
410 }
411}
412
413export const ServerTraceDiagnosticsErrorKind = Schema.Literals([
414 "trace-file-not-found",
415 "trace-file-read-failed",
416]);
417export type ServerTraceDiagnosticsErrorKind = typeof ServerTraceDiagnosticsErrorKind.Type;
418
419export const ServerTraceDiagnosticsSpanSummary = Schema.Struct({
420 name: TrimmedNonEmptyString,
421 count: NonNegativeInt,
422 failureCount: NonNegativeInt,
423 totalDurationMs: Schema.Number,
424 averageDurationMs: Schema.Number,
425 maxDurationMs: Schema.Number,
426});
427export type ServerTraceDiagnosticsSpanSummary = typeof ServerTraceDiagnosticsSpanSummary.Type;
428
429export const ServerTraceDiagnosticsFailureSummary = Schema.Struct({
430 name: TrimmedNonEmptyString,
431 cause: TrimmedNonEmptyString,
432 count: NonNegativeInt,
433 lastSeenAt: Schema.DateTimeUtc,
434 traceId: TrimmedNonEmptyString,
435 spanId: TrimmedNonEmptyString,
436});
437export type ServerTraceDiagnosticsFailureSummary = typeof ServerTraceDiagnosticsFailureSummary.Type;
438
439export const ServerTraceDiagnosticsRecentFailure = Schema.Struct({
440 name: TrimmedNonEmptyString,
441 cause: TrimmedNonEmptyString,
442 durationMs: Schema.Number,
443 endedAt: Schema.DateTimeUtc,
444 traceId: TrimmedNonEmptyString,
445 spanId: TrimmedNonEmptyString,
446});
447export type ServerTraceDiagnosticsRecentFailure = typeof ServerTraceDiagnosticsRecentFailure.Type;
448
449export const ServerTraceDiagnosticsSpanOccurrence = Schema.Struct({
450 name: TrimmedNonEmptyString,
451 durationMs: Schema.Number,
452 endedAt: Schema.DateTimeUtc,
453 traceId: TrimmedNonEmptyString,
454 spanId: TrimmedNonEmptyString,
455});
456export type ServerTraceDiagnosticsSpanOccurrence = typeof ServerTraceDiagnosticsSpanOccurrence.Type;
457
458export const ServerTraceDiagnosticsLogEvent = Schema.Struct({
459 spanName: TrimmedNonEmptyString,
460 level: TrimmedNonEmptyString,
461 message: TrimmedNonEmptyString,
462 seenAt: Schema.DateTimeUtc,
463 traceId: TrimmedNonEmptyString,
464 spanId: TrimmedNonEmptyString,
465});
466export type ServerTraceDiagnosticsLogEvent = typeof ServerTraceDiagnosticsLogEvent.Type;
467
468export const ServerTraceDiagnosticsResult = Schema.Struct({
469 traceFilePath: TrimmedNonEmptyString,
470 scannedFilePaths: Schema.Array(TrimmedNonEmptyString),
471 readAt: Schema.DateTimeUtc,
472 recordCount: NonNegativeInt,
473 parseErrorCount: NonNegativeInt,
474 firstSpanAt: Schema.Option(Schema.DateTimeUtc),
475 lastSpanAt: Schema.Option(Schema.DateTimeUtc),
476 failureCount: NonNegativeInt,
477 interruptionCount: NonNegativeInt,
478 slowSpanThresholdMs: NonNegativeInt,
479 slowSpanCount: NonNegativeInt,
480 logLevelCounts: Schema.Record(TrimmedNonEmptyString, NonNegativeInt),
481 topSpansByCount: Schema.Array(ServerTraceDiagnosticsSpanSummary),
482 slowestSpans: Schema.Array(ServerTraceDiagnosticsSpanOccurrence),
483 commonFailures: Schema.Array(ServerTraceDiagnosticsFailureSummary),
484 latestFailures: Schema.Array(ServerTraceDiagnosticsRecentFailure),
485 latestWarningAndErrorLogs: Schema.Array(ServerTraceDiagnosticsLogEvent),
486 partialFailure: Schema.Option(Schema.Boolean),
487 error: Schema.Option(
488 Schema.Struct({
489 kind: ServerTraceDiagnosticsErrorKind,
490 message: TrimmedNonEmptyString,
491 }),
492 ),
493});
494export type ServerTraceDiagnosticsResult = typeof ServerTraceDiagnosticsResult.Type;
495
496export const ServerProcessSignal = Schema.Literals(["SIGINT", "SIGKILL"]);
497export type ServerProcessSignal = typeof ServerProcessSignal.Type;
498
499export const ServerProcessDiagnosticsEntry = Schema.Struct({
500 pid: PositiveInt,
501 startTimeMs: NonNegativeInt,
502 ppid: NonNegativeInt,
503 pgid: Schema.Option(Schema.Int),
504 status: TrimmedNonEmptyString,
505 cpuPercent: Schema.Number,
506 rssBytes: NonNegativeInt,
507 elapsed: TrimmedNonEmptyString,
508 command: TrimmedNonEmptyString,
509 depth: NonNegativeInt,
510 childPids: Schema.Array(PositiveInt),
511});
512export type ServerProcessDiagnosticsEntry = typeof ServerProcessDiagnosticsEntry.Type;
513
514export const ServerProcessDiagnosticsResult = Schema.Struct({
515 serverPid: PositiveInt,
516 readAt: Schema.DateTimeUtc,
517 processCount: NonNegativeInt,
518 totalRssBytes: NonNegativeInt,
519 totalCpuPercent: Schema.Number,
520 processes: Schema.Array(ServerProcessDiagnosticsEntry),
521 error: Schema.Option(
522 Schema.Struct({
523 message: TrimmedNonEmptyString,
524 }),
525 ),
526});
527export type ServerProcessDiagnosticsResult = typeof ServerProcessDiagnosticsResult.Type;
528
529export const ServerProcessResourceHistoryInput = Schema.Struct({
530 windowMs: NonNegativeInt,
531 bucketMs: NonNegativeInt,
532});
533export type ServerProcessResourceHistoryInput = typeof ServerProcessResourceHistoryInput.Type;
534
535export const ServerProcessResourceHistoryBucket = Schema.Struct({
536 startedAt: Schema.DateTimeUtc,
537 endedAt: Schema.DateTimeUtc,
538 avgCpuPercent: Schema.Number,
539 maxCpuPercent: Schema.Number,
540 maxRssBytes: NonNegativeInt,
541 maxProcessCount: NonNegativeInt,
542});
543export type ServerProcessResourceHistoryBucket = typeof ServerProcessResourceHistoryBucket.Type;
544
545export const ServerProcessResourceHistorySummary = Schema.Struct({
546 processKey: TrimmedNonEmptyString,
547 pid: PositiveInt,
548 ppid: NonNegativeInt,
549 command: TrimmedNonEmptyString,
550 depth: NonNegativeInt,
551 isServerRoot: Schema.Boolean,
552 firstSeenAt: Schema.DateTimeUtc,
553 lastSeenAt: Schema.DateTimeUtc,
554 currentCpuPercent: Schema.Number,
555 avgCpuPercent: Schema.Number,
556 maxCpuPercent: Schema.Number,
557 cpuSecondsApprox: Schema.Number,
558 currentRssBytes: NonNegativeInt,
559 maxRssBytes: NonNegativeInt,
560 sampleCount: NonNegativeInt,
561});
562export type ServerProcessResourceHistorySummary = typeof ServerProcessResourceHistorySummary.Type;
563
564export const ServerProcessResourceHistoryFailureTag = Schema.Literals([
565 "ProcessDiagnosticsQueryTimeoutError",
566 "ProcessDiagnosticsQueryFailedError",
567 "ProcessDiagnosticsServerProcessSignalError",
568 "ProcessDiagnosticsNotDescendantError",
569 "ProcessDiagnosticsSignalFailedError",
570]);
571export type ServerProcessResourceHistoryFailureTag =
572 typeof ServerProcessResourceHistoryFailureTag.Type;
573
574export const ServerProcessResourceHistoryResult = Schema.Struct({
575 readAt: Schema.DateTimeUtc,
576 windowMs: NonNegativeInt,
577 bucketMs: NonNegativeInt,
578 sampleIntervalMs: NonNegativeInt,
579 retainedSampleCount: NonNegativeInt,
580 totalCpuSecondsApprox: Schema.Number,
581 buckets: Schema.Array(ServerProcessResourceHistoryBucket),
582 topProcesses: Schema.Array(ServerProcessResourceHistorySummary),
583 error: Schema.Option(
584 Schema.Struct({
585 failureTag: ServerProcessResourceHistoryFailureTag,
586 message: TrimmedNonEmptyString,
587 }),
588 ),
589});
590export type ServerProcessResourceHistoryResult = typeof ServerProcessResourceHistoryResult.Type;
591
592export const ServerSignalProcessInput = Schema.Struct({
593 pid: PositiveInt,
594 startTimeMs: NonNegativeInt,
595 signal: ServerProcessSignal,
596});
597export type ServerSignalProcessInput = typeof ServerSignalProcessInput.Type;
598
599export const ServerSignalProcessResult = Schema.Struct({
600 pid: PositiveInt,
601 signal: ServerProcessSignal,
602 signaled: Schema.Boolean,
603 message: Schema.Option(TrimmedNonEmptyString),
604});
605export type ServerSignalProcessResult = typeof ServerSignalProcessResult.Type;
606
607export const EnvironmentThemeColor = Schema.String.check(
608 Schema.isPattern(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/),
609);
610export type EnvironmentThemeColor = typeof EnvironmentThemeColor.Type;
611
612/** Reserve appearance keywords so published themes cannot replace stock preferences. */
613export const EnvironmentThemeId = Schema.String.check(
614 Schema.isPattern(/^(?!(?:system|light|dark)$)[a-z0-9](?:[a-z0-9-]{0,47})$/),
615);
616export type EnvironmentThemeId = typeof EnvironmentThemeId.Type;
617
618const EnvironmentThemeColors = Schema.Record(
619 Schema.String.check(Schema.isPattern(/^[a-zA-Z][a-zA-Z0-9]{0,63}$/)),
620 TrimmedNonEmptyString.check(Schema.isMaxLength(64)),
621);
622
623const environmentThemeFields = {
624 version: Schema.optional(Schema.Literal(1)),
625 name: TrimmedNonEmptyString.check(Schema.isMaxLength(48)),
626 appearance: Schema.Literals(["light", "dark"]),
627 /** Derive the palette from canvas/accent, then overlay colors; without them, colors is the palette. */
628 canvas: Schema.optional(EnvironmentThemeColor),
629 accent: Schema.optional(EnvironmentThemeColor),
630 colors: Schema.optional(EnvironmentThemeColors),
631 variants: Schema.optional(
632 Schema.Struct({
633 light: Schema.optional(EnvironmentThemeColors),
634 dark: Schema.optional(EnvironmentThemeColors),
635 }),
636 ),
637};
638
639export const EnvironmentThemeFile = Schema.Struct(environmentThemeFields);
640export type EnvironmentThemeFile = typeof EnvironmentThemeFile.Type;
641
642export const EnvironmentTheme = Schema.Struct({
643 id: EnvironmentThemeId,
644 ...environmentThemeFields,
645});
646export type EnvironmentTheme = typeof EnvironmentTheme.Type;
647
648export function environmentThemeFileHasColors(file: EnvironmentThemeFile): boolean {
649 return (
650 (file.canvas !== undefined && file.accent !== undefined) ||
651 (file.colors !== undefined && Object.keys(file.colors).length > 0)
652 );
653}
654
655/** tailnet means this machine's Tailscale interface; other private addresses are lan. */
656export const ServerDirectEndpointKind = Schema.Literals(["lan", "tailnet"]);
657export type ServerDirectEndpointKind = typeof ServerDirectEndpointKind.Type;
658
659export const ServerDirectEndpoint = Schema.Struct({
660 kind: ServerDirectEndpointKind,
661 httpBaseUrl: TrimmedNonEmptyString,
662});
663export type ServerDirectEndpoint = typeof ServerDirectEndpoint.Type;
664
665/**
666 * A stretch where the server's event loop could not run, so it answered
667 * nothing and clients may have dropped the connection.
668 */
669export const ServerEventLoopStall = Schema.Struct({
670 detectedAt: IsoDateTime,
671 durationMs: NonNegativeInt,
672 /** One-minute load average when the stall was seen. Absent on Windows, which has none. */
673 loadAverage: Schema.optionalKey(Schema.Number),
674 cpuCount: PositiveInt,
675});
676export type ServerEventLoopStall = typeof ServerEventLoopStall.Type;
677
678export const ServerConfig = Schema.Struct({
679 environment: ExecutionEnvironmentDescriptor,
680 auth: ServerAuthDescriptor,
681 cwd: TrimmedNonEmptyString,
682 keybindingsConfigPath: TrimmedNonEmptyString,
683 keybindings: ResolvedKeybindingsConfig,
684 issues: ServerConfigIssues,
685 providers: ServerProviders,
686 availableEditors: ForwardCompatibleArray(EditorId),
687 remoteOpenTargets: Schema.optionalKey(ForwardCompatibleArray(RemoteOpenTarget)),
688 /** Hints only; verify each address answers as this environment. */
689 directEndpoints: Schema.optionalKey(ForwardCompatibleArray(ServerDirectEndpoint)),
690 observability: ServerObservability,
691 settings: ServerSettings,
692 /** Present when an administrator's policy file manages this environment. */
693 managedPolicy: Schema.optionalKey(ManagedPolicySummary),
694 shellResumeCompletionMarker: Schema.optionalKey(Schema.Boolean),
695 /**
696 * The shell can leave idle subagent children out of snapshots (`omitIdleSubagents`), and
697 * `getThreadFamily` and `getWorktreeThreadIds` serve the rows it leaves out.
698 */
699 shellThreadFamilies: Schema.optionalKey(Schema.Boolean),
700 threadLinkMetadata: Schema.optionalKey(Schema.Boolean),
701 /**
702 * The shell can leave older settled threads out of snapshots (`omitOlderSettled`), and
703 * `getOlderSettledThreads` serves them. Only servers that also advertise `shellThreadFamilies`.
704 */
705 shellOlderSettled: Schema.optionalKey(Schema.Boolean),
706 shellRevealInFileManager: Schema.optionalKey(Schema.Boolean),
707 shellRevealInFileManagerKind: Schema.optionalKey(FileManagerRevealKind),
708 threadResumeCompletionMarker: Schema.optionalKey(Schema.Boolean),
709 /** Send window fields only when advertised. */
710 threadSnapshotPagination: Schema.optionalKey(Schema.Boolean),
711 threadFind: Schema.optionalKey(Schema.Boolean),
712 threadFindProgressive: Schema.optionalKey(Schema.Boolean),
713 /** Settings patches may carry `secretProviders`; older servers drop the key without an error. */
714 secretProviderSettings: Schema.optionalKey(Schema.Boolean),
715 /** Secret settings may point at a secret provider; older servers drop the reference. */
716 secretReferences: Schema.optionalKey(Schema.Boolean),
717 /** A secret request card may be answered with a secret provider reference. */
718 secretRequestReferences: Schema.optionalKey(Schema.Boolean),
719 scratchWorkspaceRoot: Schema.optionalKey(TrimmedNonEmptyString),
720 newProjectsRoot: Schema.optionalKey(TrimmedNonEmptyString),
721 /**
722 * The latest stall long enough to notice, sent only for a few minutes after
723 * it. A client that reconnects reads it to say why the host stopped
724 * answering. Clients do not cache it, since it describes the host at connect.
725 */
726 lastEventLoopStall: Schema.optionalKey(ServerEventLoopStall),
727 /**
728 * Never sent in a config snapshot: the theme stream emits the current set
729 * before any change, so a snapshot carrying it too would hand every
730 * subscriber the same array twice per connect.
731 */
732 environmentThemes: Schema.optional(Schema.Array(EnvironmentTheme)),
733 /** Stream-only and opt-in; the source stream emits the current set on subscribe. */
734 usageLimitSources: Schema.optional(UsageLimitSourceSnapshots),
735});
736export type ServerConfig = typeof ServerConfig.Type;
737
738export function resolveEnvironmentMachineKind(
739 config: {
740 readonly environment: Pick<ExecutionEnvironmentDescriptor, "platform">;
741 readonly settings?: Pick<ServerSettings, "environmentIcon">;
742 } | null,
743): EnvironmentMachineKind {
744 return config?.settings?.environmentIcon ?? config?.environment.platform.machine ?? "server";
745}
746
747const ServerUpsertKeybindingReplaceTarget = Schema.Struct({
748 key: KeybindingValue,
749 command: KeybindingCommand,
750 when: Schema.optional(KeybindingWhen),
751});
752
753export const ServerUpsertKeybindingInput = Schema.Struct({
754 key: KeybindingValue,
755 command: KeybindingCommand,
756 when: Schema.optional(KeybindingWhen),
757 replace: Schema.optional(ServerUpsertKeybindingReplaceTarget),
758});
759export type ServerUpsertKeybindingInput = typeof ServerUpsertKeybindingInput.Type;
760
761export const ServerRemoveKeybindingInput = ServerUpsertKeybindingReplaceTarget;
762export type ServerRemoveKeybindingInput = typeof ServerRemoveKeybindingInput.Type;
763
764export const ServerUpsertKeybindingResult = Schema.Struct({
765 keybindings: ResolvedKeybindingsConfig,
766 issues: ServerConfigIssues,
767});
768export type ServerUpsertKeybindingResult = typeof ServerUpsertKeybindingResult.Type;
769
770export const ServerRemoveKeybindingResult = ServerUpsertKeybindingResult;
771export type ServerRemoveKeybindingResult = typeof ServerRemoveKeybindingResult.Type;
772
773export const ServerConfigUpdatedPayload = Schema.Struct({
774 issues: ServerConfigIssues,
775 providers: ServerProviders,
776 settings: Schema.optional(ServerSettings),
777});
778export type ServerConfigUpdatedPayload = typeof ServerConfigUpdatedPayload.Type;
779
780export const ServerConfigKeybindingsUpdatedPayload = Schema.Struct({
781 keybindings: ResolvedKeybindingsConfig,
782 issues: ServerConfigIssues,
783});
784export type ServerConfigKeybindingsUpdatedPayload =
785 typeof ServerConfigKeybindingsUpdatedPayload.Type;
786
787export const ServerConfigProviderStatusesPayload = Schema.Struct({
788 providers: ServerProviders,
789});
790export type ServerConfigProviderStatusesPayload = typeof ServerConfigProviderStatusesPayload.Type;
791
792export const ServerConfigProviderStatusDeltasPayload = Schema.Struct({
793 /** Every provider in order, as `serverProviderDeltas` from the list this client last received. */
794 providers: ForwardCompatibleArray(ServerProviderDelta),
795});
796export type ServerConfigProviderStatusDeltasPayload =
797 typeof ServerConfigProviderStatusDeltasPayload.Type;
798
799export const ServerConfigSettingsUpdatedPayload = Schema.Struct({
800 settings: ServerSettings,
801});
802export type ServerConfigSettingsUpdatedPayload = typeof ServerConfigSettingsUpdatedPayload.Type;
803
804export const ServerConfigStreamSnapshotEvent = Schema.Struct({
805 version: Schema.Literal(1),
806 type: Schema.Literal("snapshot"),
807 config: ServerConfig,
808});
809export type ServerConfigStreamSnapshotEvent = typeof ServerConfigStreamSnapshotEvent.Type;
810
811export const ServerConfigStreamKeybindingsUpdatedEvent = Schema.Struct({
812 version: Schema.Literal(1),
813 type: Schema.Literal("keybindingsUpdated"),
814 payload: ServerConfigKeybindingsUpdatedPayload,
815});
816export type ServerConfigStreamKeybindingsUpdatedEvent =
817 typeof ServerConfigStreamKeybindingsUpdatedEvent.Type;
818
819export const ServerConfigStreamProviderStatusesEvent = Schema.Struct({
820 version: Schema.Literal(1),
821 type: Schema.Literal("providerStatuses"),
822 payload: ServerConfigProviderStatusesPayload,
823});
824export type ServerConfigStreamProviderStatusesEvent =
825 typeof ServerConfigStreamProviderStatusesEvent.Type;
826
827export const ServerConfigStreamProviderStatusDeltasEvent = Schema.Struct({
828 version: Schema.Literal(1),
829 type: Schema.Literal("providerStatusDeltas"),
830 payload: ServerConfigProviderStatusDeltasPayload,
831});
832export type ServerConfigStreamProviderStatusDeltasEvent =
833 typeof ServerConfigStreamProviderStatusDeltasEvent.Type;
834
835export const ServerConfigStreamSettingsUpdatedEvent = Schema.Struct({
836 version: Schema.Literal(1),
837 type: Schema.Literal("settingsUpdated"),
838 payload: ServerConfigSettingsUpdatedPayload,
839});
840export type ServerConfigStreamSettingsUpdatedEvent =
841 typeof ServerConfigStreamSettingsUpdatedEvent.Type;
842
843export const ServerConfigEnvironmentThemesUpdatedPayload = Schema.Struct({
844 themes: Schema.Array(EnvironmentTheme),
845});
846export type ServerConfigEnvironmentThemesUpdatedPayload =
847 typeof ServerConfigEnvironmentThemesUpdatedPayload.Type;
848
849export const ServerConfigStreamEnvironmentThemesUpdatedEvent = Schema.Struct({
850 version: Schema.Literal(1),
851 type: Schema.Literal("environmentThemesUpdated"),
852 payload: ServerConfigEnvironmentThemesUpdatedPayload,
853});
854export type ServerConfigStreamEnvironmentThemesUpdatedEvent =
855 typeof ServerConfigStreamEnvironmentThemesUpdatedEvent.Type;
856
857export const ServerConfigUsageLimitSourcesUpdatedPayload = Schema.Struct({
858 sources: UsageLimitSourceSnapshots,
859});
860export type ServerConfigUsageLimitSourcesUpdatedPayload =
861 typeof ServerConfigUsageLimitSourcesUpdatedPayload.Type;
862
863export const ServerConfigStreamUsageLimitSourcesUpdatedEvent = Schema.Struct({
864 version: Schema.Literal(1),
865 type: Schema.Literal("usageLimitSourcesUpdated"),
866 payload: ServerConfigUsageLimitSourcesUpdatedPayload,
867});
868export type ServerConfigStreamUsageLimitSourcesUpdatedEvent =
869 typeof ServerConfigStreamUsageLimitSourcesUpdatedEvent.Type;
870
871export const ServerConfigStreamEvent = Schema.Union([
872 ServerConfigStreamSnapshotEvent,
873 ServerConfigStreamKeybindingsUpdatedEvent,
874 ServerConfigStreamProviderStatusesEvent,
875 ServerConfigStreamProviderStatusDeltasEvent,
876 ServerConfigStreamSettingsUpdatedEvent,
877 ServerConfigStreamEnvironmentThemesUpdatedEvent,
878 ServerConfigStreamUsageLimitSourcesUpdatedEvent,
879]);
880export type ServerConfigStreamEvent = typeof ServerConfigStreamEvent.Type;
881
882export const ServerSelfUpdateOutcome = Schema.Struct({
883 id: TrimmedNonEmptyString,
884 fromVersion: TrimmedNonEmptyString,
885 targetVersion: TrimmedNonEmptyString,
886 status: Schema.Literals(["committed", "rolled-back", "failed"]),
887 reason: Schema.optionalKey(TrimmedNonEmptyString),
888});
889export type ServerSelfUpdateOutcome = typeof ServerSelfUpdateOutcome.Type;
890
891export const ServerLifecycleReadyPayload = Schema.Struct({
892 at: IsoDateTime,
893 environment: ExecutionEnvironmentDescriptor,
894 updateOutcome: Schema.optionalKey(ServerSelfUpdateOutcome),
895});
896export type ServerLifecycleReadyPayload = typeof ServerLifecycleReadyPayload.Type;
897
898export const ServerLifecycleWelcomePayload = Schema.Struct({
899 environment: ExecutionEnvironmentDescriptor,
900 cwd: TrimmedNonEmptyString,
901 projectName: TrimmedNonEmptyString,
902 bootstrapStatus: Schema.optional(Schema.Literals(["pending", "complete"])),
903 bootstrapProjectId: Schema.optional(ProjectId),
904 bootstrapThreadId: Schema.optional(ThreadId),
905 bootstrapProjectCreated: Schema.optional(Schema.Boolean),
906 bootstrapThreadCreated: Schema.optional(Schema.Boolean),
907});
908export type ServerLifecycleWelcomePayload = typeof ServerLifecycleWelcomePayload.Type;
909
910export const ServerLifecycleLegacyThreadMigrationPayload = Schema.Struct({
911 status: Schema.Union([Schema.Literal("running"), Schema.Literal("complete")]),
912 totalThreadCount: NonNegativeInt,
913});
914export type ServerLifecycleLegacyThreadMigrationPayload =
915 typeof ServerLifecycleLegacyThreadMigrationPayload.Type;
916
917export const ServerLifecycleStreamWelcomeEvent = Schema.Struct({
918 version: Schema.Literal(1),
919 sequence: NonNegativeInt,
920 type: Schema.Literal("welcome"),
921 payload: ServerLifecycleWelcomePayload,
922});
923export type ServerLifecycleStreamWelcomeEvent = typeof ServerLifecycleStreamWelcomeEvent.Type;
924
925export const ServerLifecycleStreamReadyEvent = Schema.Struct({
926 version: Schema.Literal(1),
927 sequence: NonNegativeInt,
928 type: Schema.Literal("ready"),
929 payload: ServerLifecycleReadyPayload,
930});
931export type ServerLifecycleStreamReadyEvent = typeof ServerLifecycleStreamReadyEvent.Type;
932
933export const ServerLifecycleStreamLegacyThreadMigrationEvent = Schema.Struct({
934 version: Schema.Literal(1),
935 sequence: NonNegativeInt,
936 type: Schema.Literal("legacyThreadMigration"),
937 payload: ServerLifecycleLegacyThreadMigrationPayload,
938});
939export type ServerLifecycleStreamLegacyThreadMigrationEvent =
940 typeof ServerLifecycleStreamLegacyThreadMigrationEvent.Type;
941
942export const ServerLifecycleStreamEvent = Schema.Union([
943 ServerLifecycleStreamWelcomeEvent,
944 ServerLifecycleStreamReadyEvent,
945 ServerLifecycleStreamLegacyThreadMigrationEvent,
946]);
947export type ServerLifecycleStreamEvent = typeof ServerLifecycleStreamEvent.Type;
948
949export const ServerProviderUpdatedPayload = Schema.Struct({
950 providers: ServerProviders,
951});
952export type ServerProviderUpdatedPayload = typeof ServerProviderUpdatedPayload.Type;
953
954export const ServerProviderUpdateInput = Schema.Struct({
955 provider: ProviderDriverKind,
956 targetVersion: Schema.optionalKey(TrimmedNonEmptyString),
957 instanceId: Schema.optionalKey(ProviderInstanceId),
958});
959export type ServerProviderUpdateInput = typeof ServerProviderUpdateInput.Type;
960
961export class ServerProviderUpdateError extends Schema.TaggedError<ServerProviderUpdateError>()(
962 "ServerProviderUpdateError",
963 {
964 provider: ProviderDriverKind,
965 reason: TrimmedNonEmptyString,
966 cause: Schema.optional(Schema.Defect()),
967 },
968) {
969 override get message(): string {
970 return `Provider update failed for ${this.provider}: ${this.reason}`;
971 }
972}
973
974export const ServerNpmReleaseInput = Schema.Struct({
975 spec: Schema.String.check(
976 Schema.isMaxLength(64),
977 Schema.isPattern(/^(?:latest|nightly|\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/),
978 ),
979});
980export type ServerNpmReleaseInput = typeof ServerNpmReleaseInput.Type;
981
982export const ServerNpmRelease = Schema.Struct({
983 version: Schema.String,
984 databaseMigration: Schema.optionalKey(Schema.Int),
985});
986export type ServerNpmRelease = typeof ServerNpmRelease.Type;
987
988export class ServerNpmReleaseError extends Schema.TaggedError<ServerNpmReleaseError>()(
989 "ServerNpmReleaseError",
990 { reason: Schema.String },
991) {
992 override get message(): string {
993 return `Could not check the configured npm registry: ${this.reason}`;
994 }
995}
996
997export const ServerSelfUpdateInput = Schema.Struct({
998 /** Exact npm version, never a dist-tag, so server and client agree on the request. */
999 targetVersion: TrimmedNonEmptyString,
1000 /** Desktop-managed hosts move their app to this update track first. Sent only for a track switch. */
1001 channel: Schema.optionalKey(DesktopUpdateChannelSchema),
1002 /** The target release's highest migration; the host refuses to leave Nightly without it. */
1003 targetDatabaseMigration: Schema.optionalKey(Schema.Int),
1004});
1005export type ServerSelfUpdateInput = typeof ServerSelfUpdateInput.Type;
1006
1007export const ServerSelfUpdateResult = Schema.Struct({
1008 targetVersion: TrimmedNonEmptyString,
1009 method: ServerSelfUpdateMethod,
1010 updateId: Schema.optionalKey(TrimmedNonEmptyString),
1011 desktopUpdateToken: Schema.optionalKey(TrimmedNonEmptyString),
1012});
1013export type ServerSelfUpdateResult = typeof ServerSelfUpdateResult.Type;
1014
1015export const DesktopUpdateCommitInput = Schema.Struct({
1016 requestId: TrimmedNonEmptyString,
1017});
1018export type DesktopUpdateCommitInput = typeof DesktopUpdateCommitInput.Type;
1019
1020export const ServerSelfUpdateProgressStage = Schema.Literals(["downloading", "installing"]);
1021export type ServerSelfUpdateProgressStage = typeof ServerSelfUpdateProgressStage.Type;
1022
1023export const ServerSelfUpdateProgressEvent = Schema.Union([
1024 Schema.Struct({
1025 type: Schema.Literal("progress"),
1026 stage: ServerSelfUpdateProgressStage,
1027 }),
1028 Schema.Struct({
1029 type: Schema.Literal("complete"),
1030 result: ServerSelfUpdateResult,
1031 }),
1032]);
1033export type ServerSelfUpdateProgressEvent = typeof ServerSelfUpdateProgressEvent.Type;
1034
1035export class ServerSelfUpdateError extends Schema.TaggedError<ServerSelfUpdateError>()(
1036 "ServerSelfUpdateError",
1037 {
1038 reason: TrimmedNonEmptyString,
1039 cause: Schema.optional(Schema.Defect()),
1040 },
1041) {
1042 override get message(): string {
1043 return `Server update failed: ${this.reason}`;
1044 }
1045}