Skip to content

Commit e2a1242

Browse files
authored
Merge branch 'main' into kayden/skip-oversized-diff-lines
2 parents 0932c71 + 86c94b4 commit e2a1242

218 files changed

Lines changed: 18108 additions & 6544 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more
55
## Installation
66

77
> [!WARNING]
8-
> T3 Code currently supports Codex and Claude.
8+
> T3 Code currently supports Codex, Claude, and OpenCode.
99
> Install and authenticate at least one provider before use:
1010
>
11-
> - Codex: install [Codex CLI](https://github.com/openai/codex) and run `codex login`
12-
> - Claude: install Claude Code and run `claude auth login`
11+
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
12+
> - Claude: install [Claude Code](https://claude.com/product/claude-code) and run `claude auth login`
13+
> - OpenCode: install [OpenCode](https://opencode.ai) and run `opencode auth login`
1314
1415
### Run without installing
1516

apps/desktop/src/clientPersistence.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const clientSettings: ClientSettings = {
5454
confirmThreadDelete: false,
5555
diffWordWrap: true,
5656
favorites: [],
57+
providerModelPreferences: {},
5758
sidebarProjectGroupingMode: "repository_path",
5859
sidebarProjectGroupingOverrides: {
5960
"environment-1:/tmp/project-a": "separate",

apps/server/integration/OrchestrationEngineHarness.integration.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { execFileSync } from "node:child_process";
33
import * as NodeServices from "@effect/platform-node/NodeServices";
44
import {
55
ApprovalRequestId,
6-
ProviderKind,
6+
CodexSettings,
7+
ProviderDriverKind,
78
type OrchestrationEvent,
89
type OrchestrationThread,
910
} from "@t3tools/contracts";
@@ -36,13 +37,16 @@ import { ProviderSessionRuntimeRepositoryLive } from "../src/persistence/Layers/
3637
import { makeSqlitePersistenceLive } from "../src/persistence/Layers/Sqlite.ts";
3738
import { ProjectionCheckpointRepository } from "../src/persistence/Services/ProjectionCheckpoints.ts";
3839
import { ProjectionPendingApprovalRepository } from "../src/persistence/Services/ProjectionPendingApprovals.ts";
39-
import { ProviderUnsupportedError } from "../src/provider/Errors.ts";
40+
import { makeAdapterRegistryMock } from "../src/provider/testUtils/providerAdapterRegistryMock.ts";
4041
import { ProviderAdapterRegistry } from "../src/provider/Services/ProviderAdapterRegistry.ts";
4142
import { ProviderSessionDirectoryLive } from "../src/provider/Layers/ProviderSessionDirectory.ts";
4243
import { ServerSettingsService } from "../src/serverSettings.ts";
4344
import { makeProviderServiceLive } from "../src/provider/Layers/ProviderService.ts";
44-
import { makeCodexAdapterLive } from "../src/provider/Layers/CodexAdapter.ts";
45-
import { CodexAdapter } from "../src/provider/Services/CodexAdapter.ts";
45+
import { makeCodexAdapter } from "../src/provider/Layers/CodexAdapter.ts";
46+
import {
47+
NoOpProviderEventLoggers,
48+
ProviderEventLoggers,
49+
} from "../src/provider/Layers/ProviderEventLoggers.ts";
4650
import { ProviderService } from "../src/provider/Services/ProviderService.ts";
4751
import { AnalyticsService } from "../src/telemetry/Services/AnalyticsService.ts";
4852
import { CheckpointReactorLive } from "../src/orchestration/Layers/CheckpointReactor.ts";
@@ -214,7 +218,7 @@ export interface OrchestrationIntegrationHarness {
214218
}
215219

216220
interface MakeOrchestrationIntegrationHarnessOptions {
217-
readonly provider?: ProviderKind;
221+
readonly provider?: ProviderDriverKind;
218222
readonly realCodex?: boolean;
219223
}
220224

@@ -225,21 +229,18 @@ export const makeOrchestrationIntegrationHarness = (
225229
const path = yield* Path.Path;
226230
const fileSystem = yield* FileSystem.FileSystem;
227231

228-
const provider = options?.provider ?? "codex";
232+
const provider = options?.provider ?? ProviderDriverKind.make("codex");
229233
const useRealCodex = options?.realCodex === true;
230234
const adapterHarness = useRealCodex
231235
? null
232236
: yield* makeTestProviderAdapterHarness({
233237
provider,
234238
});
235239
const fakeRegistry = adapterHarness
236-
? Layer.succeed(ProviderAdapterRegistry, {
237-
getByProvider: (resolvedProvider) =>
238-
resolvedProvider === adapterHarness.provider
239-
? Effect.succeed(adapterHarness.adapter)
240-
: Effect.fail(new ProviderUnsupportedError({ provider: resolvedProvider })),
241-
listProviders: () => Effect.succeed([adapterHarness.provider]),
242-
} as typeof ProviderAdapterRegistry.Service)
240+
? Layer.succeed(
241+
ProviderAdapterRegistry,
242+
makeAdapterRegistryMock({ [adapterHarness.provider]: adapterHarness.adapter }),
243+
)
243244
: null;
244245
const rootDir = yield* fileSystem.makeTempDirectoryScoped({
245246
prefix: "t3-orchestration-integration-",
@@ -264,31 +265,30 @@ export const makeOrchestrationIntegrationHarness = (
264265
const realCodexRegistry = Layer.effect(
265266
ProviderAdapterRegistry,
266267
Effect.gen(function* () {
267-
const codexAdapter = yield* CodexAdapter;
268-
return {
269-
getByProvider: (resolvedProvider) =>
270-
resolvedProvider === "codex"
271-
? Effect.succeed(codexAdapter)
272-
: Effect.fail(new ProviderUnsupportedError({ provider: resolvedProvider })),
273-
listProviders: () => Effect.succeed(["codex"] as const),
274-
} as typeof ProviderAdapterRegistry.Service;
268+
const codexSettings = Schema.decodeSync(CodexSettings)({});
269+
const codexAdapter = yield* makeCodexAdapter(codexSettings);
270+
return makeAdapterRegistryMock({
271+
[ProviderDriverKind.make("codex")]: codexAdapter,
272+
});
275273
}),
276274
).pipe(
277-
Layer.provide(makeCodexAdapterLive()),
278275
Layer.provideMerge(ServerConfig.layerTest(workspaceDir, rootDir)),
279276
Layer.provideMerge(NodeServices.layer),
280277
Layer.provideMerge(providerSessionDirectoryLayer),
281278
);
279+
const providerEventLoggersLayer = Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers);
282280
const providerLayer = useRealCodex
283281
? makeProviderServiceLive().pipe(
284282
Layer.provide(providerSessionDirectoryLayer),
285283
Layer.provide(realCodexRegistry),
286284
Layer.provide(AnalyticsService.layerTest),
285+
Layer.provide(providerEventLoggersLayer),
287286
)
288287
: makeProviderServiceLive().pipe(
289288
Layer.provide(providerSessionDirectoryLayer),
290289
Layer.provide(fakeRegistry!),
291290
Layer.provide(AnalyticsService.layerTest),
291+
Layer.provide(providerEventLoggersLayer),
292292
);
293293

294294
const checkpointStoreLayer = CheckpointStoreLive.pipe(Layer.provide(GitCoreLive));

apps/server/integration/TestProviderAdapter.integration.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
ProviderTurnStartResult,
1111
ThreadId,
1212
TurnId,
13-
ProviderKind,
13+
ProviderDriverKind,
1414
} from "@t3tools/contracts";
1515
import { Effect, Queue, Stream } from "effect";
1616

@@ -36,7 +36,7 @@ export interface TestTurnResponse {
3636
export type FixtureProviderRuntimeEvent = {
3737
readonly type: string;
3838
readonly eventId: EventId;
39-
readonly provider: ProviderKind;
39+
readonly provider: ProviderDriverKind;
4040
readonly createdAt: string;
4141
readonly threadId: string;
4242
readonly turnId?: string | undefined;
@@ -178,7 +178,7 @@ function normalizeFixtureEvent(rawEvent: Record<string, unknown>): ProviderRunti
178178

179179
export interface TestProviderAdapterHarness {
180180
readonly adapter: ProviderAdapterShape<ProviderAdapterError>;
181-
readonly provider: ProviderKind;
181+
readonly provider: ProviderDriverKind;
182182
readonly queueTurnResponse: (
183183
threadId: ThreadId,
184184
response: TestTurnResponse,
@@ -198,15 +198,15 @@ export interface TestProviderAdapterHarness {
198198
}
199199

200200
interface MakeTestProviderAdapterHarnessOptions {
201-
readonly provider?: ProviderKind;
201+
readonly provider?: ProviderDriverKind;
202202
}
203203

204204
function nowIso(): string {
205205
return new Date().toISOString();
206206
}
207207

208208
function sessionNotFound(
209-
provider: ProviderKind,
209+
provider: ProviderDriverKind,
210210
threadId: ThreadId,
211211
): ProviderAdapterSessionNotFoundError {
212212
return new ProviderAdapterSessionNotFoundError({
@@ -216,15 +216,15 @@ function sessionNotFound(
216216
}
217217

218218
function missingSessionEffect(
219-
provider: ProviderKind,
219+
provider: ProviderDriverKind,
220220
threadId: ThreadId,
221221
): Effect.Effect<never, ProviderAdapterError> {
222222
return Effect.fail(sessionNotFound(provider, threadId));
223223
}
224224

225225
export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapterHarnessOptions) =>
226226
Effect.gen(function* () {
227-
const provider = options?.provider ?? "codex";
227+
const provider = options?.provider ?? ProviderDriverKind.make("codex");
228228
const runtimeEvents = yield* Queue.unbounded<ProviderRuntimeEvent>();
229229
let sessionCount = 0;
230230
const sessions = new Map<ThreadId, SessionState>();
@@ -257,6 +257,9 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter
257257

258258
const session: ProviderSession = {
259259
provider,
260+
...(input.providerInstanceId !== undefined
261+
? { providerInstanceId: input.providerInstanceId }
262+
: {}),
260263
status: "ready",
261264
runtimeMode: input.runtimeMode,
262265
threadId,

apps/server/integration/fixtures/providerRuntime.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { EventId, RuntimeRequestId } from "@t3tools/contracts";
1+
import { EventId, ProviderDriverKind, RuntimeRequestId } from "@t3tools/contracts";
22
import type { LegacyProviderRuntimeEvent } from "../TestProviderAdapter.integration.ts";
33

4-
const PROVIDER = "codex" as const;
4+
const PROVIDER = ProviderDriverKind.make("codex");
55
const SESSION_ID = "fixture-session";
66
const THREAD_ID = "fixture-thread";
77
const TURN_ID = "fixture-turn";

0 commit comments

Comments
 (0)