Open History to see the last commit
1import * as Effect from "effect/Effect";
2import * as Schema from "effect/Schema";
3
4import {
5 EnvironmentId,
6 ForwardCompatibleOptional,
7 ProjectId,
8 ThreadId,
9 TrimmedNonEmptyString,
10} from "./baseSchemas.ts";
11import { SourceControlProviderKind } from "./sourceControl.ts";
12
13export const ORCHESTRATION_PROTOCOL_VERSION = 2;
14export const ORCHESTRATION_PROTOCOL_VERSION_TEXT = "2";
15export const ORCHESTRATION_PROTOCOL_QUERY_PARAM = "orchestrationProtocol";
16export const ORCHESTRATION_PROTOCOL_HEADER = "x-t3-orchestration-protocol";
17
18/** Wire shapes a client understands, comma-separated; a client that omits one gets the older shape. */
19export const CLIENT_CAPABILITIES_QUERY_PARAM = "clientCapabilities";
20/** Secret fields may hold a secret provider reference instead of a string. */
21export const SETTINGS_SECRET_REFERENCES_CAPABILITY = "settingsSecretReferences";
22
23export const ExecutionEnvironmentPlatformOs = Schema.Literals([
24 "darwin",
25 "linux",
26 "windows",
27 "unknown",
28]);
29export type ExecutionEnvironmentPlatformOs = typeof ExecutionEnvironmentPlatformOs.Type;
30
31export const ExecutionEnvironmentPlatformArch = Schema.Literals(["arm64", "x64", "other"]);
32export type ExecutionEnvironmentPlatformArch = typeof ExecutionEnvironmentPlatformArch.Type;
33
34export const ENVIRONMENT_MACHINE_KINDS = [
35 "server",
36 "cloud",
37 "linux",
38 "desktop",
39 "laptop",
40 "mac-mini",
41 "mac-studio",
42] as const;
43export const EnvironmentMachineKind = Schema.Literals(ENVIRONMENT_MACHINE_KINDS);
44export type EnvironmentMachineKind = typeof EnvironmentMachineKind.Type;
45export const isEnvironmentMachineKind = Schema.is(EnvironmentMachineKind);
46
47export const ExecutionEnvironmentPlatform = Schema.Struct({
48 os: ExecutionEnvironmentPlatformOs,
49 arch: ExecutionEnvironmentPlatformArch,
50 machine: ForwardCompatibleOptional(EnvironmentMachineKind),
51});
52
53// Kept outside settings.ts to avoid an orchestration import cycle.
54export const ThreadEnvMode = Schema.Literals(["local", "worktree"]);
55export type ThreadEnvMode = typeof ThreadEnvMode.Type;
56
57export const WorktreeSubmodules = Schema.Literals(["recursive", "top-level", "none"]);
58export type WorktreeSubmodules = typeof WorktreeSubmodules.Type;
59export type ExecutionEnvironmentPlatform = typeof ExecutionEnvironmentPlatform.Type;
60
61export const ServerSelfUpdateMethod = Schema.Literals(["boot-service", "respawn", "desktop-app"]);
62export type ServerSelfUpdateMethod = typeof ServerSelfUpdateMethod.Type;
63
64export const ServerInstallation = Schema.Union([
65 Schema.Struct({ kind: Schema.Literals(["npx", "pnpm-dlx", "bunx"]) }),
66 Schema.Struct({ kind: Schema.Literal("npm-global"), prefix: TrimmedNonEmptyString }),
67]);
68export type ServerInstallation = typeof ServerInstallation.Type;
69
70export const ServerSelfUpdateCapability = Schema.Literals([
71 "boot-service",
72 "respawn",
73 "desktop-managed",
74]);
75export type ServerSelfUpdateCapability = typeof ServerSelfUpdateCapability.Type;
76
77export const ExecutionEnvironmentCapabilities = Schema.Struct({
78 repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
79 connectionProbe: Schema.optionalKey(Schema.Boolean),
80 attachmentUploads: Schema.optionalKey(Schema.Boolean),
81 questionAttachments: Schema.optionalKey(Schema.Boolean),
82 fileAttachments: Schema.optionalKey(
83 Schema.Struct({
84 maxUploadBytes: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
85 }),
86 ),
87 pullRequests: Schema.optionalKey(Schema.Boolean),
88 pullRequestChecks: Schema.optionalKey(Schema.Boolean),
89 /** Side chats: hidden `lineage.sideChat` forks. Older servers ignore the fork flag. */
90 sideChats: Schema.optionalKey(Schema.Boolean),
91 vcsBranchStatus: Schema.optionalKey(Schema.Boolean),
92 /** Every protocol-2 server sends this; older mobile builds still read it. */
93 inlineMessageContext: Schema.optionalKey(Schema.Boolean),
94 requiredWorktreeBootstrap: Schema.optionalKey(Schema.Boolean),
95 threadSettlement: Schema.optionalKey(Schema.Boolean),
96 threadAutoSettlement: Schema.optionalKey(Schema.Boolean),
97 storageCleanup: Schema.optionalKey(Schema.Boolean),
98 storageCleanupRun: Schema.optionalKey(Schema.Boolean),
99 databaseStorage: Schema.optionalKey(Schema.Boolean),
100 otlpEndpointCheck: Schema.optionalKey(Schema.Boolean),
101 projectWorktreeCleanup: Schema.optionalKey(Schema.Boolean),
102 settledWorktreeCleanup: Schema.optionalKey(Schema.Boolean),
103 worktreesDirectory: Schema.optionalKey(Schema.Boolean),
104 /** Sent by macOS servers, which honor the fastWorktreeCheckout setting. */
105 fastWorktreeCheckout: Schema.optionalKey(Schema.Boolean),
106 threadAutoSettlementScope: Schema.optionalKey(Schema.Boolean),
107 threadRestartContinuation: Schema.optionalKey(Schema.Boolean),
108 projectSettingsOverrides: Schema.optionalKey(Schema.Boolean),
109 /** Hide the switch when absent; older servers silently drop per-project provider patches. */
110 projectProviderInstanceOverrides: Schema.optionalKey(Schema.Boolean),
111 threadSnooze: Schema.optionalKey(Schema.Boolean),
112 /** Serves `orchestration.forceStopThread`; hide Force stop where it is absent. */
113 threadForceStop: Schema.optionalKey(Schema.Boolean),
114 /** Every protocol-2 server sends this; older mobile builds still read it. */
115 environmentThemes: Schema.optionalKey(Schema.Boolean),
116 usageLimitSources: Schema.optionalKey(Schema.Boolean),
117 /** Honors `workspaceSnapshotsOnDemand`; older servers send every snapshot and drop them in the stream. */
118 providerWorkspaceSnapshotsOnDemand: Schema.optionalKey(Schema.Boolean),
119 /** Honors `modelCatalogOnly`; older servers drop the field and probe every provider. */
120 modelCatalogRefresh: Schema.optionalKey(Schema.Boolean),
121 usagePriceOverrides: Schema.optionalKey(Schema.Boolean),
122 usageModelAliases: Schema.optionalKey(Schema.Boolean),
123 threadPinning: Schema.optionalKey(Schema.Boolean),
124 threadPinReorder: Schema.optionalKey(Schema.Boolean),
125 threadActiveReorder: Schema.optionalKey(Schema.Boolean),
126 threadAutoSettleOptOut: Schema.optionalKey(Schema.Boolean),
127 threadProjectFromScratch: Schema.optionalKey(Schema.Boolean),
128 threadTitleRegeneration: Schema.optionalKey(Schema.Boolean),
129 threadVisitedTracking: Schema.optionalKey(Schema.Boolean),
130 threadPullRequestLinking: Schema.optionalKey(Schema.Boolean),
131 serverResolvedCommandContext: Schema.optionalKey(Schema.Boolean),
132 threadStop: Schema.optionalKey(Schema.Boolean),
133 /** Absent on older servers and on Windows hosts, which cannot stop a discovered server. */
134 localServerStop: Schema.optionalKey(Schema.Boolean),
135 threadPullRequests: Schema.optionalKey(Schema.Boolean),
136 threadPullRequestWatch: Schema.optionalKey(Schema.Boolean),
137 pullRequestStackActions: Schema.optionalKey(Schema.Boolean),
138 serverSelfUpdate: Schema.optionalKey(ServerSelfUpdateCapability),
139 /** Server answers server.getNpmRelease using its configured npm registry. */
140 npmReleaseLookup: Schema.optionalKey(Schema.Boolean),
141 /** Manual commands must update this install, not the host's default global prefix. */
142 serverInstallation: ForwardCompatibleOptional(ServerInstallation),
143 serverSelfUpdateProgress: Schema.optionalKey(Schema.Boolean),
144 serverUpdateThreadContinuation: Schema.optionalKey(Schema.Boolean),
145 /** Only explicit false skips Live Activity seeding; older servers may still publish. */
146 agentActivityPublishing: Schema.optionalKey(Schema.Boolean),
147 projectCloneTracking: Schema.optionalKey(Schema.Boolean),
148 /** Server keeps `pinned` and `archived` from project.update. Older servers drop them. */
149 projectOrganization: Schema.optionalKey(Schema.Boolean),
150 /** Server answers projects.listIgnoredFiles. */
151 ignoredFileListing: Schema.optionalKey(Schema.Boolean),
152 environmentIcon: Schema.optionalKey(Schema.Boolean),
153 desktopAppUpdate: Schema.optionalKey(Schema.Boolean),
154 /** The desktop app switches update tracks when a server update request names one. */
155 desktopAppChannelSwitch: Schema.optionalKey(Schema.Boolean),
156 /** Subscribe to command output only when advertised; older servers never send it. */
157 commandOutputStreaming: Schema.optionalKey(Schema.Boolean),
158 /** Server streams conversation counts while importing agent history
159 (`agentSessions.importWithProgress`). Absent on older servers, where
160 clients must use the unary `agentSessions.import`. */
161 agentSessionImportProgress: Schema.optionalKey(Schema.Boolean),
162 /** Hosts headless Chromium tabs streamed over /api/preview-stream for clients without a local runtime. */
163 serverBrowser: Schema.optionalKey(Schema.Boolean),
164 /** Server links to other environments (`PeerLink`) and its agents can work
165 in them. Absent on servers from before linking, which clients must not
166 offer linking for. */
167 peerLinks: Schema.optionalKey(Schema.Boolean),
168 /** Server's `/mcp` narrows an OAuth client's modes from `T3-Mode-Limit`, so
169 a linked environment's calls keep its agent's limits. Another environment
170 links to this one only when it is set. */
171 mcpModeLimitHeader: Schema.optionalKey(Schema.Boolean),
172 /** Work a linked environment starts here stays within its link
173 (`linkOrigin`). Another environment links to this one only when it is
174 set, since without it that work could change the user's own threads. */
175 linkFence: Schema.optionalKey(Schema.Boolean),
176 /** Mints pairing codes that approve one agent sign-in at a set level (`AUTO-…`). */
177 mcpApprovalCodes: Schema.optionalKey(Schema.Boolean),
178 /** Agent sign-ins on its T3 Connect address are approved on the hosted app, without a code. */
179 mcpHostedApproval: Schema.optionalKey(Schema.Boolean),
180 /** Server answers server.prepareTriage. */
181 triage: Schema.optionalKey(Schema.Boolean),
182 /** Server accepts `{ type: "once" }` scheduled tasks; older servers reject them on save. */
183 oneTimeSchedules: Schema.optionalKey(Schema.Boolean),
184 /** Server honors `freshContext` on sends; older servers ignore it and keep the old context. */
185 freshContext: Schema.optionalKey(Schema.Boolean),
186 /** Server saves and runs scheduled task `threadMode`; older servers ignore it. */
187 scheduledTaskThreadModes: Schema.optionalKey(Schema.Boolean),
188 /** Server can transcribe 16 kHz mono PCM audio on the environment machine. */
189 voiceTranscription: Schema.optionalKey(Schema.Boolean),
190 cloudVoiceTranscription: Schema.optionalKey(Schema.Boolean),
191 /**
192 * The server config's flags of the same names. A server that names them here lets a client
193 * load the shell snapshot before the socket opens, and answers its `resumeFrom`.
194 */
195 shellThreadFamilies: Schema.optionalKey(Schema.Boolean),
196 shellOlderSettled: Schema.optionalKey(Schema.Boolean),
197});
198export type ExecutionEnvironmentCapabilities = typeof ExecutionEnvironmentCapabilities.Type;
199
200export const ExecutionEnvironmentDescriptor = Schema.Struct({
201 environmentId: EnvironmentId,
202 label: TrimmedNonEmptyString,
203 platform: ExecutionEnvironmentPlatform,
204 serverVersion: TrimmedNonEmptyString,
205 orchestrationProtocolVersion: Schema.optionalKey(Schema.Int),
206 /** Highest migration this server's database holds; absent on older servers. */
207 databaseMigration: Schema.optionalKey(Schema.Int),
208 capabilities: ExecutionEnvironmentCapabilities,
209});
210export type ExecutionEnvironmentDescriptor = typeof ExecutionEnvironmentDescriptor.Type;
211
212export const RepositoryIdentityLocator = Schema.Struct({
213 source: Schema.Literal("git-remote"),
214 remoteName: TrimmedNonEmptyString,
215 remoteUrl: TrimmedNonEmptyString,
216});
217export type RepositoryIdentityLocator = typeof RepositoryIdentityLocator.Type;
218
219export const RepositoryOrigin = Schema.Struct({
220 canonicalKey: TrimmedNonEmptyString,
221 remoteUrl: Schema.optionalKey(TrimmedNonEmptyString),
222 displayName: Schema.optionalKey(TrimmedNonEmptyString),
223});
224export type RepositoryOrigin = typeof RepositoryOrigin.Type;
225
226export const RepositoryIdentity = Schema.Struct({
227 canonicalKey: TrimmedNonEmptyString,
228 locator: RepositoryIdentityLocator,
229 webUrl: Schema.optionalKey(TrimmedNonEmptyString),
230 /** Work tree root, or the git dir for a bare repository. */
231 rootPath: Schema.optionalKey(TrimmedNonEmptyString),
232 displayName: Schema.optionalKey(TrimmedNonEmptyString),
233 provider: Schema.optionalKey(SourceControlProviderKind),
234 owner: Schema.optionalKey(TrimmedNonEmptyString),
235 name: Schema.optionalKey(TrimmedNonEmptyString),
236 origin: Schema.optionalKey(RepositoryOrigin),
237});
238export type RepositoryIdentity = typeof RepositoryIdentity.Type;
239
240export function repositoryGroupingKeyOf(identity: RepositoryIdentity): string {
241 return identity.origin?.canonicalKey ?? identity.canonicalKey;
242}
243
244export function repositoryGroupingDisplayNameOf(identity: RepositoryIdentity): string | undefined {
245 return identity.origin
246 ? (identity.origin.displayName ?? identity.origin.canonicalKey)
247 : identity.displayName;
248}
249
250export const ScopedProjectRef = Schema.Struct({
251 environmentId: EnvironmentId,
252 projectId: ProjectId,
253});
254export type ScopedProjectRef = typeof ScopedProjectRef.Type;
255
256export const ScopedThreadRef = Schema.Struct({
257 environmentId: EnvironmentId,
258 threadId: ThreadId,
259});
260export type ScopedThreadRef = typeof ScopedThreadRef.Type;