Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7d9aaf6
feat(web): add pull request merge defaults (#8088)
Bil0000 Sep 8, 2026
1f14d6d
fix(usage): keep account columns aligned across limit rows (#10690)
juliusmarminge Sep 8, 2026
11601da
fix(web): chat text no longer shows through a 1px gap under composer …
vitalyiegorov Sep 8, 2026
6f4cd07
refactor(server): classify runtime exports (#10274)
juliusmarminge Sep 8, 2026
0af04f1
refactor(server): classify orchestration exports (#10275)
juliusmarminge Sep 8, 2026
161715b
refactor(server): classify service exports (#10276)
juliusmarminge Sep 8, 2026
77d9ffc
refactor(server): classify telemetry exports (#10277)
juliusmarminge Sep 8, 2026
060c576
refactor(server): classify provider exports (#10278)
juliusmarminge Sep 8, 2026
3b6ce93
refactor(server): classify source control exports (#10279)
juliusmarminge Sep 8, 2026
7cdeb69
refactor(server): classify source control registry API (#10280)
juliusmarminge Sep 8, 2026
1f0a14c
refactor(server): classify preview toolkit exports (#10281)
juliusmarminge Sep 8, 2026
b284715
chore(mobile): bump app version to 1.1.1
t3-code[bot] Sep 8, 2026
7d62050
ci(knip): enforce server exports (#10282)
juliusmarminge Sep 8, 2026
134b719
feat(web): add previous/next turn navigation in minimap (#8531)
UtkarshUsername Sep 8, 2026
d6dbe8d
fix(web): stop the settings sidebar shifting when switching pages (#1…
t3dotgg Sep 8, 2026
83b865f
fix(web): copy terminal selection with Ctrl+Insert (#8541)
iamshadmantaqi Sep 8, 2026
82451ee
fix(web): show the same project icon in the command palette as everyw…
t3dotgg Sep 8, 2026
d7a59c6
fix(web): stop sidebar rows flashing and shifting on click (#10713)
t3dotgg Sep 8, 2026
eb11506
refactor(web): pass the project record to ProjectFavicon so icons can…
t3dotgg Sep 8, 2026
bde39d4
feat(web): accept file drops into sidebar threads (#7892)
UtkarshUsername Sep 8, 2026
b5d8903
feat(web): accept file drops into sidebar threads (#7892)
UtkarshUsername Sep 8, 2026
061543e
fix(mcp): keep preview snapshots usable by the agent and let it save …
t3dotgg Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/desktop/src/preview/Manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ const ZOOM_EPSILON = 0.001;
const MAX_EVALUATION_BYTES = 64_000;
const MAX_VISIBLE_TEXT_LENGTH = 20_000;
const MAX_INTERACTIVE_ELEMENTS = 200;
/**
* A `[role]` container's innerText is its whole subtree, which turned one
* snapshot's element list into 60 KB of repeated page text. Names are labels,
* not content, so cap them where they are read.
*/
const MAX_INTERACTIVE_ELEMENT_NAME_LENGTH = 200;
const MAX_SCREENSHOT_WIDTH = 1280;
/** How long an armed tab keeps the exclusive display-media slot before another tab may take it. */
const RECORDING_ARM_GRACE_MS = 10_000;
Expand Down Expand Up @@ -3582,7 +3588,7 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function
return {
tag: element.tagName.toLowerCase(),
role: element.getAttribute("role"),
name: element.getAttribute("aria-label") || element.innerText || element.getAttribute("name") || "",
name: (element.getAttribute("aria-label") || element.innerText || element.getAttribute("name") || "").slice(0, ${MAX_INTERACTIVE_ELEMENT_NAME_LENGTH}),
selector: selectorFor(element),
x: rect.x,
y: rect.y,
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/settings/DesktopClientSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const clientSettings: ClientSettings = {
legacySidebarEnabled: false,
loadBalancingEnabled: false,
loadBalancingWeights: { "environment-1": 75, "environment-2": 0 },
pullRequestMergeMethodOverrides: {},
timestampFormat: "24-hour",
wordWrap: true,
};
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ const config: ExpoConfig = {
slug: "t3-code",
platforms: ["ios", "android"],
scheme: variant.scheme,
version: "1.1.0",
version: "1.1.1",
runtimeVersion: {
// Development manifests resolve on every launch, so avoid fingerprint's
// expensive native-project calculation there. Preview and production stay
Expand Down
48 changes: 26 additions & 22 deletions apps/mobile/src/features/usage/UsageLimitsPooled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,30 +116,34 @@ function PoolWindowCard({
</Text>
) : null}
<View className="flex-row gap-1">
{pool.members.map(({ account, window }, index) => (
<Pressable
key={account.key}
accessibilityRole="button"
accessibilityLabel={`Segment ${index + 1}, ${accountName(account)}, ${remainingPercent(window)}% left`}
accessibilityHint="Show account details"
onPress={() => openAccount(account)}
className="h-7 min-w-0 flex-1 overflow-hidden rounded-md bg-subtle"
>
<AccountSegment
remaining={remainingPercent(window)}
color={color}
pending={Boolean(window.resetsAt)}
/>
<View pointerEvents="none" className="absolute inset-0 items-center justify-center">
<Text className="text-xs font-t3-medium tabular-nums text-foreground">
{index + 1}
</Text>
</View>
</Pressable>
))}
{pool.columns.map(({ account, window }, index) => {
if (!window) return <View key={account.key} className="h-7 min-w-0 flex-1" />;
return (
<Pressable
key={account.key}
accessibilityRole="button"
accessibilityLabel={`Segment ${index + 1}, ${accountName(account)}, ${remainingPercent(window)}% left`}
accessibilityHint="Show account details"
onPress={() => openAccount(account)}
className="h-7 min-w-0 flex-1 overflow-hidden rounded-md bg-subtle"
>
<AccountSegment
remaining={remainingPercent(window)}
color={color}
pending={Boolean(window.resetsAt)}
/>
<View pointerEvents="none" className="absolute inset-0 items-center justify-center">
<Text className="text-xs font-t3-medium tabular-nums text-foreground">
{index + 1}
</Text>
</View>
</Pressable>
);
})}
</View>
<View>
{pool.members.map(({ account, window }, index) => {
{pool.columns.map(({ account, window }, index) => {
if (!window) return null;
const credits = account.limits.resetCredits?.availableCount ?? 0;
const resetsIn = formatResetsIn(window, now);
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function rawDataBytes(data: NodeSocket.NodeWS.RawData): number {
return data.byteLength;
}

export function makeWebSocketTransferRecorder(): WebSocketTransferRecorder {
function makeWebSocketTransferRecorder(): WebSocketTransferRecorder {
let socket: NodeWebSocketWithTransport | null = null;
// Held separately from the WebSocket so wire totals survive a close, which
// is when a reconnect measurement reads them.
Expand Down Expand Up @@ -176,7 +176,7 @@ export function transferDelta(
};
}

export function countingWsRpcProtocolLayer(input: {
function countingWsRpcProtocolLayer(input: {
readonly url: string;
readonly cookie: string;
readonly recorder: WebSocketTransferRecorder;
Expand All @@ -194,7 +194,7 @@ export function countingWsRpcProtocolLayer(input: {
);
}

export const makeCountingWsRpcClient = RpcClient.make(WsRpcGroup);
const makeCountingWsRpcClient = RpcClient.make(WsRpcGroup);
export type CountingWsRpcClient = Effect.Success<typeof makeCountingWsRpcClient>;

export interface MeasuredWsClient {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const TRANSFER_BUDGET = {
measuredTurnWebSocketMessages: 21,
} satisfies ProviderTransferBudget;

export const TRANSFER_BUDGETS: Readonly<Record<string, ProviderTransferBudget>> = {
const TRANSFER_BUDGETS: Readonly<Record<string, ProviderTransferBudget>> = {
codex: TRANSFER_BUDGET,
claudeAgent: TRANSFER_BUDGET,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
TRANSFER_HISTORY_TURN_COUNT,
} from "./fixtures/transferBudget.ts";

export const TRANSFER_PROJECT_ID = ProjectId.make("transfer-budget-project");
const TRANSFER_PROJECT_ID = ProjectId.make("transfer-budget-project");
export const TRANSFER_THREAD_ID = ThreadId.make("transfer-budget-thread");
export const TRANSFER_MEASURED_TURN_INDEX = TRANSFER_HISTORY_TURN_COUNT;

Expand Down
2 changes: 1 addition & 1 deletion apps/server/scripts/t3-sqlite-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export const runSqliteState = Effect.fn("runSqliteState")(function* (
);
});

export const t3SqliteStateCommand = Command.make(
const t3SqliteStateCommand = Command.make(
"t3-sqlite-state",
{
operation: Argument.choice("operation", SqliteStateOperation.literals).pipe(
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/assets/NativeAppIconResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ const resolveNativeAppIconUncached = Effect.fn("NativeAppIconResolver.resolveUnc
return yield* existingFile(cachePath);
});

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const fileSystem = yield* FileSystem.FileSystem;
const hostPlatform = yield* HostProcessPlatform;
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/attachmentStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const ATTACHMENT_ID_PATTERN = new RegExp(
);

export const PENDING_ATTACHMENT_THREAD_SEGMENT = "pending";
export const PENDING_ATTACHMENT_MAX_AGE_MS = 24 * 60 * 60 * 1000;
const PENDING_ATTACHMENT_MAX_AGE_MS = 24 * 60 * 60 * 1000;
const PARTIAL_UPLOAD_MAX_AGE_MS = 60 * 60 * 1000;

export function toSafeThreadAttachmentSegment(threadId: string): string | null {
Expand Down
5 changes: 3 additions & 2 deletions apps/server/src/auth/EnvironmentAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import * as SessionStore from "./SessionStore.ts";
import { verifyRequestDpopProof } from "./dpop.ts";
import { layerConfig as SqlitePersistenceLayer } from "../persistence/Layers/Sqlite.ts";

export const DEFAULT_SESSION_SUBJECT = "cli-issued-session";
const DEFAULT_SESSION_SUBJECT = "cli-issued-session";
export const INTERNAL_ADMINISTRATIVE_BOOTSTRAP_SUBJECT = "administrative-bootstrap";

export interface IssuedPairingLink {
Expand Down Expand Up @@ -591,6 +591,7 @@ export function selectRequestCredential(
return undefined;
}

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const policy = yield* EnvironmentAuthPolicy.EnvironmentAuthPolicy;
const bootstrapCredentials = yield* PairingGrantStore.PairingGrantStore;
Expand Down Expand Up @@ -1033,7 +1034,7 @@ export const layer = Layer.effect(EnvironmentAuth, make).pipe(
Layer.provideMerge(EnvironmentAuthPolicy.layer),
);

export const storageLayer = Layer.mergeAll(ServerSecretStore.layer, SqlitePersistenceLayer);
const storageLayer = Layer.mergeAll(ServerSecretStore.layer, SqlitePersistenceLayer);

export const runtimeLayer = layer.pipe(
Layer.provideMerge(storageLayer),
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/auth/EnvironmentAuthPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class EnvironmentAuthPolicy extends Context.Service<
}
>()("t3/auth/EnvironmentAuthPolicy") {}

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const config = yield* ServerConfig.ServerConfig;
const serverEnvironment = yield* ServerEnvironment.ServerEnvironmentIdentity;
Expand Down
2 changes: 0 additions & 2 deletions apps/server/src/auth/PairingGrantStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export const BootstrapCredentialInvalidError = Schema.Union([
UnavailableBootstrapCredentialError,
]);
export type BootstrapCredentialInvalidError = typeof BootstrapCredentialInvalidError.Type;
export const isBootstrapCredentialInvalidError = Schema.is(BootstrapCredentialInvalidError);

export class ActivePairingLinksLoadError extends Schema.TaggedError<ActivePairingLinksLoadError>()(
"ActivePairingLinksLoadError",
Expand Down Expand Up @@ -173,7 +172,6 @@ export const BootstrapCredentialError = Schema.Union([
BootstrapCredentialInternalError,
]);
export type BootstrapCredentialError = typeof BootstrapCredentialError.Type;
export const isBootstrapCredentialError = Schema.is(BootstrapCredentialError);

export interface IssuedBootstrapCredential {
readonly id: string;
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/auth/ServerSecretStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export class ServerSecretStore extends Context.Service<
}
>()("t3/auth/ServerSecretStore") {}

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const crypto = yield* Crypto.Crypto;
const fileSystem = yield* FileSystem.FileSystem;
Expand Down
2 changes: 0 additions & 2 deletions apps/server/src/auth/SessionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,12 @@ export const SessionCredentialInternalError = Schema.Union([
OtherSessionsRevocationError,
]);
export type SessionCredentialInternalError = typeof SessionCredentialInternalError.Type;
export const isSessionCredentialInternalError = Schema.is(SessionCredentialInternalError);

export const SessionCredentialError = Schema.Union([
SessionCredentialInvalidError,
SessionCredentialInternalError,
]);
export type SessionCredentialError = typeof SessionCredentialError.Type;
export const isSessionCredentialError = Schema.is(SessionCredentialError);

export class SessionStore extends Context.Service<
SessionStore,
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/auth/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const appendDpopChallengeOnUnauthorized = (error: EnvironmentAuthInvalidError) =
return yield* error;
});

export const currentEnvironmentTraceId = Effect.currentParentSpan.pipe(
const currentEnvironmentTraceId = Effect.currentParentSpan.pipe(
Effect.map((span) => span.traceId),
Effect.orElseSucceed(() => "unavailable"),
);
Expand Down
3 changes: 2 additions & 1 deletion apps/server/src/background/BackgroundPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function leaseKey(lease: Pick<ClientActivityLease, "sessionId" | "rpcClientId" |
return JSON.stringify([lease.sessionId, lease.rpcClientId, lease.clientId]);
}

export function upsertClientActivityLease(
function upsertClientActivityLease(
leases: ReadonlyMap<string, ClientActivityLease>,
lease: ClientActivityLease,
now: DateTime.Utc,
Expand Down Expand Up @@ -208,6 +208,7 @@ function computeSnapshot(input: {
};
}

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.fn("background.policy.make")(function* () {
const hostPowerMonitor = yield* HostPowerMonitor.HostPowerMonitor;
const serverSettings = yield* ServerSettingsService;
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/background/HostPowerMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class HostPowerMonitor extends Context.Service<
}
>()("t3/background/HostPowerMonitor") {}

export const makeUnknownSnapshot = (
const makeUnknownSnapshot = (
source: HostPowerSnapshot["source"],
updatedAt: HostPowerSnapshot["updatedAt"],
): HostPowerSnapshot => ({
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/checkpointing/CheckpointDiffQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ function buildTurnDiffResult(
};
}

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery.ProjectionSnapshotQuery;
const checkpointStore = yield* CheckpointStore.CheckpointStore;
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/checkpointing/CheckpointStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class CheckpointStore extends Context.Service<
}
>()("t3/checkpointing/CheckpointStore") {}

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const vcsRegistry = yield* VcsDriverRegistry.VcsDriverRegistry;

Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/checkpointing/Utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Encoding from "effect/Encoding";
import { CheckpointRef, ProjectId, type ThreadId } from "@t3tools/contracts";

export const CHECKPOINT_REFS_PREFIX = "refs/t3/checkpoints";
const CHECKPOINT_REFS_PREFIX = "refs/t3/checkpoints";

export function checkpointRefForThreadTurn(threadId: ThreadId, turnCount: number): CheckpointRef {
return CheckpointRef.make(
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/cli/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function isDesktopPlatform(platform: NodeJS.Platform): platform is DesktopAppAct
return platform === "darwin" || platform === "linux" || platform === "win32";
}

export function sendDesktopAppActivationRequest(input: {
function sendDesktopAppActivationRequest(input: {
readonly address: string;
readonly fallbackAddress?: string;
readonly request: DesktopAppActivationRequest;
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/cli/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { readBootstrapEnvelope } from "../bootstrap.ts";
import * as ServerConfig from "../config.ts";
import { expandHomePath, resolveBaseDir } from "../os-jank.ts";

export const modeFlag = Flag.choice("mode", ServerConfig.RuntimeMode.literals).pipe(
const modeFlag = Flag.choice("mode", ServerConfig.RuntimeMode.literals).pipe(
Flag.withDescription("Runtime mode. `desktop` keeps loopback defaults unless overridden."),
Flag.optional,
);
Expand Down Expand Up @@ -69,7 +69,7 @@ const tailscaleServeFlag = Flag.boolean("tailscale-serve").pipe(
),
Flag.optional,
);
export const tailscaleServePortFlag = Flag.integer("tailscale-serve-port").pipe(
const tailscaleServePortFlag = Flag.integer("tailscale-serve-port").pipe(
Flag.withSchema(PortSchema),
Flag.withDescription("HTTPS port for Tailscale Serve when --tailscale-serve is enabled."),
Flag.optional,
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/cli/pair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export const resolveTailscaleLocalTarget = (
return { localPort: state.port };
};

export const formatPairOutput = (input: {
const formatPairOutput = (input: {
readonly serverLabel: string;
readonly origin: string;
readonly pairingUrl: string;
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/cloud/CliTokenManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ export const outOfBandOAuthLogin = Effect.fn("cloud.cli_token.out_of_band_oauth_
});
});

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
// Capture exactly the services the login/refresh flows need at build time
// (matching the behavior before the out-of-band flow captured the instances), not
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/cloud/ManagedEndpointRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const stopConnector = (connector: ActiveConnector | null) =>
)
: Effect.void;

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
const relayClient = yield* RelayClient.RelayClient;
Expand Down
8 changes: 4 additions & 4 deletions apps/server/src/cloud/publicConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ function normalizeSecureUrl(value: string): string | null {
}
}

export const buildTimeRelayUrl =
const buildTimeRelayUrl =
typeof __T3CODE_BUILD_RELAY_URL__ === "undefined"
? ""
: (normalizeSecureRelayUrl(__T3CODE_BUILD_RELAY_URL__) ?? "");
export const buildTimeClerkPublishableKey = readBuildTimeValue(
const buildTimeClerkPublishableKey = readBuildTimeValue(
typeof __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__ === "undefined"
? undefined
: __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__,
);
export const buildTimeClerkCliOAuthClientId = readBuildTimeValue(
const buildTimeClerkCliOAuthClientId = readBuildTimeValue(
typeof __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__ === "undefined"
? undefined
: __T3CODE_BUILD_CLERK_CLI_OAUTH_CLIENT_ID__,
);
export const buildTimeRelayClientTracing = {
const buildTimeRelayClientTracing = {
tracesUrl: readBuildTimeValue(
typeof __T3CODE_BUILD_RELAY_CLIENT_OTLP_TRACES_URL__ === "undefined"
? undefined
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/cloud/serviceProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const isExactServiceVersion = (version: string): boolean =>
const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null && !Array.isArray(value);

export function decodeServiceUpdate(value: unknown): ServiceUpdateRecord | undefined {
function decodeServiceUpdate(value: unknown): ServiceUpdateRecord | undefined {
if (!isRecord(value)) return undefined;
const { id, fromVersion, targetVersion, status } = value;
if (
Expand Down
Loading
Loading