authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-08 01:11:10-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-08 01:11:10-07:00
log060c576f8922703725f0dbdd01443ed88ecc9baa
tree3997f9cf71a5f1c28cb29c70fc161c11aa0d83d4
parent77d9ffc822ac4c1f3600dc6c97e92fc94e9e12a3
signature Signed by PGP key B5690EEEBB952194

refactor(server): classify provider exports (#10278)


19 files changed, 23 insertions(+), 67 deletions(-)

apps/server/src/provider/ClaudeModelCatalog.ts+2-2
...@@ -118,7 +118,7 @@ export function scopeClaudeModelCatalog(...@@ -118,7 +118,7 @@ export function scopeClaudeModelCatalog(
118 return { models: [...builtInModels, ...customCatalogModels] };118 return { models: [...builtInModels, ...customCatalogModels] };
119}119}
120120
121export function resolveClaudeCatalogModel(121function resolveClaudeCatalogModel(
122 catalog: ClaudeModelCatalog,122 catalog: ClaudeModelCatalog,
123 slugOrAlias: string | null | undefined,123 slugOrAlias: string | null | undefined,
124): ClaudeCatalogModel | undefined {124): ClaudeCatalogModel | undefined {
...@@ -215,7 +215,7 @@ export function isClaudeCatalogUltracodeEffort(effort: string | null | undefined...@@ -215,7 +215,7 @@ export function isClaudeCatalogUltracodeEffort(effort: string | null | undefined
215 return effort === "ultracode";215 return effort === "ultracode";
216}216}
217217
218export function resolveClaudeCatalogContextWindow(218function resolveClaudeCatalogContextWindow(
219 catalog: ClaudeModelCatalog,219 catalog: ClaudeModelCatalog,
220 modelSelection: ModelSelection | undefined,220 modelSelection: ModelSelection | undefined,
221): string | undefined {221): string | undefined {
apps/server/src/provider/Drivers/ClaudeSkills.ts+1-1
...@@ -104,7 +104,7 @@ function parseSkillFrontmatter(contents: string): SkillFrontmatter {...@@ -104,7 +104,7 @@ function parseSkillFrontmatter(contents: string): SkillFrontmatter {
104 * user and project one. Absent on almost every machine, which is why a missing104 * user and project one. Absent on almost every machine, which is why a missing
105 * file is the normal case rather than an error.105 * file is the normal case rather than an error.
106 */106 */
107export function claudeManagedSettingsPath(107function claudeManagedSettingsPath(
108 path: Path.Path,108 path: Path.Path,
109 platform: NodeJS.Platform,109 platform: NodeJS.Platform,
110 environment: NodeJS.ProcessEnv,110 environment: NodeJS.ProcessEnv,
apps/server/src/provider/Layers/ProviderAdapterRegistry.ts-7
...@@ -80,13 +80,6 @@ export const ProviderAdapterRegistryLive = Layer.effect(...@@ -80,13 +80,6 @@ export const ProviderAdapterRegistryLive = Layer.effect(
80 makeProviderAdapterRegistry(),80 makeProviderAdapterRegistry(),
81);81);
8282
83// Exposed for tests that want to build a facade over a pre-assembled
84// `ProviderInstanceRegistry` without pulling in the whole boot graph.
85export { makeProviderAdapterRegistry };
86
87// Re-export for consumers that need the accessor shape. The service tag
88// itself lives in `Services/ProviderAdapterRegistry.ts`.
89export { ProviderAdapterRegistry } from "../Services/ProviderAdapterRegistry.ts";
90// Re-export for consumers (including tests) that construct a83// Re-export for consumers (including tests) that construct a
91// `ProviderInstanceId` before calling `getByInstance`.84// `ProviderInstanceId` before calling `getByInstance`.
92export { ProviderInstanceId };85export { ProviderInstanceId };
apps/server/src/provider/Layers/ProviderEventLoggers.ts+2
...@@ -61,6 +61,8 @@ export const NoOpProviderEventLoggers: ProviderEventLoggers["Service"] = {...@@ -61,6 +61,8 @@ export const NoOpProviderEventLoggers: ProviderEventLoggers["Service"] = {
61/**61/**
62 * Builds both stream views over one shared store. Setup failures are logged62 * Builds both stream views over one shared store. Setup failures are logged
63 * and downgraded to the no-op service so diagnostics never block startup.63 * and downgraded to the no-op service so diagnostics never block startup.
64 *
65 * @public Service construction is part of the canonical Effect module API.
64 */66 */
65export const make = Effect.gen(function* () {67export const make = Effect.gen(function* () {
66 const { providerEventLogPath } = yield* ServerConfig;68 const { providerEventLogPath } = yield* ServerConfig;
apps/server/src/provider/Layers/ProviderInstanceRegistryLive.ts-3
...@@ -33,7 +33,6 @@...@@ -33,7 +33,6 @@
33 * @module provider/Layers/ProviderInstanceRegistryLive33 * @module provider/Layers/ProviderInstanceRegistryLive
34 */34 */
35import {35import {
36 defaultInstanceIdForDriver,
37 providerInstanceConfigEnabledFlag,36 providerInstanceConfigEnabledFlag,
38 ProviderInstanceId,37 ProviderInstanceId,
39 type ProviderInstanceConfig,38 type ProviderInstanceConfig,
...@@ -430,5 +429,3 @@ export const ProviderInstanceRegistryMutableLayer = <R>(input: {...@@ -430,5 +429,3 @@ export const ProviderInstanceRegistryMutableLayer = <R>(input: {
430 ),429 ),
431 ),430 ),
432 ) as Layer.Layer<ProviderInstanceRegistry | ProviderInstanceRegistryMutator, never, R>;431 ) as Layer.Layer<ProviderInstanceRegistry | ProviderInstanceRegistryMutator, never, R>;
433
434export { defaultInstanceIdForDriver };
apps/server/src/provider/Layers/codexLaunchArgs.ts+2-3
...@@ -1,14 +1,13 @@...@@ -1,14 +1,13 @@
1import { tokenizeCliArgs } from "@t3tools/shared/cliArgs";1import { tokenizeCliArgs } from "@t3tools/shared/cliArgs";
22
3export const T3CODE_CODEX_LAUNCH_ARGS_ENV = "T3CODE_CODEX_LAUNCH_ARGS";3const T3CODE_CODEX_LAUNCH_ARGS_ENV = "T3CODE_CODEX_LAUNCH_ARGS";
44
5export const resolveCodexLaunchArgs = (5export const resolveCodexLaunchArgs = (
6 launchArgs?: string,6 launchArgs?: string,
7 environment: NodeJS.ProcessEnv = process.env,7 environment: NodeJS.ProcessEnv = process.env,
8) => environment[T3CODE_CODEX_LAUNCH_ARGS_ENV]?.trim() || launchArgs?.trim() || "";8) => environment[T3CODE_CODEX_LAUNCH_ARGS_ENV]?.trim() || launchArgs?.trim() || "";
99
10export const codexLaunchArgv = (launchArgs?: string): ReadonlyArray<string> =>10const codexLaunchArgv = (launchArgs?: string): ReadonlyArray<string> => tokenizeCliArgs(launchArgs);
11 tokenizeCliArgs(launchArgs);
1211
13export const codexAppServerArgs = (launchArgs?: string) => [12export const codexAppServerArgs = (launchArgs?: string) => [
14 "app-server",13 "app-server",
apps/server/src/provider/Layers/codexResetCredit.ts+1
...@@ -45,6 +45,7 @@ export class CodexResetCreditCoordinator extends Context.Service<...@@ -45,6 +45,7 @@ export class CodexResetCreditCoordinator extends Context.Service<
45 }45 }
46>()("t3/provider/Layers/codexResetCredit/CodexResetCreditCoordinator") {}46>()("t3/provider/Layers/codexResetCredit/CodexResetCreditCoordinator") {}
4747
48/** @public Service construction is part of the canonical Effect module API. */
48export const make = Effect.gen(function* () {49export const make = Effect.gen(function* () {
49 const crypto = yield* Crypto.Crypto;50 const crypto = yield* Crypto.Crypto;
50 const statesRef = yield* Ref.make<ReadonlyMap<string, AccountRedemptionState>>(new Map());51 const statesRef = yield* Ref.make<ReadonlyMap<string, AccountRedemptionState>>(new Map());
apps/server/src/provider/Layers/codexUsageLimits.ts+1-1
...@@ -67,7 +67,7 @@ function labelForKind(kind: ServerProviderUsageWindow["kind"]): string {...@@ -67,7 +67,7 @@ function labelForKind(kind: ServerProviderUsageWindow["kind"]): string {
67 * `windowDurationMins`; when it does not, paid plans expose the 5-hour and67 * `windowDurationMins`; when it does not, paid plans expose the 5-hour and
68 * weekly pair and Free/Go expose one monthly allowance.68 * weekly pair and Free/Go expose one monthly allowance.
69 */69 */
70export function codexRateLimitsToWindows(70function codexRateLimitsToWindows(
71 snapshot: CodexRateLimitSnapshot,71 snapshot: CodexRateLimitSnapshot,
72): ReadonlyArray<ServerProviderUsageWindow> {72): ReadonlyArray<ServerProviderUsageWindow> {
73 // Show the main allowance only. Model-specific notifications (such as Spark)73 // Show the main allowance only. Model-specific notifications (such as Spark)
apps/server/src/provider/ModelManifest.ts+3-3
...@@ -207,7 +207,7 @@ export const encodeManifestCache = Schema.encodeEffect(...@@ -207,7 +207,7 @@ export const encodeManifestCache = Schema.encodeEffect(
207);207);
208208
209/** True when the manifest classifies `slug` as legacy for `driverKind`. */209/** True when the manifest classifies `slug` as legacy for `driverKind`. */
210export function isLegacyModel(210function isLegacyModel(
211 manifest: ModelManifestData,211 manifest: ModelManifestData,
212 driverKind: ProviderDriverKind,212 driverKind: ProviderDriverKind,
213 slug: string,213 slug: string,
...@@ -310,8 +310,8 @@ export class ModelManifest extends Context.Service<...@@ -310,8 +310,8 @@ export class ModelManifest extends Context.Service<
310 }310 }
311>()("t3/provider/ModelManifest") {}311>()("t3/provider/ModelManifest") {}
312312
313/** Constant service for tests and callers that only need the bundled data. */313/** Constant service backing the bundled-data test layer. */
314export const BundledOnlyModelManifest: ModelManifest["Service"] = {314const BundledOnlyModelManifest: ModelManifest["Service"] = {
315 current: Effect.succeed(BUNDLED_MODEL_MANIFEST),315 current: Effect.succeed(BUNDLED_MODEL_MANIFEST),
316 refresh: Effect.succeed(BUNDLED_MODEL_MANIFEST),316 refresh: Effect.succeed(BUNDLED_MODEL_MANIFEST),
317 refreshInBackground: Effect.void,317 refreshInBackground: Effect.void,
apps/server/src/provider/OpenCodeServerOwner.ts+2-1
...@@ -8,7 +8,7 @@ import * as Semaphore from "effect/Semaphore";...@@ -8,7 +8,7 @@ import * as Semaphore from "effect/Semaphore";
88
9import * as OpenCodeRuntime from "./opencodeRuntime.ts";9import * as OpenCodeRuntime from "./opencodeRuntime.ts";
1010
11export const OPENCODE_SERVER_IDLE_TTL = "30 seconds";11const OPENCODE_SERVER_IDLE_TTL = "30 seconds";
1212
13interface OpenCodeServerOwnerState {13interface OpenCodeServerOwnerState {
14 server: OpenCodeRuntime.OpenCodeServerProcess | null;14 server: OpenCodeRuntime.OpenCodeServerProcess | null;
...@@ -176,6 +176,7 @@ export const make = Effect.fn("OpenCodeServerOwner.make")(function* (input: {...@@ -176,6 +176,7 @@ export const make = Effect.fn("OpenCodeServerOwner.make")(function* (input: {
176 });176 });
177});177});
178178
179/** @public Service construction is part of the canonical Effect module API. */
179export const layer = (input: {180export const layer = (input: {
180 readonly binaryPath: string;181 readonly binaryPath: string;
181 readonly directory: string;182 readonly directory: string;
apps/server/src/provider/acp/AntigravityAcpSupport.ts+1-1
...@@ -181,7 +181,7 @@ const AUDIO_MIME_TYPES = new Set([...@@ -181,7 +181,7 @@ const AUDIO_MIME_TYPES = new Set([
181 "audio/x-wav",181 "audio/x-wav",
182 "audio/webm",182 "audio/webm",
183]);183]);
184export const ANTIGRAVITY_MAX_AUDIO_ATTACHMENT_BYTES = 20 * 1024 * 1024;184const ANTIGRAVITY_MAX_AUDIO_ATTACHMENT_BYTES = 20 * 1024 * 1024;
185const TEXT_MIME_TYPES = new Set([185const TEXT_MIME_TYPES = new Set([
186 "application/json",186 "application/json",
187 "application/ld+json",187 "application/ld+json",
apps/server/src/provider/acp/AntigravityProtocol.ts+1-3
...@@ -72,9 +72,7 @@ const decodeSecurityWarning = Schema.decodeUnknownOption(...@@ -72,9 +72,7 @@ const decodeSecurityWarning = Schema.decodeUnknownOption(
72 * The agent marks "Allow Always" on shell and web tools with a prompt injection72 * The agent marks "Allow Always" on shell and web tools with a prompt injection
73 * warning in `_meta`. Surface it as option text so both clients can show it.73 * warning in `_meta`. Surface it as option text so both clients can show it.
74 */74 */
75export function antigravitySecurityWarning(75function antigravitySecurityWarning(option: EffectAcpSchema.PermissionOption): string | undefined {
76 option: EffectAcpSchema.PermissionOption,
77): string | undefined {
78 const meta = option._meta;76 const meta = option._meta;
79 if (!Predicate.isObject(meta)) return undefined;77 if (!Predicate.isObject(meta)) return undefined;
80 const warning = Option.getOrUndefined(decodeSecurityWarning(meta[SECURITY_WARNING_META_KEY]));78 const warning = Option.getOrUndefined(decodeSecurityWarning(meta[SECURITY_WARNING_META_KEY]));
apps/server/src/provider/antigravityRelease.ts+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1export const ANTIGRAVITY_RELEASE_VERSION = "agy_acp_server_1.1.1";1const ANTIGRAVITY_RELEASE_VERSION = "agy_acp_server_1.1.1";
22
3export interface AntigravityReleaseAsset {3export interface AntigravityReleaseAsset {
4 readonly version: string;4 readonly version: string;
apps/server/src/provider/opencodeRuntime.ts+2-2
...@@ -438,9 +438,9 @@ export function openCodeQuestionId(...@@ -438,9 +438,9 @@ export function openCodeQuestionId(
438 * puts in the prompt.438 * puts in the prompt.
439 */439 */
440const OPENCODE_NATIVE_IMAGE_MIMES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);440const OPENCODE_NATIVE_IMAGE_MIMES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
441export const OPENCODE_NATIVE_FILE_PART_MAX_BYTES = 20 * 1024 * 1024;441const OPENCODE_NATIVE_FILE_PART_MAX_BYTES = 20 * 1024 * 1024;
442442
443export function isOpenCodeNativeFilePart(input: {443function isOpenCodeNativeFilePart(input: {
444 readonly mimeType: string;444 readonly mimeType: string;
445 readonly sizeBytes: number;445 readonly sizeBytes: number;
446}): boolean {446}): boolean {
apps/server/src/provider/providerMaintenance.ts+1-1
...@@ -33,7 +33,7 @@ const PROVIDER_UPDATE_ACTION_TOAST_MESSAGE = "Install the update now or review p...@@ -33,7 +33,7 @@ const PROVIDER_UPDATE_ACTION_TOAST_MESSAGE = "Install the update now or review p
33 * move on their own, so this mostly bounds how stale a Homebrew "latest" can33 * move on their own, so this mostly bounds how stale a Homebrew "latest" can
34 * get; the npm registry check keeps its own cache.34 * get; the npm registry check keeps its own cache.
35 */35 */
36export const MAINTENANCE_CAPABILITIES_CACHE_TTL = Duration.hours(1);36const MAINTENANCE_CAPABILITIES_CACHE_TTL = Duration.hours(1);
3737
38const compactEnv = (input: Record<string, Option.Option<string>>): NodeJS.ProcessEnv =>38const compactEnv = (input: Record<string, Option.Option<string>>): NodeJS.ProcessEnv =>
39 Object.fromEntries(39 Object.fromEntries(
apps/server/src/provider/providerMaintenanceRunner.ts+1
...@@ -211,6 +211,7 @@ function makeUpdateState(input: {...@@ -211,6 +211,7 @@ function makeUpdateState(input: {
211 };211 };
212}212}
213213
214/** @public Service construction is part of the canonical Effect module API. */
214export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () {215export const make = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
215 const providerRegistry = yield* ProviderRegistry;216 const providerRegistry = yield* ProviderRegistry;
216 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;217 const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
apps/server/src/provider/providerSnapshot.ts-36
...@@ -105,42 +105,6 @@ export const spawnAndCollect = (binaryPath: string, command: ChildProcess.Comman...@@ -105,42 +105,6 @@ export const spawnAndCollect = (binaryPath: string, command: ChildProcess.Comman
105 return result;105 return result;
106 }).pipe(Effect.scoped);106 }).pipe(Effect.scoped);
107107
108export function detailFromResult(
109 result: CommandResult & { readonly timedOut?: boolean },
110): string | undefined {
111 if (result.timedOut) return "Timed out while running command.";
112 const stderr = nonEmptyTrimmed(result.stderr);
113 if (stderr) return stderr;
114 const stdout = nonEmptyTrimmed(result.stdout);
115 if (stdout) return stdout;
116 if (result.code !== 0) {
117 return `Command exited with code ${result.code}.`;
118 }
119 return undefined;
120}
121
122export function extractAuthBoolean(value: unknown): boolean | undefined {
123 if (globalThis.Array.isArray(value)) {
124 for (const entry of value) {
125 const nested = extractAuthBoolean(entry);
126 if (nested !== undefined) return nested;
127 }
128 return undefined;
129 }
130
131 if (!value || typeof value !== "object") return undefined;
132
133 const record = value as Record<string, unknown>;
134 for (const key of ["authenticated", "isAuthenticated", "loggedIn", "isLoggedIn"] as const) {
135 if (typeof record[key] === "boolean") return record[key];
136 }
137 for (const key of ["auth", "status", "session", "account"] as const) {
138 const nested = extractAuthBoolean(record[key]);
139 if (nested !== undefined) return nested;
140 }
141 return undefined;
142}
143
144export function parseGenericCliVersion(output: string): string | null {108export function parseGenericCliVersion(output: string): string | null {
145 const match = output.match(/\b(\d+\.\d+\.\d+)\b/);109 const match = output.match(/\b(\d+\.\d+\.\d+)\b/);
146 return match?.[1] ?? null;110 return match?.[1] ?? null;
apps/server/src/provider/providerUpdateSettings.ts+1-1
...@@ -10,7 +10,7 @@ export interface ProviderSnapshotSettings<Settings> {...@@ -10,7 +10,7 @@ export interface ProviderSnapshotSettings<Settings> {
10 readonly enableProviderUpdateChecks: boolean;10 readonly enableProviderUpdateChecks: boolean;
11}11}
1212
13export function makeProviderSnapshotSettings<Settings>(13function makeProviderSnapshotSettings<Settings>(
14 provider: Settings,14 provider: Settings,
15 settings: ServerSettings,15 settings: ServerSettings,
16): ProviderSnapshotSettings<Settings> {16): ProviderSnapshotSettings<Settings> {
apps/server/src/provider/testUtils/providerRegistryMock.ts+1-1
...@@ -5,7 +5,7 @@ import * as Layer from "effect/Layer";...@@ -5,7 +5,7 @@ import * as Layer from "effect/Layer";
5import * as Stream from "effect/Stream";5import * as Stream from "effect/Stream";
6import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMaintenance.ts";6import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMaintenance.ts";
77
8export const makeProviderRegistryMock = (8const makeProviderRegistryMock = (
9 providers: ReadonlyArray<ServerProvider> = [],9 providers: ReadonlyArray<ServerProvider> = [],
10): ProviderRegistryShape => ({10): ProviderRegistryShape => ({
11 getProviders: Effect.succeed(providers),11 getProviders: Effect.succeed(providers),