From 56e9e1ca6636422dea2f43e5c28d3af1b025386a Mon Sep 17 00:00:00 2001 From: Henry Chu Date: Wed, 21 Oct 2026 13:10:39 -0400 Subject: [PATCH] Fix the 688ee52f0e sync review findings - Show a draft video attached to a question answer: the composer has no video tiles, so composerOtherFilesForPresentation now lists videos with the other files instead of dropping them. - Remove code that cut surfaces left unused, found with tsc --noUnusedLocals and kept only where upstream's own file has the same leftover: imports and locals across web, server, gateway, and tests; upstream's Claude history-fork worker, which points at a script the fork does not carry; the fork's unused helpers in client-runtime; and themePalettes.ts back to upstream's file. - ChatView uses upstream's inline activeProject checks, drops blank lines left by cuts, and moves the local-editor note to where that code was cut. - Add or normalize Coder: notes where kept code differs from upstream. - coder-only.md: document cut prompt links, the composer video listing, and every attachmentDisplay user; drop the removed RunExecutionService test note. Co-Authored-By: Claude Opus 5.5 --- apps/coder-gateway/src/server.ts | 3 - apps/server/src/git/GitManager.test.ts | 1 - .../Adapters/ClaudeAdapterV2.test.ts | 78 ------------------- .../Adapters/ClaudeAdapterV2.ts | 59 -------------- .../ProviderAdapterRegistry.test.ts | 1 - .../RunExecutionService.test.ts | 25 ------ ...estratorReplayRecovery.integration.test.ts | 1 - .../src/provider/AcpRegistryProbe.test.ts | 4 - apps/server/src/provider/CodexRuntimeModes.ts | 4 - .../src/provider/ProviderAuthService.ts | 4 - .../provider/ProviderInstanceRegistry.test.ts | 3 - .../src/provider/ProviderRegistry.test.ts | 2 - .../PullRequestService.coder.test.ts | 2 +- .../pullRequest/PullRequestService.test.ts | 1 - .../scheduledTasks/ScheduledTaskService.ts | 2 - .../SourceControlDiscovery.test.ts | 1 - .../SourceControlRepositoryService.ts | 2 - apps/server/src/terminal/Manager.test.ts | 3 - apps/server/src/ws.test.ts | 3 - apps/server/src/ws.ts | 2 - apps/web/src/components/ChatMarkdown.tsx | 1 - apps/web/src/components/ChatView.logic.ts | 2 +- apps/web/src/components/ChatView.tsx | 13 ++-- apps/web/src/components/CommandPalette.tsx | 7 +- apps/web/src/components/RightPanelTabs.tsx | 1 - apps/web/src/components/chat/ChatComposer.tsx | 8 +- .../chat/ComposerFooterControls.tsx | 2 +- .../components/chat/ExpandedImageDialog.tsx | 1 - .../components/chat/TimelineAssistantRows.tsx | 1 + .../chat/UserMessageContextChips.tsx | 1 + apps/web/src/components/chat/chatViewSend.ts | 2 + .../chat/composerAttachmentFiles.ts | 21 +---- .../files/AttachmentFilePreview.tsx | 2 +- .../src/components/files/FilePreviewPanel.tsx | 1 - .../pullRequestDetail.logic.test.ts | 1 - .../settings/AppearanceSettingsPanel.tsx | 1 - .../settings/BackgroundActivitySettings.tsx | 1 - .../settings/KeybindingsSettings.tsx | 6 -- .../settings/ProjectSettingsPanel.tsx | 1 - .../settings/ProviderInstanceCard.tsx | 1 - .../components/settings/SettingsPanels.tsx | 4 +- .../components/sidebar/SidebarDraftBlock.tsx | 1 + apps/web/src/hooks/useSettings.ts | 1 - apps/web/src/modelSelection.test.ts | 1 - apps/web/src/routes/__root.tsx | 1 - apps/web/src/state/server.ts | 2 +- docs/internals/coder-only.md | 13 ++-- .../client-runtime/src/connection/catalog.ts | 4 - packages/client-runtime/src/state/server.ts | 9 --- .../src/state/shellSnapshotHttp.ts | 1 - .../src/server/adapter.ts | 1 - packages/shared/src/themePalettes.ts | 16 ++-- 52 files changed, 41 insertions(+), 288 deletions(-) diff --git a/apps/coder-gateway/src/server.ts b/apps/coder-gateway/src/server.ts index 6551dee6cd6f..482b7dae23d2 100644 --- a/apps/coder-gateway/src/server.ts +++ b/apps/coder-gateway/src/server.ts @@ -47,16 +47,13 @@ import { type CoderInvocation, } from "@t3tools/coder-cli/command"; import { - CoderHelperConnectionError, CoderHelperInstallRequiredError, connectCoderHelper, type CoderHelperConnection, - type CoderHelperExit, } from "@t3tools/coder-cli/helperConnection"; import { connectCoderPortForward, type CoderPortForwardConnection, - type CoderPortForwardExit, } from "@t3tools/coder-cli/portForward"; import { hashCoderHelperBundle, diff --git a/apps/server/src/git/GitManager.test.ts b/apps/server/src/git/GitManager.test.ts index 772855f89b67..38cf8f4fb23a 100644 --- a/apps/server/src/git/GitManager.test.ts +++ b/apps/server/src/git/GitManager.test.ts @@ -9,7 +9,6 @@ import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import * as Context from "effect/Context"; import * as Deferred from "effect/Deferred"; -import * as Exit from "effect/Exit"; import * as Fiber from "effect/Fiber"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; diff --git a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts index 3aede3a05d54..09a42d61f479 100644 --- a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts @@ -1,5 +1,4 @@ // @effect-diagnostics nodeBuiltinImport:off -- workflow fixtures use files and the fake Claude CLI uses Node streams -import { OrchestrationV2UserInputQuestion } from "@t3tools/contracts"; import * as NodeFS from "node:fs"; import * as NodePath from "node:path"; @@ -32,7 +31,6 @@ import { type OrchestrationV2ProviderThread, ProjectId, ProviderInstanceId, - type ProviderInstanceEnvironment, ProviderDriverKind, type ProviderReplayTranscript, type ProviderApprovalDecision, @@ -65,7 +63,6 @@ import { getModelSelectionStringOptionValue } from "@t3tools/shared/model"; import { attachmentRelativePath } from "../../attachmentStore.ts"; import { WorkflowAgentTranscriptReadObserver } from "../workflowAgentTranscript.ts"; -import * as ServerConfig from "../../config.ts"; import * as McpProviderSession from "@t3tools/provider-core/server/mcpSession"; import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers"; @@ -86,12 +83,6 @@ import { projectionFor, } from "../testkit/fixtures/shared.ts"; -// Coder: the Agent SDK is type-only, so the adapter reads Claude's settings files itself and -// these tests write those files instead of mocking the SDK's `resolveSettings`. -const decodeUserInputQuestions = Schema.decodeUnknownSync( - Schema.Array(OrchestrationV2UserInputQuestion), -); - const DEFAULT_CLAUDE_SETTINGS = Schema.decodeSync(ClaudeSettings)({}); const AUTO_COMPACT_CLAUDE_SETTINGS = Schema.decodeSync(ClaudeSettings)({ autoCompactWindow: "300000", @@ -900,75 +891,6 @@ describe("ClaudeAdapterV2 approval cancellation", () => { ); }); -const captureSdkExecutablePaths = Effect.fn("captureSdkExecutablePaths")(function* ( - binaryPath: string, - environment: ProviderInstanceEnvironment = [], -) { - const executablePaths: Array = []; - const taskToolEnvironment: Array = []; - const adapter = yield* ClaudeAdapterV2.createClaudeAdapterV2( - { - instanceId: ClaudeAdapterV2.CLAUDE_DEFAULT_INSTANCE_ID, - displayName: undefined, - environment, - enabled: true, - config: { ...DEFAULT_CLAUDE_SETTINGS, binaryPath }, - }, - {}, - ).pipe( - Effect.provide( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-claude-binary-path-", - }), - ), - Effect.provideService(ClaudeAdapterV2.ClaudeAgentSdkQueryRunner, { - allocateSessionId: Effect.succeed("native-thread-claude-binary-path"), - open: (input) => - Effect.sync(() => { - executablePaths.push(input.options.pathToClaudeCodeExecutable); - taskToolEnvironment.push(input.options.env?.CLAUDE_CODE_ENABLE_TODO_TOOLS); - return { - messages: Stream.never, - offer: () => Effect.void, - setModel: () => Effect.void, - applyFlagSettings: () => Effect.void, - setPermissionMode: () => Effect.void, - backgroundTasks: () => Effect.succeed(false), - stopTask: () => Effect.void, - interrupt: Effect.void, - close: Effect.void, - }; - }), - forkSession: () => Effect.die("unused"), - subagentLaunchToolUseId: () => Effect.succeed(null), - assertComplete: Effect.void, - }), - ); - const threadId = ThreadId.make("thread-claude-binary-path"); - const runtime = yield* adapter.openSession({ - threadId, - providerSessionId: ProviderSessionId.make("provider-session-claude-binary-path"), - modelSelection: CLAUDE_TEST_MODEL_SELECTION, - runtimePolicy: CLAUDE_TEST_RUNTIME_POLICY, - }); - const providerThread = yield* runtime.ensureThread({ - threadId, - modelSelection: CLAUDE_TEST_MODEL_SELECTION, - runtimePolicy: CLAUDE_TEST_RUNTIME_POLICY, - }); - yield* runtime.startTurn( - makeClaudeTestTurnInput({ - threadId, - providerThread, - now: yield* DateTime.now, - attemptId: RunAttemptId.make("attempt-claude-binary-path"), - text: "hello", - attachments: [], - }), - ); - return { executablePaths, taskToolEnvironment }; -}); - describe("ClaudeAdapterV2 resumeThread", () => { it.effect("fails for a transcript without messages so a fresh session replaces it", () => Effect.scoped( diff --git a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts index 2734a36708ae..6aefc2472593 100644 --- a/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts @@ -113,7 +113,6 @@ import * as Ref from "effect/Ref"; import * as Schema from "effect/Schema"; import * as Semaphore from "effect/Semaphore"; import * as Stream from "effect/Stream"; -import * as ChildProcess from "effect/process/ChildProcess"; import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner"; import { @@ -130,7 +129,6 @@ import { } from "../../claudeModelOptions.ts"; import * as ServerConfig from "../../config.ts"; import { expandHomePath } from "@t3tools/provider-core/server/pathExpansion"; -import { spawnAndCollect } from "@t3tools/provider-core/server/snapshotProbe"; import { signalProcessGroup } from "@t3tools/provider-core/server/processGroup"; import { claudeSignedOutMessage, @@ -809,61 +807,6 @@ function makeClaudeAgentSdkProtocolLogger(input: { }; } -const encodeClaudeHistoryOptions = Schema.encodeSync(Schema.fromJsonString(Schema.Unknown)); -const decodeClaudeHistoryFork = Schema.decodeUnknownEffect( - Schema.fromJsonString( - Schema.Struct({ sessionId: Schema.String, headMessageId: Schema.optionalKey(Schema.String) }), - ), -); - -const claudeConfigDirOf = ( - path: Path.Path, - environment: NodeJS.ProcessEnv, - homeDirectory: string, -) => path.resolve(environment.CLAUDE_CONFIG_DIR ?? path.join(homeDirectory, ".claude")); - -// The SDK reads CLAUDE_CONFIG_DIR from process.env. Isolate custom homes in a -// worker so concurrent providers keep the server's environment. -const forkClaudeSessionInWorker = Effect.fn("forkClaudeSessionInWorker")(function* ( - input: ClaudeAgentSdkSessionForkInput, -) { - const path = yield* Path.Path; - const fromSource = import.meta.url.endsWith(".ts"); - // A single executable hosts the worker itself; it has no sibling script. - const workerArguments = (yield* HostProcess.IsExecutable) - ? ["__claude-history"] - : [ - ...(fromSource ? ["--experimental-strip-types"] : []), - yield* path.fromFileUrl( - new URL( - fromSource ? "../../claude-history-worker.ts" : "./claude-history-worker.mjs", - import.meta.url, - ), - ), - ]; - const executablePath = yield* HostProcess.ExecutablePath; - const result = yield* spawnAndCollect( - executablePath, - ChildProcess.make( - executablePath, - [ - ...workerArguments, - "forkSession", - input.sessionId, - encodeClaudeHistoryOptions(input.options), - ], - { env: { ...input.environment, ELECTRON_RUN_AS_NODE: "1" } }, - ), - ).pipe(Effect.timeout("30 seconds")); - if (result.code !== 0) { - return yield* new ClaudeAgentSdkQueryRunnerError({ - method: "forkSession", - cause: result.stderr.trim() || `Claude history worker exited with code ${result.code}.`, - }); - } - return yield* decodeClaudeHistoryFork(result.stdout); -}); - export const layerQueryRunner: Layer.Layer< ClaudeAgentSdkQueryRunner, never, @@ -875,8 +818,6 @@ export const layerQueryRunner: Layer.Layer< ClaudeAgentSdkQueryRunner, Effect.gen(function* () { const crypto = yield* Crypto.Crypto; - const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; - const path = yield* Path.Path; const { native: nativeEventLogger } = yield* ProviderEventLoggers.ProviderEventLoggers; const agentScope = yield* AgentScope; const platform = yield* HostProcess.Platform; diff --git a/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts b/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts index 23712f8491e8..38bc9e9d0d8c 100644 --- a/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts +++ b/apps/server/src/orchestration-v2/ProviderAdapterRegistry.test.ts @@ -1,4 +1,3 @@ -import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; import { ProviderDriverKind, diff --git a/apps/server/src/orchestration-v2/RunExecutionService.test.ts b/apps/server/src/orchestration-v2/RunExecutionService.test.ts index 6913da1d142e..4dcfaa069f5d 100644 --- a/apps/server/src/orchestration-v2/RunExecutionService.test.ts +++ b/apps/server/src/orchestration-v2/RunExecutionService.test.ts @@ -1,4 +1,3 @@ -import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; import { CheckpointScopeId, @@ -26,7 +25,6 @@ import { ServerSettingsError, ThreadId, TurnItemId, - EnvironmentId, } from "@t3tools/contracts"; import * as Cause from "effect/Cause"; import * as Exit from "effect/Exit"; @@ -38,10 +36,6 @@ import * as Option from "effect/Option"; import * as Ref from "effect/Ref"; import * as Stream from "effect/Stream"; -import * as CoderEnvironment from "../coderEnvironment.ts"; -import * as T3ToolDispatch from "../mcp/bridge/T3ToolDispatch.ts"; - -import * as McpSessionRegistry from "../mcp/McpSessionRegistry.ts"; import * as ServerSettings from "../serverSettings.ts"; import * as CheckpointService from "./CheckpointService.ts"; import type { PendingOrchestrationEffectV2 } from "./EffectOutbox.ts"; @@ -1095,25 +1089,6 @@ it.effect( }).pipe(Effect.provide(layerRunExecutionTest)), ); -const layerMcpSessionRegistryTest = McpSessionRegistry.layer.pipe( - Layer.provide( - Layer.mergeAll( - NodeServices.layer, - // Coder: the registry reads the Coder environment and the T3 tool dispatch, not an HTTP - // server and upstream's ServerEnvironment. - Layer.succeed( - CoderEnvironment.CoderEnvironment, - CoderEnvironment.CoderEnvironment.of({ - descriptor: { - environmentId: EnvironmentId.make("environment:mcp-liveness"), - } as CoderEnvironment.CoderEnvironment["Service"]["descriptor"], - }), - ), - T3ToolDispatch.layer, - ), - ), -); - it.effect("starts the provider when checkpoint baseline capture fails", () => Effect.gen(function* () { const threadId = ThreadId.make("thread:run-execution-baseline-failure"); diff --git a/apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts b/apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts index 0ab0dda081c1..7275ca7113cd 100644 --- a/apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts +++ b/apps/server/src/orchestration-v2/testkit/OrchestratorReplayRecovery.integration.test.ts @@ -50,7 +50,6 @@ import { runOrchestratorV2ProviderReplayScenario, } from "./ProviderReplayHarness.ts"; import { checkpointWorkspace } from "@t3tools/provider-testing/replayWorkspace"; -import { materializeReplayTranscriptRuntimeInstructions } from "./ReplayRuntimeInstructions.ts"; import { materializeReplayTranscriptWorkspace, readProviderReplayTranscript, diff --git a/apps/server/src/provider/AcpRegistryProbe.test.ts b/apps/server/src/provider/AcpRegistryProbe.test.ts index e171c0707c53..cbaa78659daa 100644 --- a/apps/server/src/provider/AcpRegistryProbe.test.ts +++ b/apps/server/src/provider/AcpRegistryProbe.test.ts @@ -2,8 +2,6 @@ import * as TestClock from "effect/testing/TestClock"; import * as Fiber from "effect/Fiber"; import * as Deferred from "effect/Deferred"; -import * as NodePath from "node:path"; -import * as NodeURL from "node:url"; import * as NodeServices from "@effect/platform-node/NodeServices"; import { ProviderInstanceId } from "@t3tools/contracts"; @@ -24,8 +22,6 @@ import { import * as AcpRegistrySupport from "@t3tools/provider-acp-registry/server/AcpRegistrySupport"; const instanceId = ProviderInstanceId.make("acpRegistry_codex"); -const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); -const mockAgentPath = NodePath.join(__dirname, "../../scripts/acp-mock-agent.ts"); const decodeSettings = Schema.decodeSync(AcpRegistrySettings); describe("ACP Registry probe", () => { diff --git a/apps/server/src/provider/CodexRuntimeModes.ts b/apps/server/src/provider/CodexRuntimeModes.ts index 15068c5b46ab..806be1672fde 100644 --- a/apps/server/src/provider/CodexRuntimeModes.ts +++ b/apps/server/src/provider/CodexRuntimeModes.ts @@ -68,10 +68,6 @@ export const CODEX_RUNTIME_MODE_CONFIG = { }, } as const satisfies Readonly>; -function getCodexRuntimeModeConfig(runtimeMode: RuntimeMode): CodexRuntimeModeConfig { - return CODEX_RUNTIME_MODE_CONFIG[runtimeMode]; -} - export function resolveCodexSupportedRuntimeModes( response: CodexRuntimeRequirementsResponse | undefined, ): ReadonlyArray { diff --git a/apps/server/src/provider/ProviderAuthService.ts b/apps/server/src/provider/ProviderAuthService.ts index 05855641f81a..ab5f72d51975 100644 --- a/apps/server/src/provider/ProviderAuthService.ts +++ b/apps/server/src/provider/ProviderAuthService.ts @@ -13,16 +13,12 @@ import { type ProviderAuthStartInput, type ProviderAuthState, type ProviderInstanceId, - type ProviderSessionId, } from "@t3tools/contracts"; import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; -import * as Function from "effect/Function"; import * as Layer from "effect/Layer"; import * as Stream from "effect/Stream"; -import type { ProviderAuthController } from "@t3tools/provider-core/server/auth"; - export type { ProviderAuthController } from "@t3tools/provider-core/server/auth"; interface ProviderAuthTarget { diff --git a/apps/server/src/provider/ProviderInstanceRegistry.test.ts b/apps/server/src/provider/ProviderInstanceRegistry.test.ts index fa76c3ec870c..d3479d352caf 100644 --- a/apps/server/src/provider/ProviderInstanceRegistry.test.ts +++ b/apps/server/src/provider/ProviderInstanceRegistry.test.ts @@ -12,7 +12,6 @@ import { import * as ProviderLatestVersions from "@t3tools/provider-core/server/ProviderLatestVersions"; import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions"; import * as HostProcess from "@t3tools/shared/HostProcess"; -import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; @@ -45,8 +44,6 @@ const layerTestHttpClient = Layer.succeed( // The mock CLIs from makeTildeProviderFixtures are scripts Windows cannot execute. const windowsHost = HostProcess.Platform.defaultValue() === "win32"; -const TEST_EPOCH = DateTime.makeUnsafe("1970-01-01T00:00:00.000Z"); - const layerBackgroundPolicyAlwaysRun = Layer.mock(BackgroundPolicy.BackgroundPolicy)({ shouldRunScopeWork: () => Effect.succeed(true), }); diff --git a/apps/server/src/provider/ProviderRegistry.test.ts b/apps/server/src/provider/ProviderRegistry.test.ts index d34522a31f80..83c4b0b4b24a 100644 --- a/apps/server/src/provider/ProviderRegistry.test.ts +++ b/apps/server/src/provider/ProviderRegistry.test.ts @@ -2,7 +2,6 @@ import { vi } from "vite-plus/test"; import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; import * as NodeServices from "@effect/platform-node/NodeServices"; import { describe, it, assert, expect } from "@effect/vitest"; -import * as DateTime from "effect/DateTime"; import * as Deferred from "effect/Deferred"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; @@ -84,7 +83,6 @@ const defaultCodexSettings: CodexSettings = Schema.decodeSync(CodexSettings)({}) process.env.T3CODE_CURSOR_ENABLED = "1"; const encoder = new TextEncoder(); -const TEST_EPOCH = DateTime.makeUnsafe("1970-01-01T00:00:00.000Z"); const withBundledCompatibility = (snapshot: ServerProvider) => applyProviderCompatibility( snapshot, diff --git a/apps/server/src/pullRequest/PullRequestService.coder.test.ts b/apps/server/src/pullRequest/PullRequestService.coder.test.ts index 8a648c08fccc..b2144c72d9a7 100644 --- a/apps/server/src/pullRequest/PullRequestService.coder.test.ts +++ b/apps/server/src/pullRequest/PullRequestService.coder.test.ts @@ -1,7 +1,7 @@ import { SourceControlProviderKind } from "@t3tools/contracts"; import { PullRequestFilesViewedRepository } from "../persistence/PullRequestFilesViewed.ts"; import * as PullRequestReadCache from "./PullRequestReadCache.ts"; -import { assert, expect, it, vi } from "@effect/vitest"; +import { expect, it, vi } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Fiber from "effect/Fiber"; import * as Layer from "effect/Layer"; diff --git a/apps/server/src/pullRequest/PullRequestService.test.ts b/apps/server/src/pullRequest/PullRequestService.test.ts index cf691951a602..d1c65867a4c0 100644 --- a/apps/server/src/pullRequest/PullRequestService.test.ts +++ b/apps/server/src/pullRequest/PullRequestService.test.ts @@ -15,7 +15,6 @@ import type { PullRequestReviewCapabilities, PullRequestReviewerCapabilities, } from "@t3tools/contracts"; -import { PullRequestOperationError } from "@t3tools/contracts"; import * as ProjectService from "../project/ProjectService.ts"; import * as RepositoryIdentityResolver from "../project/RepositoryIdentityResolver.ts"; diff --git a/apps/server/src/scheduledTasks/ScheduledTaskService.ts b/apps/server/src/scheduledTasks/ScheduledTaskService.ts index 822b9eb6eae4..225408edf315 100644 --- a/apps/server/src/scheduledTasks/ScheduledTaskService.ts +++ b/apps/server/src/scheduledTasks/ScheduledTaskService.ts @@ -30,8 +30,6 @@ import * as Data from "effect/Data"; import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; -import * as Duration from "effect/Duration"; -import * as Metric from "effect/Metric"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as PubSub from "effect/PubSub"; diff --git a/apps/server/src/sourceControl/SourceControlDiscovery.test.ts b/apps/server/src/sourceControl/SourceControlDiscovery.test.ts index fb3ef9c1f821..501f1390cb2a 100644 --- a/apps/server/src/sourceControl/SourceControlDiscovery.test.ts +++ b/apps/server/src/sourceControl/SourceControlDiscovery.test.ts @@ -6,7 +6,6 @@ import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import { ChildProcessSpawner } from "effect/process"; -import * as ServerSettings from "../serverSettings.ts"; import * as ServerConfig from "../config.ts"; import * as VcsProcess from "../vcs/VcsProcess.ts"; import * as SourceControlDiscovery from "./SourceControlDiscovery.ts"; diff --git a/apps/server/src/sourceControl/SourceControlRepositoryService.ts b/apps/server/src/sourceControl/SourceControlRepositoryService.ts index 383f8480d770..187839004bee 100644 --- a/apps/server/src/sourceControl/SourceControlRepositoryService.ts +++ b/apps/server/src/sourceControl/SourceControlRepositoryService.ts @@ -7,7 +7,6 @@ import * as Schedule from "effect/Schedule"; import * as Schema from "effect/Schema"; import { - SourceControlProviderError, SourceControlRepositoryError, type GitCommandFailureReason, type SourceControlCloneRepositoryInput, @@ -32,7 +31,6 @@ import * as SourceControlProviderRegistry from "./SourceControlProviderRegistry. import { parseGitLabCloneSource } from "@t3tools/shared/sourceControl"; import * as HostProcess from "@t3tools/shared/HostProcess"; const isSourceControlRepositoryError = Schema.is(SourceControlRepositoryError); -const isSourceControlProviderError = Schema.is(SourceControlProviderError); export class SourceControlRepositoryService extends Context.Service< SourceControlRepositoryService, diff --git a/apps/server/src/terminal/Manager.test.ts b/apps/server/src/terminal/Manager.test.ts index 1ed0353e09ff..4bd346115c18 100644 --- a/apps/server/src/terminal/Manager.test.ts +++ b/apps/server/src/terminal/Manager.test.ts @@ -21,7 +21,6 @@ import * as Layer from "effect/Layer"; import * as PlatformError from "effect/PlatformError"; import * as Path from "effect/Path"; import * as Ref from "effect/Ref"; -import * as Schema from "effect/Schema"; import * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; import * as SynchronizedRef from "effect/SynchronizedRef"; @@ -43,8 +42,6 @@ vi.mock("effect/SynchronizedRef", async (importOriginal) => { // The server omits DOM types, which include TypeScript's WebAssembly declarations. -const encodeUnknownJson = Schema.encodeUnknownSync(Schema.fromJsonString(Schema.Unknown)); - class FakePtyProcess implements PtyAdapter.PtyProcess { readonly writes: string[] = []; readonly resizeCalls: Array<{ cols: number; rows: number }> = []; diff --git a/apps/server/src/ws.test.ts b/apps/server/src/ws.test.ts index 85f1ef53f4d2..91cf249796b1 100644 --- a/apps/server/src/ws.test.ts +++ b/apps/server/src/ws.test.ts @@ -1,10 +1,7 @@ -import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; import { ProjectId, ThreadId, - WS_METHODS, - WsSubscribeServerConfigRpc, type OrchestrationV2StoredEvent, type OrchestrationProjectShell, } from "@t3tools/contracts"; diff --git a/apps/server/src/ws.ts b/apps/server/src/ws.ts index 207336234818..8ec282e4a997 100644 --- a/apps/server/src/ws.ts +++ b/apps/server/src/ws.ts @@ -51,7 +51,6 @@ import * as Keybindings from "./keybindings.ts"; import * as ThreadManagementService from "./orchestration-v2/ThreadManagementService.ts"; import * as CommandOutputHub from "./orchestration-v2/CommandOutputHub.ts"; import * as McpAppRequests from "./mcpApps/McpAppRequests.ts"; -import * as ProviderSessionManager from "./orchestration-v2/ProviderSessionManager.ts"; import * as ThreadLaunchService from "./orchestration-v2/ThreadLaunchService.ts"; import * as ThreadMessageIntake from "./orchestration-v2/ThreadMessageIntake.ts"; import * as ScheduledTasks from "./scheduledTasks/ScheduledTaskService.ts"; @@ -803,7 +802,6 @@ const layerWsRpc = () => // Coder: helper stdio has no client-origin attribution or analytics. const threadLaunch = yield* ThreadLaunchService.ThreadLaunchService; const commandOutputHub = yield* CommandOutputHub.CommandOutputHub; - const providerSessionManager = yield* ProviderSessionManager.ProviderSessionManagerV2; const scheduledTasks = yield* ScheduledTasks.ScheduledTaskService; const secretRequests = yield* SecretRequests.SecretRequests; const pullRequests = yield* PullRequestService.PullRequestService; diff --git a/apps/web/src/components/ChatMarkdown.tsx b/apps/web/src/components/ChatMarkdown.tsx index d52e69c4d5a0..30a43d7cca6b 100644 --- a/apps/web/src/components/ChatMarkdown.tsx +++ b/apps/web/src/components/ChatMarkdown.tsx @@ -841,7 +841,6 @@ const CHAT_MARKDOWN_COMPONENTS = { a: function MarkdownAnchor({ node, href, children, title: _title, ...props }) { const { canOperateHost, - canOperatePreview, cwd, environmentId, imageBaseDir, diff --git a/apps/web/src/components/ChatView.logic.ts b/apps/web/src/components/ChatView.logic.ts index 693c1c560629..8f259f25a424 100644 --- a/apps/web/src/components/ChatView.logic.ts +++ b/apps/web/src/components/ChatView.logic.ts @@ -1400,7 +1400,7 @@ export function optimisticMessageAttachments( ); } -/** Fallback title sources for a message with no text of its own. */ +/** Fallback title sources for a message with no text of its own. Coder: no preview annotations. */ export function sendTitleFallbackLabels(snapshot: ComposerSendSnapshot) { const terminalContext = snapshot.terminalContexts[0]; const reviewComment = snapshot.reviewComments[0]; diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 46ba7010cdb5..8e399fc69ae9 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -443,6 +443,7 @@ const EMPTY_PROVIDERS: ServerProvider[] = []; const EMPTY_PROVIDER_MODELS: ServerProvider["models"] = []; import type { CodexArtifactTemplate } from "@t3tools/shared/codexArtifactTemplates"; +// Coder: no feedback uploads, so no messages anchor to the timeline. const EMPTY_ANCHORED_TIMELINE_MESSAGES: ReadonlyArray = []; const RELATED_THREAD_SHELL_WAIT_MS = 1_000; const EMPTY_PROVIDER_SKILLS: ServerProvider["skills"] = []; @@ -528,6 +529,7 @@ export default function ChatView(props: ChatViewProps) { const resumeThreadQueue = useOrchestrationCommand(threadEnvironment.resumeThreadQueue, { reportFailure: false, }); + // Coder: rewinding re-stages sent images from the helper's bounded reads. const readRewindImage = useAtomCommand(projectEnvironment.readScreenshotArtifact, { reportFailure: false, }); @@ -2051,11 +2053,11 @@ export default function ChatView(props: ChatViewProps) { refresh: gitStatusQuery.refresh, resourceKey: `git-status:${activeThreadKey ?? ""}:${gitStatusCwd ?? ""}`, }); - // Coder: there are no local editors to open. const keybindings = useAtomValue(primaryServerKeybindingsAtom); const scriptKeybindings = useAtomValue(serverEnvironment.configValueAtom(environmentId))?.keybindings ?? DEFAULT_RESOLVED_KEYBINDINGS; + // Coder: there are no local editors to open. const manualCompactionProviderAvailable = hasAvailableCompactionProvider({ providers: providerInstanceEntries, driverKind: selectedProvider, @@ -2104,7 +2106,6 @@ export default function ChatView(props: ChatViewProps) { const activeProjectCwd = activeProject?.workspaceRoot ?? null; const activeThreadWorktreePath = activeThread?.worktreePath ?? null; const activeWorkspaceRoot = activeThreadWorktreePath ?? activeProjectCwd ?? undefined; - const filesAvailable = activeProject !== null; useLayoutEffect(() => { if ( threadDetailLoading || @@ -2541,7 +2542,7 @@ export default function ChatView(props: ChatViewProps) { }; const openChangesFromThreadPanelStable = useStableCallback(openChangesFromThreadPanel); const addFilesSurface = () => { - if (!activeThreadRef || !filesAvailable) return; + if (!activeThreadRef || !activeProject) return; useRightPanelStore.getState().open(activeThreadRef, "files"); }; const addFilesSurfaceStable = useStableCallback(addFilesSurface); @@ -2559,7 +2560,7 @@ export default function ChatView(props: ChatViewProps) { }; const addPullRequestsSurfaceStable = useStableCallback(addPullRequestsSurface); const openFileSurface = (relativePath: string) => { - if (!activeThreadRef || !filesAvailable) return; + if (!activeThreadRef || !activeProject) return; useRightPanelStore.getState().openFile(activeThreadRef, relativePath); }; const openFileSurfaceStable = useStableCallback(openFileSurface); @@ -5161,7 +5162,6 @@ export default function ChatView(props: ChatViewProps) { } else { turnStartSucceeded = true; setKeepFullHistory(routeThreadKey, false); - if (turnUsesAttachmentUploads) { releaseDraftAttachments(composerAttachmentsSnapshot); } @@ -6415,7 +6415,6 @@ export default function ChatView(props: ChatViewProps) { scheduleComposerFocus={scheduleComposerFocusStable} setThreadError={setThreadError} onExpandImage={onExpandTimelineImageStable} - editingQueuedAttachments={queuedRunEdit.editingAttachments} onRemoveEditingQueuedAttachment={ queuedRunEdit.removeEditingAttachment @@ -6608,7 +6607,7 @@ export default function ChatView(props: ChatViewProps) { onAddPullRequests={addPullRequestsSurfaceStable} terminalAvailable={activeProject !== null && canOperateTerminal} diffAvailable={isServerThread && isGitRepo} - filesAvailable={filesAvailable} + filesAvailable={activeProject !== null} pullRequestAvailable={pullRequestSurfaceAvailable} pullRequestsAvailable={pullRequestsSurfaceAvailable} > diff --git a/apps/web/src/components/CommandPalette.tsx b/apps/web/src/components/CommandPalette.tsx index 425863822fc4..c032eb7529be 100644 --- a/apps/web/src/components/CommandPalette.tsx +++ b/apps/web/src/components/CommandPalette.tsx @@ -93,11 +93,7 @@ import { useAtomQueryRunner } from "../state/use-atom-query-runner"; import { useScratchProject } from "../hooks/useScratchProject"; import { useNewProject } from "../hooks/useNewProject"; import { isScratchProject } from "@t3tools/client-runtime/state/projects"; -import { - useEnvironmentProviders, - useEnvironments, - usePrimaryEnvironmentId, -} from "../state/environments"; +import { useEnvironments, usePrimaryEnvironmentId } from "../state/environments"; import { useProjects, useServerConfigs, useThreadShells, waitForProject } from "../state/entities"; import { resolveThreadActionProjectRef, startNewThreadFromContext } from "../lib/chatThreadActions"; import { @@ -537,7 +533,6 @@ function OpenCommandPaletteDialog(props: { }; const threads = useThreadShells(); const keybindings = useAtomValue(primaryServerKeybindingsAtom); - const providersByEnvironment = useEnvironmentProviders(); const { changeThemeItem, changeAppearanceItem, themeEditorItem } = useCommandPaletteThemeItems(); const currentView = viewStack.at(-1)?.view ?? null; const threadSearchQuery = currentView === null && !isActionsOnly ? deferredQuery : ""; diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index 43f22f424fbc..08751bd5febd 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -35,7 +35,6 @@ import { Smartphone, TerminalSquare, } from "lucide-react"; -import { Volume2, VolumeOff } from "lucide"; import { type ComponentProps, type KeyboardEvent as ReactKeyboardEvent, diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx index 7eb2dc6efaf8..6bdff91846a3 100644 --- a/apps/web/src/components/chat/ChatComposer.tsx +++ b/apps/web/src/components/chat/ChatComposer.tsx @@ -1660,11 +1660,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) .map((file) => file.id), ); })(); - const composerOtherFiles = composerOtherFilesForPresentation( - composerFiles, - environmentId, - inlineFileIdSet, - ); + const composerOtherFiles = composerOtherFilesForPresentation(composerFiles, inlineFileIdSet); const composerTerminalContexts = composerDraft.terminalContexts; const composerReviewComments = composerDraft.reviewComments; const composerThreadContexts = attachmentDraft.threadContexts; @@ -1876,7 +1872,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) selectedProviderEntry === undefined && multipleModelSelections === null; const providerCatalogPending = noProviderAvailable && !providerCatalogKnown; const showProviderUnavailable = noProviderAvailable && !providerCatalogPending; - // Coder has no provider setup flow; provider credentials live in the workspace. + // Coder: no provider setup flow; provider credentials live in the workspace. const providerSetupInstanceId = noProviderAvailable ? unavailableProviderInstanceId : undefined; const resolvedCompactDisabledReason = compactDisabledReason ?? (noProviderAvailable ? "Compacting is unavailable right now" : null); diff --git a/apps/web/src/components/chat/ComposerFooterControls.tsx b/apps/web/src/components/chat/ComposerFooterControls.tsx index 8e91e3027132..f211b4921636 100644 --- a/apps/web/src/components/chat/ComposerFooterControls.tsx +++ b/apps/web/src/components/chat/ComposerFooterControls.tsx @@ -34,7 +34,7 @@ export const ComposerFooterModeControls = memo(function ComposerFooterModeContro showInteractionModeToggle: boolean; interactionMode: ProviderInteractionMode; runtimeMode: RuntimeMode; - /** Coder offers only safe modes until the provider is ready. */ + /** Coder: only safe modes are offered until the provider is ready. */ runtimeModeOptions: ReadonlyArray; size?: "sm" | "xs"; hidden?: boolean; diff --git a/apps/web/src/components/chat/ExpandedImageDialog.tsx b/apps/web/src/components/chat/ExpandedImageDialog.tsx index 792d7bf84636..1a8ebf2ec408 100644 --- a/apps/web/src/components/chat/ExpandedImageDialog.tsx +++ b/apps/web/src/components/chat/ExpandedImageDialog.tsx @@ -4,7 +4,6 @@ import { memo, useEffect, useRef, useState, type KeyboardEvent } from "react"; import { ChevronLeftIcon, ChevronRightIcon, XIcon } from "lucide-react"; import { Button } from "../ui/button"; -import { MorphIcon } from "~/components/MorphIcon"; import { Dialog, DialogPopup, DialogTitle } from "../ui/dialog"; import { wrapExpandedImageIndex, diff --git a/apps/web/src/components/chat/TimelineAssistantRows.tsx b/apps/web/src/components/chat/TimelineAssistantRows.tsx index 67813b78fa9d..86ed77fcba17 100644 --- a/apps/web/src/components/chat/TimelineAssistantRows.tsx +++ b/apps/web/src/components/chat/TimelineAssistantRows.tsx @@ -250,6 +250,7 @@ export function HtmlRenderTimelineRow({ > = { jpeg: "image/jpeg", jpg: "image/jpeg", @@ -73,25 +72,13 @@ export function classifyComposerAttachmentFile( return isProviderSendTurnSupportedImageMimeType(file.type) ? "image" : "unsupported-image"; } -export function isPreviewableComposerVideo( - file: ComposerFileAttachment, - environmentId: EnvironmentId, -): boolean { - return ( - isVideoAttachment(file) && - (file.file !== null || - (file.uploadedAttachmentId !== undefined && file.uploadEnvironmentId === environmentId)) - ); -} - +// Coder: the composer has no video tiles (a draft video plays from no signed asset URL), so +// videos list with the other files instead of being left out. export function composerOtherFilesForPresentation( files: ReadonlyArray, - environmentId: EnvironmentId, inlineFileIds: ReadonlySet, ): ComposerFileAttachment[] { - return files.filter( - (file) => !isPreviewableComposerVideo(file, environmentId) && !inlineFileIds.has(file.id), - ); + return files.filter((file) => !inlineFileIds.has(file.id)); } export function fileAttachmentStagingLimit(input: FileAttachmentCapabilityState): number | null { diff --git a/apps/web/src/components/files/AttachmentFilePreview.tsx b/apps/web/src/components/files/AttachmentFilePreview.tsx index fbfb32899b05..cf50fc03ef9f 100644 --- a/apps/web/src/components/files/AttachmentFilePreview.tsx +++ b/apps/web/src/components/files/AttachmentFilePreview.tsx @@ -1,7 +1,7 @@ import { filePreviewDelimiter } from "@t3tools/shared/delimitedPreview"; import type { ScopedThreadRef } from "@t3tools/contracts"; import { readFilePreviewResponse } from "@t3tools/client-runtime/file-preview"; -import { filePreviewKind, FILE_TEXT_PREVIEW_MAX_BYTES } from "@t3tools/shared/filePreview"; +import { filePreviewKind } from "@t3tools/shared/filePreview"; import { ChevronRightIcon, DownloadIcon, Trash2Icon, WrapTextIcon, XIcon } from "lucide-react"; import { Check, Code2, Copy, Eye, Table2 } from "lucide"; import { lazy, Suspense, useEffect, useState } from "react"; diff --git a/apps/web/src/components/files/FilePreviewPanel.tsx b/apps/web/src/components/files/FilePreviewPanel.tsx index 71b01f8c891a..c8851f1f4c27 100644 --- a/apps/web/src/components/files/FilePreviewPanel.tsx +++ b/apps/web/src/components/files/FilePreviewPanel.tsx @@ -12,7 +12,6 @@ import { isWorkspaceImagePreviewPath, isWorkspaceVideoPreviewPath, } from "@t3tools/shared/filePreview"; -import { useAtomValue } from "@effect/atom-react"; import { DEFAULT_TOKENIZE_MAX_LENGTH, VirtualizedFile, diff --git a/apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts b/apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts index 6e42be0286f9..72aff250f089 100644 --- a/apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts +++ b/apps/web/src/components/pullRequest/pullRequestDetail.logic.test.ts @@ -42,7 +42,6 @@ import { newestPullRequestCommitAt, mergePullRequestThreadComments, orderPullRequestComments, - pullRequestCheckoutCommand, checkoutFailureDescription, readPullRequestDetailSnapshot, resolveDisplayedPullRequestDetail, diff --git a/apps/web/src/components/settings/AppearanceSettingsPanel.tsx b/apps/web/src/components/settings/AppearanceSettingsPanel.tsx index c2d6bcf28b0d..a13bc93bb9ce 100644 --- a/apps/web/src/components/settings/AppearanceSettingsPanel.tsx +++ b/apps/web/src/components/settings/AppearanceSettingsPanel.tsx @@ -32,7 +32,6 @@ import { searchableSetting } from "./settingsSearch"; import { PanelAnimationsPreview } from "./PanelAnimationsPreview"; import { TypographySection } from "./TypographySettings"; -import { SidebarProjectSortOrder } from "@t3tools/contracts/settings"; const ENVIRONMENT_IDENTIFICATION_LABELS: Record = { artwork: "Artwork", pill: "Version pill", diff --git a/apps/web/src/components/settings/BackgroundActivitySettings.tsx b/apps/web/src/components/settings/BackgroundActivitySettings.tsx index 7dfc4bee1b59..184b2e79f156 100644 --- a/apps/web/src/components/settings/BackgroundActivitySettings.tsx +++ b/apps/web/src/components/settings/BackgroundActivitySettings.tsx @@ -30,7 +30,6 @@ import { NumberFieldInput, } from "../ui/number-field"; import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ui/select"; -import { Switch } from "../ui/switch"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { backgroundActivityOverrideSettings, diff --git a/apps/web/src/components/settings/KeybindingsSettings.tsx b/apps/web/src/components/settings/KeybindingsSettings.tsx index 59ff32d4aea1..3bb38549ac6f 100644 --- a/apps/web/src/components/settings/KeybindingsSettings.tsx +++ b/apps/web/src/components/settings/KeybindingsSettings.tsx @@ -1,4 +1,3 @@ -import { useEnvironmentScope } from "../../state/session"; import { useEnvironmentsWithScope, readEnvironmentScope } from "../../state/session"; import { ChevronDownIcon, @@ -20,7 +19,6 @@ import { useState, } from "react"; import { - AuthOrchestrationOperateScope, AuthSettingsWriteScope, type KeybindingCommand, type KeybindingWhenNode, @@ -1288,10 +1286,6 @@ function useKeybindingCatalog() { export function KeybindingsSettingsPanel() { const { environment: primaryEnvironment, connectedEnvironments } = useSettingsScope(); - const canOpenKeybindingsFile = useEnvironmentScope( - primaryEnvironment?.environmentId ?? null, - AuthOrchestrationOperateScope, - ); const writableIds = useEnvironmentsWithScope(connectedEnvironments, AuthSettingsWriteScope); const canWriteSettings = connectedEnvironments.length > 0 && diff --git a/apps/web/src/components/settings/ProjectSettingsPanel.tsx b/apps/web/src/components/settings/ProjectSettingsPanel.tsx index b804e5f63bd1..558d69b78af5 100644 --- a/apps/web/src/components/settings/ProjectSettingsPanel.tsx +++ b/apps/web/src/components/settings/ProjectSettingsPanel.tsx @@ -1,5 +1,4 @@ // Coder: no Integrations category or external favicon picker (desktop bridge only). -import { useComposerMenuState } from "../chat/useComposerMenuState"; import { useOrchestrationCommand } from "../../state/use-orchestration-command"; import { AuthOrchestrationOperateScope } from "@t3tools/contracts"; import { useEnvironmentsWithScope, readEnvironmentScope } from "../../state/session"; diff --git a/apps/web/src/components/settings/ProviderInstanceCard.tsx b/apps/web/src/components/settings/ProviderInstanceCard.tsx index 3be19a0281d7..5b8e5ed11dec 100644 --- a/apps/web/src/components/settings/ProviderInstanceCard.tsx +++ b/apps/web/src/components/settings/ProviderInstanceCard.tsx @@ -37,7 +37,6 @@ import { useStableCallback } from "../../hooks/useStableCallback"; import { normalizeProviderAccentColor } from "../../providerInstances"; import { Badge } from "../ui/badge"; import { Button } from "../ui/button"; -import { MorphIcon } from "~/components/MorphIcon"; import { DraftInput } from "../ui/draft-input"; import { SecretInput } from "./SecretInput"; import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; diff --git a/apps/web/src/components/settings/SettingsPanels.tsx b/apps/web/src/components/settings/SettingsPanels.tsx index a415dab99091..3e7a41e892a2 100644 --- a/apps/web/src/components/settings/SettingsPanels.tsx +++ b/apps/web/src/components/settings/SettingsPanels.tsx @@ -59,7 +59,6 @@ import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ import { Switch } from "../ui/switch"; import { ScopedSwitch } from "./ScopedSwitch"; import { stackedThreadToast, toastManager } from "../ui/toast"; -import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { getChangedBrowserSettingLabels, getChangedTypographySettingLabels, @@ -530,9 +529,8 @@ export function GeneralSettingsPanel() { const settings = useScopedSettings(); const updateSettings = useUpdateScopedSettings(); const navigate = useNavigate(); - const { scope, environment, connectedEnvironments, target } = useSettingsScope(); + const { environment, connectedEnvironments, target } = useSettingsScope(); const environmentId = environment?.environmentId ?? null; - const isEnvironmentScope = scope.environmentIds.length === 1 && environmentId !== null; const hasServerTargets = connectedEnvironments.length > 0; const mixedResponseStreamingMode = useScopedSettingsMixed(["responseStreamingMode"]); const lastEnabledProjectGroupingMode = useRef( diff --git a/apps/web/src/components/sidebar/SidebarDraftBlock.tsx b/apps/web/src/components/sidebar/SidebarDraftBlock.tsx index 6eb58da5d921..1f7ea382df70 100644 --- a/apps/web/src/components/sidebar/SidebarDraftBlock.tsx +++ b/apps/web/src/components/sidebar/SidebarDraftBlock.tsx @@ -38,6 +38,7 @@ const SidebarDraftRow = memo(function SidebarDraftRow(props: { .split("\n", 1)[0] ?? ""; // images mirrors persistedAttachments once rehydration finishes; before // that only the persisted list is populated, hence max not sum. + // Coder: no browser preview, so preview annotations do not count. const attachmentCount = Math.max(composer.images.length, composer.persistedAttachments.length) + composer.files.length + diff --git a/apps/web/src/hooks/useSettings.ts b/apps/web/src/hooks/useSettings.ts index 7b04c3383bd8..758341b77ef3 100644 --- a/apps/web/src/hooks/useSettings.ts +++ b/apps/web/src/hooks/useSettings.ts @@ -52,7 +52,6 @@ import { useEnvironments, usePrimaryEnvironment } from "~/state/environments"; import { useAtomCommand } from "~/state/use-atom-command"; import { useTheme } from "./useTheme"; import { readEnvironmentScope, useEnvironmentScope } from "~/state/session"; -import { appAtomRegistry } from "~/rpc/atomRegistry"; const CLIENT_SETTINGS_PERSISTENCE_ERROR_SCOPE = "[CLIENT_SETTINGS]"; diff --git a/apps/web/src/modelSelection.test.ts b/apps/web/src/modelSelection.test.ts index 308ada6a4144..6b855adfbf6a 100644 --- a/apps/web/src/modelSelection.test.ts +++ b/apps/web/src/modelSelection.test.ts @@ -1,5 +1,4 @@ import { - ANTIGRAVITY_DEFAULT_MODEL, DEFAULT_TEXT_GENERATION_MODEL, ProviderDriverKind, ProviderInstanceId, diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx index 39af7259d4e6..b33cc8829558 100644 --- a/apps/web/src/routes/__root.tsx +++ b/apps/web/src/routes/__root.tsx @@ -17,7 +17,6 @@ import { useLocation, useNavigate, } from "@tanstack/react-router"; -import { CheckIcon, CopyIcon } from "lucide-react"; import { useEffect, useEffectEvent, useRef } from "react"; import { APP_BASE_NAME, APP_DISPLAY_NAME, APP_STAGE_LABEL, APP_VERSION } from "../branding"; diff --git a/apps/web/src/state/server.ts b/apps/web/src/state/server.ts index 7040a6acc568..fc2db89d65f6 100644 --- a/apps/web/src/state/server.ts +++ b/apps/web/src/state/server.ts @@ -130,7 +130,7 @@ const environmentConnectionsAtom = Atom.make((get) => { EnvironmentId, Pick >(); - for (const [environmentId, entry] of get(environmentCatalog.catalogValueAtom).entries) { + for (const [environmentId] of get(environmentCatalog.catalogValueAtom).entries) { const state = Option.getOrElse( AsyncResult.value(get(environmentCatalog.stateAtom(environmentId))), () => AVAILABLE_CONNECTION_STATE, diff --git a/docs/internals/coder-only.md b/docs/internals/coder-only.md index 60c01e6b3275..ddd7aefcb628 100644 --- a/docs/internals/coder-only.md +++ b/docs/internals/coder-only.md @@ -309,7 +309,8 @@ id through bounded helper chunks for previews, Save, and rewind. The composer uses upstream's structured context records (`t3-context://v1//` links plus `message.context`) without preview annotations, element captures, or SnapShot frames. `ComposerAttachmentStrip.tsx`'s media row shows image tiles only; videos list with the other -files, and a draft file previews only while its bytes are still in memory. The work log +files (`composerOtherFilesForPresentation` keeps them, so a video attached to a question answer +stays visible and removable), and a draft file previews only while its bytes are still in memory. The work log uses upstream's client-runtime presentation without provider tool sources, favicons, logos, or native app icons. File chip icons and size tooltips use upstream's `filesystem.getMetadata`, which stats absolute workspace paths and reads at most 512 header bytes of an extensionless file to name @@ -866,7 +867,8 @@ listed here is drift to remove rather than fork behavior to keep. id (`workspace.readAttachmentFile`, bounded by the composer file limit) into memory, and the right panel shows them in `files/SentAttachmentFilePreview.tsx` where upstream's `FilePreviewPanel` loads a signed URL. Native app icons fall back to the tool glyph. - `WorkspaceEntryIcon.tsx` formats sizes with the web's `lib/attachmentDisplay.ts`, because + `WorkspaceEntryIcon.tsx`, `UserMessageContextChips.tsx`, the composer, and its attachment + strip format sizes and limits with the web's `lib/attachmentDisplay.ts`, because client-runtime's attachment upload module is not carried. Upstream's v1 importer carries only messages, and upstream migration 063 drops the v1 `projection_thread_activities` rows, so screenshots that pre-v2 conversations saved as @@ -1265,8 +1267,7 @@ listed here is drift to remove rather than fork behavior to keep. client-runtime's `threadShell.test.ts` omits upstream's switched-off environment test, because the Coder config owns registration and there is no per-environment switch. `ws.test.ts` omits upstream's config-RPC buffering test, which builds upstream's session-scoped - `layerWsRpc`; `RunExecutionService.test.ts` gives `McpSessionRegistry` the Coder environment - and T3 tool dispatch it reads. Upstream's `composerContextUndo.test.ts` (preview annotations + `layerWsRpc`. Upstream's `composerContextUndo.test.ts` (preview annotations only), `HtmlRenderFrame.browser.test.tsx`, and `BrowserDocumentFrame.browser.test.tsx` (signed URLs) are not carried; `DiffPanel.browser.test.tsx` passes `onOpenFile` without an editor mock, and `ProjectSettingsPanel.browser.test.tsx` keeps `projects.getConfig` pending as upstream @@ -1288,7 +1289,9 @@ listed here is drift to remove rather than fork behavior to keep. export, the diagnostics page, usage dashboards, and hosted providers other than GitLab. Without browser preview, `composerDraftStore.ts` does not keep an empty draft alive for an open page, and the desktop default-browser handoff (`DesktopWebLinkCoordinator`) is not carried. Without - the usage page, `timestampFormat.ts` has no `resolveHour12`. + the usage page, `timestampFormat.ts` has no `resolveHour12`. Prompt links (upstream's + `components/promptLinks/`, the "Copy prompt link" actions in the command palette and on user + messages) are not carried, because they open the hosted web app. ## Distribution diff --git a/packages/client-runtime/src/connection/catalog.ts b/packages/client-runtime/src/connection/catalog.ts index b6fee6146794..04f585fb9d5a 100644 --- a/packages/client-runtime/src/connection/catalog.ts +++ b/packages/client-runtime/src/connection/catalog.ts @@ -16,10 +16,6 @@ export class ConnectionRegistration extends Schema.TaggedClass, - event: ServerConfigStreamEvent, -): readonly [Option.Option, ReadonlyArray] { - const next = applyServerConfigProjection(current, event); - return [next, Option.toArray(next)]; -} - const cachedConfigSnapshotEvent = (config: ServerConfig): ServerConfigStreamEvent => ({ version: 1, type: "snapshot", diff --git a/packages/client-runtime/src/state/shellSnapshotHttp.ts b/packages/client-runtime/src/state/shellSnapshotHttp.ts index 70b4bbd12b34..099805418e1e 100644 --- a/packages/client-runtime/src/state/shellSnapshotHttp.ts +++ b/packages/client-runtime/src/state/shellSnapshotHttp.ts @@ -1,4 +1,3 @@ -import type { OrchestrationV2ShellSnapshot } from "@t3tools/contracts"; import type { DeferredShellSnapshot } from "./shellPullRequests.ts"; import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; diff --git a/packages/provider-acp-registry/src/server/adapter.ts b/packages/provider-acp-registry/src/server/adapter.ts index fd3abee690c5..2daa75276e3c 100644 --- a/packages/provider-acp-registry/src/server/adapter.ts +++ b/packages/provider-acp-registry/src/server/adapter.ts @@ -35,7 +35,6 @@ import { import { AcpProviderCapabilitiesV2, makeAcpAdapterV2, - type AcpAdapterV2ExtensionContext, type AcpAdapterV2Flavor, type AcpAdapterV2RuntimeInput, } from "@t3tools/provider-acp/server/adapter"; diff --git a/packages/shared/src/themePalettes.ts b/packages/shared/src/themePalettes.ts index a016ab4dd9ac..bff06383aadc 100644 --- a/packages/shared/src/themePalettes.ts +++ b/packages/shared/src/themePalettes.ts @@ -1,9 +1,15 @@ export const BUILT_IN_THEME_IDS = ["t3-chat", "grove", "ocean", "ember", "iris"] as const; -const MOBILE_DEFAULT_THEME_ID = "t3-code"; +export const MOBILE_DEFAULT_THEME_ID = "t3-code"; -const MOBILE_THEME_IDS = [MOBILE_DEFAULT_THEME_ID, ...BUILT_IN_THEME_IDS] as const; +export const MOBILE_THEME_IDS = [MOBILE_DEFAULT_THEME_ID, ...BUILT_IN_THEME_IDS] as const; +/** + * Ids a theme may not take: the appearance keywords a stored preference uses, + * every built-in, and the legacy aliases older saves still carry. Taking one + * would either be shadowed by the built-in or capture clients that never chose + * it, so the client library and the publish path both consult this set. + */ export const RESERVED_THEME_IDS: ReadonlySet = new Set([ "system", "light", @@ -920,11 +926,7 @@ export const BUILT_IN_THEMES: ReadonlyArray = [ IRIS_THEME, ]; -function getBuiltInTheme(id: string): ThemeDefinition | null { - return BUILT_IN_THEMES.find((theme) => theme.id === id) ?? null; -} - -function getThemeColorsForAppearance( +export function getThemeColorsForAppearance( theme: ThemeDefinition, appearance: ThemeAppearance, ): ThemeColors | null {