| author | |
| committer | |
| log | 3405a64dd8fdf3affe14c057692484fffb63b0af |
| tree | 7a9d4be187f3f4b47e6108867bc917b71dca1886 |
| parent | 1cba2f64d39073bb77faac7234e88f52aa395643 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius@macmini.local>
Co-authored-by: codex <codex@users.noreply.github.com>174 files changed, 1853 insertions(+), 1870 deletions(-)
apps/desktop/src/clientPersistence.test.ts+1-1| ... | ... | @@ -58,7 +58,7 @@ const clientSettings: ClientSettings = { |
| 58 | 58 | }; |
| 59 | 59 | |
| 60 | 60 | const savedRegistryRecord: PersistedSavedEnvironmentRecord = { |
| 61 | environmentId: EnvironmentId.makeUnsafe("environment-1"), | |
| 61 | environmentId: EnvironmentId.make("environment-1"), | |
| 62 | 62 | label: "Remote environment", |
| 63 | 63 | httpBaseUrl: "https://remote.example.com/", |
| 64 | 64 | wsBaseUrl: "wss://remote.example.com/", |
apps/server/integration/OrchestrationEngineHarness.integration.ts+1-1| ... | ... | @@ -438,7 +438,7 @@ export const makeOrchestrationIntegrationHarness = ( |
| 438 | 438 | ) => |
| 439 | 439 | waitFor( |
| 440 | 440 | pendingApprovalRepository |
| 441 | .getByRequestId({ requestId: ApprovalRequestId.makeUnsafe(requestId) }) | |
| 441 | .getByRequestId({ requestId: ApprovalRequestId.make(requestId) }) | |
| 442 | 442 | .pipe( |
| 443 | 443 | Effect.map((row) => |
| 444 | 444 | Option.match(row, { |
apps/server/integration/TestProviderAdapter.integration.ts+3-3| ... | ... | @@ -289,7 +289,7 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter |
| 289 | 289 | |
| 290 | 290 | state.turnCount += 1; |
| 291 | 291 | const turnCount = state.turnCount; |
| 292 | const turnId = TurnId.makeUnsafe(`turn-${turnCount}`); | |
| 292 | const turnId = TurnId.make(`turn-${turnCount}`); | |
| 293 | 293 | |
| 294 | 294 | const response = state.queuedResponses.shift(); |
| 295 | 295 | if (!response) { |
| ... | ... | @@ -307,7 +307,7 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter |
| 307 | 307 | ...(fixtureEvent as Record<string, unknown>), |
| 308 | 308 | eventId: randomUUID(), |
| 309 | 309 | provider, |
| 310 | sessionId: RuntimeSessionId.makeUnsafe(String(input.threadId)), | |
| 310 | sessionId: RuntimeSessionId.make(String(input.threadId)), | |
| 311 | 311 | createdAt: nowIso(), |
| 312 | 312 | }; |
| 313 | 313 | rawEvent.threadId = state.snapshot.threadId; |
| ... | ... | @@ -363,7 +363,7 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter |
| 363 | 363 | if (deferredTurnCompletedEvents.length === 0) { |
| 364 | 364 | yield* emit({ |
| 365 | 365 | type: "turn.completed", |
| 366 | eventId: EventId.makeUnsafe(randomUUID()), | |
| 366 | eventId: EventId.make(randomUUID()), | |
| 367 | 367 | provider, |
| 368 | 368 | createdAt: nowIso(), |
| 369 | 369 | threadId: state.snapshot.threadId, |
apps/server/integration/fixtures/providerRuntime.ts+2-2| ... | ... | @@ -5,14 +5,14 @@ const PROVIDER = "codex" as const; |
| 5 | 5 | const SESSION_ID = "fixture-session"; |
| 6 | 6 | const THREAD_ID = "fixture-thread"; |
| 7 | 7 | const TURN_ID = "fixture-turn"; |
| 8 | const REQUEST_ID = RuntimeRequestId.makeUnsafe("req-1"); | |
| 8 | const REQUEST_ID = RuntimeRequestId.make("req-1"); | |
| 9 | 9 | |
| 10 | 10 | function baseEvent( |
| 11 | 11 | eventId: string, |
| 12 | 12 | createdAt: string, |
| 13 | 13 | ): Pick<LegacyProviderRuntimeEvent, "eventId" | "provider" | "sessionId" | "createdAt"> { |
| 14 | 14 | return { |
| 15 | eventId: EventId.makeUnsafe(eventId), | |
| 15 | eventId: EventId.make(eventId), | |
| 16 | 16 | provider: PROVIDER, |
| 17 | 17 | sessionId: SESSION_ID, |
| 18 | 18 | createdAt, |
apps/server/integration/orchestrationEngine.integration.test.ts+18-19| ... | ... | @@ -30,14 +30,13 @@ import type { |
| 30 | 30 | } from "../src/orchestration/Services/RuntimeReceiptBus.ts"; |
| 31 | 31 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 32 | 32 | |
| 33 | const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value); | |
| 34 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 35 | const asEventId = (value: string): EventId => EventId.makeUnsafe(value); | |
| 36 | const asApprovalRequestId = (value: string): ApprovalRequestId => | |
| 37 | ApprovalRequestId.makeUnsafe(value); | |
| 33 | const asMessageId = (value: string): MessageId => MessageId.make(value); | |
| 34 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 35 | const asEventId = (value: string): EventId => EventId.make(value); | |
| 36 | const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value); | |
| 38 | 37 | |
| 39 | 38 | const PROJECT_ID = asProjectId("project-1"); |
| 40 | const THREAD_ID = ThreadId.makeUnsafe("thread-1"); | |
| 39 | const THREAD_ID = ThreadId.make("thread-1"); | |
| 41 | 40 | const FIXTURE_TURN_ID = "fixture-turn"; |
| 42 | 41 | const APPROVAL_REQUEST_ID = asApprovalRequestId("req-approval-1"); |
| 43 | 42 | type IntegrationProvider = ProviderKind; |
| ... | ... | @@ -112,7 +111,7 @@ const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) => |
| 112 | 111 | |
| 113 | 112 | yield* harness.engine.dispatch({ |
| 114 | 113 | type: "project.create", |
| 115 | commandId: CommandId.makeUnsafe("cmd-project-create"), | |
| 114 | commandId: CommandId.make("cmd-project-create"), | |
| 116 | 115 | projectId: PROJECT_ID, |
| 117 | 116 | title: "Integration Project", |
| 118 | 117 | workspaceRoot: harness.workspaceDir, |
| ... | ... | @@ -125,7 +124,7 @@ const seedProjectAndThread = (harness: OrchestrationIntegrationHarness) => |
| 125 | 124 | |
| 126 | 125 | yield* harness.engine.dispatch({ |
| 127 | 126 | type: "thread.create", |
| 128 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 127 | commandId: CommandId.make("cmd-thread-create"), | |
| 129 | 128 | threadId: THREAD_ID, |
| 130 | 129 | projectId: PROJECT_ID, |
| 131 | 130 | title: "Integration Thread", |
| ... | ... | @@ -150,7 +149,7 @@ const startTurn = (input: { |
| 150 | 149 | }) => |
| 151 | 150 | input.harness.engine.dispatch({ |
| 152 | 151 | type: "thread.turn.start", |
| 153 | commandId: CommandId.makeUnsafe(input.commandId), | |
| 152 | commandId: CommandId.make(input.commandId), | |
| 154 | 153 | threadId: THREAD_ID, |
| 155 | 154 | message: { |
| 156 | 155 | messageId: asMessageId(input.messageId), |
| ... | ... | @@ -261,7 +260,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)( |
| 261 | 260 | |
| 262 | 261 | yield* harness.engine.dispatch({ |
| 263 | 262 | type: "project.create", |
| 264 | commandId: CommandId.makeUnsafe("cmd-project-create-real-codex"), | |
| 263 | commandId: CommandId.make("cmd-project-create-real-codex"), | |
| 265 | 264 | projectId: PROJECT_ID, |
| 266 | 265 | title: "Integration Project", |
| 267 | 266 | workspaceRoot: harness.workspaceDir, |
| ... | ... | @@ -274,7 +273,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)( |
| 274 | 273 | |
| 275 | 274 | yield* harness.engine.dispatch({ |
| 276 | 275 | type: "thread.create", |
| 277 | commandId: CommandId.makeUnsafe("cmd-thread-create-real-codex"), | |
| 276 | commandId: CommandId.make("cmd-thread-create-real-codex"), | |
| 278 | 277 | threadId: THREAD_ID, |
| 279 | 278 | projectId: PROJECT_ID, |
| 280 | 279 | title: "Integration Thread", |
| ... | ... | @@ -291,7 +290,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)( |
| 291 | 290 | |
| 292 | 291 | yield* harness.engine.dispatch({ |
| 293 | 292 | type: "thread.turn.start", |
| 294 | commandId: CommandId.makeUnsafe("cmd-turn-start-real-codex-1"), | |
| 293 | commandId: CommandId.make("cmd-turn-start-real-codex-1"), | |
| 295 | 294 | threadId: THREAD_ID, |
| 296 | 295 | message: { |
| 297 | 296 | messageId: asMessageId("msg-real-codex-1"), |
| ... | ... | @@ -318,7 +317,7 @@ it.live.skipIf(!process.env.CODEX_BINARY_PATH)( |
| 318 | 317 | |
| 319 | 318 | yield* harness.engine.dispatch({ |
| 320 | 319 | type: "thread.turn.start", |
| 321 | commandId: CommandId.makeUnsafe("cmd-turn-start-real-codex-2"), | |
| 320 | commandId: CommandId.make("cmd-turn-start-real-codex-2"), | |
| 322 | 321 | threadId: THREAD_ID, |
| 323 | 322 | message: { |
| 324 | 323 | messageId: asMessageId("msg-real-codex-2"), |
| ... | ... | @@ -583,7 +582,7 @@ it.live("tracks approval requests and resolves pending approvals on user respons |
| 583 | 582 | |
| 584 | 583 | yield* harness.engine.dispatch({ |
| 585 | 584 | type: "thread.approval.respond", |
| 586 | commandId: CommandId.makeUnsafe("cmd-approval-respond"), | |
| 585 | commandId: CommandId.make("cmd-approval-respond"), | |
| 587 | 586 | threadId: THREAD_ID, |
| 588 | 587 | requestId: APPROVAL_REQUEST_ID, |
| 589 | 588 | decision: "accept", |
| ... | ... | @@ -815,7 +814,7 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git |
| 815 | 814 | |
| 816 | 815 | yield* harness.engine.dispatch({ |
| 817 | 816 | type: "thread.checkpoint.revert", |
| 818 | commandId: CommandId.makeUnsafe("cmd-checkpoint-revert"), | |
| 817 | commandId: CommandId.make("cmd-checkpoint-revert"), | |
| 819 | 818 | threadId: THREAD_ID, |
| 820 | 819 | turnCount: 1, |
| 821 | 820 | createdAt: nowIso(), |
| ... | ... | @@ -875,7 +874,7 @@ it.live( |
| 875 | 874 | |
| 876 | 875 | yield* harness.engine.dispatch({ |
| 877 | 876 | type: "thread.checkpoint.revert", |
| 878 | commandId: CommandId.makeUnsafe("cmd-checkpoint-revert-no-session"), | |
| 877 | commandId: CommandId.make("cmd-checkpoint-revert-no-session"), | |
| 879 | 878 | threadId: THREAD_ID, |
| 880 | 879 | turnCount: 0, |
| 881 | 880 | createdAt: nowIso(), |
| ... | ... | @@ -1119,7 +1118,7 @@ it.live("forwards claudeAgent approval responses to the provider session", () => |
| 1119 | 1118 | |
| 1120 | 1119 | yield* harness.engine.dispatch({ |
| 1121 | 1120 | type: "thread.approval.respond", |
| 1122 | commandId: CommandId.makeUnsafe("cmd-claude-approval-respond"), | |
| 1121 | commandId: CommandId.make("cmd-claude-approval-respond"), | |
| 1123 | 1122 | threadId: THREAD_ID, |
| 1124 | 1123 | requestId: APPROVAL_REQUEST_ID, |
| 1125 | 1124 | decision: "accept", |
| ... | ... | @@ -1192,7 +1191,7 @@ it.live("forwards thread.turn.interrupt to claudeAgent provider sessions", () => |
| 1192 | 1191 | |
| 1193 | 1192 | yield* harness.engine.dispatch({ |
| 1194 | 1193 | type: "thread.turn.interrupt", |
| 1195 | commandId: CommandId.makeUnsafe("cmd-turn-interrupt-claude"), | |
| 1194 | commandId: CommandId.make("cmd-turn-interrupt-claude"), | |
| 1196 | 1195 | threadId: THREAD_ID, |
| 1197 | 1196 | createdAt: nowIso(), |
| 1198 | 1197 | }); |
| ... | ... | @@ -1309,7 +1308,7 @@ it.live("reverts claudeAgent turns and rolls back provider conversation state", |
| 1309 | 1308 | |
| 1310 | 1309 | yield* harness.engine.dispatch({ |
| 1311 | 1310 | type: "thread.checkpoint.revert", |
| 1312 | commandId: CommandId.makeUnsafe("cmd-checkpoint-revert-claude"), | |
| 1311 | commandId: CommandId.make("cmd-checkpoint-revert-claude"), | |
| 1313 | 1312 | threadId: THREAD_ID, |
| 1314 | 1313 | turnCount: 1, |
| 1315 | 1314 | createdAt: nowIso(), |
apps/server/integration/providerService.integration.test.ts+24-36| ... | ... | @@ -122,15 +122,12 @@ it.live("replays typed runtime fixture events", () => |
| 122 | 122 | |
| 123 | 123 | yield* Effect.gen(function* () { |
| 124 | 124 | const provider = yield* ProviderService; |
| 125 | const session = yield* provider.startSession( | |
| 126 | ThreadId.makeUnsafe("thread-integration-typed"), | |
| 127 | { | |
| 128 | threadId: ThreadId.makeUnsafe("thread-integration-typed"), | |
| 129 | provider: "codex", | |
| 130 | cwd: fixture.cwd, | |
| 131 | runtimeMode: "full-access", | |
| 132 | }, | |
| 133 | ); | |
| 125 | const session = yield* provider.startSession(ThreadId.make("thread-integration-typed"), { | |
| 126 | threadId: ThreadId.make("thread-integration-typed"), | |
| 127 | provider: "codex", | |
| 128 | cwd: fixture.cwd, | |
| 129 | runtimeMode: "full-access", | |
| 130 | }); | |
| 134 | 131 | assert.equal((session.threadId ?? "").length > 0, true); |
| 135 | 132 | |
| 136 | 133 | const observedEvents = yield* runTurn({ |
| ... | ... | @@ -157,15 +154,12 @@ it.live("replays file-changing fixture turn events", () => |
| 157 | 154 | |
| 158 | 155 | yield* Effect.gen(function* () { |
| 159 | 156 | const provider = yield* ProviderService; |
| 160 | const session = yield* provider.startSession( | |
| 161 | ThreadId.makeUnsafe("thread-integration-tools"), | |
| 162 | { | |
| 163 | threadId: ThreadId.makeUnsafe("thread-integration-tools"), | |
| 164 | provider: "codex", | |
| 165 | cwd: fixture.cwd, | |
| 166 | runtimeMode: "full-access", | |
| 167 | }, | |
| 168 | ); | |
| 157 | const session = yield* provider.startSession(ThreadId.make("thread-integration-tools"), { | |
| 158 | threadId: ThreadId.make("thread-integration-tools"), | |
| 159 | provider: "codex", | |
| 160 | cwd: fixture.cwd, | |
| 161 | runtimeMode: "full-access", | |
| 162 | }); | |
| 169 | 163 | assert.equal((session.threadId ?? "").length > 0, true); |
| 170 | 164 | |
| 171 | 165 | const observedEvents = yield* runTurn({ |
| ... | ... | @@ -196,15 +190,12 @@ it.live("runs multi-turn tool/approval flow", () => |
| 196 | 190 | |
| 197 | 191 | yield* Effect.gen(function* () { |
| 198 | 192 | const provider = yield* ProviderService; |
| 199 | const session = yield* provider.startSession( | |
| 200 | ThreadId.makeUnsafe("thread-integration-multi"), | |
| 201 | { | |
| 202 | threadId: ThreadId.makeUnsafe("thread-integration-multi"), | |
| 203 | provider: "codex", | |
| 204 | cwd: fixture.cwd, | |
| 205 | runtimeMode: "full-access", | |
| 206 | }, | |
| 207 | ); | |
| 193 | const session = yield* provider.startSession(ThreadId.make("thread-integration-multi"), { | |
| 194 | threadId: ThreadId.make("thread-integration-multi"), | |
| 195 | provider: "codex", | |
| 196 | cwd: fixture.cwd, | |
| 197 | runtimeMode: "full-access", | |
| 198 | }); | |
| 208 | 199 | assert.equal((session.threadId ?? "").length > 0, true); |
| 209 | 200 | |
| 210 | 201 | const firstTurnEvents = yield* runTurn({ |
| ... | ... | @@ -250,15 +241,12 @@ it.live("rolls back provider conversation state only", () => |
| 250 | 241 | |
| 251 | 242 | yield* Effect.gen(function* () { |
| 252 | 243 | const provider = yield* ProviderService; |
| 253 | const session = yield* provider.startSession( | |
| 254 | ThreadId.makeUnsafe("thread-integration-rollback"), | |
| 255 | { | |
| 256 | threadId: ThreadId.makeUnsafe("thread-integration-rollback"), | |
| 257 | provider: "codex", | |
| 258 | cwd: fixture.cwd, | |
| 259 | runtimeMode: "full-access", | |
| 260 | }, | |
| 261 | ); | |
| 244 | const session = yield* provider.startSession(ThreadId.make("thread-integration-rollback"), { | |
| 245 | threadId: ThreadId.make("thread-integration-rollback"), | |
| 246 | provider: "codex", | |
| 247 | cwd: fixture.cwd, | |
| 248 | runtimeMode: "full-access", | |
| 249 | }); | |
| 262 | 250 | assert.equal((session.threadId ?? "").length > 0, true); |
| 263 | 251 | |
| 264 | 252 | yield* runTurn({ |
apps/server/src/auth/Layers/SessionCredentialService.ts+1-1| ... | ... | @@ -188,7 +188,7 @@ export const makeSessionCredentialService = Effect.gen(function* () { |
| 188 | 188 | |
| 189 | 189 | const issue: SessionCredentialServiceShape["issue"] = (input) => |
| 190 | 190 | Effect.gen(function* () { |
| 191 | const sessionId = AuthSessionId.makeUnsafe(crypto.randomUUID()); | |
| 191 | const sessionId = AuthSessionId.make(crypto.randomUUID()); | |
| 192 | 192 | const issuedAt = yield* DateTime.now; |
| 193 | 193 | const expiresAt = DateTime.add(issuedAt, { |
| 194 | 194 | milliseconds: Duration.toMillis(input?.ttl ?? DEFAULT_SESSION_TTL), |
apps/server/src/auth/Services/AuthControlPlane.ts+2-2| ... | ... | @@ -4,7 +4,7 @@ import type { |
| 4 | 4 | AuthPairingLink, |
| 5 | 5 | AuthSessionId, |
| 6 | 6 | } from "@t3tools/contracts"; |
| 7 | import { Data, DateTime, Duration, Effect, ServiceMap } from "effect"; | |
| 7 | import { Data, DateTime, Duration, Effect, Context } from "effect"; | |
| 8 | 8 | import { SessionRole } from "./SessionCredentialService"; |
| 9 | 9 | |
| 10 | 10 | export const DEFAULT_SESSION_SUBJECT = "cli-issued-session"; |
| ... | ... | @@ -64,6 +64,6 @@ export interface AuthControlPlaneShape { |
| 64 | 64 | ) => Effect.Effect<number, AuthControlPlaneError>; |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | export class AuthControlPlane extends ServiceMap.Service<AuthControlPlane, AuthControlPlaneShape>()( | |
| 67 | export class AuthControlPlane extends Context.Service<AuthControlPlane, AuthControlPlaneShape>()( | |
| 68 | 68 | "t3/AuthControlPlane", |
| 69 | 69 | ) {} |
apps/server/src/auth/Services/BootstrapCredentialService.ts+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | import type { AuthPairingLink, ServerAuthBootstrapMethod } from "@t3tools/contracts"; |
| 2 | import { Data, DateTime, Duration, ServiceMap } from "effect"; | |
| 2 | import { Data, DateTime, Duration, Context } from "effect"; | |
| 3 | 3 | import type { Effect, Stream } from "effect"; |
| 4 | 4 | |
| 5 | 5 | export type BootstrapCredentialRole = "owner" | "client"; |
| ... | ... | @@ -51,7 +51,7 @@ export interface BootstrapCredentialServiceShape { |
| 51 | 51 | readonly consume: (credential: string) => Effect.Effect<BootstrapGrant, BootstrapCredentialError>; |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | export class BootstrapCredentialService extends ServiceMap.Service< | |
| 54 | export class BootstrapCredentialService extends Context.Service< | |
| 55 | 55 | BootstrapCredentialService, |
| 56 | 56 | BootstrapCredentialServiceShape |
| 57 | 57 | >()("t3/auth/Services/BootstrapCredentialService") {} |
apps/server/src/auth/Services/ServerAuth.ts+2-2| ... | ... | @@ -12,7 +12,7 @@ import type { |
| 12 | 12 | ServerAuthSessionMethod, |
| 13 | 13 | AuthWebSocketTokenResult, |
| 14 | 14 | } from "@t3tools/contracts"; |
| 15 | import { Data, DateTime, ServiceMap } from "effect"; | |
| 15 | import { Data, DateTime, Context } from "effect"; | |
| 16 | 16 | import type { Effect } from "effect"; |
| 17 | 17 | import type * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"; |
| 18 | 18 | import type { SessionRole } from "./SessionCredentialService.ts"; |
| ... | ... | @@ -79,6 +79,6 @@ export interface ServerAuthShape { |
| 79 | 79 | readonly issueStartupPairingUrl: (baseUrl: string) => Effect.Effect<string, AuthError>; |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | export class ServerAuth extends ServiceMap.Service<ServerAuth, ServerAuthShape>()( | |
| 82 | export class ServerAuth extends Context.Service<ServerAuth, ServerAuthShape>()( | |
| 83 | 83 | "t3/auth/Services/ServerAuth", |
| 84 | 84 | ) {} |
apps/server/src/auth/Services/ServerAuthPolicy.ts+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | import type { ServerAuthDescriptor } from "@t3tools/contracts"; |
| 2 | import { ServiceMap } from "effect"; | |
| 2 | import { Context } from "effect"; | |
| 3 | 3 | import type { Effect } from "effect"; |
| 4 | 4 | |
| 5 | 5 | export interface ServerAuthPolicyShape { |
| 6 | 6 | readonly getDescriptor: () => Effect.Effect<ServerAuthDescriptor>; |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | export class ServerAuthPolicy extends ServiceMap.Service<ServerAuthPolicy, ServerAuthPolicyShape>()( | |
| 9 | export class ServerAuthPolicy extends Context.Service<ServerAuthPolicy, ServerAuthPolicyShape>()( | |
| 10 | 10 | "t3/auth/Services/ServerAuthPolicy", |
| 11 | 11 | ) {} |
apps/server/src/auth/Services/ServerSecretStore.ts+4-5| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { Data, ServiceMap } from "effect"; | |
| 1 | import { Data, Context } from "effect"; | |
| 2 | 2 | import type { Effect } from "effect"; |
| 3 | 3 | |
| 4 | 4 | export class SecretStoreError extends Data.TaggedError("SecretStoreError")<{ |
| ... | ... | @@ -16,7 +16,6 @@ export interface ServerSecretStoreShape { |
| 16 | 16 | readonly remove: (name: string) => Effect.Effect<void, SecretStoreError>; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | export class ServerSecretStore extends ServiceMap.Service< | |
| 20 | ServerSecretStore, | |
| 21 | ServerSecretStoreShape | |
| 22 | >()("t3/auth/Services/ServerSecretStore") {} | |
| 19 | export class ServerSecretStore extends Context.Service<ServerSecretStore, ServerSecretStoreShape>()( | |
| 20 | "t3/auth/Services/ServerSecretStore", | |
| 21 | ) {} |
apps/server/src/auth/Services/SessionCredentialService.ts+2-2| ... | ... | @@ -4,7 +4,7 @@ import type { |
| 4 | 4 | AuthSessionId, |
| 5 | 5 | ServerAuthSessionMethod, |
| 6 | 6 | } from "@t3tools/contracts"; |
| 7 | import { Data, DateTime, Duration, ServiceMap } from "effect"; | |
| 7 | import { Data, DateTime, Duration, Context } from "effect"; | |
| 8 | 8 | import type { Effect, Stream } from "effect"; |
| 9 | 9 | |
| 10 | 10 | export type SessionRole = "owner" | "client"; |
| ... | ... | @@ -81,7 +81,7 @@ export interface SessionCredentialServiceShape { |
| 81 | 81 | readonly markDisconnected: (sessionId: AuthSessionId) => Effect.Effect<void, never>; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | export class SessionCredentialService extends ServiceMap.Service< | |
| 84 | export class SessionCredentialService extends Context.Service< | |
| 85 | 85 | SessionCredentialService, |
| 86 | 86 | SessionCredentialServiceShape |
| 87 | 87 | >()("t3/auth/Services/SessionCredentialService") {} |
apps/server/src/checkpointing/Layers/CheckpointDiffQuery.test.ts+4-4| ... | ... | @@ -26,7 +26,7 @@ function makeThreadCheckpointContext(input: { |
| 26 | 26 | worktreePath: input.worktreePath, |
| 27 | 27 | checkpoints: [ |
| 28 | 28 | { |
| 29 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 29 | turnId: TurnId.make("turn-1"), | |
| 30 | 30 | checkpointTurnCount: input.checkpointTurnCount, |
| 31 | 31 | checkpointRef: input.checkpointRef, |
| 32 | 32 | status: "ready", |
| ... | ... | @@ -40,8 +40,8 @@ function makeThreadCheckpointContext(input: { |
| 40 | 40 | |
| 41 | 41 | describe("CheckpointDiffQueryLive", () => { |
| 42 | 42 | it("computes diffs using canonical turn-0 checkpoint refs", async () => { |
| 43 | const projectId = ProjectId.makeUnsafe("project-1"); | |
| 44 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 43 | const projectId = ProjectId.make("project-1"); | |
| 44 | const threadId = ThreadId.make("thread-1"); | |
| 45 | 45 | const toCheckpointRef = checkpointRefForThreadTurn(threadId, 1); |
| 46 | 46 | const hasCheckpointRefCalls: Array<CheckpointRef> = []; |
| 47 | 47 | const diffCheckpointsCalls: Array<{ |
| ... | ... | @@ -119,7 +119,7 @@ describe("CheckpointDiffQueryLive", () => { |
| 119 | 119 | }); |
| 120 | 120 | |
| 121 | 121 | it("fails when the thread is missing from the snapshot", async () => { |
| 122 | const threadId = ThreadId.makeUnsafe("thread-missing"); | |
| 122 | const threadId = ThreadId.make("thread-missing"); | |
| 123 | 123 | |
| 124 | 124 | const checkpointStore: CheckpointStoreShape = { |
| 125 | 125 | isGitRepository: () => Effect.succeed(true), |
apps/server/src/checkpointing/Layers/CheckpointStore.test.ts+1-1| ... | ... | @@ -93,7 +93,7 @@ it.layer(TestLayer)("CheckpointStoreLive", (it) => { |
| 93 | 93 | const tmp = yield* makeTmpDir(); |
| 94 | 94 | yield* initRepoWithCommit(tmp); |
| 95 | 95 | const checkpointStore = yield* CheckpointStore; |
| 96 | const threadId = ThreadId.makeUnsafe("thread-checkpoint-store"); | |
| 96 | const threadId = ThreadId.make("thread-checkpoint-store"); | |
| 97 | 97 | const fromCheckpointRef = checkpointRefForThreadTurn(threadId, 0); |
| 98 | 98 | const toCheckpointRef = checkpointRefForThreadTurn(threadId, 1); |
| 99 | 99 |
apps/server/src/checkpointing/Services/CheckpointDiffQuery.ts+2-2| ... | ... | @@ -12,7 +12,7 @@ import type { |
| 12 | 12 | OrchestrationGetTurnDiffInput, |
| 13 | 13 | OrchestrationGetTurnDiffResult, |
| 14 | 14 | } from "@t3tools/contracts"; |
| 15 | import { ServiceMap } from "effect"; | |
| 15 | import { Context } from "effect"; | |
| 16 | 16 | import type { Effect } from "effect"; |
| 17 | 17 | |
| 18 | 18 | import type { CheckpointServiceError } from "../Errors.ts"; |
| ... | ... | @@ -43,7 +43,7 @@ export interface CheckpointDiffQueryShape { |
| 43 | 43 | /** |
| 44 | 44 | * CheckpointDiffQuery - Service tag for checkpoint diff queries. |
| 45 | 45 | */ |
| 46 | export class CheckpointDiffQuery extends ServiceMap.Service< | |
| 46 | export class CheckpointDiffQuery extends Context.Service< | |
| 47 | 47 | CheckpointDiffQuery, |
| 48 | 48 | CheckpointDiffQueryShape |
| 49 | 49 | >()("t3/checkpointing/Services/CheckpointDiffQuery") {} |
apps/server/src/checkpointing/Services/CheckpointStore.ts+3-3| ... | ... | @@ -5,12 +5,12 @@ |
| 5 | 5 | * workspace thread timeline. It does not store user-facing checkpoint metadata |
| 6 | 6 | * and does not coordinate provider conversation rollback. |
| 7 | 7 | * |
| 8 | * Uses Effect `ServiceMap.Service` for dependency injection and exposes typed | |
| 8 | * Uses Effect `Context.Service` for dependency injection and exposes typed | |
| 9 | 9 | * domain errors for checkpoint storage operations. |
| 10 | 10 | * |
| 11 | 11 | * @module CheckpointStore |
| 12 | 12 | */ |
| 13 | import { ServiceMap } from "effect"; | |
| 13 | import { Context } from "effect"; | |
| 14 | 14 | import type { Effect } from "effect"; |
| 15 | 15 | |
| 16 | 16 | import type { CheckpointStoreError } from "../Errors.ts"; |
| ... | ... | @@ -95,6 +95,6 @@ export interface CheckpointStoreShape { |
| 95 | 95 | /** |
| 96 | 96 | * CheckpointStore - Service tag for checkpoint persistence and restore operations. |
| 97 | 97 | */ |
| 98 | export class CheckpointStore extends ServiceMap.Service<CheckpointStore, CheckpointStoreShape>()( | |
| 98 | export class CheckpointStore extends Context.Service<CheckpointStore, CheckpointStoreShape>()( | |
| 99 | 99 | "t3/checkpointing/Services/CheckpointStore", |
| 100 | 100 | ) {} |
apps/server/src/checkpointing/Utils.ts+1-1| ... | ... | @@ -4,7 +4,7 @@ import { CheckpointRef, ProjectId, type ThreadId } from "@t3tools/contracts"; |
| 4 | 4 | export const CHECKPOINT_REFS_PREFIX = "refs/t3/checkpoints"; |
| 5 | 5 | |
| 6 | 6 | export function checkpointRefForThreadTurn(threadId: ThreadId, turnCount: number): CheckpointRef { |
| 7 | return CheckpointRef.makeUnsafe( | |
| 7 | return CheckpointRef.make( | |
| 8 | 8 | `${CHECKPOINT_REFS_PREFIX}/${Encoding.encodeBase64Url(threadId)}/turn/${turnCount}`, |
| 9 | 9 | ); |
| 10 | 10 | } |
apps/server/src/cli-config.test.ts+63| ... | ... | @@ -153,6 +153,69 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => { |
| 153 | 153 | }), |
| 154 | 154 | ); |
| 155 | 155 | |
| 156 | it.effect("preserves explicit false CLI boolean flags over env and bootstrap values", () => | |
| 157 | Effect.gen(function* () { | |
| 158 | const { join } = yield* Path.Path; | |
| 159 | const baseDir = join(os.tmpdir(), "t3-cli-config-false-flags"); | |
| 160 | const fd = yield* openBootstrapFd({ | |
| 161 | noBrowser: true, | |
| 162 | autoBootstrapProjectFromCwd: true, | |
| 163 | logWebSocketEvents: true, | |
| 164 | }); | |
| 165 | const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173")); | |
| 166 | ||
| 167 | const resolved = yield* resolveServerConfig( | |
| 168 | { | |
| 169 | mode: Option.some("web"), | |
| 170 | port: Option.some(8788), | |
| 171 | host: Option.some("127.0.0.1"), | |
| 172 | baseDir: Option.some(baseDir), | |
| 173 | cwd: Option.none(), | |
| 174 | devUrl: Option.some(new URL("http://127.0.0.1:4173")), | |
| 175 | noBrowser: Option.some(false), | |
| 176 | bootstrapFd: Option.none(), | |
| 177 | autoBootstrapProjectFromCwd: Option.some(false), | |
| 178 | logWebSocketEvents: Option.some(false), | |
| 179 | }, | |
| 180 | Option.none(), | |
| 181 | ).pipe( | |
| 182 | Effect.provide( | |
| 183 | Layer.mergeAll( | |
| 184 | ConfigProvider.layer( | |
| 185 | ConfigProvider.fromEnv({ | |
| 186 | env: { | |
| 187 | T3CODE_BOOTSTRAP_FD: String(fd), | |
| 188 | T3CODE_NO_BROWSER: "true", | |
| 189 | T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "true", | |
| 190 | T3CODE_LOG_WS_EVENTS: "true", | |
| 191 | }, | |
| 192 | }), | |
| 193 | ), | |
| 194 | NetService.layer, | |
| 195 | ), | |
| 196 | ), | |
| 197 | ); | |
| 198 | ||
| 199 | expect(resolved).toEqual({ | |
| 200 | logLevel: "Info", | |
| 201 | ...defaultObservabilityConfig, | |
| 202 | mode: "web", | |
| 203 | port: 8788, | |
| 204 | cwd: process.cwd(), | |
| 205 | baseDir, | |
| 206 | ...derivedPaths, | |
| 207 | host: "127.0.0.1", | |
| 208 | staticDir: undefined, | |
| 209 | devUrl: new URL("http://127.0.0.1:4173"), | |
| 210 | noBrowser: false, | |
| 211 | startupPresentation: "browser", | |
| 212 | desktopBootstrapToken: undefined, | |
| 213 | autoBootstrapProjectFromCwd: false, | |
| 214 | logWebSocketEvents: false, | |
| 215 | }); | |
| 216 | }), | |
| 217 | ); | |
| 218 | ||
| 156 | 219 | it.effect("uses bootstrap envelope values as fallbacks when flags and env are absent", () => |
| 157 | 220 | Effect.gen(function* () { |
| 158 | 221 | const { join } = yield* Path.Path; |
apps/server/src/cli.test.ts+4| ... | ... | @@ -152,6 +152,10 @@ it.layer(NodeServices.layer)("cli log-level parsing", (it) => { |
| 152 | 152 | runCliWithRuntime(["--log-level", "debug", "--version"]), |
| 153 | 153 | ); |
| 154 | 154 | |
| 155 | it.effect("accepts canonical --no-<flag> boolean negation", () => | |
| 156 | runCliWithRuntime(["--no-log-websocket-events", "--version"]), | |
| 157 | ); | |
| 158 | ||
| 155 | 159 | it.effect("rejects invalid log-level casing before launching the server", () => |
| 156 | 160 | Effect.gen(function* () { |
| 157 | 161 | const error = yield* runCliWithRuntime(["--log-level", "Debug"]).pipe(Effect.flip); |
apps/server/src/cli.ts+37-68| ... | ... | @@ -193,9 +193,6 @@ interface CliAuthLocationFlags { |
| 193 | 193 | readonly devUrl?: Option.Option<URL>; |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | const resolveBooleanFlag = (flag: Option.Option<boolean>, envValue: boolean) => | |
| 197 | Option.getOrElse(Option.filter(flag, Boolean), () => envValue); | |
| 198 | ||
| 199 | 196 | const resolveOptionPrecedence = <Value>( |
| 200 | 197 | ...values: ReadonlyArray<Option.Option<Value>> |
| 201 | 198 | ): Option.Option<Value> => Option.firstSomeOf(values); |
| ... | ... | @@ -241,12 +238,13 @@ export const resolveServerConfig = ( |
| 241 | 238 | bootstrapFd !== undefined |
| 242 | 239 | ? yield* readBootstrapEnvelope(BootstrapEnvelopeSchema, bootstrapFd) |
| 243 | 240 | : Option.none(); |
| 241 | const bootstrap = Option.getOrUndefined(bootstrapEnvelope); | |
| 244 | 242 | |
| 245 | 243 | const mode: RuntimeMode = Option.getOrElse( |
| 246 | 244 | resolveOptionPrecedence( |
| 247 | 245 | normalizedFlags.mode, |
| 248 | 246 | Option.fromUndefinedOr(env.mode), |
| 249 | Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.mode)), | |
| 247 | Option.fromUndefinedOr(bootstrap?.mode), | |
| 250 | 248 | ), |
| 251 | 249 | () => "web", |
| 252 | 250 | ); |
| ... | ... | @@ -255,7 +253,7 @@ export const resolveServerConfig = ( |
| 255 | 253 | resolveOptionPrecedence( |
| 256 | 254 | normalizedFlags.port, |
| 257 | 255 | Option.fromUndefinedOr(env.port), |
| 258 | Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.port)), | |
| 256 | Option.fromUndefinedOr(bootstrap?.port), | |
| 259 | 257 | ), |
| 260 | 258 | { |
| 261 | 259 | onSome: (value) => Effect.succeed(value), |
| ... | ... | @@ -271,7 +269,7 @@ export const resolveServerConfig = ( |
| 271 | 269 | resolveOptionPrecedence( |
| 272 | 270 | normalizedFlags.devUrl, |
| 273 | 271 | Option.fromUndefinedOr(env.devUrl), |
| 274 | Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.devUrl)), | |
| 272 | Option.fromUndefinedOr(bootstrap?.devUrl), | |
| 275 | 273 | ), |
| 276 | 274 | () => undefined, |
| 277 | 275 | ); |
| ... | ... | @@ -280,9 +278,7 @@ export const resolveServerConfig = ( |
| 280 | 278 | resolveOptionPrecedence( |
| 281 | 279 | normalizedFlags.baseDir, |
| 282 | 280 | Option.fromUndefinedOr(env.t3Home), |
| 283 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 284 | Option.fromUndefinedOr(bootstrap.t3Home), | |
| 285 | ), | |
| 281 | Option.fromUndefinedOr(bootstrap?.t3Home), | |
| 286 | 282 | ), |
| 287 | 283 | ), |
| 288 | 284 | ); |
| ... | ... | @@ -297,60 +293,41 @@ export const resolveServerConfig = ( |
| 297 | 293 | const serverTracePath = env.traceFile ?? derivedPaths.serverTracePath; |
| 298 | 294 | yield* fs.makeDirectory(path.dirname(serverTracePath), { recursive: true }); |
| 299 | 295 | const startupPresentation = options?.startupPresentation ?? "browser"; |
| 300 | const noBrowser = | |
| 301 | startupPresentation === "headless" | |
| 302 | ? true | |
| 303 | : resolveBooleanFlag( | |
| 304 | normalizedFlags.noBrowser, | |
| 305 | Option.getOrElse( | |
| 306 | resolveOptionPrecedence( | |
| 307 | Option.fromUndefinedOr(env.noBrowser), | |
| 308 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 309 | Option.fromUndefinedOr(bootstrap.noBrowser), | |
| 310 | ), | |
| 311 | ), | |
| 312 | () => mode === "desktop", | |
| 313 | ), | |
| 314 | ); | |
| 315 | const desktopBootstrapToken = Option.getOrUndefined( | |
| 316 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 317 | Option.fromUndefinedOr(bootstrap.desktopBootstrapToken), | |
| 296 | const isHeadlessStartup = startupPresentation === "headless"; | |
| 297 | const noBrowser = Option.getOrElse( | |
| 298 | resolveOptionPrecedence( | |
| 299 | isHeadlessStartup ? Option.some(true) : Option.none(), | |
| 300 | normalizedFlags.noBrowser, | |
| 301 | Option.fromUndefinedOr(env.noBrowser), | |
| 302 | Option.fromUndefinedOr(bootstrap?.noBrowser), | |
| 318 | 303 | ), |
| 304 | () => mode === "desktop", | |
| 319 | 305 | ); |
| 320 | const autoBootstrapProjectFromCwd = | |
| 321 | options?.forceAutoBootstrapProjectFromCwd ?? | |
| 322 | (startupPresentation === "headless" | |
| 323 | ? false | |
| 324 | : resolveBooleanFlag( | |
| 325 | normalizedFlags.autoBootstrapProjectFromCwd, | |
| 326 | Option.getOrElse( | |
| 327 | resolveOptionPrecedence( | |
| 328 | Option.fromUndefinedOr(env.autoBootstrapProjectFromCwd), | |
| 329 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 330 | Option.fromUndefinedOr(bootstrap.autoBootstrapProjectFromCwd), | |
| 331 | ), | |
| 332 | ), | |
| 333 | () => mode === "web", | |
| 334 | ), | |
| 335 | )); | |
| 336 | const logWebSocketEvents = resolveBooleanFlag( | |
| 337 | normalizedFlags.logWebSocketEvents, | |
| 338 | Option.getOrElse( | |
| 339 | resolveOptionPrecedence( | |
| 340 | Option.fromUndefinedOr(env.logWebSocketEvents), | |
| 341 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 342 | Option.fromUndefinedOr(bootstrap.logWebSocketEvents), | |
| 343 | ), | |
| 344 | ), | |
| 345 | () => Boolean(devUrl), | |
| 306 | const desktopBootstrapToken = bootstrap?.desktopBootstrapToken; | |
| 307 | const autoBootstrapProjectFromCwd = Option.getOrElse( | |
| 308 | resolveOptionPrecedence( | |
| 309 | Option.fromUndefinedOr(options?.forceAutoBootstrapProjectFromCwd), | |
| 310 | isHeadlessStartup ? Option.some(false) : Option.none(), | |
| 311 | normalizedFlags.autoBootstrapProjectFromCwd, | |
| 312 | Option.fromUndefinedOr(env.autoBootstrapProjectFromCwd), | |
| 313 | Option.fromUndefinedOr(bootstrap?.autoBootstrapProjectFromCwd), | |
| 314 | ), | |
| 315 | () => mode === "web", | |
| 316 | ); | |
| 317 | const logWebSocketEvents = Option.getOrElse( | |
| 318 | resolveOptionPrecedence( | |
| 319 | normalizedFlags.logWebSocketEvents, | |
| 320 | Option.fromUndefinedOr(env.logWebSocketEvents), | |
| 321 | Option.fromUndefinedOr(bootstrap?.logWebSocketEvents), | |
| 346 | 322 | ), |
| 323 | () => Boolean(devUrl), | |
| 347 | 324 | ); |
| 348 | 325 | const staticDir = devUrl ? undefined : yield* resolveStaticDir(); |
| 349 | 326 | const host = Option.getOrElse( |
| 350 | 327 | resolveOptionPrecedence( |
| 351 | 328 | normalizedFlags.host, |
| 352 | 329 | Option.fromUndefinedOr(env.host), |
| 353 | Option.flatMap(bootstrapEnvelope, (bootstrap) => Option.fromUndefinedOr(bootstrap.host)), | |
| 330 | Option.fromUndefinedOr(bootstrap?.host), | |
| 354 | 331 | ), |
| 355 | 332 | () => (mode === "desktop" ? "127.0.0.1" : undefined), |
| 356 | 333 | ); |
| ... | ... | @@ -365,19 +342,11 @@ export const resolveServerConfig = ( |
| 365 | 342 | traceMaxFiles: env.traceMaxFiles, |
| 366 | 343 | otlpTracesUrl: |
| 367 | 344 | env.otlpTracesUrl ?? |
| 368 | Option.getOrUndefined( | |
| 369 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 370 | Option.fromUndefinedOr(bootstrap.otlpTracesUrl), | |
| 371 | ), | |
| 372 | ) ?? | |
| 345 | bootstrap?.otlpTracesUrl ?? | |
| 373 | 346 | persistedObservabilitySettings.otlpTracesUrl, |
| 374 | 347 | otlpMetricsUrl: |
| 375 | 348 | env.otlpMetricsUrl ?? |
| 376 | Option.getOrUndefined( | |
| 377 | Option.flatMap(bootstrapEnvelope, (bootstrap) => | |
| 378 | Option.fromUndefinedOr(bootstrap.otlpMetricsUrl), | |
| 379 | ), | |
| 380 | ) ?? | |
| 349 | bootstrap?.otlpMetricsUrl ?? | |
| 381 | 350 | persistedObservabilitySettings.otlpMetricsUrl, |
| 382 | 351 | otlpExportIntervalMs: env.otlpExportIntervalMs, |
| 383 | 352 | otlpServiceName: env.otlpServiceName, |
| ... | ... | @@ -1030,10 +999,10 @@ const projectAddCommand = Command.make("add", { |
| 1030 | 999 | } |
| 1031 | 1000 | |
| 1032 | 1001 | const title = yield* resolveProjectTitle(workspaceRoot, Option.getOrUndefined(flags.title)); |
| 1033 | const projectId = ProjectId.makeUnsafe(crypto.randomUUID()); | |
| 1002 | const projectId = ProjectId.make(crypto.randomUUID()); | |
| 1034 | 1003 | yield* dispatch({ |
| 1035 | 1004 | type: "project.create", |
| 1036 | commandId: CommandId.makeUnsafe(crypto.randomUUID()), | |
| 1005 | commandId: CommandId.make(crypto.randomUUID()), | |
| 1037 | 1006 | projectId, |
| 1038 | 1007 | title, |
| 1039 | 1008 | workspaceRoot, |
| ... | ... | @@ -1071,7 +1040,7 @@ const projectRemoveCommand = Command.make("remove", { |
| 1071 | 1040 | }); |
| 1072 | 1041 | yield* dispatch({ |
| 1073 | 1042 | type: "project.delete", |
| 1074 | commandId: CommandId.makeUnsafe(crypto.randomUUID()), | |
| 1043 | commandId: CommandId.make(crypto.randomUUID()), | |
| 1075 | 1044 | projectId: project.id, |
| 1076 | 1045 | }); |
| 1077 | 1046 | return `Removed project ${project.id} (${project.title}).`; |
| ... | ... | @@ -1111,7 +1080,7 @@ const projectRenameCommand = Command.make("rename", { |
| 1111 | 1080 | |
| 1112 | 1081 | yield* dispatch({ |
| 1113 | 1082 | type: "project.meta.update", |
| 1114 | commandId: CommandId.makeUnsafe(crypto.randomUUID()), | |
| 1083 | commandId: CommandId.make(crypto.randomUUID()), | |
| 1115 | 1084 | projectId: project.id, |
| 1116 | 1085 | title: nextTitle, |
| 1117 | 1086 | }); |
apps/server/src/codexAppServerManager.test.ts+5-5| ... | ... | @@ -17,7 +17,7 @@ import { |
| 17 | 17 | resolveCodexModelForAccount, |
| 18 | 18 | } from "./codexAppServerManager"; |
| 19 | 19 | |
| 20 | const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value); | |
| 20 | const asThreadId = (value: string): ThreadId => ThreadId.make(value); | |
| 21 | 21 | |
| 22 | 22 | function createSendTurnHarness() { |
| 23 | 23 | const manager = new CodexAppServerManager(); |
| ... | ... | @@ -111,9 +111,9 @@ function createPendingUserInputHarness() { |
| 111 | 111 | }, |
| 112 | 112 | pendingUserInputs: new Map([ |
| 113 | 113 | [ |
| 114 | ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 114 | ApprovalRequestId.make("req-user-input-1"), | |
| 115 | 115 | { |
| 116 | requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 116 | requestId: ApprovalRequestId.make("req-user-input-1"), | |
| 117 | 117 | jsonRpcId: 42, |
| 118 | 118 | threadId: asThreadId("thread_1"), |
| 119 | 119 | }, |
| ... | ... | @@ -743,7 +743,7 @@ describe("respondToUserInput", () => { |
| 743 | 743 | |
| 744 | 744 | await manager.respondToUserInput( |
| 745 | 745 | asThreadId("thread_1"), |
| 746 | ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 746 | ApprovalRequestId.make("req-user-input-1"), | |
| 747 | 747 | { |
| 748 | 748 | scope: "All request methods", |
| 749 | 749 | compat: "Keep current envelope", |
| ... | ... | @@ -780,7 +780,7 @@ describe("respondToUserInput", () => { |
| 780 | 780 | |
| 781 | 781 | await manager.respondToUserInput( |
| 782 | 782 | asThreadId("thread_1"), |
| 783 | ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 783 | ApprovalRequestId.make("req-user-input-1"), | |
| 784 | 784 | { |
| 785 | 785 | scope: [], |
| 786 | 786 | }, |
apps/server/src/codexAppServerManager.ts+16-16| ... | ... | @@ -19,7 +19,7 @@ import { |
| 19 | 19 | ProviderInteractionMode, |
| 20 | 20 | } from "@t3tools/contracts"; |
| 21 | 21 | import { normalizeModelSlug } from "@t3tools/shared/model"; |
| 22 | import { Effect, ServiceMap } from "effect"; | |
| 22 | import { Effect, Context } from "effect"; | |
| 23 | 23 | |
| 24 | 24 | import { |
| 25 | 25 | formatCodexCliUpgradeMessage, |
| ... | ... | @@ -439,7 +439,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 439 | 439 | private readonly sessions = new Map<ThreadId, CodexSessionContext>(); |
| 440 | 440 | |
| 441 | 441 | private runPromise: (effect: Effect.Effect<unknown, never>) => Promise<unknown>; |
| 442 | constructor(services?: ServiceMap.ServiceMap<never>) { | |
| 442 | constructor(services?: Context.Context<never>) { | |
| 443 | 443 | super(); |
| 444 | 444 | this.runPromise = services ? Effect.runPromiseWith(services) : Effect.runPromise; |
| 445 | 445 | } |
| ... | ... | @@ -640,7 +640,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 640 | 640 | this.stopSession(threadId); |
| 641 | 641 | } else { |
| 642 | 642 | this.emitEvent({ |
| 643 | id: EventId.makeUnsafe(randomUUID()), | |
| 643 | id: EventId.make(randomUUID()), | |
| 644 | 644 | kind: "error", |
| 645 | 645 | provider: "codex", |
| 646 | 646 | threadId, |
| ... | ... | @@ -739,7 +739,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 739 | 739 | if (!turnIdRaw) { |
| 740 | 740 | throw new Error("turn/start response did not include a turn id."); |
| 741 | 741 | } |
| 742 | const turnId = TurnId.makeUnsafe(turnIdRaw); | |
| 742 | const turnId = TurnId.make(turnIdRaw); | |
| 743 | 743 | |
| 744 | 744 | this.updateSession(context, { |
| 745 | 745 | status: "running", |
| ... | ... | @@ -840,7 +840,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 840 | 840 | }); |
| 841 | 841 | |
| 842 | 842 | this.emitEvent({ |
| 843 | id: EventId.makeUnsafe(randomUUID()), | |
| 843 | id: EventId.make(randomUUID()), | |
| 844 | 844 | kind: "notification", |
| 845 | 845 | provider: "codex", |
| 846 | 846 | threadId: context.session.threadId, |
| ... | ... | @@ -879,7 +879,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 879 | 879 | }); |
| 880 | 880 | |
| 881 | 881 | this.emitEvent({ |
| 882 | id: EventId.makeUnsafe(randomUUID()), | |
| 882 | id: EventId.make(randomUUID()), | |
| 883 | 883 | kind: "notification", |
| 884 | 884 | provider: "codex", |
| 885 | 885 | threadId: context.session.threadId, |
| ... | ... | @@ -1061,7 +1061,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1061 | 1061 | : undefined; |
| 1062 | 1062 | |
| 1063 | 1063 | this.emitEvent({ |
| 1064 | id: EventId.makeUnsafe(randomUUID()), | |
| 1064 | id: EventId.make(randomUUID()), | |
| 1065 | 1065 | kind: "notification", |
| 1066 | 1066 | provider: "codex", |
| 1067 | 1067 | threadId: context.session.threadId, |
| ... | ... | @@ -1134,7 +1134,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1134 | 1134 | const requestKind = this.requestKindForMethod(request.method); |
| 1135 | 1135 | let requestId: ApprovalRequestId | undefined; |
| 1136 | 1136 | if (requestKind) { |
| 1137 | requestId = ApprovalRequestId.makeUnsafe(randomUUID()); | |
| 1137 | requestId = ApprovalRequestId.make(randomUUID()); | |
| 1138 | 1138 | const pendingRequest: PendingApprovalRequest = { |
| 1139 | 1139 | requestId, |
| 1140 | 1140 | jsonRpcId: request.id, |
| ... | ... | @@ -1153,7 +1153,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1153 | 1153 | } |
| 1154 | 1154 | |
| 1155 | 1155 | if (request.method === "item/tool/requestUserInput") { |
| 1156 | requestId = ApprovalRequestId.makeUnsafe(randomUUID()); | |
| 1156 | requestId = ApprovalRequestId.make(randomUUID()); | |
| 1157 | 1157 | context.pendingUserInputs.set(requestId, { |
| 1158 | 1158 | requestId, |
| 1159 | 1159 | jsonRpcId: request.id, |
| ... | ... | @@ -1164,7 +1164,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1164 | 1164 | } |
| 1165 | 1165 | |
| 1166 | 1166 | this.emitEvent({ |
| 1167 | id: EventId.makeUnsafe(randomUUID()), | |
| 1167 | id: EventId.make(randomUUID()), | |
| 1168 | 1168 | kind: "request", |
| 1169 | 1169 | provider: "codex", |
| 1170 | 1170 | threadId: context.session.threadId, |
| ... | ... | @@ -1254,7 +1254,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1254 | 1254 | |
| 1255 | 1255 | private emitLifecycleEvent(context: CodexSessionContext, method: string, message: string): void { |
| 1256 | 1256 | this.emitEvent({ |
| 1257 | id: EventId.makeUnsafe(randomUUID()), | |
| 1257 | id: EventId.make(randomUUID()), | |
| 1258 | 1258 | kind: "session", |
| 1259 | 1259 | provider: "codex", |
| 1260 | 1260 | threadId: context.session.threadId, |
| ... | ... | @@ -1266,7 +1266,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1266 | 1266 | |
| 1267 | 1267 | private emitErrorEvent(context: CodexSessionContext, method: string, message: string): void { |
| 1268 | 1268 | this.emitEvent({ |
| 1269 | id: EventId.makeUnsafe(randomUUID()), | |
| 1269 | id: EventId.make(randomUUID()), | |
| 1270 | 1270 | kind: "error", |
| 1271 | 1271 | provider: "codex", |
| 1272 | 1272 | threadId: context.session.threadId, |
| ... | ... | @@ -1282,7 +1282,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1282 | 1282 | message: string, |
| 1283 | 1283 | ): void { |
| 1284 | 1284 | this.emitEvent({ |
| 1285 | id: EventId.makeUnsafe(randomUUID()), | |
| 1285 | id: EventId.make(randomUUID()), | |
| 1286 | 1286 | kind: "notification", |
| 1287 | 1287 | provider: "codex", |
| 1288 | 1288 | threadId: context.session.threadId, |
| ... | ... | @@ -1341,7 +1341,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve |
| 1341 | 1341 | const turns = turnsRaw.map((turnValue, index) => { |
| 1342 | 1342 | const turn = this.readObject(turnValue); |
| 1343 | 1343 | const turnIdRaw = this.readString(turn, "id") ?? `${threadIdRaw}:turn:${index + 1}`; |
| 1344 | const turnId = TurnId.makeUnsafe(turnIdRaw); | |
| 1344 | const turnId = TurnId.make(turnIdRaw); | |
| 1345 | 1345 | const items = this.readArray(turn, "items") ?? []; |
| 1346 | 1346 | return { |
| 1347 | 1347 | id: turnId, |
| ... | ... | @@ -1590,9 +1590,9 @@ function readResumeThreadId(input: { |
| 1590 | 1590 | } |
| 1591 | 1591 | |
| 1592 | 1592 | function toTurnId(value: string | undefined): TurnId | undefined { |
| 1593 | return brandIfNonEmpty(value, TurnId.makeUnsafe); | |
| 1593 | return brandIfNonEmpty(value, TurnId.make); | |
| 1594 | 1594 | } |
| 1595 | 1595 | |
| 1596 | 1596 | function toProviderItemId(value: string | undefined): ProviderItemId | undefined { |
| 1597 | return brandIfNonEmpty(value, ProviderItemId.makeUnsafe); | |
| 1597 | return brandIfNonEmpty(value, ProviderItemId.make); | |
| 1598 | 1598 | } |
apps/server/src/config.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module ServerConfig |
| 8 | 8 | */ |
| 9 | import { Effect, FileSystem, Layer, LogLevel, Path, Schema, ServiceMap } from "effect"; | |
| 9 | import { Effect, FileSystem, Layer, LogLevel, Path, Schema, Context } from "effect"; | |
| 10 | 10 | |
| 11 | 11 | export const DEFAULT_PORT = 3773; |
| 12 | 12 | |
| ... | ... | @@ -120,7 +120,7 @@ export const ensureServerDirectories = Effect.fn(function* (derivedPaths: Server |
| 120 | 120 | /** |
| 121 | 121 | * ServerConfig - Service tag for server runtime configuration. |
| 122 | 122 | */ |
| 123 | export class ServerConfig extends ServiceMap.Service<ServerConfig, ServerConfigShape>()( | |
| 123 | export class ServerConfig extends Context.Service<ServerConfig, ServerConfigShape>()( | |
| 124 | 124 | "t3/config/ServerConfig", |
| 125 | 125 | ) { |
| 126 | 126 | static readonly layerTest = (cwd: string, baseDirOrPrefix: string | { prefix: string }) => |
apps/server/src/environment/Layers/ServerEnvironment.ts+1-1| ... | ... | @@ -64,7 +64,7 @@ export const makeServerEnvironment = Effect.fn("makeServerEnvironment")(function |
| 64 | 64 | return generated; |
| 65 | 65 | }); |
| 66 | 66 | |
| 67 | const environmentId = EnvironmentId.makeUnsafe(environmentIdRaw); | |
| 67 | const environmentId = EnvironmentId.make(environmentIdRaw); | |
| 68 | 68 | const cwdBaseName = path.basename(serverConfig.cwd).trim(); |
| 69 | 69 | const label = yield* resolveServerEnvironmentLabel({ |
| 70 | 70 | cwdBaseName, |
apps/server/src/environment/Layers/ServerEnvironmentLabel.ts+7-5| ... | ... | @@ -51,11 +51,13 @@ const runFriendlyLabelCommand = Effect.fn("runFriendlyLabelCommand")(function* ( |
| 51 | 51 | command: string, |
| 52 | 52 | args: readonly string[], |
| 53 | 53 | ) { |
| 54 | const result = yield* Effect.tryPromise(() => | |
| 55 | runProcess(command, args, { | |
| 56 | allowNonZeroExit: true, | |
| 57 | }), | |
| 58 | ).pipe(Effect.orElseSucceed(() => null)); | |
| 54 | const result = yield* Effect.tryPromise({ | |
| 55 | try: () => | |
| 56 | runProcess(command, args, { | |
| 57 | allowNonZeroExit: true, | |
| 58 | }), | |
| 59 | catch: () => null, | |
| 60 | }).pipe(Effect.orElseSucceed(() => null)); | |
| 59 | 61 | |
| 60 | 62 | if (!result || result.code !== 0) { |
| 61 | 63 | return null; |
apps/server/src/environment/Services/ServerEnvironment.ts+4-5| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | import type { EnvironmentId, ExecutionEnvironmentDescriptor } from "@t3tools/contracts"; |
| 2 | import { ServiceMap } from "effect"; | |
| 2 | import { Context } from "effect"; | |
| 3 | 3 | import type { Effect } from "effect"; |
| 4 | 4 | |
| 5 | 5 | export interface ServerEnvironmentShape { |
| ... | ... | @@ -7,7 +7,6 @@ export interface ServerEnvironmentShape { |
| 7 | 7 | readonly getDescriptor: Effect.Effect<ExecutionEnvironmentDescriptor>; |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | export class ServerEnvironment extends ServiceMap.Service< | |
| 11 | ServerEnvironment, | |
| 12 | ServerEnvironmentShape | |
| 13 | >()("t3/environment/Services/ServerEnvironment") {} | |
| 10 | export class ServerEnvironment extends Context.Service<ServerEnvironment, ServerEnvironmentShape>()( | |
| 11 | "t3/environment/Services/ServerEnvironment", | |
| 12 | ) {} |
apps/server/src/git/Layers/GitCore.test.ts+2-2| ... | ... | @@ -649,8 +649,8 @@ it.layer(TestLayer)("git integration", (it) => { |
| 649 | 649 | |
| 650 | 650 | it.effect("refreshes upstream behind count after checkout when remote branch advanced", () => |
| 651 | 651 | Effect.gen(function* () { |
| 652 | const services = yield* Effect.services(); | |
| 653 | const runPromise = Effect.runPromiseWith(services); | |
| 652 | const context = yield* Effect.context<never>(); | |
| 653 | const runPromise = Effect.runPromiseWith(context); | |
| 654 | 654 | |
| 655 | 655 | const remote = yield* makeTmpDir(); |
| 656 | 656 | const source = yield* makeTmpDir(); |
apps/server/src/git/Layers/GitCore.ts+1-2| ... | ... | @@ -933,9 +933,8 @@ export const makeGitCore = Effect.fn("makeGitCore")(function* (options?: { |
| 933 | 933 | return true as const; |
| 934 | 934 | }); |
| 935 | 935 | |
| 936 | const statusUpstreamRefreshCache = yield* Cache.makeWith({ | |
| 936 | const statusUpstreamRefreshCache = yield* Cache.makeWith(refreshStatusUpstreamCacheEntry, { | |
| 937 | 937 | capacity: STATUS_UPSTREAM_REFRESH_CACHE_CAPACITY, |
| 938 | lookup: refreshStatusUpstreamCacheEntry, | |
| 939 | 938 | // Keep successful refreshes warm and briefly back off failed refreshes to avoid retry storms. |
| 940 | 939 | timeToLive: (exit) => |
| 941 | 940 | Exit.isSuccess(exit) |
apps/server/src/git/Layers/GitManager.ts+2-4| ... | ... | @@ -731,9 +731,8 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () { |
| 731 | 731 | workingTree: details.workingTree, |
| 732 | 732 | } satisfies GitStatusLocalResult; |
| 733 | 733 | }); |
| 734 | const localStatusResultCache = yield* Cache.makeWith({ | |
| 734 | const localStatusResultCache = yield* Cache.makeWith(readLocalStatus, { | |
| 735 | 735 | capacity: STATUS_RESULT_CACHE_CAPACITY, |
| 736 | lookup: readLocalStatus, | |
| 737 | 736 | timeToLive: (exit) => (Exit.isSuccess(exit) ? STATUS_RESULT_CACHE_TTL : Duration.zero), |
| 738 | 737 | }); |
| 739 | 738 | const invalidateLocalStatusResultCache = (cwd: string) => |
| ... | ... | @@ -764,9 +763,8 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () { |
| 764 | 763 | pr, |
| 765 | 764 | } satisfies GitStatusRemoteResult; |
| 766 | 765 | }); |
| 767 | const remoteStatusResultCache = yield* Cache.makeWith({ | |
| 766 | const remoteStatusResultCache = yield* Cache.makeWith(readRemoteStatus, { | |
| 768 | 767 | capacity: STATUS_RESULT_CACHE_CAPACITY, |
| 769 | lookup: readRemoteStatus, | |
| 770 | 768 | timeToLive: (exit) => (Exit.isSuccess(exit) ? STATUS_RESULT_CACHE_TTL : Duration.zero), |
| 771 | 769 | }); |
| 772 | 770 | const invalidateRemoteStatusResultCache = (cwd: string) => |
apps/server/src/git/Layers/RoutingTextGeneration.ts+3-3| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | * |
| 10 | 10 | * @module RoutingTextGeneration |
| 11 | 11 | */ |
| 12 | import { Effect, Layer, ServiceMap } from "effect"; | |
| 12 | import { Effect, Layer, Context } from "effect"; | |
| 13 | 13 | |
| 14 | 14 | import { |
| 15 | 15 | TextGeneration, |
| ... | ... | @@ -23,11 +23,11 @@ import { ClaudeTextGenerationLive } from "./ClaudeTextGeneration.ts"; |
| 23 | 23 | // Internal service tags so both concrete layers can coexist. |
| 24 | 24 | // --------------------------------------------------------------------------- |
| 25 | 25 | |
| 26 | class CodexTextGen extends ServiceMap.Service<CodexTextGen, TextGenerationShape>()( | |
| 26 | class CodexTextGen extends Context.Service<CodexTextGen, TextGenerationShape>()( | |
| 27 | 27 | "t3/git/Layers/RoutingTextGeneration/CodexTextGen", |
| 28 | 28 | ) {} |
| 29 | 29 | |
| 30 | class ClaudeTextGen extends ServiceMap.Service<ClaudeTextGen, TextGenerationShape>()( | |
| 30 | class ClaudeTextGen extends Context.Service<ClaudeTextGen, TextGenerationShape>()( | |
| 31 | 31 | "t3/git/Layers/RoutingTextGeneration/ClaudeTextGen", |
| 32 | 32 | ) {} |
| 33 | 33 |
apps/server/src/git/Services/GitCore.ts+2-4| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module GitCore |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect } from "effect"; |
| 11 | 11 | import type { |
| 12 | 12 | GitCheckoutInput, |
| ... | ... | @@ -310,6 +310,4 @@ export interface GitCoreShape { |
| 310 | 310 | /** |
| 311 | 311 | * GitCore - Service tag for low-level Git repository operations. |
| 312 | 312 | */ |
| 313 | export class GitCore extends ServiceMap.Service<GitCore, GitCoreShape>()( | |
| 314 | "t3/git/Services/GitCore", | |
| 315 | ) {} | |
| 313 | export class GitCore extends Context.Service<GitCore, GitCoreShape>()("t3/git/Services/GitCore") {} |
apps/server/src/git/Services/GitHubCli.ts+2-2| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | * |
| 6 | 6 | * @module GitHubCli |
| 7 | 7 | */ |
| 8 | import { ServiceMap } from "effect"; | |
| 8 | import { Context } from "effect"; | |
| 9 | 9 | import type { Effect } from "effect"; |
| 10 | 10 | |
| 11 | 11 | import type { ProcessRunResult } from "../../processRunner"; |
| ... | ... | @@ -98,6 +98,6 @@ export interface GitHubCliShape { |
| 98 | 98 | /** |
| 99 | 99 | * GitHubCli - Service tag for GitHub CLI process execution. |
| 100 | 100 | */ |
| 101 | export class GitHubCli extends ServiceMap.Service<GitHubCli, GitHubCliShape>()( | |
| 101 | export class GitHubCli extends Context.Service<GitHubCli, GitHubCliShape>()( | |
| 102 | 102 | "t3/git/Services/GitHubCli", |
| 103 | 103 | ) {} |
apps/server/src/git/Services/GitManager.ts+2-2| ... | ... | @@ -19,7 +19,7 @@ import { |
| 19 | 19 | GitStatusInput, |
| 20 | 20 | GitStatusResult, |
| 21 | 21 | } from "@t3tools/contracts"; |
| 22 | import { ServiceMap } from "effect"; | |
| 22 | import { Context } from "effect"; | |
| 23 | 23 | import type { Effect } from "effect"; |
| 24 | 24 | import type { GitManagerServiceError } from "@t3tools/contracts"; |
| 25 | 25 | |
| ... | ... | @@ -99,6 +99,6 @@ export interface GitManagerShape { |
| 99 | 99 | /** |
| 100 | 100 | * GitManager - Service tag for stacked Git workflow orchestration. |
| 101 | 101 | */ |
| 102 | export class GitManager extends ServiceMap.Service<GitManager, GitManagerShape>()( | |
| 102 | export class GitManager extends Context.Service<GitManager, GitManagerShape>()( | |
| 103 | 103 | "t3/git/Services/GitManager", |
| 104 | 104 | ) {} |
apps/server/src/git/Services/GitStatusBroadcaster.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { ServiceMap } from "effect"; | |
| 1 | import { Context } from "effect"; | |
| 2 | 2 | import type { Effect, Stream } from "effect"; |
| 3 | 3 | import type { |
| 4 | 4 | GitManagerServiceError, |
| ... | ... | @@ -21,7 +21,7 @@ export interface GitStatusBroadcasterShape { |
| 21 | 21 | ) => Stream.Stream<GitStatusStreamEvent, GitManagerServiceError>; |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | export class GitStatusBroadcaster extends ServiceMap.Service< | |
| 24 | export class GitStatusBroadcaster extends Context.Service< | |
| 25 | 25 | GitStatusBroadcaster, |
| 26 | 26 | GitStatusBroadcasterShape |
| 27 | 27 | >()("t3/git/Services/GitStatusBroadcaster") {} |
apps/server/src/git/Services/TextGeneration.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module TextGeneration |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect } from "effect"; |
| 11 | 11 | import type { ChatAttachment, ModelSelection } from "@t3tools/contracts"; |
| 12 | 12 | |
| ... | ... | @@ -118,6 +118,6 @@ export interface TextGenerationShape { |
| 118 | 118 | /** |
| 119 | 119 | * TextGeneration - Service tag for commit and PR text generation. |
| 120 | 120 | */ |
| 121 | export class TextGeneration extends ServiceMap.Service<TextGeneration, TextGenerationShape>()( | |
| 121 | export class TextGeneration extends Context.Service<TextGeneration, TextGenerationShape>()( | |
| 122 | 122 | "t3/git/Services/TextGeneration", |
| 123 | 123 | ) {} |
apps/server/src/keybindings.ts+2-2| ... | ... | @@ -39,7 +39,7 @@ import { |
| 39 | 39 | SchemaIssue, |
| 40 | 40 | SchemaTransformation, |
| 41 | 41 | Ref, |
| 42 | ServiceMap, | |
| 42 | Context, | |
| 43 | 43 | Scope, |
| 44 | 44 | Stream, |
| 45 | 45 | } from "effect"; |
| ... | ... | @@ -521,7 +521,7 @@ export interface KeybindingsShape { |
| 521 | 521 | /** |
| 522 | 522 | * Keybindings - Service tag for keybinding configuration operations. |
| 523 | 523 | */ |
| 524 | export class Keybindings extends ServiceMap.Service<Keybindings, KeybindingsShape>()( | |
| 524 | export class Keybindings extends Context.Service<Keybindings, KeybindingsShape>()( | |
| 525 | 525 | "t3/keybindings", |
| 526 | 526 | ) {} |
| 527 | 527 |
apps/server/src/observability/Services/BrowserTraceCollector.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { ServiceMap } from "effect"; | |
| 1 | import { Context } from "effect"; | |
| 2 | 2 | import type { Effect } from "effect"; |
| 3 | 3 | |
| 4 | 4 | import type { TraceRecord } from "../TraceRecord.ts"; |
| ... | ... | @@ -7,7 +7,7 @@ export interface BrowserTraceCollectorShape { |
| 7 | 7 | readonly record: (records: ReadonlyArray<TraceRecord>) => Effect.Effect<void>; |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | export class BrowserTraceCollector extends ServiceMap.Service< | |
| 10 | export class BrowserTraceCollector extends Context.Service< | |
| 11 | 11 | BrowserTraceCollector, |
| 12 | 12 | BrowserTraceCollectorShape |
| 13 | 13 | >()("t3/observability/Services/BrowserTraceCollector") {} |
apps/server/src/open.ts+2-2| ... | ... | @@ -11,7 +11,7 @@ import { accessSync, constants, statSync } from "node:fs"; |
| 11 | 11 | import { extname, join } from "node:path"; |
| 12 | 12 | |
| 13 | 13 | import { EDITORS, OpenError, type EditorId } from "@t3tools/contracts"; |
| 14 | import { ServiceMap, Effect, Layer } from "effect"; | |
| 14 | import { Context, Effect, Layer } from "effect"; | |
| 15 | 15 | |
| 16 | 16 | // ============================== |
| 17 | 17 | // Definitions |
| ... | ... | @@ -247,7 +247,7 @@ export interface OpenShape { |
| 247 | 247 | /** |
| 248 | 248 | * Open - Service tag for browser/editor launch operations. |
| 249 | 249 | */ |
| 250 | export class Open extends ServiceMap.Service<Open, OpenShape>()("t3/open") {} | |
| 250 | export class Open extends Context.Service<Open, OpenShape>()("t3/open") {} | |
| 251 | 251 | |
| 252 | 252 | // ============================== |
| 253 | 253 | // Implementations |
apps/server/src/orchestration/Layers/CheckpointReactor.test.ts+118-120| ... | ... | @@ -44,8 +44,8 @@ import { ServerConfig } from "../../config.ts"; |
| 44 | 44 | import { WorkspaceEntriesLive } from "../../workspace/Layers/WorkspaceEntries.ts"; |
| 45 | 45 | import { WorkspacePathsLive } from "../../workspace/Layers/WorkspacePaths.ts"; |
| 46 | 46 | |
| 47 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 48 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 47 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 48 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 49 | 49 | |
| 50 | 50 | type LegacyProviderRuntimeEvent = { |
| 51 | 51 | readonly type: string; |
| ... | ... | @@ -81,7 +81,7 @@ function createProviderServiceHarness( |
| 81 | 81 | provider: providerName, |
| 82 | 82 | status: "ready", |
| 83 | 83 | runtimeMode: "full-access", |
| 84 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 84 | threadId: ThreadId.make("thread-1"), | |
| 85 | 85 | cwd: sessionCwd, |
| 86 | 86 | createdAt: now, |
| 87 | 87 | updatedAt: now, |
| ... | ... | @@ -130,7 +130,7 @@ async function waitForThread( |
| 130 | 130 | activities: ReadonlyArray<{ kind: string }>; |
| 131 | 131 | }> => { |
| 132 | 132 | const readModel = await Effect.runPromise(engine.getReadModel()); |
| 133 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 133 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 134 | 134 | if (thread && predicate(thread)) { |
| 135 | 135 | return thread; |
| 136 | 136 | } |
| ... | ... | @@ -310,7 +310,7 @@ describe("CheckpointReactor", () => { |
| 310 | 310 | await Effect.runPromise( |
| 311 | 311 | engine.dispatch({ |
| 312 | 312 | type: "project.create", |
| 313 | commandId: CommandId.makeUnsafe("cmd-project-create"), | |
| 313 | commandId: CommandId.make("cmd-project-create"), | |
| 314 | 314 | projectId: asProjectId("project-1"), |
| 315 | 315 | title: "Test Project", |
| 316 | 316 | workspaceRoot: options?.projectWorkspaceRoot ?? cwd, |
| ... | ... | @@ -324,8 +324,8 @@ describe("CheckpointReactor", () => { |
| 324 | 324 | await Effect.runPromise( |
| 325 | 325 | engine.dispatch({ |
| 326 | 326 | type: "thread.create", |
| 327 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 328 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 327 | commandId: CommandId.make("cmd-thread-create"), | |
| 328 | threadId: ThreadId.make("thread-1"), | |
| 329 | 329 | projectId: asProjectId("project-1"), |
| 330 | 330 | title: "Thread", |
| 331 | 331 | modelSelection: { |
| ... | ... | @@ -344,21 +344,21 @@ describe("CheckpointReactor", () => { |
| 344 | 344 | await runtime.runPromise( |
| 345 | 345 | checkpointStore.captureCheckpoint({ |
| 346 | 346 | cwd, |
| 347 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 347 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 348 | 348 | }), |
| 349 | 349 | ); |
| 350 | 350 | fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8"); |
| 351 | 351 | await runtime.runPromise( |
| 352 | 352 | checkpointStore.captureCheckpoint({ |
| 353 | 353 | cwd, |
| 354 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1), | |
| 354 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | |
| 355 | 355 | }), |
| 356 | 356 | ); |
| 357 | 357 | fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8"); |
| 358 | 358 | await runtime.runPromise( |
| 359 | 359 | checkpointStore.captureCheckpoint({ |
| 360 | 360 | cwd, |
| 361 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2), | |
| 361 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2), | |
| 362 | 362 | }), |
| 363 | 363 | ); |
| 364 | 364 | } |
| ... | ... | @@ -378,10 +378,10 @@ describe("CheckpointReactor", () => { |
| 378 | 378 | await Effect.runPromise( |
| 379 | 379 | harness.engine.dispatch({ |
| 380 | 380 | type: "thread.session.set", |
| 381 | commandId: CommandId.makeUnsafe("cmd-session-set-capture"), | |
| 382 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 381 | commandId: CommandId.make("cmd-session-set-capture"), | |
| 382 | threadId: ThreadId.make("thread-1"), | |
| 383 | 383 | session: { |
| 384 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 384 | threadId: ThreadId.make("thread-1"), | |
| 385 | 385 | status: "ready", |
| 386 | 386 | providerName: "codex", |
| 387 | 387 | runtimeMode: "approval-required", |
| ... | ... | @@ -395,26 +395,26 @@ describe("CheckpointReactor", () => { |
| 395 | 395 | |
| 396 | 396 | harness.provider.emit({ |
| 397 | 397 | type: "turn.started", |
| 398 | eventId: EventId.makeUnsafe("evt-turn-started-1"), | |
| 398 | eventId: EventId.make("evt-turn-started-1"), | |
| 399 | 399 | provider: "codex", |
| 400 | 400 | |
| 401 | 401 | createdAt: new Date().toISOString(), |
| 402 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 402 | threadId: ThreadId.make("thread-1"), | |
| 403 | 403 | turnId: asTurnId("turn-1"), |
| 404 | 404 | }); |
| 405 | 405 | await waitForGitRefExists( |
| 406 | 406 | harness.cwd, |
| 407 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 407 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 408 | 408 | ); |
| 409 | 409 | |
| 410 | 410 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 411 | 411 | harness.provider.emit({ |
| 412 | 412 | type: "turn.completed", |
| 413 | eventId: EventId.makeUnsafe("evt-turn-completed-1"), | |
| 413 | eventId: EventId.make("evt-turn-completed-1"), | |
| 414 | 414 | provider: "codex", |
| 415 | 415 | |
| 416 | 416 | createdAt: new Date().toISOString(), |
| 417 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 417 | threadId: ThreadId.make("thread-1"), | |
| 418 | 418 | turnId: asTurnId("turn-1"), |
| 419 | 419 | payload: { state: "completed" }, |
| 420 | 420 | }); |
| ... | ... | @@ -426,22 +426,22 @@ describe("CheckpointReactor", () => { |
| 426 | 426 | ); |
| 427 | 427 | expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1); |
| 428 | 428 | expect( |
| 429 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0)), | |
| 429 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0)), | |
| 430 | 430 | ).toBe(true); |
| 431 | 431 | expect( |
| 432 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1)), | |
| 432 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1)), | |
| 433 | 433 | ).toBe(true); |
| 434 | 434 | expect( |
| 435 | 435 | gitShowFileAtRef( |
| 436 | 436 | harness.cwd, |
| 437 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 437 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 438 | 438 | "README.md", |
| 439 | 439 | ), |
| 440 | 440 | ).toBe("v1\n"); |
| 441 | 441 | expect( |
| 442 | 442 | gitShowFileAtRef( |
| 443 | 443 | harness.cwd, |
| 444 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1), | |
| 444 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | |
| 445 | 445 | "README.md", |
| 446 | 446 | ), |
| 447 | 447 | ).toBe("v2\n"); |
| ... | ... | @@ -456,10 +456,10 @@ describe("CheckpointReactor", () => { |
| 456 | 456 | |
| 457 | 457 | harness.provider.emit({ |
| 458 | 458 | type: "turn.completed", |
| 459 | eventId: EventId.makeUnsafe("evt-turn-completed-refresh-local-status"), | |
| 459 | eventId: EventId.make("evt-turn-completed-refresh-local-status"), | |
| 460 | 460 | provider: "codex", |
| 461 | 461 | createdAt: new Date().toISOString(), |
| 462 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 462 | threadId: ThreadId.make("thread-1"), | |
| 463 | 463 | turnId: asTurnId("turn-refresh-local-status"), |
| 464 | 464 | payload: { state: "completed" }, |
| 465 | 465 | }); |
| ... | ... | @@ -476,10 +476,10 @@ describe("CheckpointReactor", () => { |
| 476 | 476 | await Effect.runPromise( |
| 477 | 477 | harness.engine.dispatch({ |
| 478 | 478 | type: "thread.session.set", |
| 479 | commandId: CommandId.makeUnsafe("cmd-session-set-primary-running"), | |
| 480 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 479 | commandId: CommandId.make("cmd-session-set-primary-running"), | |
| 480 | threadId: ThreadId.make("thread-1"), | |
| 481 | 481 | session: { |
| 482 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 482 | threadId: ThreadId.make("thread-1"), | |
| 483 | 483 | status: "running", |
| 484 | 484 | providerName: "codex", |
| 485 | 485 | runtimeMode: "approval-required", |
| ... | ... | @@ -493,45 +493,43 @@ describe("CheckpointReactor", () => { |
| 493 | 493 | |
| 494 | 494 | harness.provider.emit({ |
| 495 | 495 | type: "turn.started", |
| 496 | eventId: EventId.makeUnsafe("evt-turn-started-main"), | |
| 496 | eventId: EventId.make("evt-turn-started-main"), | |
| 497 | 497 | provider: "codex", |
| 498 | 498 | |
| 499 | 499 | createdAt: new Date().toISOString(), |
| 500 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 500 | threadId: ThreadId.make("thread-1"), | |
| 501 | 501 | turnId: asTurnId("turn-main"), |
| 502 | 502 | }); |
| 503 | 503 | await waitForGitRefExists( |
| 504 | 504 | harness.cwd, |
| 505 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 505 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 506 | 506 | ); |
| 507 | 507 | |
| 508 | 508 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 509 | 509 | |
| 510 | 510 | harness.provider.emit({ |
| 511 | 511 | type: "turn.completed", |
| 512 | eventId: EventId.makeUnsafe("evt-turn-completed-aux"), | |
| 512 | eventId: EventId.make("evt-turn-completed-aux"), | |
| 513 | 513 | provider: "codex", |
| 514 | 514 | |
| 515 | 515 | createdAt: new Date().toISOString(), |
| 516 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 516 | threadId: ThreadId.make("thread-1"), | |
| 517 | 517 | turnId: asTurnId("turn-aux"), |
| 518 | 518 | payload: { state: "completed" }, |
| 519 | 519 | }); |
| 520 | 520 | |
| 521 | 521 | await harness.drain(); |
| 522 | 522 | const midReadModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 523 | const midThread = midReadModel.threads.find( | |
| 524 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 525 | ); | |
| 523 | const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 526 | 524 | expect(midThread?.checkpoints).toHaveLength(0); |
| 527 | 525 | |
| 528 | 526 | harness.provider.emit({ |
| 529 | 527 | type: "turn.completed", |
| 530 | eventId: EventId.makeUnsafe("evt-turn-completed-main"), | |
| 528 | eventId: EventId.make("evt-turn-completed-main"), | |
| 531 | 529 | provider: "codex", |
| 532 | 530 | |
| 533 | 531 | createdAt: new Date().toISOString(), |
| 534 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 532 | threadId: ThreadId.make("thread-1"), | |
| 535 | 533 | turnId: asTurnId("turn-main"), |
| 536 | 534 | payload: { state: "completed" }, |
| 537 | 535 | }); |
| ... | ... | @@ -553,10 +551,10 @@ describe("CheckpointReactor", () => { |
| 553 | 551 | await Effect.runPromise( |
| 554 | 552 | harness.engine.dispatch({ |
| 555 | 553 | type: "thread.session.set", |
| 556 | commandId: CommandId.makeUnsafe("cmd-session-set-capture-claude"), | |
| 557 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 554 | commandId: CommandId.make("cmd-session-set-capture-claude"), | |
| 555 | threadId: ThreadId.make("thread-1"), | |
| 558 | 556 | session: { |
| 559 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 557 | threadId: ThreadId.make("thread-1"), | |
| 560 | 558 | status: "ready", |
| 561 | 559 | providerName: "claudeAgent", |
| 562 | 560 | runtimeMode: "approval-required", |
| ... | ... | @@ -570,24 +568,24 @@ describe("CheckpointReactor", () => { |
| 570 | 568 | |
| 571 | 569 | harness.provider.emit({ |
| 572 | 570 | type: "turn.started", |
| 573 | eventId: EventId.makeUnsafe("evt-turn-started-claude-1"), | |
| 571 | eventId: EventId.make("evt-turn-started-claude-1"), | |
| 574 | 572 | provider: "claudeAgent", |
| 575 | 573 | createdAt: new Date().toISOString(), |
| 576 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 574 | threadId: ThreadId.make("thread-1"), | |
| 577 | 575 | turnId: asTurnId("turn-claude-1"), |
| 578 | 576 | }); |
| 579 | 577 | await waitForGitRefExists( |
| 580 | 578 | harness.cwd, |
| 581 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 579 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 582 | 580 | ); |
| 583 | 581 | |
| 584 | 582 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 585 | 583 | harness.provider.emit({ |
| 586 | 584 | type: "turn.completed", |
| 587 | eventId: EventId.makeUnsafe("evt-turn-completed-claude-1"), | |
| 585 | eventId: EventId.make("evt-turn-completed-claude-1"), | |
| 588 | 586 | provider: "claudeAgent", |
| 589 | 587 | createdAt: new Date().toISOString(), |
| 590 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 588 | threadId: ThreadId.make("thread-1"), | |
| 591 | 589 | turnId: asTurnId("turn-claude-1"), |
| 592 | 590 | payload: { state: "completed" }, |
| 593 | 591 | }); |
| ... | ... | @@ -600,7 +598,7 @@ describe("CheckpointReactor", () => { |
| 600 | 598 | |
| 601 | 599 | expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1); |
| 602 | 600 | expect( |
| 603 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1)), | |
| 601 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1)), | |
| 604 | 602 | ).toBe(true); |
| 605 | 603 | }); |
| 606 | 604 | |
| ... | ... | @@ -611,10 +609,10 @@ describe("CheckpointReactor", () => { |
| 611 | 609 | await Effect.runPromise( |
| 612 | 610 | harness.engine.dispatch({ |
| 613 | 611 | type: "thread.session.set", |
| 614 | commandId: CommandId.makeUnsafe("cmd-session-set-missing-baseline-diff"), | |
| 615 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 612 | commandId: CommandId.make("cmd-session-set-missing-baseline-diff"), | |
| 613 | threadId: ThreadId.make("thread-1"), | |
| 616 | 614 | session: { |
| 617 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 615 | threadId: ThreadId.make("thread-1"), | |
| 618 | 616 | status: "ready", |
| 619 | 617 | providerName: "codex", |
| 620 | 618 | runtimeMode: "approval-required", |
| ... | ... | @@ -628,11 +626,11 @@ describe("CheckpointReactor", () => { |
| 628 | 626 | |
| 629 | 627 | harness.provider.emit({ |
| 630 | 628 | type: "turn.completed", |
| 631 | eventId: EventId.makeUnsafe("evt-turn-completed-missing-baseline"), | |
| 629 | eventId: EventId.make("evt-turn-completed-missing-baseline"), | |
| 632 | 630 | provider: "codex", |
| 633 | 631 | |
| 634 | 632 | createdAt: new Date().toISOString(), |
| 635 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 633 | threadId: ThreadId.make("thread-1"), | |
| 636 | 634 | turnId: asTurnId("turn-missing-baseline"), |
| 637 | 635 | payload: { state: "completed" }, |
| 638 | 636 | }); |
| ... | ... | @@ -661,10 +659,10 @@ describe("CheckpointReactor", () => { |
| 661 | 659 | await Effect.runPromise( |
| 662 | 660 | harness.engine.dispatch({ |
| 663 | 661 | type: "thread.turn.start", |
| 664 | commandId: CommandId.makeUnsafe("cmd-turn-start-for-baseline"), | |
| 665 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 662 | commandId: CommandId.make("cmd-turn-start-for-baseline"), | |
| 663 | threadId: ThreadId.make("thread-1"), | |
| 666 | 664 | message: { |
| 667 | messageId: MessageId.makeUnsafe("message-user-1"), | |
| 665 | messageId: MessageId.make("message-user-1"), | |
| 668 | 666 | role: "user", |
| 669 | 667 | text: "start turn", |
| 670 | 668 | attachments: [], |
| ... | ... | @@ -677,12 +675,12 @@ describe("CheckpointReactor", () => { |
| 677 | 675 | |
| 678 | 676 | await waitForGitRefExists( |
| 679 | 677 | harness.cwd, |
| 680 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 678 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 681 | 679 | ); |
| 682 | 680 | expect( |
| 683 | 681 | gitShowFileAtRef( |
| 684 | 682 | harness.cwd, |
| 685 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 683 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 686 | 684 | "README.md", |
| 687 | 685 | ), |
| 688 | 686 | ).toBe("v1\n"); |
| ... | ... | @@ -699,10 +697,10 @@ describe("CheckpointReactor", () => { |
| 699 | 697 | await Effect.runPromise( |
| 700 | 698 | harness.engine.dispatch({ |
| 701 | 699 | type: "thread.session.set", |
| 702 | commandId: CommandId.makeUnsafe("cmd-session-set-missing-provider-cwd"), | |
| 703 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 700 | commandId: CommandId.make("cmd-session-set-missing-provider-cwd"), | |
| 701 | threadId: ThreadId.make("thread-1"), | |
| 704 | 702 | session: { |
| 705 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 703 | threadId: ThreadId.make("thread-1"), | |
| 706 | 704 | status: "running", |
| 707 | 705 | providerName: "codex", |
| 708 | 706 | runtimeMode: "approval-required", |
| ... | ... | @@ -717,23 +715,23 @@ describe("CheckpointReactor", () => { |
| 717 | 715 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 718 | 716 | harness.provider.emit({ |
| 719 | 717 | type: "turn.completed", |
| 720 | eventId: EventId.makeUnsafe("evt-turn-completed-missing-provider-cwd"), | |
| 718 | eventId: EventId.make("evt-turn-completed-missing-provider-cwd"), | |
| 721 | 719 | provider: "codex", |
| 722 | 720 | |
| 723 | 721 | createdAt: new Date().toISOString(), |
| 724 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 722 | threadId: ThreadId.make("thread-1"), | |
| 725 | 723 | turnId: asTurnId("turn-missing-cwd"), |
| 726 | 724 | payload: { state: "completed" }, |
| 727 | 725 | }); |
| 728 | 726 | |
| 729 | 727 | await waitForEvent(harness.engine, (event) => event.type === "thread.turn-diff-completed"); |
| 730 | 728 | expect( |
| 731 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1)), | |
| 729 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1)), | |
| 732 | 730 | ).toBe(true); |
| 733 | 731 | expect( |
| 734 | 732 | gitShowFileAtRef( |
| 735 | 733 | harness.cwd, |
| 736 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1), | |
| 734 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | |
| 737 | 735 | "README.md", |
| 738 | 736 | ), |
| 739 | 737 | ).toBe("v2\n"); |
| ... | ... | @@ -746,10 +744,10 @@ describe("CheckpointReactor", () => { |
| 746 | 744 | await Effect.runPromise( |
| 747 | 745 | harness.engine.dispatch({ |
| 748 | 746 | type: "thread.session.set", |
| 749 | commandId: CommandId.makeUnsafe("cmd-session-set-checkpoint-captured"), | |
| 750 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 747 | commandId: CommandId.make("cmd-session-set-checkpoint-captured"), | |
| 748 | threadId: ThreadId.make("thread-1"), | |
| 751 | 749 | session: { |
| 752 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 750 | threadId: ThreadId.make("thread-1"), | |
| 753 | 751 | status: "ready", |
| 754 | 752 | providerName: "codex", |
| 755 | 753 | runtimeMode: "approval-required", |
| ... | ... | @@ -763,11 +761,11 @@ describe("CheckpointReactor", () => { |
| 763 | 761 | |
| 764 | 762 | harness.provider.emit({ |
| 765 | 763 | type: "checkpoint.captured", |
| 766 | eventId: EventId.makeUnsafe("evt-checkpoint-captured-3"), | |
| 764 | eventId: EventId.make("evt-checkpoint-captured-3"), | |
| 767 | 765 | provider: "codex", |
| 768 | 766 | |
| 769 | 767 | createdAt: new Date().toISOString(), |
| 770 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 768 | threadId: ThreadId.make("thread-1"), | |
| 771 | 769 | turnId: asTurnId("turn-3"), |
| 772 | 770 | turnCount: 3, |
| 773 | 771 | status: "completed", |
| ... | ... | @@ -775,7 +773,7 @@ describe("CheckpointReactor", () => { |
| 775 | 773 | |
| 776 | 774 | await harness.drain(); |
| 777 | 775 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 778 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 776 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 779 | 777 | expect(thread?.checkpoints.some((checkpoint) => checkpoint.checkpointTurnCount === 3)).toBe( |
| 780 | 778 | false, |
| 781 | 779 | ); |
| ... | ... | @@ -796,10 +794,10 @@ describe("CheckpointReactor", () => { |
| 796 | 794 | await Effect.runPromise( |
| 797 | 795 | harness.engine.dispatch({ |
| 798 | 796 | type: "thread.session.set", |
| 799 | commandId: CommandId.makeUnsafe("cmd-session-set-non-repo-runtime"), | |
| 800 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 797 | commandId: CommandId.make("cmd-session-set-non-repo-runtime"), | |
| 798 | threadId: ThreadId.make("thread-1"), | |
| 801 | 799 | session: { |
| 802 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 800 | threadId: ThreadId.make("thread-1"), | |
| 803 | 801 | status: "ready", |
| 804 | 802 | providerName: "codex", |
| 805 | 803 | runtimeMode: "approval-required", |
| ... | ... | @@ -813,31 +811,31 @@ describe("CheckpointReactor", () => { |
| 813 | 811 | |
| 814 | 812 | harness.provider.emit({ |
| 815 | 813 | type: "turn.completed", |
| 816 | eventId: EventId.makeUnsafe("evt-runtime-capture-failure"), | |
| 814 | eventId: EventId.make("evt-runtime-capture-failure"), | |
| 817 | 815 | provider: "codex", |
| 818 | 816 | |
| 819 | 817 | createdAt: new Date().toISOString(), |
| 820 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 818 | threadId: ThreadId.make("thread-1"), | |
| 821 | 819 | turnId: asTurnId("turn-runtime-failure"), |
| 822 | 820 | payload: { state: "completed" }, |
| 823 | 821 | }); |
| 824 | 822 | |
| 825 | 823 | harness.provider.emit({ |
| 826 | 824 | type: "turn.started", |
| 827 | eventId: EventId.makeUnsafe("evt-turn-started-after-runtime-failure"), | |
| 825 | eventId: EventId.make("evt-turn-started-after-runtime-failure"), | |
| 828 | 826 | provider: "codex", |
| 829 | 827 | |
| 830 | 828 | createdAt: new Date().toISOString(), |
| 831 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 829 | threadId: ThreadId.make("thread-1"), | |
| 832 | 830 | turnId: asTurnId("turn-after-runtime-failure"), |
| 833 | 831 | }); |
| 834 | 832 | |
| 835 | 833 | await waitForGitRefExists( |
| 836 | 834 | harness.cwd, |
| 837 | checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0), | |
| 835 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | |
| 838 | 836 | ); |
| 839 | 837 | expect( |
| 840 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 0)), | |
| 838 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0)), | |
| 841 | 839 | ).toBe(true); |
| 842 | 840 | }); |
| 843 | 841 | |
| ... | ... | @@ -848,10 +846,10 @@ describe("CheckpointReactor", () => { |
| 848 | 846 | await Effect.runPromise( |
| 849 | 847 | harness.engine.dispatch({ |
| 850 | 848 | type: "thread.session.set", |
| 851 | commandId: CommandId.makeUnsafe("cmd-session-set"), | |
| 852 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 849 | commandId: CommandId.make("cmd-session-set"), | |
| 850 | threadId: ThreadId.make("thread-1"), | |
| 853 | 851 | session: { |
| 854 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 852 | threadId: ThreadId.make("thread-1"), | |
| 855 | 853 | status: "ready", |
| 856 | 854 | providerName: "codex", |
| 857 | 855 | runtimeMode: "approval-required", |
| ... | ... | @@ -866,11 +864,11 @@ describe("CheckpointReactor", () => { |
| 866 | 864 | await Effect.runPromise( |
| 867 | 865 | harness.engine.dispatch({ |
| 868 | 866 | type: "thread.turn.diff.complete", |
| 869 | commandId: CommandId.makeUnsafe("cmd-diff-1"), | |
| 870 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 867 | commandId: CommandId.make("cmd-diff-1"), | |
| 868 | threadId: ThreadId.make("thread-1"), | |
| 871 | 869 | turnId: asTurnId("turn-1"), |
| 872 | 870 | completedAt: createdAt, |
| 873 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1), | |
| 871 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | |
| 874 | 872 | status: "ready", |
| 875 | 873 | files: [], |
| 876 | 874 | checkpointTurnCount: 1, |
| ... | ... | @@ -880,11 +878,11 @@ describe("CheckpointReactor", () => { |
| 880 | 878 | await Effect.runPromise( |
| 881 | 879 | harness.engine.dispatch({ |
| 882 | 880 | type: "thread.turn.diff.complete", |
| 883 | commandId: CommandId.makeUnsafe("cmd-diff-2"), | |
| 884 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 881 | commandId: CommandId.make("cmd-diff-2"), | |
| 882 | threadId: ThreadId.make("thread-1"), | |
| 885 | 883 | turnId: asTurnId("turn-2"), |
| 886 | 884 | completedAt: createdAt, |
| 887 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2), | |
| 885 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2), | |
| 888 | 886 | status: "ready", |
| 889 | 887 | files: [], |
| 890 | 888 | checkpointTurnCount: 2, |
| ... | ... | @@ -895,8 +893,8 @@ describe("CheckpointReactor", () => { |
| 895 | 893 | await Effect.runPromise( |
| 896 | 894 | harness.engine.dispatch({ |
| 897 | 895 | type: "thread.checkpoint.revert", |
| 898 | commandId: CommandId.makeUnsafe("cmd-revert-request"), | |
| 899 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 896 | commandId: CommandId.make("cmd-revert-request"), | |
| 897 | threadId: ThreadId.make("thread-1"), | |
| 900 | 898 | turnCount: 1, |
| 901 | 899 | createdAt, |
| 902 | 900 | }), |
| ... | ... | @@ -910,12 +908,12 @@ describe("CheckpointReactor", () => { |
| 910 | 908 | expect(thread.checkpoints[0]?.checkpointTurnCount).toBe(1); |
| 911 | 909 | expect(harness.provider.rollbackConversation).toHaveBeenCalledTimes(1); |
| 912 | 910 | expect(harness.provider.rollbackConversation).toHaveBeenCalledWith({ |
| 913 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 911 | threadId: ThreadId.make("thread-1"), | |
| 914 | 912 | numTurns: 1, |
| 915 | 913 | }); |
| 916 | 914 | expect(fs.readFileSync(path.join(harness.cwd, "README.md"), "utf8")).toBe("v2\n"); |
| 917 | 915 | expect( |
| 918 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2)), | |
| 916 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2)), | |
| 919 | 917 | ).toBe(false); |
| 920 | 918 | }); |
| 921 | 919 | |
| ... | ... | @@ -926,10 +924,10 @@ describe("CheckpointReactor", () => { |
| 926 | 924 | await Effect.runPromise( |
| 927 | 925 | harness.engine.dispatch({ |
| 928 | 926 | type: "thread.session.set", |
| 929 | commandId: CommandId.makeUnsafe("cmd-session-set-claude"), | |
| 930 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 927 | commandId: CommandId.make("cmd-session-set-claude"), | |
| 928 | threadId: ThreadId.make("thread-1"), | |
| 931 | 929 | session: { |
| 932 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 930 | threadId: ThreadId.make("thread-1"), | |
| 933 | 931 | status: "ready", |
| 934 | 932 | providerName: "claudeAgent", |
| 935 | 933 | runtimeMode: "approval-required", |
| ... | ... | @@ -944,11 +942,11 @@ describe("CheckpointReactor", () => { |
| 944 | 942 | await Effect.runPromise( |
| 945 | 943 | harness.engine.dispatch({ |
| 946 | 944 | type: "thread.turn.diff.complete", |
| 947 | commandId: CommandId.makeUnsafe("cmd-diff-claude-1"), | |
| 948 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 945 | commandId: CommandId.make("cmd-diff-claude-1"), | |
| 946 | threadId: ThreadId.make("thread-1"), | |
| 949 | 947 | turnId: asTurnId("turn-claude-1"), |
| 950 | 948 | completedAt: createdAt, |
| 951 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1), | |
| 949 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | |
| 952 | 950 | status: "ready", |
| 953 | 951 | files: [], |
| 954 | 952 | checkpointTurnCount: 1, |
| ... | ... | @@ -958,11 +956,11 @@ describe("CheckpointReactor", () => { |
| 958 | 956 | await Effect.runPromise( |
| 959 | 957 | harness.engine.dispatch({ |
| 960 | 958 | type: "thread.turn.diff.complete", |
| 961 | commandId: CommandId.makeUnsafe("cmd-diff-claude-2"), | |
| 962 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 959 | commandId: CommandId.make("cmd-diff-claude-2"), | |
| 960 | threadId: ThreadId.make("thread-1"), | |
| 963 | 961 | turnId: asTurnId("turn-claude-2"), |
| 964 | 962 | completedAt: createdAt, |
| 965 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2), | |
| 963 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2), | |
| 966 | 964 | status: "ready", |
| 967 | 965 | files: [], |
| 968 | 966 | checkpointTurnCount: 2, |
| ... | ... | @@ -973,8 +971,8 @@ describe("CheckpointReactor", () => { |
| 973 | 971 | await Effect.runPromise( |
| 974 | 972 | harness.engine.dispatch({ |
| 975 | 973 | type: "thread.checkpoint.revert", |
| 976 | commandId: CommandId.makeUnsafe("cmd-revert-request-claude"), | |
| 977 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 974 | commandId: CommandId.make("cmd-revert-request-claude"), | |
| 975 | threadId: ThreadId.make("thread-1"), | |
| 978 | 976 | turnCount: 1, |
| 979 | 977 | createdAt, |
| 980 | 978 | }), |
| ... | ... | @@ -983,7 +981,7 @@ describe("CheckpointReactor", () => { |
| 983 | 981 | await waitForEvent(harness.engine, (event) => event.type === "thread.reverted"); |
| 984 | 982 | expect(harness.provider.rollbackConversation).toHaveBeenCalledTimes(1); |
| 985 | 983 | expect(harness.provider.rollbackConversation).toHaveBeenCalledWith({ |
| 986 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 984 | threadId: ThreadId.make("thread-1"), | |
| 987 | 985 | numTurns: 1, |
| 988 | 986 | }); |
| 989 | 987 | }); |
| ... | ... | @@ -995,10 +993,10 @@ describe("CheckpointReactor", () => { |
| 995 | 993 | await Effect.runPromise( |
| 996 | 994 | harness.engine.dispatch({ |
| 997 | 995 | type: "thread.session.set", |
| 998 | commandId: CommandId.makeUnsafe("cmd-session-set-inline-revert"), | |
| 999 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 996 | commandId: CommandId.make("cmd-session-set-inline-revert"), | |
| 997 | threadId: ThreadId.make("thread-1"), | |
| 1000 | 998 | session: { |
| 1001 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 999 | threadId: ThreadId.make("thread-1"), | |
| 1002 | 1000 | status: "ready", |
| 1003 | 1001 | providerName: "codex", |
| 1004 | 1002 | runtimeMode: "approval-required", |
| ... | ... | @@ -1013,11 +1011,11 @@ describe("CheckpointReactor", () => { |
| 1013 | 1011 | await Effect.runPromise( |
| 1014 | 1012 | harness.engine.dispatch({ |
| 1015 | 1013 | type: "thread.turn.diff.complete", |
| 1016 | commandId: CommandId.makeUnsafe("cmd-inline-revert-diff-1"), | |
| 1017 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1014 | commandId: CommandId.make("cmd-inline-revert-diff-1"), | |
| 1015 | threadId: ThreadId.make("thread-1"), | |
| 1018 | 1016 | turnId: asTurnId("turn-1"), |
| 1019 | 1017 | completedAt: createdAt, |
| 1020 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 1), | |
| 1018 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | |
| 1021 | 1019 | status: "ready", |
| 1022 | 1020 | files: [], |
| 1023 | 1021 | checkpointTurnCount: 1, |
| ... | ... | @@ -1027,11 +1025,11 @@ describe("CheckpointReactor", () => { |
| 1027 | 1025 | await Effect.runPromise( |
| 1028 | 1026 | harness.engine.dispatch({ |
| 1029 | 1027 | type: "thread.turn.diff.complete", |
| 1030 | commandId: CommandId.makeUnsafe("cmd-inline-revert-diff-2"), | |
| 1031 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1028 | commandId: CommandId.make("cmd-inline-revert-diff-2"), | |
| 1029 | threadId: ThreadId.make("thread-1"), | |
| 1032 | 1030 | turnId: asTurnId("turn-2"), |
| 1033 | 1031 | completedAt: createdAt, |
| 1034 | checkpointRef: checkpointRefForThreadTurn(ThreadId.makeUnsafe("thread-1"), 2), | |
| 1032 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2), | |
| 1035 | 1033 | status: "ready", |
| 1036 | 1034 | files: [], |
| 1037 | 1035 | checkpointTurnCount: 2, |
| ... | ... | @@ -1042,8 +1040,8 @@ describe("CheckpointReactor", () => { |
| 1042 | 1040 | await Effect.runPromise( |
| 1043 | 1041 | harness.engine.dispatch({ |
| 1044 | 1042 | type: "thread.checkpoint.revert", |
| 1045 | commandId: CommandId.makeUnsafe("cmd-sequenced-revert-request-1"), | |
| 1046 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1043 | commandId: CommandId.make("cmd-sequenced-revert-request-1"), | |
| 1044 | threadId: ThreadId.make("thread-1"), | |
| 1047 | 1045 | turnCount: 1, |
| 1048 | 1046 | createdAt, |
| 1049 | 1047 | }), |
| ... | ... | @@ -1051,8 +1049,8 @@ describe("CheckpointReactor", () => { |
| 1051 | 1049 | await Effect.runPromise( |
| 1052 | 1050 | harness.engine.dispatch({ |
| 1053 | 1051 | type: "thread.checkpoint.revert", |
| 1054 | commandId: CommandId.makeUnsafe("cmd-sequenced-revert-request-0"), | |
| 1055 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1052 | commandId: CommandId.make("cmd-sequenced-revert-request-0"), | |
| 1053 | threadId: ThreadId.make("thread-1"), | |
| 1056 | 1054 | turnCount: 0, |
| 1057 | 1055 | createdAt, |
| 1058 | 1056 | }), |
| ... | ... | @@ -1062,11 +1060,11 @@ describe("CheckpointReactor", () => { |
| 1062 | 1060 | |
| 1063 | 1061 | expect(harness.provider.rollbackConversation).toHaveBeenCalledTimes(2); |
| 1064 | 1062 | expect(harness.provider.rollbackConversation.mock.calls[0]?.[0]).toEqual({ |
| 1065 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1063 | threadId: ThreadId.make("thread-1"), | |
| 1066 | 1064 | numTurns: 1, |
| 1067 | 1065 | }); |
| 1068 | 1066 | expect(harness.provider.rollbackConversation.mock.calls[1]?.[0]).toEqual({ |
| 1069 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1067 | threadId: ThreadId.make("thread-1"), | |
| 1070 | 1068 | numTurns: 1, |
| 1071 | 1069 | }); |
| 1072 | 1070 | }); |
| ... | ... | @@ -1078,8 +1076,8 @@ describe("CheckpointReactor", () => { |
| 1078 | 1076 | await Effect.runPromise( |
| 1079 | 1077 | harness.engine.dispatch({ |
| 1080 | 1078 | type: "thread.checkpoint.revert", |
| 1081 | commandId: CommandId.makeUnsafe("cmd-revert-no-session"), | |
| 1082 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1079 | commandId: CommandId.make("cmd-revert-no-session"), | |
| 1080 | threadId: ThreadId.make("thread-1"), | |
| 1083 | 1081 | turnCount: 1, |
| 1084 | 1082 | createdAt, |
| 1085 | 1083 | }), |
apps/server/src/orchestration/Layers/CheckpointReactor.ts+6-6| ... | ... | @@ -38,7 +38,7 @@ type ReactorInput = |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | 40 | function toTurnId(value: string | undefined): TurnId | null { |
| 41 | return value === undefined ? null : TurnId.makeUnsafe(String(value)); | |
| 41 | return value === undefined ? null : TurnId.make(String(value)); | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | function sameId(left: string | null | undefined, right: string | null | undefined): boolean { |
| ... | ... | @@ -62,7 +62,7 @@ function checkpointStatusFromRuntime(status: string | undefined): "ready" | "mis |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | const serverCommandId = (tag: string): CommandId => |
| 65 | CommandId.makeUnsafe(`server:${tag}:${crypto.randomUUID()}`); | |
| 65 | CommandId.make(`server:${tag}:${crypto.randomUUID()}`); | |
| 66 | 66 | |
| 67 | 67 | const make = Effect.gen(function* () { |
| 68 | 68 | const orchestrationEngine = yield* OrchestrationEngineService; |
| ... | ... | @@ -83,7 +83,7 @@ const make = Effect.gen(function* () { |
| 83 | 83 | commandId: serverCommandId("checkpoint-revert-failure"), |
| 84 | 84 | threadId: input.threadId, |
| 85 | 85 | activity: { |
| 86 | id: EventId.makeUnsafe(crypto.randomUUID()), | |
| 86 | id: EventId.make(crypto.randomUUID()), | |
| 87 | 87 | tone: "error", |
| 88 | 88 | kind: "checkpoint.revert.failed", |
| 89 | 89 | summary: "Checkpoint revert failed", |
| ... | ... | @@ -108,7 +108,7 @@ const make = Effect.gen(function* () { |
| 108 | 108 | commandId: serverCommandId("checkpoint-capture-failure"), |
| 109 | 109 | threadId: input.threadId, |
| 110 | 110 | activity: { |
| 111 | id: EventId.makeUnsafe(crypto.randomUUID()), | |
| 111 | id: EventId.make(crypto.randomUUID()), | |
| 112 | 112 | tone: "error", |
| 113 | 113 | kind: "checkpoint.capture.failed", |
| 114 | 114 | summary: "Checkpoint capture failed", |
| ... | ... | @@ -270,7 +270,7 @@ const make = Effect.gen(function* () { |
| 270 | 270 | input.thread.messages |
| 271 | 271 | .toReversed() |
| 272 | 272 | .find((entry) => entry.role === "assistant" && entry.turnId === input.turnId)?.id ?? |
| 273 | MessageId.makeUnsafe(`assistant:${input.turnId}`); | |
| 273 | MessageId.make(`assistant:${input.turnId}`); | |
| 274 | 274 | |
| 275 | 275 | yield* orchestrationEngine.dispatch({ |
| 276 | 276 | type: "thread.turn.diff.complete", |
| ... | ... | @@ -307,7 +307,7 @@ const make = Effect.gen(function* () { |
| 307 | 307 | commandId: serverCommandId("checkpoint-captured-activity"), |
| 308 | 308 | threadId: input.threadId, |
| 309 | 309 | activity: { |
| 310 | id: EventId.makeUnsafe(crypto.randomUUID()), | |
| 310 | id: EventId.make(crypto.randomUUID()), | |
| 311 | 311 | tone: "info", |
| 312 | 312 | kind: "checkpoint.captured", |
| 313 | 313 | summary: "Checkpoint captured", |
apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts+62-62| ... | ... | @@ -32,10 +32,10 @@ import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts" |
| 32 | 32 | import { ServerConfig } from "../../config.ts"; |
| 33 | 33 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 34 | 34 | |
| 35 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 36 | const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value); | |
| 37 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 38 | const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.makeUnsafe(value); | |
| 35 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 36 | const asMessageId = (value: string): MessageId => MessageId.make(value); | |
| 37 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 38 | const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.make(value); | |
| 39 | 39 | |
| 40 | 40 | async function createOrchestrationSystem() { |
| 41 | 41 | const ServerConfigLayer = ServerConfig.layerTest(process.cwd(), { |
| ... | ... | @@ -115,7 +115,7 @@ describe("OrchestrationEngine", () => { |
| 115 | 115 | ], |
| 116 | 116 | threads: [ |
| 117 | 117 | { |
| 118 | id: ThreadId.makeUnsafe("thread-bootstrap"), | |
| 118 | id: ThreadId.make("thread-bootstrap"), | |
| 119 | 119 | projectId: asProjectId("project-bootstrap"), |
| 120 | 120 | title: "Bootstrap Thread", |
| 121 | 121 | modelSelection: { |
| ... | ... | @@ -183,7 +183,7 @@ describe("OrchestrationEngine", () => { |
| 183 | 183 | await system.run( |
| 184 | 184 | engine.dispatch({ |
| 185 | 185 | type: "project.create", |
| 186 | commandId: CommandId.makeUnsafe("cmd-project-1-create"), | |
| 186 | commandId: CommandId.make("cmd-project-1-create"), | |
| 187 | 187 | projectId: asProjectId("project-1"), |
| 188 | 188 | title: "Project 1", |
| 189 | 189 | workspaceRoot: "/tmp/project-1", |
| ... | ... | @@ -197,8 +197,8 @@ describe("OrchestrationEngine", () => { |
| 197 | 197 | await system.run( |
| 198 | 198 | engine.dispatch({ |
| 199 | 199 | type: "thread.create", |
| 200 | commandId: CommandId.makeUnsafe("cmd-thread-1-create"), | |
| 201 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 200 | commandId: CommandId.make("cmd-thread-1-create"), | |
| 201 | threadId: ThreadId.make("thread-1"), | |
| 202 | 202 | projectId: asProjectId("project-1"), |
| 203 | 203 | title: "Thread", |
| 204 | 204 | modelSelection: { |
| ... | ... | @@ -215,8 +215,8 @@ describe("OrchestrationEngine", () => { |
| 215 | 215 | await system.run( |
| 216 | 216 | engine.dispatch({ |
| 217 | 217 | type: "thread.turn.start", |
| 218 | commandId: CommandId.makeUnsafe("cmd-turn-start-1"), | |
| 219 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 218 | commandId: CommandId.make("cmd-turn-start-1"), | |
| 219 | threadId: ThreadId.make("thread-1"), | |
| 220 | 220 | message: { |
| 221 | 221 | messageId: asMessageId("msg-1"), |
| 222 | 222 | role: "user", |
| ... | ... | @@ -243,7 +243,7 @@ describe("OrchestrationEngine", () => { |
| 243 | 243 | await system.run( |
| 244 | 244 | engine.dispatch({ |
| 245 | 245 | type: "project.create", |
| 246 | commandId: CommandId.makeUnsafe("cmd-project-archive-create"), | |
| 246 | commandId: CommandId.make("cmd-project-archive-create"), | |
| 247 | 247 | projectId: asProjectId("project-archive"), |
| 248 | 248 | title: "Project Archive", |
| 249 | 249 | workspaceRoot: "/tmp/project-archive", |
| ... | ... | @@ -257,8 +257,8 @@ describe("OrchestrationEngine", () => { |
| 257 | 257 | await system.run( |
| 258 | 258 | engine.dispatch({ |
| 259 | 259 | type: "thread.create", |
| 260 | commandId: CommandId.makeUnsafe("cmd-thread-archive-create"), | |
| 261 | threadId: ThreadId.makeUnsafe("thread-archive"), | |
| 260 | commandId: CommandId.make("cmd-thread-archive-create"), | |
| 261 | threadId: ThreadId.make("thread-archive"), | |
| 262 | 262 | projectId: asProjectId("project-archive"), |
| 263 | 263 | title: "Archive me", |
| 264 | 264 | modelSelection: { |
| ... | ... | @@ -276,8 +276,8 @@ describe("OrchestrationEngine", () => { |
| 276 | 276 | await system.run( |
| 277 | 277 | engine.dispatch({ |
| 278 | 278 | type: "thread.archive", |
| 279 | commandId: CommandId.makeUnsafe("cmd-thread-archive"), | |
| 280 | threadId: ThreadId.makeUnsafe("thread-archive"), | |
| 279 | commandId: CommandId.make("cmd-thread-archive"), | |
| 280 | threadId: ThreadId.make("thread-archive"), | |
| 281 | 281 | }), |
| 282 | 282 | ); |
| 283 | 283 | expect( |
| ... | ... | @@ -289,8 +289,8 @@ describe("OrchestrationEngine", () => { |
| 289 | 289 | await system.run( |
| 290 | 290 | engine.dispatch({ |
| 291 | 291 | type: "thread.unarchive", |
| 292 | commandId: CommandId.makeUnsafe("cmd-thread-unarchive"), | |
| 293 | threadId: ThreadId.makeUnsafe("thread-archive"), | |
| 292 | commandId: CommandId.make("cmd-thread-unarchive"), | |
| 293 | threadId: ThreadId.make("thread-archive"), | |
| 294 | 294 | }), |
| 295 | 295 | ); |
| 296 | 296 | expect( |
| ... | ... | @@ -310,7 +310,7 @@ describe("OrchestrationEngine", () => { |
| 310 | 310 | await system.run( |
| 311 | 311 | engine.dispatch({ |
| 312 | 312 | type: "project.create", |
| 313 | commandId: CommandId.makeUnsafe("cmd-project-replay-create"), | |
| 313 | commandId: CommandId.make("cmd-project-replay-create"), | |
| 314 | 314 | projectId: asProjectId("project-replay"), |
| 315 | 315 | title: "Replay Project", |
| 316 | 316 | workspaceRoot: "/tmp/project-replay", |
| ... | ... | @@ -324,8 +324,8 @@ describe("OrchestrationEngine", () => { |
| 324 | 324 | await system.run( |
| 325 | 325 | engine.dispatch({ |
| 326 | 326 | type: "thread.create", |
| 327 | commandId: CommandId.makeUnsafe("cmd-thread-replay-create"), | |
| 328 | threadId: ThreadId.makeUnsafe("thread-replay"), | |
| 327 | commandId: CommandId.make("cmd-thread-replay-create"), | |
| 328 | threadId: ThreadId.make("thread-replay"), | |
| 329 | 329 | projectId: asProjectId("project-replay"), |
| 330 | 330 | title: "replay", |
| 331 | 331 | modelSelection: { |
| ... | ... | @@ -342,8 +342,8 @@ describe("OrchestrationEngine", () => { |
| 342 | 342 | await system.run( |
| 343 | 343 | engine.dispatch({ |
| 344 | 344 | type: "thread.delete", |
| 345 | commandId: CommandId.makeUnsafe("cmd-thread-replay-delete"), | |
| 346 | threadId: ThreadId.makeUnsafe("thread-replay"), | |
| 345 | commandId: CommandId.make("cmd-thread-replay-delete"), | |
| 346 | threadId: ThreadId.make("thread-replay"), | |
| 347 | 347 | }), |
| 348 | 348 | ); |
| 349 | 349 | |
| ... | ... | @@ -368,7 +368,7 @@ describe("OrchestrationEngine", () => { |
| 368 | 368 | await system.run( |
| 369 | 369 | engine.dispatch({ |
| 370 | 370 | type: "project.create", |
| 371 | commandId: CommandId.makeUnsafe("cmd-project-stream-create"), | |
| 371 | commandId: CommandId.make("cmd-project-stream-create"), | |
| 372 | 372 | projectId: asProjectId("project-stream"), |
| 373 | 373 | title: "Stream Project", |
| 374 | 374 | workspaceRoot: "/tmp/project-stream", |
| ... | ... | @@ -392,8 +392,8 @@ describe("OrchestrationEngine", () => { |
| 392 | 392 | yield* Effect.sleep("10 millis"); |
| 393 | 393 | yield* engine.dispatch({ |
| 394 | 394 | type: "thread.create", |
| 395 | commandId: CommandId.makeUnsafe("cmd-stream-thread-create"), | |
| 396 | threadId: ThreadId.makeUnsafe("thread-stream"), | |
| 395 | commandId: CommandId.make("cmd-stream-thread-create"), | |
| 396 | threadId: ThreadId.make("thread-stream"), | |
| 397 | 397 | projectId: asProjectId("project-stream"), |
| 398 | 398 | title: "domain-stream", |
| 399 | 399 | modelSelection: { |
| ... | ... | @@ -408,8 +408,8 @@ describe("OrchestrationEngine", () => { |
| 408 | 408 | }); |
| 409 | 409 | yield* engine.dispatch({ |
| 410 | 410 | type: "thread.meta.update", |
| 411 | commandId: CommandId.makeUnsafe("cmd-stream-thread-update"), | |
| 412 | threadId: ThreadId.makeUnsafe("thread-stream"), | |
| 411 | commandId: CommandId.make("cmd-stream-thread-update"), | |
| 412 | threadId: ThreadId.make("thread-stream"), | |
| 413 | 413 | title: "domain-stream-updated", |
| 414 | 414 | }); |
| 415 | 415 | eventTypes.push((yield* Queue.take(eventQueue)).type); |
| ... | ... | @@ -429,7 +429,7 @@ describe("OrchestrationEngine", () => { |
| 429 | 429 | await system.run( |
| 430 | 430 | engine.dispatch({ |
| 431 | 431 | type: "project.create", |
| 432 | commandId: CommandId.makeUnsafe("cmd-project-ack-create"), | |
| 432 | commandId: CommandId.make("cmd-project-ack-create"), | |
| 433 | 433 | projectId: asProjectId("project-ack"), |
| 434 | 434 | title: "Ack Project", |
| 435 | 435 | workspaceRoot: "/tmp/project-ack", |
| ... | ... | @@ -444,8 +444,8 @@ describe("OrchestrationEngine", () => { |
| 444 | 444 | await system.run( |
| 445 | 445 | engine.dispatch({ |
| 446 | 446 | type: "thread.create", |
| 447 | commandId: CommandId.makeUnsafe("cmd-thread-ack-create"), | |
| 448 | threadId: ThreadId.makeUnsafe("thread-ack"), | |
| 447 | commandId: CommandId.make("cmd-thread-ack-create"), | |
| 448 | threadId: ThreadId.make("thread-ack"), | |
| 449 | 449 | projectId: asProjectId("project-ack"), |
| 450 | 450 | title: "Ack Thread", |
| 451 | 451 | modelSelection: { |
| ... | ... | @@ -481,8 +481,8 @@ describe("OrchestrationEngine", () => { |
| 481 | 481 | system.run( |
| 482 | 482 | engine.dispatch({ |
| 483 | 483 | type: "thread.create", |
| 484 | commandId: CommandId.makeUnsafe("cmd-thread-missing-project"), | |
| 485 | threadId: ThreadId.makeUnsafe("thread-missing-project"), | |
| 484 | commandId: CommandId.make("cmd-thread-missing-project"), | |
| 485 | threadId: ThreadId.make("thread-missing-project"), | |
| 486 | 486 | projectId: asProjectId("project-missing"), |
| 487 | 487 | title: "Missing Project Thread", |
| 488 | 488 | modelSelection: { |
| ... | ... | @@ -518,7 +518,7 @@ describe("OrchestrationEngine", () => { |
| 518 | 518 | await system.run( |
| 519 | 519 | engine.dispatch({ |
| 520 | 520 | type: "project.create", |
| 521 | commandId: CommandId.makeUnsafe("cmd-project-turn-diff-create"), | |
| 521 | commandId: CommandId.make("cmd-project-turn-diff-create"), | |
| 522 | 522 | projectId: asProjectId("project-turn-diff"), |
| 523 | 523 | title: "Turn Diff Project", |
| 524 | 524 | workspaceRoot: "/tmp/project-turn-diff", |
| ... | ... | @@ -532,8 +532,8 @@ describe("OrchestrationEngine", () => { |
| 532 | 532 | await system.run( |
| 533 | 533 | engine.dispatch({ |
| 534 | 534 | type: "thread.create", |
| 535 | commandId: CommandId.makeUnsafe("cmd-thread-turn-diff-create"), | |
| 536 | threadId: ThreadId.makeUnsafe("thread-turn-diff"), | |
| 535 | commandId: CommandId.make("cmd-thread-turn-diff-create"), | |
| 536 | threadId: ThreadId.make("thread-turn-diff"), | |
| 537 | 537 | projectId: asProjectId("project-turn-diff"), |
| 538 | 538 | title: "Turn diff thread", |
| 539 | 539 | modelSelection: { |
| ... | ... | @@ -550,8 +550,8 @@ describe("OrchestrationEngine", () => { |
| 550 | 550 | await system.run( |
| 551 | 551 | engine.dispatch({ |
| 552 | 552 | type: "thread.turn.diff.complete", |
| 553 | commandId: CommandId.makeUnsafe("cmd-turn-diff-complete"), | |
| 554 | threadId: ThreadId.makeUnsafe("thread-turn-diff"), | |
| 553 | commandId: CommandId.make("cmd-turn-diff-complete"), | |
| 554 | threadId: ThreadId.make("thread-turn-diff"), | |
| 555 | 555 | turnId: asTurnId("turn-1"), |
| 556 | 556 | completedAt: createdAt, |
| 557 | 557 | checkpointRef: asCheckpointRef("refs/t3/checkpoints/thread-turn-diff/turn/1"), |
| ... | ... | @@ -590,7 +590,7 @@ describe("OrchestrationEngine", () => { |
| 590 | 590 | |
| 591 | 591 | const flakyStore: OrchestrationEventStoreShape = { |
| 592 | 592 | append(event) { |
| 593 | if (shouldFailFirstAppend && event.commandId === CommandId.makeUnsafe("cmd-flaky-1")) { | |
| 593 | if (shouldFailFirstAppend && event.commandId === CommandId.make("cmd-flaky-1")) { | |
| 594 | 594 | shouldFailFirstAppend = false; |
| 595 | 595 | return Effect.fail( |
| 596 | 596 | new PersistenceSqlError({ |
| ... | ... | @@ -637,7 +637,7 @@ describe("OrchestrationEngine", () => { |
| 637 | 637 | await runtime.runPromise( |
| 638 | 638 | engine.dispatch({ |
| 639 | 639 | type: "project.create", |
| 640 | commandId: CommandId.makeUnsafe("cmd-project-flaky-create"), | |
| 640 | commandId: CommandId.make("cmd-project-flaky-create"), | |
| 641 | 641 | projectId: asProjectId("project-flaky"), |
| 642 | 642 | title: "Flaky Project", |
| 643 | 643 | workspaceRoot: "/tmp/project-flaky", |
| ... | ... | @@ -653,8 +653,8 @@ describe("OrchestrationEngine", () => { |
| 653 | 653 | runtime.runPromise( |
| 654 | 654 | engine.dispatch({ |
| 655 | 655 | type: "thread.create", |
| 656 | commandId: CommandId.makeUnsafe("cmd-flaky-1"), | |
| 657 | threadId: ThreadId.makeUnsafe("thread-flaky-fail"), | |
| 656 | commandId: CommandId.make("cmd-flaky-1"), | |
| 657 | threadId: ThreadId.make("thread-flaky-fail"), | |
| 658 | 658 | projectId: asProjectId("project-flaky"), |
| 659 | 659 | title: "flaky-fail", |
| 660 | 660 | modelSelection: { |
| ... | ... | @@ -673,8 +673,8 @@ describe("OrchestrationEngine", () => { |
| 673 | 673 | const result = await runtime.runPromise( |
| 674 | 674 | engine.dispatch({ |
| 675 | 675 | type: "thread.create", |
| 676 | commandId: CommandId.makeUnsafe("cmd-flaky-2"), | |
| 677 | threadId: ThreadId.makeUnsafe("thread-flaky-ok"), | |
| 676 | commandId: CommandId.make("cmd-flaky-2"), | |
| 677 | threadId: ThreadId.make("thread-flaky-ok"), | |
| 678 | 678 | projectId: asProjectId("project-flaky"), |
| 679 | 679 | title: "flaky-ok", |
| 680 | 680 | modelSelection: { |
| ... | ... | @@ -701,7 +701,7 @@ describe("OrchestrationEngine", () => { |
| 701 | 701 | projectEvent: (event) => { |
| 702 | 702 | if ( |
| 703 | 703 | shouldFailRequestedProjection && |
| 704 | event.commandId === CommandId.makeUnsafe("cmd-turn-start-atomic") && | |
| 704 | event.commandId === CommandId.make("cmd-turn-start-atomic") && | |
| 705 | 705 | event.type === "thread.turn-start-requested" |
| 706 | 706 | ) { |
| 707 | 707 | shouldFailRequestedProjection = false; |
| ... | ... | @@ -732,7 +732,7 @@ describe("OrchestrationEngine", () => { |
| 732 | 732 | await runtime.runPromise( |
| 733 | 733 | engine.dispatch({ |
| 734 | 734 | type: "project.create", |
| 735 | commandId: CommandId.makeUnsafe("cmd-project-atomic-create"), | |
| 735 | commandId: CommandId.make("cmd-project-atomic-create"), | |
| 736 | 736 | projectId: asProjectId("project-atomic"), |
| 737 | 737 | title: "Atomic Project", |
| 738 | 738 | workspaceRoot: "/tmp/project-atomic", |
| ... | ... | @@ -746,8 +746,8 @@ describe("OrchestrationEngine", () => { |
| 746 | 746 | await runtime.runPromise( |
| 747 | 747 | engine.dispatch({ |
| 748 | 748 | type: "thread.create", |
| 749 | commandId: CommandId.makeUnsafe("cmd-thread-atomic-create"), | |
| 750 | threadId: ThreadId.makeUnsafe("thread-atomic"), | |
| 749 | commandId: CommandId.make("cmd-thread-atomic-create"), | |
| 750 | threadId: ThreadId.make("thread-atomic"), | |
| 751 | 751 | projectId: asProjectId("project-atomic"), |
| 752 | 752 | title: "atomic", |
| 753 | 753 | modelSelection: { |
| ... | ... | @@ -764,8 +764,8 @@ describe("OrchestrationEngine", () => { |
| 764 | 764 | |
| 765 | 765 | const turnStartCommand = { |
| 766 | 766 | type: "thread.turn.start" as const, |
| 767 | commandId: CommandId.makeUnsafe("cmd-turn-start-atomic"), | |
| 768 | threadId: ThreadId.makeUnsafe("thread-atomic"), | |
| 767 | commandId: CommandId.make("cmd-turn-start-atomic"), | |
| 768 | threadId: ThreadId.make("thread-atomic"), | |
| 769 | 769 | message: { |
| 770 | 770 | messageId: asMessageId("msg-atomic-1"), |
| 771 | 771 | role: "user" as const, |
| ... | ... | @@ -845,7 +845,7 @@ describe("OrchestrationEngine", () => { |
| 845 | 845 | projectEvent: (event) => { |
| 846 | 846 | if ( |
| 847 | 847 | shouldFailProjection && |
| 848 | event.commandId === CommandId.makeUnsafe("cmd-thread-meta-sync-fail") | |
| 848 | event.commandId === CommandId.make("cmd-thread-meta-sync-fail") | |
| 849 | 849 | ) { |
| 850 | 850 | shouldFailProjection = false; |
| 851 | 851 | return Effect.fail( |
| ... | ... | @@ -875,7 +875,7 @@ describe("OrchestrationEngine", () => { |
| 875 | 875 | await runtime.runPromise( |
| 876 | 876 | engine.dispatch({ |
| 877 | 877 | type: "project.create", |
| 878 | commandId: CommandId.makeUnsafe("cmd-project-sync-create"), | |
| 878 | commandId: CommandId.make("cmd-project-sync-create"), | |
| 879 | 879 | projectId: asProjectId("project-sync"), |
| 880 | 880 | title: "Sync Project", |
| 881 | 881 | workspaceRoot: "/tmp/project-sync", |
| ... | ... | @@ -889,8 +889,8 @@ describe("OrchestrationEngine", () => { |
| 889 | 889 | await runtime.runPromise( |
| 890 | 890 | engine.dispatch({ |
| 891 | 891 | type: "thread.create", |
| 892 | commandId: CommandId.makeUnsafe("cmd-thread-sync-create"), | |
| 893 | threadId: ThreadId.makeUnsafe("thread-sync"), | |
| 892 | commandId: CommandId.make("cmd-thread-sync-create"), | |
| 893 | threadId: ThreadId.make("thread-sync"), | |
| 894 | 894 | projectId: asProjectId("project-sync"), |
| 895 | 895 | title: "sync-before", |
| 896 | 896 | modelSelection: { |
| ... | ... | @@ -909,8 +909,8 @@ describe("OrchestrationEngine", () => { |
| 909 | 909 | runtime.runPromise( |
| 910 | 910 | engine.dispatch({ |
| 911 | 911 | type: "thread.meta.update", |
| 912 | commandId: CommandId.makeUnsafe("cmd-thread-meta-sync-fail"), | |
| 913 | threadId: ThreadId.makeUnsafe("thread-sync"), | |
| 912 | commandId: CommandId.make("cmd-thread-meta-sync-fail"), | |
| 913 | threadId: ThreadId.make("thread-sync"), | |
| 914 | 914 | title: "sync-after-failed-projection", |
| 915 | 915 | }), |
| 916 | 916 | ), |
| ... | ... | @@ -934,8 +934,8 @@ describe("OrchestrationEngine", () => { |
| 934 | 934 | system.run( |
| 935 | 935 | engine.dispatch({ |
| 936 | 936 | type: "thread.turn.start", |
| 937 | commandId: CommandId.makeUnsafe("cmd-invariant-missing-thread"), | |
| 938 | threadId: ThreadId.makeUnsafe("thread-missing"), | |
| 937 | commandId: CommandId.make("cmd-invariant-missing-thread"), | |
| 938 | threadId: ThreadId.make("thread-missing"), | |
| 939 | 939 | message: { |
| 940 | 940 | messageId: asMessageId("msg-missing"), |
| 941 | 941 | role: "user", |
| ... | ... | @@ -960,7 +960,7 @@ describe("OrchestrationEngine", () => { |
| 960 | 960 | await system.run( |
| 961 | 961 | engine.dispatch({ |
| 962 | 962 | type: "project.create", |
| 963 | commandId: CommandId.makeUnsafe("cmd-project-duplicate-create"), | |
| 963 | commandId: CommandId.make("cmd-project-duplicate-create"), | |
| 964 | 964 | projectId: asProjectId("project-duplicate"), |
| 965 | 965 | title: "Duplicate Project", |
| 966 | 966 | workspaceRoot: "/tmp/project-duplicate", |
| ... | ... | @@ -975,8 +975,8 @@ describe("OrchestrationEngine", () => { |
| 975 | 975 | await system.run( |
| 976 | 976 | engine.dispatch({ |
| 977 | 977 | type: "thread.create", |
| 978 | commandId: CommandId.makeUnsafe("cmd-thread-duplicate-1"), | |
| 979 | threadId: ThreadId.makeUnsafe("thread-duplicate"), | |
| 978 | commandId: CommandId.make("cmd-thread-duplicate-1"), | |
| 979 | threadId: ThreadId.make("thread-duplicate"), | |
| 980 | 980 | projectId: asProjectId("project-duplicate"), |
| 981 | 981 | title: "duplicate", |
| 982 | 982 | modelSelection: { |
| ... | ... | @@ -995,8 +995,8 @@ describe("OrchestrationEngine", () => { |
| 995 | 995 | system.run( |
| 996 | 996 | engine.dispatch({ |
| 997 | 997 | type: "thread.create", |
| 998 | commandId: CommandId.makeUnsafe("cmd-thread-duplicate-2"), | |
| 999 | threadId: ThreadId.makeUnsafe("thread-duplicate"), | |
| 998 | commandId: CommandId.make("cmd-thread-duplicate-2"), | |
| 999 | threadId: ThreadId.make("thread-duplicate"), | |
| 1000 | 1000 | projectId: asProjectId("project-duplicate"), |
| 1001 | 1001 | title: "duplicate", |
| 1002 | 1002 | modelSelection: { |
apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts+302-302| ... | ... | @@ -58,16 +58,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 58 | 58 | |
| 59 | 59 | yield* eventStore.append({ |
| 60 | 60 | type: "project.created", |
| 61 | eventId: EventId.makeUnsafe("evt-1"), | |
| 61 | eventId: EventId.make("evt-1"), | |
| 62 | 62 | aggregateKind: "project", |
| 63 | aggregateId: ProjectId.makeUnsafe("project-1"), | |
| 63 | aggregateId: ProjectId.make("project-1"), | |
| 64 | 64 | occurredAt: now, |
| 65 | commandId: CommandId.makeUnsafe("cmd-1"), | |
| 65 | commandId: CommandId.make("cmd-1"), | |
| 66 | 66 | causationEventId: null, |
| 67 | correlationId: CommandId.makeUnsafe("cmd-1"), | |
| 67 | correlationId: CommandId.make("cmd-1"), | |
| 68 | 68 | metadata: {}, |
| 69 | 69 | payload: { |
| 70 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 70 | projectId: ProjectId.make("project-1"), | |
| 71 | 71 | title: "Project 1", |
| 72 | 72 | workspaceRoot: "/tmp/project-1", |
| 73 | 73 | defaultModelSelection: null, |
| ... | ... | @@ -79,17 +79,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 79 | 79 | |
| 80 | 80 | yield* eventStore.append({ |
| 81 | 81 | type: "thread.created", |
| 82 | eventId: EventId.makeUnsafe("evt-2"), | |
| 82 | eventId: EventId.make("evt-2"), | |
| 83 | 83 | aggregateKind: "thread", |
| 84 | aggregateId: ThreadId.makeUnsafe("thread-1"), | |
| 84 | aggregateId: ThreadId.make("thread-1"), | |
| 85 | 85 | occurredAt: now, |
| 86 | commandId: CommandId.makeUnsafe("cmd-2"), | |
| 86 | commandId: CommandId.make("cmd-2"), | |
| 87 | 87 | causationEventId: null, |
| 88 | correlationId: CommandId.makeUnsafe("cmd-2"), | |
| 88 | correlationId: CommandId.make("cmd-2"), | |
| 89 | 89 | metadata: {}, |
| 90 | 90 | payload: { |
| 91 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 92 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 91 | threadId: ThreadId.make("thread-1"), | |
| 92 | projectId: ProjectId.make("project-1"), | |
| 93 | 93 | title: "Thread 1", |
| 94 | 94 | modelSelection: { |
| 95 | 95 | provider: "codex", |
| ... | ... | @@ -105,17 +105,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 105 | 105 | |
| 106 | 106 | yield* eventStore.append({ |
| 107 | 107 | type: "thread.message-sent", |
| 108 | eventId: EventId.makeUnsafe("evt-3"), | |
| 108 | eventId: EventId.make("evt-3"), | |
| 109 | 109 | aggregateKind: "thread", |
| 110 | aggregateId: ThreadId.makeUnsafe("thread-1"), | |
| 110 | aggregateId: ThreadId.make("thread-1"), | |
| 111 | 111 | occurredAt: now, |
| 112 | commandId: CommandId.makeUnsafe("cmd-3"), | |
| 112 | commandId: CommandId.make("cmd-3"), | |
| 113 | 113 | causationEventId: null, |
| 114 | correlationId: CommandId.makeUnsafe("cmd-3"), | |
| 114 | correlationId: CommandId.make("cmd-3"), | |
| 115 | 115 | metadata: {}, |
| 116 | 116 | payload: { |
| 117 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 118 | messageId: MessageId.makeUnsafe("message-1"), | |
| 117 | threadId: ThreadId.make("thread-1"), | |
| 118 | messageId: MessageId.make("message-1"), | |
| 119 | 119 | role: "assistant", |
| 120 | 120 | text: "hello", |
| 121 | 121 | turnId: null, |
| ... | ... | @@ -183,17 +183,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-base-")))( |
| 183 | 183 | |
| 184 | 184 | yield* eventStore.append({ |
| 185 | 185 | type: "thread.message-sent", |
| 186 | eventId: EventId.makeUnsafe("evt-attachments"), | |
| 186 | eventId: EventId.make("evt-attachments"), | |
| 187 | 187 | aggregateKind: "thread", |
| 188 | aggregateId: ThreadId.makeUnsafe("thread-attachments"), | |
| 188 | aggregateId: ThreadId.make("thread-attachments"), | |
| 189 | 189 | occurredAt: now, |
| 190 | commandId: CommandId.makeUnsafe("cmd-attachments"), | |
| 190 | commandId: CommandId.make("cmd-attachments"), | |
| 191 | 191 | causationEventId: null, |
| 192 | correlationId: CommandId.makeUnsafe("cmd-attachments"), | |
| 192 | correlationId: CommandId.make("cmd-attachments"), | |
| 193 | 193 | metadata: {}, |
| 194 | 194 | payload: { |
| 195 | threadId: ThreadId.makeUnsafe("thread-attachments"), | |
| 196 | messageId: MessageId.makeUnsafe("message-attachments"), | |
| 195 | threadId: ThreadId.make("thread-attachments"), | |
| 196 | messageId: MessageId.make("message-attachments"), | |
| 197 | 197 | role: "user", |
| 198 | 198 | text: "Inspect this", |
| 199 | 199 | attachments: [ |
| ... | ... | @@ -249,17 +249,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 249 | 249 | |
| 250 | 250 | yield* eventStore.append({ |
| 251 | 251 | type: "thread.message-sent", |
| 252 | eventId: EventId.makeUnsafe("evt-attachments-safe"), | |
| 252 | eventId: EventId.make("evt-attachments-safe"), | |
| 253 | 253 | aggregateKind: "thread", |
| 254 | aggregateId: ThreadId.makeUnsafe("thread-attachments-safe"), | |
| 254 | aggregateId: ThreadId.make("thread-attachments-safe"), | |
| 255 | 255 | occurredAt: now, |
| 256 | commandId: CommandId.makeUnsafe("cmd-attachments-safe"), | |
| 256 | commandId: CommandId.make("cmd-attachments-safe"), | |
| 257 | 257 | causationEventId: null, |
| 258 | correlationId: CommandId.makeUnsafe("cmd-attachments-safe"), | |
| 258 | correlationId: CommandId.make("cmd-attachments-safe"), | |
| 259 | 259 | metadata: {}, |
| 260 | 260 | payload: { |
| 261 | threadId: ThreadId.makeUnsafe("thread-attachments-safe"), | |
| 262 | messageId: MessageId.makeUnsafe("message-attachments-safe"), | |
| 261 | threadId: ThreadId.make("thread-attachments-safe"), | |
| 262 | messageId: MessageId.make("message-attachments-safe"), | |
| 263 | 263 | role: "user", |
| 264 | 264 | text: "Inspect this", |
| 265 | 265 | attachments: [ |
| ... | ... | @@ -330,16 +330,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 330 | 330 | |
| 331 | 331 | yield* eventStore.append({ |
| 332 | 332 | type: "project.created", |
| 333 | eventId: EventId.makeUnsafe("evt-clear-attachments-1"), | |
| 333 | eventId: EventId.make("evt-clear-attachments-1"), | |
| 334 | 334 | aggregateKind: "project", |
| 335 | aggregateId: ProjectId.makeUnsafe("project-clear-attachments"), | |
| 335 | aggregateId: ProjectId.make("project-clear-attachments"), | |
| 336 | 336 | occurredAt: now, |
| 337 | commandId: CommandId.makeUnsafe("cmd-clear-attachments-1"), | |
| 337 | commandId: CommandId.make("cmd-clear-attachments-1"), | |
| 338 | 338 | causationEventId: null, |
| 339 | correlationId: CommandId.makeUnsafe("cmd-clear-attachments-1"), | |
| 339 | correlationId: CommandId.make("cmd-clear-attachments-1"), | |
| 340 | 340 | metadata: {}, |
| 341 | 341 | payload: { |
| 342 | projectId: ProjectId.makeUnsafe("project-clear-attachments"), | |
| 342 | projectId: ProjectId.make("project-clear-attachments"), | |
| 343 | 343 | title: "Project Clear Attachments", |
| 344 | 344 | workspaceRoot: "/tmp/project-clear-attachments", |
| 345 | 345 | defaultModelSelection: null, |
| ... | ... | @@ -351,17 +351,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 351 | 351 | |
| 352 | 352 | yield* eventStore.append({ |
| 353 | 353 | type: "thread.created", |
| 354 | eventId: EventId.makeUnsafe("evt-clear-attachments-2"), | |
| 354 | eventId: EventId.make("evt-clear-attachments-2"), | |
| 355 | 355 | aggregateKind: "thread", |
| 356 | aggregateId: ThreadId.makeUnsafe("thread-clear-attachments"), | |
| 356 | aggregateId: ThreadId.make("thread-clear-attachments"), | |
| 357 | 357 | occurredAt: now, |
| 358 | commandId: CommandId.makeUnsafe("cmd-clear-attachments-2"), | |
| 358 | commandId: CommandId.make("cmd-clear-attachments-2"), | |
| 359 | 359 | causationEventId: null, |
| 360 | correlationId: CommandId.makeUnsafe("cmd-clear-attachments-2"), | |
| 360 | correlationId: CommandId.make("cmd-clear-attachments-2"), | |
| 361 | 361 | metadata: {}, |
| 362 | 362 | payload: { |
| 363 | threadId: ThreadId.makeUnsafe("thread-clear-attachments"), | |
| 364 | projectId: ProjectId.makeUnsafe("project-clear-attachments"), | |
| 363 | threadId: ThreadId.make("thread-clear-attachments"), | |
| 364 | projectId: ProjectId.make("project-clear-attachments"), | |
| 365 | 365 | title: "Thread Clear Attachments", |
| 366 | 366 | modelSelection: { |
| 367 | 367 | provider: "codex", |
| ... | ... | @@ -377,17 +377,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 377 | 377 | |
| 378 | 378 | yield* eventStore.append({ |
| 379 | 379 | type: "thread.message-sent", |
| 380 | eventId: EventId.makeUnsafe("evt-clear-attachments-3"), | |
| 380 | eventId: EventId.make("evt-clear-attachments-3"), | |
| 381 | 381 | aggregateKind: "thread", |
| 382 | aggregateId: ThreadId.makeUnsafe("thread-clear-attachments"), | |
| 382 | aggregateId: ThreadId.make("thread-clear-attachments"), | |
| 383 | 383 | occurredAt: now, |
| 384 | commandId: CommandId.makeUnsafe("cmd-clear-attachments-3"), | |
| 384 | commandId: CommandId.make("cmd-clear-attachments-3"), | |
| 385 | 385 | causationEventId: null, |
| 386 | correlationId: CommandId.makeUnsafe("cmd-clear-attachments-3"), | |
| 386 | correlationId: CommandId.make("cmd-clear-attachments-3"), | |
| 387 | 387 | metadata: {}, |
| 388 | 388 | payload: { |
| 389 | threadId: ThreadId.makeUnsafe("thread-clear-attachments"), | |
| 390 | messageId: MessageId.makeUnsafe("message-clear-attachments"), | |
| 389 | threadId: ThreadId.make("thread-clear-attachments"), | |
| 390 | messageId: MessageId.make("message-clear-attachments"), | |
| 391 | 391 | role: "user", |
| 392 | 392 | text: "Has attachments", |
| 393 | 393 | attachments: [ |
| ... | ... | @@ -408,17 +408,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 408 | 408 | |
| 409 | 409 | yield* eventStore.append({ |
| 410 | 410 | type: "thread.message-sent", |
| 411 | eventId: EventId.makeUnsafe("evt-clear-attachments-4"), | |
| 411 | eventId: EventId.make("evt-clear-attachments-4"), | |
| 412 | 412 | aggregateKind: "thread", |
| 413 | aggregateId: ThreadId.makeUnsafe("thread-clear-attachments"), | |
| 413 | aggregateId: ThreadId.make("thread-clear-attachments"), | |
| 414 | 414 | occurredAt: later, |
| 415 | commandId: CommandId.makeUnsafe("cmd-clear-attachments-4"), | |
| 415 | commandId: CommandId.make("cmd-clear-attachments-4"), | |
| 416 | 416 | causationEventId: null, |
| 417 | correlationId: CommandId.makeUnsafe("cmd-clear-attachments-4"), | |
| 417 | correlationId: CommandId.make("cmd-clear-attachments-4"), | |
| 418 | 418 | metadata: {}, |
| 419 | 419 | payload: { |
| 420 | threadId: ThreadId.makeUnsafe("thread-clear-attachments"), | |
| 421 | messageId: MessageId.makeUnsafe("message-clear-attachments"), | |
| 420 | threadId: ThreadId.make("thread-clear-attachments"), | |
| 421 | messageId: MessageId.make("message-clear-attachments"), | |
| 422 | 422 | role: "user", |
| 423 | 423 | text: "", |
| 424 | 424 | attachments: [], |
| ... | ... | @@ -458,16 +458,16 @@ it.layer( |
| 458 | 458 | |
| 459 | 459 | yield* eventStore.append({ |
| 460 | 460 | type: "project.created", |
| 461 | eventId: EventId.makeUnsafe("evt-overwrite-1"), | |
| 461 | eventId: EventId.make("evt-overwrite-1"), | |
| 462 | 462 | aggregateKind: "project", |
| 463 | aggregateId: ProjectId.makeUnsafe("project-overwrite"), | |
| 463 | aggregateId: ProjectId.make("project-overwrite"), | |
| 464 | 464 | occurredAt: now, |
| 465 | commandId: CommandId.makeUnsafe("cmd-overwrite-1"), | |
| 465 | commandId: CommandId.make("cmd-overwrite-1"), | |
| 466 | 466 | causationEventId: null, |
| 467 | correlationId: CommandId.makeUnsafe("cmd-overwrite-1"), | |
| 467 | correlationId: CommandId.make("cmd-overwrite-1"), | |
| 468 | 468 | metadata: {}, |
| 469 | 469 | payload: { |
| 470 | projectId: ProjectId.makeUnsafe("project-overwrite"), | |
| 470 | projectId: ProjectId.make("project-overwrite"), | |
| 471 | 471 | title: "Project Overwrite", |
| 472 | 472 | workspaceRoot: "/tmp/project-overwrite", |
| 473 | 473 | defaultModelSelection: null, |
| ... | ... | @@ -479,17 +479,17 @@ it.layer( |
| 479 | 479 | |
| 480 | 480 | yield* eventStore.append({ |
| 481 | 481 | type: "thread.created", |
| 482 | eventId: EventId.makeUnsafe("evt-overwrite-2"), | |
| 482 | eventId: EventId.make("evt-overwrite-2"), | |
| 483 | 483 | aggregateKind: "thread", |
| 484 | aggregateId: ThreadId.makeUnsafe("thread-overwrite"), | |
| 484 | aggregateId: ThreadId.make("thread-overwrite"), | |
| 485 | 485 | occurredAt: now, |
| 486 | commandId: CommandId.makeUnsafe("cmd-overwrite-2"), | |
| 486 | commandId: CommandId.make("cmd-overwrite-2"), | |
| 487 | 487 | causationEventId: null, |
| 488 | correlationId: CommandId.makeUnsafe("cmd-overwrite-2"), | |
| 488 | correlationId: CommandId.make("cmd-overwrite-2"), | |
| 489 | 489 | metadata: {}, |
| 490 | 490 | payload: { |
| 491 | threadId: ThreadId.makeUnsafe("thread-overwrite"), | |
| 492 | projectId: ProjectId.makeUnsafe("project-overwrite"), | |
| 491 | threadId: ThreadId.make("thread-overwrite"), | |
| 492 | projectId: ProjectId.make("project-overwrite"), | |
| 493 | 493 | title: "Thread Overwrite", |
| 494 | 494 | modelSelection: { |
| 495 | 495 | provider: "codex", |
| ... | ... | @@ -505,17 +505,17 @@ it.layer( |
| 505 | 505 | |
| 506 | 506 | yield* eventStore.append({ |
| 507 | 507 | type: "thread.message-sent", |
| 508 | eventId: EventId.makeUnsafe("evt-overwrite-3"), | |
| 508 | eventId: EventId.make("evt-overwrite-3"), | |
| 509 | 509 | aggregateKind: "thread", |
| 510 | aggregateId: ThreadId.makeUnsafe("thread-overwrite"), | |
| 510 | aggregateId: ThreadId.make("thread-overwrite"), | |
| 511 | 511 | occurredAt: now, |
| 512 | commandId: CommandId.makeUnsafe("cmd-overwrite-3"), | |
| 512 | commandId: CommandId.make("cmd-overwrite-3"), | |
| 513 | 513 | causationEventId: null, |
| 514 | correlationId: CommandId.makeUnsafe("cmd-overwrite-3"), | |
| 514 | correlationId: CommandId.make("cmd-overwrite-3"), | |
| 515 | 515 | metadata: {}, |
| 516 | 516 | payload: { |
| 517 | threadId: ThreadId.makeUnsafe("thread-overwrite"), | |
| 518 | messageId: MessageId.makeUnsafe("message-overwrite"), | |
| 517 | threadId: ThreadId.make("thread-overwrite"), | |
| 518 | messageId: MessageId.make("message-overwrite"), | |
| 519 | 519 | role: "user", |
| 520 | 520 | text: "first image", |
| 521 | 521 | attachments: [ |
| ... | ... | @@ -536,17 +536,17 @@ it.layer( |
| 536 | 536 | |
| 537 | 537 | yield* eventStore.append({ |
| 538 | 538 | type: "thread.message-sent", |
| 539 | eventId: EventId.makeUnsafe("evt-overwrite-4"), | |
| 539 | eventId: EventId.make("evt-overwrite-4"), | |
| 540 | 540 | aggregateKind: "thread", |
| 541 | aggregateId: ThreadId.makeUnsafe("thread-overwrite"), | |
| 541 | aggregateId: ThreadId.make("thread-overwrite"), | |
| 542 | 542 | occurredAt: later, |
| 543 | commandId: CommandId.makeUnsafe("cmd-overwrite-4"), | |
| 543 | commandId: CommandId.make("cmd-overwrite-4"), | |
| 544 | 544 | causationEventId: null, |
| 545 | correlationId: CommandId.makeUnsafe("cmd-overwrite-4"), | |
| 545 | correlationId: CommandId.make("cmd-overwrite-4"), | |
| 546 | 546 | metadata: {}, |
| 547 | 547 | payload: { |
| 548 | threadId: ThreadId.makeUnsafe("thread-overwrite"), | |
| 549 | messageId: MessageId.makeUnsafe("message-overwrite"), | |
| 548 | threadId: ThreadId.make("thread-overwrite"), | |
| 549 | messageId: MessageId.make("message-overwrite"), | |
| 550 | 550 | role: "user", |
| 551 | 551 | text: "", |
| 552 | 552 | attachments: [ |
| ... | ... | @@ -606,16 +606,16 @@ it.layer( |
| 606 | 606 | |
| 607 | 607 | yield* appendAndProject({ |
| 608 | 608 | type: "project.created", |
| 609 | eventId: EventId.makeUnsafe("evt-rollback-1"), | |
| 609 | eventId: EventId.make("evt-rollback-1"), | |
| 610 | 610 | aggregateKind: "project", |
| 611 | aggregateId: ProjectId.makeUnsafe("project-rollback"), | |
| 611 | aggregateId: ProjectId.make("project-rollback"), | |
| 612 | 612 | occurredAt: now, |
| 613 | commandId: CommandId.makeUnsafe("cmd-rollback-1"), | |
| 613 | commandId: CommandId.make("cmd-rollback-1"), | |
| 614 | 614 | causationEventId: null, |
| 615 | correlationId: CorrelationId.makeUnsafe("cmd-rollback-1"), | |
| 615 | correlationId: CorrelationId.make("cmd-rollback-1"), | |
| 616 | 616 | metadata: {}, |
| 617 | 617 | payload: { |
| 618 | projectId: ProjectId.makeUnsafe("project-rollback"), | |
| 618 | projectId: ProjectId.make("project-rollback"), | |
| 619 | 619 | title: "Project Rollback", |
| 620 | 620 | workspaceRoot: "/tmp/project-rollback", |
| 621 | 621 | defaultModelSelection: null, |
| ... | ... | @@ -627,17 +627,17 @@ it.layer( |
| 627 | 627 | |
| 628 | 628 | yield* appendAndProject({ |
| 629 | 629 | type: "thread.created", |
| 630 | eventId: EventId.makeUnsafe("evt-rollback-2"), | |
| 630 | eventId: EventId.make("evt-rollback-2"), | |
| 631 | 631 | aggregateKind: "thread", |
| 632 | aggregateId: ThreadId.makeUnsafe("thread-rollback"), | |
| 632 | aggregateId: ThreadId.make("thread-rollback"), | |
| 633 | 633 | occurredAt: now, |
| 634 | commandId: CommandId.makeUnsafe("cmd-rollback-2"), | |
| 634 | commandId: CommandId.make("cmd-rollback-2"), | |
| 635 | 635 | causationEventId: null, |
| 636 | correlationId: CorrelationId.makeUnsafe("cmd-rollback-2"), | |
| 636 | correlationId: CorrelationId.make("cmd-rollback-2"), | |
| 637 | 637 | metadata: {}, |
| 638 | 638 | payload: { |
| 639 | threadId: ThreadId.makeUnsafe("thread-rollback"), | |
| 640 | projectId: ProjectId.makeUnsafe("project-rollback"), | |
| 639 | threadId: ThreadId.make("thread-rollback"), | |
| 640 | projectId: ProjectId.make("project-rollback"), | |
| 641 | 641 | title: "Thread Rollback", |
| 642 | 642 | modelSelection: { |
| 643 | 643 | provider: "codex", |
| ... | ... | @@ -663,17 +663,17 @@ it.layer( |
| 663 | 663 | const result = yield* Effect.result( |
| 664 | 664 | appendAndProject({ |
| 665 | 665 | type: "thread.message-sent", |
| 666 | eventId: EventId.makeUnsafe("evt-rollback-3"), | |
| 666 | eventId: EventId.make("evt-rollback-3"), | |
| 667 | 667 | aggregateKind: "thread", |
| 668 | aggregateId: ThreadId.makeUnsafe("thread-rollback"), | |
| 668 | aggregateId: ThreadId.make("thread-rollback"), | |
| 669 | 669 | occurredAt: now, |
| 670 | commandId: CommandId.makeUnsafe("cmd-rollback-3"), | |
| 670 | commandId: CommandId.make("cmd-rollback-3"), | |
| 671 | 671 | causationEventId: null, |
| 672 | correlationId: CorrelationId.makeUnsafe("cmd-rollback-3"), | |
| 672 | correlationId: CorrelationId.make("cmd-rollback-3"), | |
| 673 | 673 | metadata: {}, |
| 674 | 674 | payload: { |
| 675 | threadId: ThreadId.makeUnsafe("thread-rollback"), | |
| 676 | messageId: MessageId.makeUnsafe("message-rollback"), | |
| 675 | threadId: ThreadId.make("thread-rollback"), | |
| 676 | messageId: MessageId.make("message-rollback"), | |
| 677 | 677 | role: "user", |
| 678 | 678 | text: "Rollback me", |
| 679 | 679 | attachments: [ |
| ... | ... | @@ -722,7 +722,7 @@ it.layer( |
| 722 | 722 | const eventStore = yield* OrchestrationEventStore; |
| 723 | 723 | const { attachmentsDir } = yield* ServerConfig; |
| 724 | 724 | const now = new Date().toISOString(); |
| 725 | const threadId = ThreadId.makeUnsafe("Thread Revert.Files"); | |
| 725 | const threadId = ThreadId.make("Thread Revert.Files"); | |
| 726 | 726 | const keepAttachmentId = "thread-revert-files-00000000-0000-4000-8000-000000000001"; |
| 727 | 727 | const removeAttachmentId = "thread-revert-files-00000000-0000-4000-8000-000000000002"; |
| 728 | 728 | const otherThreadAttachmentId = |
| ... | ... | @@ -735,16 +735,16 @@ it.layer( |
| 735 | 735 | |
| 736 | 736 | yield* appendAndProject({ |
| 737 | 737 | type: "project.created", |
| 738 | eventId: EventId.makeUnsafe("evt-revert-files-1"), | |
| 738 | eventId: EventId.make("evt-revert-files-1"), | |
| 739 | 739 | aggregateKind: "project", |
| 740 | aggregateId: ProjectId.makeUnsafe("project-revert-files"), | |
| 740 | aggregateId: ProjectId.make("project-revert-files"), | |
| 741 | 741 | occurredAt: now, |
| 742 | commandId: CommandId.makeUnsafe("cmd-revert-files-1"), | |
| 742 | commandId: CommandId.make("cmd-revert-files-1"), | |
| 743 | 743 | causationEventId: null, |
| 744 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-1"), | |
| 744 | correlationId: CorrelationId.make("cmd-revert-files-1"), | |
| 745 | 745 | metadata: {}, |
| 746 | 746 | payload: { |
| 747 | projectId: ProjectId.makeUnsafe("project-revert-files"), | |
| 747 | projectId: ProjectId.make("project-revert-files"), | |
| 748 | 748 | title: "Project Revert Files", |
| 749 | 749 | workspaceRoot: "/tmp/project-revert-files", |
| 750 | 750 | defaultModelSelection: null, |
| ... | ... | @@ -756,17 +756,17 @@ it.layer( |
| 756 | 756 | |
| 757 | 757 | yield* appendAndProject({ |
| 758 | 758 | type: "thread.created", |
| 759 | eventId: EventId.makeUnsafe("evt-revert-files-2"), | |
| 759 | eventId: EventId.make("evt-revert-files-2"), | |
| 760 | 760 | aggregateKind: "thread", |
| 761 | 761 | aggregateId: threadId, |
| 762 | 762 | occurredAt: now, |
| 763 | commandId: CommandId.makeUnsafe("cmd-revert-files-2"), | |
| 763 | commandId: CommandId.make("cmd-revert-files-2"), | |
| 764 | 764 | causationEventId: null, |
| 765 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-2"), | |
| 765 | correlationId: CorrelationId.make("cmd-revert-files-2"), | |
| 766 | 766 | metadata: {}, |
| 767 | 767 | payload: { |
| 768 | 768 | threadId, |
| 769 | projectId: ProjectId.makeUnsafe("project-revert-files"), | |
| 769 | projectId: ProjectId.make("project-revert-files"), | |
| 770 | 770 | title: "Thread Revert Files", |
| 771 | 771 | modelSelection: { |
| 772 | 772 | provider: "codex", |
| ... | ... | @@ -782,39 +782,39 @@ it.layer( |
| 782 | 782 | |
| 783 | 783 | yield* appendAndProject({ |
| 784 | 784 | type: "thread.turn-diff-completed", |
| 785 | eventId: EventId.makeUnsafe("evt-revert-files-3"), | |
| 785 | eventId: EventId.make("evt-revert-files-3"), | |
| 786 | 786 | aggregateKind: "thread", |
| 787 | 787 | aggregateId: threadId, |
| 788 | 788 | occurredAt: now, |
| 789 | commandId: CommandId.makeUnsafe("cmd-revert-files-3"), | |
| 789 | commandId: CommandId.make("cmd-revert-files-3"), | |
| 790 | 790 | causationEventId: null, |
| 791 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-3"), | |
| 791 | correlationId: CorrelationId.make("cmd-revert-files-3"), | |
| 792 | 792 | metadata: {}, |
| 793 | 793 | payload: { |
| 794 | 794 | threadId, |
| 795 | turnId: TurnId.makeUnsafe("turn-keep"), | |
| 795 | turnId: TurnId.make("turn-keep"), | |
| 796 | 796 | checkpointTurnCount: 1, |
| 797 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert-files/turn/1"), | |
| 797 | checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert-files/turn/1"), | |
| 798 | 798 | status: "ready", |
| 799 | 799 | files: [], |
| 800 | assistantMessageId: MessageId.makeUnsafe("message-keep"), | |
| 800 | assistantMessageId: MessageId.make("message-keep"), | |
| 801 | 801 | completedAt: now, |
| 802 | 802 | }, |
| 803 | 803 | }); |
| 804 | 804 | |
| 805 | 805 | yield* appendAndProject({ |
| 806 | 806 | type: "thread.message-sent", |
| 807 | eventId: EventId.makeUnsafe("evt-revert-files-4"), | |
| 807 | eventId: EventId.make("evt-revert-files-4"), | |
| 808 | 808 | aggregateKind: "thread", |
| 809 | 809 | aggregateId: threadId, |
| 810 | 810 | occurredAt: now, |
| 811 | commandId: CommandId.makeUnsafe("cmd-revert-files-4"), | |
| 811 | commandId: CommandId.make("cmd-revert-files-4"), | |
| 812 | 812 | causationEventId: null, |
| 813 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-4"), | |
| 813 | correlationId: CorrelationId.make("cmd-revert-files-4"), | |
| 814 | 814 | metadata: {}, |
| 815 | 815 | payload: { |
| 816 | 816 | threadId, |
| 817 | messageId: MessageId.makeUnsafe("message-keep"), | |
| 817 | messageId: MessageId.make("message-keep"), | |
| 818 | 818 | role: "assistant", |
| 819 | 819 | text: "Keep", |
| 820 | 820 | attachments: [ |
| ... | ... | @@ -826,7 +826,7 @@ it.layer( |
| 826 | 826 | sizeBytes: 5, |
| 827 | 827 | }, |
| 828 | 828 | ], |
| 829 | turnId: TurnId.makeUnsafe("turn-keep"), | |
| 829 | turnId: TurnId.make("turn-keep"), | |
| 830 | 830 | streaming: false, |
| 831 | 831 | createdAt: now, |
| 832 | 832 | updatedAt: now, |
| ... | ... | @@ -835,39 +835,39 @@ it.layer( |
| 835 | 835 | |
| 836 | 836 | yield* appendAndProject({ |
| 837 | 837 | type: "thread.turn-diff-completed", |
| 838 | eventId: EventId.makeUnsafe("evt-revert-files-5"), | |
| 838 | eventId: EventId.make("evt-revert-files-5"), | |
| 839 | 839 | aggregateKind: "thread", |
| 840 | 840 | aggregateId: threadId, |
| 841 | 841 | occurredAt: now, |
| 842 | commandId: CommandId.makeUnsafe("cmd-revert-files-5"), | |
| 842 | commandId: CommandId.make("cmd-revert-files-5"), | |
| 843 | 843 | causationEventId: null, |
| 844 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-5"), | |
| 844 | correlationId: CorrelationId.make("cmd-revert-files-5"), | |
| 845 | 845 | metadata: {}, |
| 846 | 846 | payload: { |
| 847 | 847 | threadId, |
| 848 | turnId: TurnId.makeUnsafe("turn-remove"), | |
| 848 | turnId: TurnId.make("turn-remove"), | |
| 849 | 849 | checkpointTurnCount: 2, |
| 850 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert-files/turn/2"), | |
| 850 | checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert-files/turn/2"), | |
| 851 | 851 | status: "ready", |
| 852 | 852 | files: [], |
| 853 | assistantMessageId: MessageId.makeUnsafe("message-remove"), | |
| 853 | assistantMessageId: MessageId.make("message-remove"), | |
| 854 | 854 | completedAt: now, |
| 855 | 855 | }, |
| 856 | 856 | }); |
| 857 | 857 | |
| 858 | 858 | yield* appendAndProject({ |
| 859 | 859 | type: "thread.message-sent", |
| 860 | eventId: EventId.makeUnsafe("evt-revert-files-6"), | |
| 860 | eventId: EventId.make("evt-revert-files-6"), | |
| 861 | 861 | aggregateKind: "thread", |
| 862 | 862 | aggregateId: threadId, |
| 863 | 863 | occurredAt: now, |
| 864 | commandId: CommandId.makeUnsafe("cmd-revert-files-6"), | |
| 864 | commandId: CommandId.make("cmd-revert-files-6"), | |
| 865 | 865 | causationEventId: null, |
| 866 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-6"), | |
| 866 | correlationId: CorrelationId.make("cmd-revert-files-6"), | |
| 867 | 867 | metadata: {}, |
| 868 | 868 | payload: { |
| 869 | 869 | threadId, |
| 870 | messageId: MessageId.makeUnsafe("message-remove"), | |
| 870 | messageId: MessageId.make("message-remove"), | |
| 871 | 871 | role: "assistant", |
| 872 | 872 | text: "Remove", |
| 873 | 873 | attachments: [ |
| ... | ... | @@ -879,7 +879,7 @@ it.layer( |
| 879 | 879 | sizeBytes: 5, |
| 880 | 880 | }, |
| 881 | 881 | ], |
| 882 | turnId: TurnId.makeUnsafe("turn-remove"), | |
| 882 | turnId: TurnId.make("turn-remove"), | |
| 883 | 883 | streaming: false, |
| 884 | 884 | createdAt: now, |
| 885 | 885 | updatedAt: now, |
| ... | ... | @@ -899,13 +899,13 @@ it.layer( |
| 899 | 899 | |
| 900 | 900 | yield* appendAndProject({ |
| 901 | 901 | type: "thread.reverted", |
| 902 | eventId: EventId.makeUnsafe("evt-revert-files-7"), | |
| 902 | eventId: EventId.make("evt-revert-files-7"), | |
| 903 | 903 | aggregateKind: "thread", |
| 904 | 904 | aggregateId: threadId, |
| 905 | 905 | occurredAt: now, |
| 906 | commandId: CommandId.makeUnsafe("cmd-revert-files-7"), | |
| 906 | commandId: CommandId.make("cmd-revert-files-7"), | |
| 907 | 907 | causationEventId: null, |
| 908 | correlationId: CorrelationId.makeUnsafe("cmd-revert-files-7"), | |
| 908 | correlationId: CorrelationId.make("cmd-revert-files-7"), | |
| 909 | 909 | metadata: {}, |
| 910 | 910 | payload: { |
| 911 | 911 | threadId, |
| ... | ... | @@ -931,7 +931,7 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 931 | 931 | const eventStore = yield* OrchestrationEventStore; |
| 932 | 932 | const { attachmentsDir } = yield* ServerConfig; |
| 933 | 933 | const now = new Date().toISOString(); |
| 934 | const threadId = ThreadId.makeUnsafe("Thread Delete.Files"); | |
| 934 | const threadId = ThreadId.make("Thread Delete.Files"); | |
| 935 | 935 | const attachmentId = "thread-delete-files-00000000-0000-4000-8000-000000000001"; |
| 936 | 936 | const otherThreadAttachmentId = |
| 937 | 937 | "thread-delete-files-extra-00000000-0000-4000-8000-000000000002"; |
| ... | ... | @@ -943,16 +943,16 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 943 | 943 | |
| 944 | 944 | yield* appendAndProject({ |
| 945 | 945 | type: "project.created", |
| 946 | eventId: EventId.makeUnsafe("evt-delete-files-1"), | |
| 946 | eventId: EventId.make("evt-delete-files-1"), | |
| 947 | 947 | aggregateKind: "project", |
| 948 | aggregateId: ProjectId.makeUnsafe("project-delete-files"), | |
| 948 | aggregateId: ProjectId.make("project-delete-files"), | |
| 949 | 949 | occurredAt: now, |
| 950 | commandId: CommandId.makeUnsafe("cmd-delete-files-1"), | |
| 950 | commandId: CommandId.make("cmd-delete-files-1"), | |
| 951 | 951 | causationEventId: null, |
| 952 | correlationId: CorrelationId.makeUnsafe("cmd-delete-files-1"), | |
| 952 | correlationId: CorrelationId.make("cmd-delete-files-1"), | |
| 953 | 953 | metadata: {}, |
| 954 | 954 | payload: { |
| 955 | projectId: ProjectId.makeUnsafe("project-delete-files"), | |
| 955 | projectId: ProjectId.make("project-delete-files"), | |
| 956 | 956 | title: "Project Delete Files", |
| 957 | 957 | workspaceRoot: "/tmp/project-delete-files", |
| 958 | 958 | defaultModelSelection: null, |
| ... | ... | @@ -964,17 +964,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 964 | 964 | |
| 965 | 965 | yield* appendAndProject({ |
| 966 | 966 | type: "thread.created", |
| 967 | eventId: EventId.makeUnsafe("evt-delete-files-2"), | |
| 967 | eventId: EventId.make("evt-delete-files-2"), | |
| 968 | 968 | aggregateKind: "thread", |
| 969 | 969 | aggregateId: threadId, |
| 970 | 970 | occurredAt: now, |
| 971 | commandId: CommandId.makeUnsafe("cmd-delete-files-2"), | |
| 971 | commandId: CommandId.make("cmd-delete-files-2"), | |
| 972 | 972 | causationEventId: null, |
| 973 | correlationId: CorrelationId.makeUnsafe("cmd-delete-files-2"), | |
| 973 | correlationId: CorrelationId.make("cmd-delete-files-2"), | |
| 974 | 974 | metadata: {}, |
| 975 | 975 | payload: { |
| 976 | 976 | threadId, |
| 977 | projectId: ProjectId.makeUnsafe("project-delete-files"), | |
| 977 | projectId: ProjectId.make("project-delete-files"), | |
| 978 | 978 | title: "Thread Delete Files", |
| 979 | 979 | modelSelection: { |
| 980 | 980 | provider: "codex", |
| ... | ... | @@ -990,17 +990,17 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 990 | 990 | |
| 991 | 991 | yield* appendAndProject({ |
| 992 | 992 | type: "thread.message-sent", |
| 993 | eventId: EventId.makeUnsafe("evt-delete-files-3"), | |
| 993 | eventId: EventId.make("evt-delete-files-3"), | |
| 994 | 994 | aggregateKind: "thread", |
| 995 | 995 | aggregateId: threadId, |
| 996 | 996 | occurredAt: now, |
| 997 | commandId: CommandId.makeUnsafe("cmd-delete-files-3"), | |
| 997 | commandId: CommandId.make("cmd-delete-files-3"), | |
| 998 | 998 | causationEventId: null, |
| 999 | correlationId: CorrelationId.makeUnsafe("cmd-delete-files-3"), | |
| 999 | correlationId: CorrelationId.make("cmd-delete-files-3"), | |
| 1000 | 1000 | metadata: {}, |
| 1001 | 1001 | payload: { |
| 1002 | 1002 | threadId, |
| 1003 | messageId: MessageId.makeUnsafe("message-delete-files"), | |
| 1003 | messageId: MessageId.make("message-delete-files"), | |
| 1004 | 1004 | role: "user", |
| 1005 | 1005 | text: "Delete", |
| 1006 | 1006 | attachments: [ |
| ... | ... | @@ -1032,13 +1032,13 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 1032 | 1032 | |
| 1033 | 1033 | yield* appendAndProject({ |
| 1034 | 1034 | type: "thread.deleted", |
| 1035 | eventId: EventId.makeUnsafe("evt-delete-files-4"), | |
| 1035 | eventId: EventId.make("evt-delete-files-4"), | |
| 1036 | 1036 | aggregateKind: "thread", |
| 1037 | 1037 | aggregateId: threadId, |
| 1038 | 1038 | occurredAt: now, |
| 1039 | commandId: CommandId.makeUnsafe("cmd-delete-files-4"), | |
| 1039 | commandId: CommandId.make("cmd-delete-files-4"), | |
| 1040 | 1040 | causationEventId: null, |
| 1041 | correlationId: CorrelationId.makeUnsafe("cmd-delete-files-4"), | |
| 1041 | correlationId: CorrelationId.make("cmd-delete-files-4"), | |
| 1042 | 1042 | metadata: {}, |
| 1043 | 1043 | payload: { |
| 1044 | 1044 | threadId, |
| ... | ... | @@ -1072,16 +1072,16 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 1072 | 1072 | |
| 1073 | 1073 | yield* eventStore.append({ |
| 1074 | 1074 | type: "thread.deleted", |
| 1075 | eventId: EventId.makeUnsafe("evt-unsafe-thread-delete"), | |
| 1075 | eventId: EventId.make("evt-unsafe-thread-delete"), | |
| 1076 | 1076 | aggregateKind: "thread", |
| 1077 | aggregateId: ThreadId.makeUnsafe(".."), | |
| 1077 | aggregateId: ThreadId.make(".."), | |
| 1078 | 1078 | occurredAt: now, |
| 1079 | commandId: CommandId.makeUnsafe("cmd-unsafe-thread-delete"), | |
| 1079 | commandId: CommandId.make("cmd-unsafe-thread-delete"), | |
| 1080 | 1080 | causationEventId: null, |
| 1081 | correlationId: CorrelationId.makeUnsafe("cmd-unsafe-thread-delete"), | |
| 1081 | correlationId: CorrelationId.make("cmd-unsafe-thread-delete"), | |
| 1082 | 1082 | metadata: {}, |
| 1083 | 1083 | payload: { |
| 1084 | threadId: ThreadId.makeUnsafe(".."), | |
| 1084 | threadId: ThreadId.make(".."), | |
| 1085 | 1085 | deletedAt: now, |
| 1086 | 1086 | }, |
| 1087 | 1087 | }); |
| ... | ... | @@ -1106,16 +1106,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1106 | 1106 | |
| 1107 | 1107 | yield* eventStore.append({ |
| 1108 | 1108 | type: "project.created", |
| 1109 | eventId: EventId.makeUnsafe("evt-a1"), | |
| 1109 | eventId: EventId.make("evt-a1"), | |
| 1110 | 1110 | aggregateKind: "project", |
| 1111 | aggregateId: ProjectId.makeUnsafe("project-a"), | |
| 1111 | aggregateId: ProjectId.make("project-a"), | |
| 1112 | 1112 | occurredAt: now, |
| 1113 | commandId: CommandId.makeUnsafe("cmd-a1"), | |
| 1113 | commandId: CommandId.make("cmd-a1"), | |
| 1114 | 1114 | causationEventId: null, |
| 1115 | correlationId: CorrelationId.makeUnsafe("cmd-a1"), | |
| 1115 | correlationId: CorrelationId.make("cmd-a1"), | |
| 1116 | 1116 | metadata: {}, |
| 1117 | 1117 | payload: { |
| 1118 | projectId: ProjectId.makeUnsafe("project-a"), | |
| 1118 | projectId: ProjectId.make("project-a"), | |
| 1119 | 1119 | title: "Project A", |
| 1120 | 1120 | workspaceRoot: "/tmp/project-a", |
| 1121 | 1121 | defaultModelSelection: null, |
| ... | ... | @@ -1127,17 +1127,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1127 | 1127 | |
| 1128 | 1128 | yield* eventStore.append({ |
| 1129 | 1129 | type: "thread.created", |
| 1130 | eventId: EventId.makeUnsafe("evt-a2"), | |
| 1130 | eventId: EventId.make("evt-a2"), | |
| 1131 | 1131 | aggregateKind: "thread", |
| 1132 | aggregateId: ThreadId.makeUnsafe("thread-a"), | |
| 1132 | aggregateId: ThreadId.make("thread-a"), | |
| 1133 | 1133 | occurredAt: now, |
| 1134 | commandId: CommandId.makeUnsafe("cmd-a2"), | |
| 1134 | commandId: CommandId.make("cmd-a2"), | |
| 1135 | 1135 | causationEventId: null, |
| 1136 | correlationId: CorrelationId.makeUnsafe("cmd-a2"), | |
| 1136 | correlationId: CorrelationId.make("cmd-a2"), | |
| 1137 | 1137 | metadata: {}, |
| 1138 | 1138 | payload: { |
| 1139 | threadId: ThreadId.makeUnsafe("thread-a"), | |
| 1140 | projectId: ProjectId.makeUnsafe("project-a"), | |
| 1139 | threadId: ThreadId.make("thread-a"), | |
| 1140 | projectId: ProjectId.make("project-a"), | |
| 1141 | 1141 | title: "Thread A", |
| 1142 | 1142 | modelSelection: { |
| 1143 | 1143 | provider: "codex", |
| ... | ... | @@ -1153,17 +1153,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1153 | 1153 | |
| 1154 | 1154 | yield* eventStore.append({ |
| 1155 | 1155 | type: "thread.message-sent", |
| 1156 | eventId: EventId.makeUnsafe("evt-a3"), | |
| 1156 | eventId: EventId.make("evt-a3"), | |
| 1157 | 1157 | aggregateKind: "thread", |
| 1158 | aggregateId: ThreadId.makeUnsafe("thread-a"), | |
| 1158 | aggregateId: ThreadId.make("thread-a"), | |
| 1159 | 1159 | occurredAt: now, |
| 1160 | commandId: CommandId.makeUnsafe("cmd-a3"), | |
| 1160 | commandId: CommandId.make("cmd-a3"), | |
| 1161 | 1161 | causationEventId: null, |
| 1162 | correlationId: CorrelationId.makeUnsafe("cmd-a3"), | |
| 1162 | correlationId: CorrelationId.make("cmd-a3"), | |
| 1163 | 1163 | metadata: {}, |
| 1164 | 1164 | payload: { |
| 1165 | threadId: ThreadId.makeUnsafe("thread-a"), | |
| 1166 | messageId: MessageId.makeUnsafe("message-a"), | |
| 1165 | threadId: ThreadId.make("thread-a"), | |
| 1166 | messageId: MessageId.make("message-a"), | |
| 1167 | 1167 | role: "assistant", |
| 1168 | 1168 | text: "hello", |
| 1169 | 1169 | turnId: null, |
| ... | ... | @@ -1177,17 +1177,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1177 | 1177 | |
| 1178 | 1178 | yield* eventStore.append({ |
| 1179 | 1179 | type: "thread.message-sent", |
| 1180 | eventId: EventId.makeUnsafe("evt-a4"), | |
| 1180 | eventId: EventId.make("evt-a4"), | |
| 1181 | 1181 | aggregateKind: "thread", |
| 1182 | aggregateId: ThreadId.makeUnsafe("thread-a"), | |
| 1182 | aggregateId: ThreadId.make("thread-a"), | |
| 1183 | 1183 | occurredAt: now, |
| 1184 | commandId: CommandId.makeUnsafe("cmd-a4"), | |
| 1184 | commandId: CommandId.make("cmd-a4"), | |
| 1185 | 1185 | causationEventId: null, |
| 1186 | correlationId: CorrelationId.makeUnsafe("cmd-a4"), | |
| 1186 | correlationId: CorrelationId.make("cmd-a4"), | |
| 1187 | 1187 | metadata: {}, |
| 1188 | 1188 | payload: { |
| 1189 | threadId: ThreadId.makeUnsafe("thread-a"), | |
| 1190 | messageId: MessageId.makeUnsafe("message-a"), | |
| 1189 | threadId: ThreadId.make("thread-a"), | |
| 1190 | messageId: MessageId.make("message-a"), | |
| 1191 | 1191 | role: "assistant", |
| 1192 | 1192 | text: " world", |
| 1193 | 1193 | turnId: null, |
| ... | ... | @@ -1233,16 +1233,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1233 | 1233 | |
| 1234 | 1234 | yield* eventStore.append({ |
| 1235 | 1235 | type: "project.created", |
| 1236 | eventId: EventId.makeUnsafe("evt-empty-1"), | |
| 1236 | eventId: EventId.make("evt-empty-1"), | |
| 1237 | 1237 | aggregateKind: "project", |
| 1238 | aggregateId: ProjectId.makeUnsafe("project-empty"), | |
| 1238 | aggregateId: ProjectId.make("project-empty"), | |
| 1239 | 1239 | occurredAt: now, |
| 1240 | commandId: CommandId.makeUnsafe("cmd-empty-1"), | |
| 1240 | commandId: CommandId.make("cmd-empty-1"), | |
| 1241 | 1241 | causationEventId: null, |
| 1242 | correlationId: CorrelationId.makeUnsafe("cmd-empty-1"), | |
| 1242 | correlationId: CorrelationId.make("cmd-empty-1"), | |
| 1243 | 1243 | metadata: {}, |
| 1244 | 1244 | payload: { |
| 1245 | projectId: ProjectId.makeUnsafe("project-empty"), | |
| 1245 | projectId: ProjectId.make("project-empty"), | |
| 1246 | 1246 | title: "Project Empty", |
| 1247 | 1247 | workspaceRoot: "/tmp/project-empty", |
| 1248 | 1248 | defaultModelSelection: null, |
| ... | ... | @@ -1254,17 +1254,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1254 | 1254 | |
| 1255 | 1255 | yield* eventStore.append({ |
| 1256 | 1256 | type: "thread.created", |
| 1257 | eventId: EventId.makeUnsafe("evt-empty-2"), | |
| 1257 | eventId: EventId.make("evt-empty-2"), | |
| 1258 | 1258 | aggregateKind: "thread", |
| 1259 | aggregateId: ThreadId.makeUnsafe("thread-empty"), | |
| 1259 | aggregateId: ThreadId.make("thread-empty"), | |
| 1260 | 1260 | occurredAt: now, |
| 1261 | commandId: CommandId.makeUnsafe("cmd-empty-2"), | |
| 1261 | commandId: CommandId.make("cmd-empty-2"), | |
| 1262 | 1262 | causationEventId: null, |
| 1263 | correlationId: CorrelationId.makeUnsafe("cmd-empty-2"), | |
| 1263 | correlationId: CorrelationId.make("cmd-empty-2"), | |
| 1264 | 1264 | metadata: {}, |
| 1265 | 1265 | payload: { |
| 1266 | threadId: ThreadId.makeUnsafe("thread-empty"), | |
| 1267 | projectId: ProjectId.makeUnsafe("project-empty"), | |
| 1266 | threadId: ThreadId.make("thread-empty"), | |
| 1267 | projectId: ProjectId.make("project-empty"), | |
| 1268 | 1268 | title: "Thread Empty", |
| 1269 | 1269 | modelSelection: { |
| 1270 | 1270 | provider: "codex", |
| ... | ... | @@ -1280,17 +1280,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1280 | 1280 | |
| 1281 | 1281 | yield* eventStore.append({ |
| 1282 | 1282 | type: "thread.message-sent", |
| 1283 | eventId: EventId.makeUnsafe("evt-empty-3"), | |
| 1283 | eventId: EventId.make("evt-empty-3"), | |
| 1284 | 1284 | aggregateKind: "thread", |
| 1285 | aggregateId: ThreadId.makeUnsafe("thread-empty"), | |
| 1285 | aggregateId: ThreadId.make("thread-empty"), | |
| 1286 | 1286 | occurredAt: now, |
| 1287 | commandId: CommandId.makeUnsafe("cmd-empty-3"), | |
| 1287 | commandId: CommandId.make("cmd-empty-3"), | |
| 1288 | 1288 | causationEventId: null, |
| 1289 | correlationId: CorrelationId.makeUnsafe("cmd-empty-3"), | |
| 1289 | correlationId: CorrelationId.make("cmd-empty-3"), | |
| 1290 | 1290 | metadata: {}, |
| 1291 | 1291 | payload: { |
| 1292 | threadId: ThreadId.makeUnsafe("thread-empty"), | |
| 1293 | messageId: MessageId.makeUnsafe("assistant-empty"), | |
| 1292 | threadId: ThreadId.make("thread-empty"), | |
| 1293 | messageId: MessageId.make("assistant-empty"), | |
| 1294 | 1294 | role: "assistant", |
| 1295 | 1295 | text: "Hello", |
| 1296 | 1296 | turnId: null, |
| ... | ... | @@ -1302,17 +1302,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1302 | 1302 | |
| 1303 | 1303 | yield* eventStore.append({ |
| 1304 | 1304 | type: "thread.message-sent", |
| 1305 | eventId: EventId.makeUnsafe("evt-empty-4"), | |
| 1305 | eventId: EventId.make("evt-empty-4"), | |
| 1306 | 1306 | aggregateKind: "thread", |
| 1307 | aggregateId: ThreadId.makeUnsafe("thread-empty"), | |
| 1307 | aggregateId: ThreadId.make("thread-empty"), | |
| 1308 | 1308 | occurredAt: now, |
| 1309 | commandId: CommandId.makeUnsafe("cmd-empty-4"), | |
| 1309 | commandId: CommandId.make("cmd-empty-4"), | |
| 1310 | 1310 | causationEventId: null, |
| 1311 | correlationId: CorrelationId.makeUnsafe("cmd-empty-4"), | |
| 1311 | correlationId: CorrelationId.make("cmd-empty-4"), | |
| 1312 | 1312 | metadata: {}, |
| 1313 | 1313 | payload: { |
| 1314 | threadId: ThreadId.makeUnsafe("thread-empty"), | |
| 1315 | messageId: MessageId.makeUnsafe("assistant-empty"), | |
| 1314 | threadId: ThreadId.make("thread-empty"), | |
| 1315 | messageId: MessageId.make("assistant-empty"), | |
| 1316 | 1316 | role: "assistant", |
| 1317 | 1317 | text: " world", |
| 1318 | 1318 | turnId: null, |
| ... | ... | @@ -1324,17 +1324,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1324 | 1324 | |
| 1325 | 1325 | yield* eventStore.append({ |
| 1326 | 1326 | type: "thread.message-sent", |
| 1327 | eventId: EventId.makeUnsafe("evt-empty-5"), | |
| 1327 | eventId: EventId.make("evt-empty-5"), | |
| 1328 | 1328 | aggregateKind: "thread", |
| 1329 | aggregateId: ThreadId.makeUnsafe("thread-empty"), | |
| 1329 | aggregateId: ThreadId.make("thread-empty"), | |
| 1330 | 1330 | occurredAt: now, |
| 1331 | commandId: CommandId.makeUnsafe("cmd-empty-5"), | |
| 1331 | commandId: CommandId.make("cmd-empty-5"), | |
| 1332 | 1332 | causationEventId: null, |
| 1333 | correlationId: CorrelationId.makeUnsafe("cmd-empty-5"), | |
| 1333 | correlationId: CorrelationId.make("cmd-empty-5"), | |
| 1334 | 1334 | metadata: {}, |
| 1335 | 1335 | payload: { |
| 1336 | threadId: ThreadId.makeUnsafe("thread-empty"), | |
| 1337 | messageId: MessageId.makeUnsafe("assistant-empty"), | |
| 1336 | threadId: ThreadId.make("thread-empty"), | |
| 1337 | messageId: MessageId.make("assistant-empty"), | |
| 1338 | 1338 | role: "assistant", |
| 1339 | 1339 | text: "", |
| 1340 | 1340 | turnId: null, |
| ... | ... | @@ -1373,16 +1373,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1373 | 1373 | |
| 1374 | 1374 | yield* appendAndProject({ |
| 1375 | 1375 | type: "project.created", |
| 1376 | eventId: EventId.makeUnsafe("evt-conflict-1"), | |
| 1376 | eventId: EventId.make("evt-conflict-1"), | |
| 1377 | 1377 | aggregateKind: "project", |
| 1378 | aggregateId: ProjectId.makeUnsafe("project-conflict"), | |
| 1378 | aggregateId: ProjectId.make("project-conflict"), | |
| 1379 | 1379 | occurredAt: "2026-02-26T13:00:00.000Z", |
| 1380 | commandId: CommandId.makeUnsafe("cmd-conflict-1"), | |
| 1380 | commandId: CommandId.make("cmd-conflict-1"), | |
| 1381 | 1381 | causationEventId: null, |
| 1382 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-1"), | |
| 1382 | correlationId: CorrelationId.make("cmd-conflict-1"), | |
| 1383 | 1383 | metadata: {}, |
| 1384 | 1384 | payload: { |
| 1385 | projectId: ProjectId.makeUnsafe("project-conflict"), | |
| 1385 | projectId: ProjectId.make("project-conflict"), | |
| 1386 | 1386 | title: "Project Conflict", |
| 1387 | 1387 | workspaceRoot: "/tmp/project-conflict", |
| 1388 | 1388 | defaultModelSelection: null, |
| ... | ... | @@ -1394,17 +1394,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1394 | 1394 | |
| 1395 | 1395 | yield* appendAndProject({ |
| 1396 | 1396 | type: "thread.created", |
| 1397 | eventId: EventId.makeUnsafe("evt-conflict-2"), | |
| 1397 | eventId: EventId.make("evt-conflict-2"), | |
| 1398 | 1398 | aggregateKind: "thread", |
| 1399 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1399 | aggregateId: ThreadId.make("thread-conflict"), | |
| 1400 | 1400 | occurredAt: "2026-02-26T13:00:01.000Z", |
| 1401 | commandId: CommandId.makeUnsafe("cmd-conflict-2"), | |
| 1401 | commandId: CommandId.make("cmd-conflict-2"), | |
| 1402 | 1402 | causationEventId: null, |
| 1403 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-2"), | |
| 1403 | correlationId: CorrelationId.make("cmd-conflict-2"), | |
| 1404 | 1404 | metadata: {}, |
| 1405 | 1405 | payload: { |
| 1406 | threadId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1407 | projectId: ProjectId.makeUnsafe("project-conflict"), | |
| 1406 | threadId: ThreadId.make("thread-conflict"), | |
| 1407 | projectId: ProjectId.make("project-conflict"), | |
| 1408 | 1408 | title: "Thread Conflict", |
| 1409 | 1409 | modelSelection: { |
| 1410 | 1410 | provider: "codex", |
| ... | ... | @@ -1420,37 +1420,37 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1420 | 1420 | |
| 1421 | 1421 | yield* appendAndProject({ |
| 1422 | 1422 | type: "thread.turn-interrupt-requested", |
| 1423 | eventId: EventId.makeUnsafe("evt-conflict-3"), | |
| 1423 | eventId: EventId.make("evt-conflict-3"), | |
| 1424 | 1424 | aggregateKind: "thread", |
| 1425 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1425 | aggregateId: ThreadId.make("thread-conflict"), | |
| 1426 | 1426 | occurredAt: "2026-02-26T13:00:02.000Z", |
| 1427 | commandId: CommandId.makeUnsafe("cmd-conflict-3"), | |
| 1427 | commandId: CommandId.make("cmd-conflict-3"), | |
| 1428 | 1428 | causationEventId: null, |
| 1429 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-3"), | |
| 1429 | correlationId: CorrelationId.make("cmd-conflict-3"), | |
| 1430 | 1430 | metadata: {}, |
| 1431 | 1431 | payload: { |
| 1432 | threadId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1433 | turnId: TurnId.makeUnsafe("turn-interrupted"), | |
| 1432 | threadId: ThreadId.make("thread-conflict"), | |
| 1433 | turnId: TurnId.make("turn-interrupted"), | |
| 1434 | 1434 | createdAt: "2026-02-26T13:00:02.000Z", |
| 1435 | 1435 | }, |
| 1436 | 1436 | }); |
| 1437 | 1437 | |
| 1438 | 1438 | yield* appendAndProject({ |
| 1439 | 1439 | type: "thread.message-sent", |
| 1440 | eventId: EventId.makeUnsafe("evt-conflict-4"), | |
| 1440 | eventId: EventId.make("evt-conflict-4"), | |
| 1441 | 1441 | aggregateKind: "thread", |
| 1442 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1442 | aggregateId: ThreadId.make("thread-conflict"), | |
| 1443 | 1443 | occurredAt: "2026-02-26T13:00:03.000Z", |
| 1444 | commandId: CommandId.makeUnsafe("cmd-conflict-4"), | |
| 1444 | commandId: CommandId.make("cmd-conflict-4"), | |
| 1445 | 1445 | causationEventId: null, |
| 1446 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-4"), | |
| 1446 | correlationId: CorrelationId.make("cmd-conflict-4"), | |
| 1447 | 1447 | metadata: {}, |
| 1448 | 1448 | payload: { |
| 1449 | threadId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1450 | messageId: MessageId.makeUnsafe("assistant-conflict"), | |
| 1449 | threadId: ThreadId.make("thread-conflict"), | |
| 1450 | messageId: MessageId.make("assistant-conflict"), | |
| 1451 | 1451 | role: "assistant", |
| 1452 | 1452 | text: "done", |
| 1453 | turnId: TurnId.makeUnsafe("turn-completed"), | |
| 1453 | turnId: TurnId.make("turn-completed"), | |
| 1454 | 1454 | streaming: false, |
| 1455 | 1455 | createdAt: "2026-02-26T13:00:03.000Z", |
| 1456 | 1456 | updatedAt: "2026-02-26T13:00:03.000Z", |
| ... | ... | @@ -1459,22 +1459,22 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1459 | 1459 | |
| 1460 | 1460 | yield* appendAndProject({ |
| 1461 | 1461 | type: "thread.turn-diff-completed", |
| 1462 | eventId: EventId.makeUnsafe("evt-conflict-5"), | |
| 1462 | eventId: EventId.make("evt-conflict-5"), | |
| 1463 | 1463 | aggregateKind: "thread", |
| 1464 | aggregateId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1464 | aggregateId: ThreadId.make("thread-conflict"), | |
| 1465 | 1465 | occurredAt: "2026-02-26T13:00:04.000Z", |
| 1466 | commandId: CommandId.makeUnsafe("cmd-conflict-5"), | |
| 1466 | commandId: CommandId.make("cmd-conflict-5"), | |
| 1467 | 1467 | causationEventId: null, |
| 1468 | correlationId: CorrelationId.makeUnsafe("cmd-conflict-5"), | |
| 1468 | correlationId: CorrelationId.make("cmd-conflict-5"), | |
| 1469 | 1469 | metadata: {}, |
| 1470 | 1470 | payload: { |
| 1471 | threadId: ThreadId.makeUnsafe("thread-conflict"), | |
| 1472 | turnId: TurnId.makeUnsafe("turn-completed"), | |
| 1471 | threadId: ThreadId.make("thread-conflict"), | |
| 1472 | turnId: TurnId.make("turn-completed"), | |
| 1473 | 1473 | checkpointTurnCount: 1, |
| 1474 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-conflict/turn/1"), | |
| 1474 | checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-conflict/turn/1"), | |
| 1475 | 1475 | status: "ready", |
| 1476 | 1476 | files: [], |
| 1477 | assistantMessageId: MessageId.makeUnsafe("assistant-conflict"), | |
| 1477 | assistantMessageId: MessageId.make("assistant-conflict"), | |
| 1478 | 1478 | completedAt: "2026-02-26T13:00:04.000Z", |
| 1479 | 1479 | }, |
| 1480 | 1480 | }); |
| ... | ... | @@ -1517,16 +1517,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1517 | 1517 | |
| 1518 | 1518 | yield* appendAndProject({ |
| 1519 | 1519 | type: "project.created", |
| 1520 | eventId: EventId.makeUnsafe("evt-revert-1"), | |
| 1520 | eventId: EventId.make("evt-revert-1"), | |
| 1521 | 1521 | aggregateKind: "project", |
| 1522 | aggregateId: ProjectId.makeUnsafe("project-revert"), | |
| 1522 | aggregateId: ProjectId.make("project-revert"), | |
| 1523 | 1523 | occurredAt: "2026-02-26T12:00:00.000Z", |
| 1524 | commandId: CommandId.makeUnsafe("cmd-revert-1"), | |
| 1524 | commandId: CommandId.make("cmd-revert-1"), | |
| 1525 | 1525 | causationEventId: null, |
| 1526 | correlationId: CorrelationId.makeUnsafe("cmd-revert-1"), | |
| 1526 | correlationId: CorrelationId.make("cmd-revert-1"), | |
| 1527 | 1527 | metadata: {}, |
| 1528 | 1528 | payload: { |
| 1529 | projectId: ProjectId.makeUnsafe("project-revert"), | |
| 1529 | projectId: ProjectId.make("project-revert"), | |
| 1530 | 1530 | title: "Project Revert", |
| 1531 | 1531 | workspaceRoot: "/tmp/project-revert", |
| 1532 | 1532 | defaultModelSelection: null, |
| ... | ... | @@ -1538,17 +1538,17 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1538 | 1538 | |
| 1539 | 1539 | yield* appendAndProject({ |
| 1540 | 1540 | type: "thread.created", |
| 1541 | eventId: EventId.makeUnsafe("evt-revert-2"), | |
| 1541 | eventId: EventId.make("evt-revert-2"), | |
| 1542 | 1542 | aggregateKind: "thread", |
| 1543 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1543 | aggregateId: ThreadId.make("thread-revert"), | |
| 1544 | 1544 | occurredAt: "2026-02-26T12:00:01.000Z", |
| 1545 | commandId: CommandId.makeUnsafe("cmd-revert-2"), | |
| 1545 | commandId: CommandId.make("cmd-revert-2"), | |
| 1546 | 1546 | causationEventId: null, |
| 1547 | correlationId: CorrelationId.makeUnsafe("cmd-revert-2"), | |
| 1547 | correlationId: CorrelationId.make("cmd-revert-2"), | |
| 1548 | 1548 | metadata: {}, |
| 1549 | 1549 | payload: { |
| 1550 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1551 | projectId: ProjectId.makeUnsafe("project-revert"), | |
| 1550 | threadId: ThreadId.make("thread-revert"), | |
| 1551 | projectId: ProjectId.make("project-revert"), | |
| 1552 | 1552 | title: "Thread Revert", |
| 1553 | 1553 | modelSelection: { |
| 1554 | 1554 | provider: "codex", |
| ... | ... | @@ -1564,42 +1564,42 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1564 | 1564 | |
| 1565 | 1565 | yield* appendAndProject({ |
| 1566 | 1566 | type: "thread.turn-diff-completed", |
| 1567 | eventId: EventId.makeUnsafe("evt-revert-3"), | |
| 1567 | eventId: EventId.make("evt-revert-3"), | |
| 1568 | 1568 | aggregateKind: "thread", |
| 1569 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1569 | aggregateId: ThreadId.make("thread-revert"), | |
| 1570 | 1570 | occurredAt: "2026-02-26T12:00:02.000Z", |
| 1571 | commandId: CommandId.makeUnsafe("cmd-revert-3"), | |
| 1571 | commandId: CommandId.make("cmd-revert-3"), | |
| 1572 | 1572 | causationEventId: null, |
| 1573 | correlationId: CorrelationId.makeUnsafe("cmd-revert-3"), | |
| 1573 | correlationId: CorrelationId.make("cmd-revert-3"), | |
| 1574 | 1574 | metadata: {}, |
| 1575 | 1575 | payload: { |
| 1576 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1577 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1576 | threadId: ThreadId.make("thread-revert"), | |
| 1577 | turnId: TurnId.make("turn-1"), | |
| 1578 | 1578 | checkpointTurnCount: 1, |
| 1579 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert/turn/1"), | |
| 1579 | checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert/turn/1"), | |
| 1580 | 1580 | status: "ready", |
| 1581 | 1581 | files: [], |
| 1582 | assistantMessageId: MessageId.makeUnsafe("assistant-keep"), | |
| 1582 | assistantMessageId: MessageId.make("assistant-keep"), | |
| 1583 | 1583 | completedAt: "2026-02-26T12:00:02.000Z", |
| 1584 | 1584 | }, |
| 1585 | 1585 | }); |
| 1586 | 1586 | |
| 1587 | 1587 | yield* appendAndProject({ |
| 1588 | 1588 | type: "thread.message-sent", |
| 1589 | eventId: EventId.makeUnsafe("evt-revert-4"), | |
| 1589 | eventId: EventId.make("evt-revert-4"), | |
| 1590 | 1590 | aggregateKind: "thread", |
| 1591 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1591 | aggregateId: ThreadId.make("thread-revert"), | |
| 1592 | 1592 | occurredAt: "2026-02-26T12:00:02.100Z", |
| 1593 | commandId: CommandId.makeUnsafe("cmd-revert-4"), | |
| 1593 | commandId: CommandId.make("cmd-revert-4"), | |
| 1594 | 1594 | causationEventId: null, |
| 1595 | correlationId: CorrelationId.makeUnsafe("cmd-revert-4"), | |
| 1595 | correlationId: CorrelationId.make("cmd-revert-4"), | |
| 1596 | 1596 | metadata: {}, |
| 1597 | 1597 | payload: { |
| 1598 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1599 | messageId: MessageId.makeUnsafe("assistant-keep"), | |
| 1598 | threadId: ThreadId.make("thread-revert"), | |
| 1599 | messageId: MessageId.make("assistant-keep"), | |
| 1600 | 1600 | role: "assistant", |
| 1601 | 1601 | text: "kept", |
| 1602 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1602 | turnId: TurnId.make("turn-1"), | |
| 1603 | 1603 | streaming: false, |
| 1604 | 1604 | createdAt: "2026-02-26T12:00:02.100Z", |
| 1605 | 1605 | updatedAt: "2026-02-26T12:00:02.100Z", |
| ... | ... | @@ -1608,42 +1608,42 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1608 | 1608 | |
| 1609 | 1609 | yield* appendAndProject({ |
| 1610 | 1610 | type: "thread.turn-diff-completed", |
| 1611 | eventId: EventId.makeUnsafe("evt-revert-5"), | |
| 1611 | eventId: EventId.make("evt-revert-5"), | |
| 1612 | 1612 | aggregateKind: "thread", |
| 1613 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1613 | aggregateId: ThreadId.make("thread-revert"), | |
| 1614 | 1614 | occurredAt: "2026-02-26T12:00:03.000Z", |
| 1615 | commandId: CommandId.makeUnsafe("cmd-revert-5"), | |
| 1615 | commandId: CommandId.make("cmd-revert-5"), | |
| 1616 | 1616 | causationEventId: null, |
| 1617 | correlationId: CorrelationId.makeUnsafe("cmd-revert-5"), | |
| 1617 | correlationId: CorrelationId.make("cmd-revert-5"), | |
| 1618 | 1618 | metadata: {}, |
| 1619 | 1619 | payload: { |
| 1620 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1621 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 1620 | threadId: ThreadId.make("thread-revert"), | |
| 1621 | turnId: TurnId.make("turn-2"), | |
| 1622 | 1622 | checkpointTurnCount: 2, |
| 1623 | checkpointRef: CheckpointRef.makeUnsafe("refs/t3/checkpoints/thread-revert/turn/2"), | |
| 1623 | checkpointRef: CheckpointRef.make("refs/t3/checkpoints/thread-revert/turn/2"), | |
| 1624 | 1624 | status: "ready", |
| 1625 | 1625 | files: [], |
| 1626 | assistantMessageId: MessageId.makeUnsafe("assistant-remove"), | |
| 1626 | assistantMessageId: MessageId.make("assistant-remove"), | |
| 1627 | 1627 | completedAt: "2026-02-26T12:00:03.000Z", |
| 1628 | 1628 | }, |
| 1629 | 1629 | }); |
| 1630 | 1630 | |
| 1631 | 1631 | yield* appendAndProject({ |
| 1632 | 1632 | type: "thread.message-sent", |
| 1633 | eventId: EventId.makeUnsafe("evt-revert-6"), | |
| 1633 | eventId: EventId.make("evt-revert-6"), | |
| 1634 | 1634 | aggregateKind: "thread", |
| 1635 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1635 | aggregateId: ThreadId.make("thread-revert"), | |
| 1636 | 1636 | occurredAt: "2026-02-26T12:00:03.050Z", |
| 1637 | commandId: CommandId.makeUnsafe("cmd-revert-6"), | |
| 1637 | commandId: CommandId.make("cmd-revert-6"), | |
| 1638 | 1638 | causationEventId: null, |
| 1639 | correlationId: CorrelationId.makeUnsafe("cmd-revert-6"), | |
| 1639 | correlationId: CorrelationId.make("cmd-revert-6"), | |
| 1640 | 1640 | metadata: {}, |
| 1641 | 1641 | payload: { |
| 1642 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1643 | messageId: MessageId.makeUnsafe("user-remove"), | |
| 1642 | threadId: ThreadId.make("thread-revert"), | |
| 1643 | messageId: MessageId.make("user-remove"), | |
| 1644 | 1644 | role: "user", |
| 1645 | 1645 | text: "removed", |
| 1646 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 1646 | turnId: TurnId.make("turn-2"), | |
| 1647 | 1647 | streaming: false, |
| 1648 | 1648 | createdAt: "2026-02-26T12:00:03.050Z", |
| 1649 | 1649 | updatedAt: "2026-02-26T12:00:03.050Z", |
| ... | ... | @@ -1652,20 +1652,20 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1652 | 1652 | |
| 1653 | 1653 | yield* appendAndProject({ |
| 1654 | 1654 | type: "thread.message-sent", |
| 1655 | eventId: EventId.makeUnsafe("evt-revert-7"), | |
| 1655 | eventId: EventId.make("evt-revert-7"), | |
| 1656 | 1656 | aggregateKind: "thread", |
| 1657 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1657 | aggregateId: ThreadId.make("thread-revert"), | |
| 1658 | 1658 | occurredAt: "2026-02-26T12:00:03.100Z", |
| 1659 | commandId: CommandId.makeUnsafe("cmd-revert-7"), | |
| 1659 | commandId: CommandId.make("cmd-revert-7"), | |
| 1660 | 1660 | causationEventId: null, |
| 1661 | correlationId: CorrelationId.makeUnsafe("cmd-revert-7"), | |
| 1661 | correlationId: CorrelationId.make("cmd-revert-7"), | |
| 1662 | 1662 | metadata: {}, |
| 1663 | 1663 | payload: { |
| 1664 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1665 | messageId: MessageId.makeUnsafe("assistant-remove"), | |
| 1664 | threadId: ThreadId.make("thread-revert"), | |
| 1665 | messageId: MessageId.make("assistant-remove"), | |
| 1666 | 1666 | role: "assistant", |
| 1667 | 1667 | text: "removed", |
| 1668 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 1668 | turnId: TurnId.make("turn-2"), | |
| 1669 | 1669 | streaming: false, |
| 1670 | 1670 | createdAt: "2026-02-26T12:00:03.100Z", |
| 1671 | 1671 | updatedAt: "2026-02-26T12:00:03.100Z", |
| ... | ... | @@ -1674,16 +1674,16 @@ it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1674 | 1674 | |
| 1675 | 1675 | yield* appendAndProject({ |
| 1676 | 1676 | type: "thread.reverted", |
| 1677 | eventId: EventId.makeUnsafe("evt-revert-8"), | |
| 1677 | eventId: EventId.make("evt-revert-8"), | |
| 1678 | 1678 | aggregateKind: "thread", |
| 1679 | aggregateId: ThreadId.makeUnsafe("thread-revert"), | |
| 1679 | aggregateId: ThreadId.make("thread-revert"), | |
| 1680 | 1680 | occurredAt: "2026-02-26T12:00:04.000Z", |
| 1681 | commandId: CommandId.makeUnsafe("cmd-revert-8"), | |
| 1681 | commandId: CommandId.make("cmd-revert-8"), | |
| 1682 | 1682 | causationEventId: null, |
| 1683 | correlationId: CorrelationId.makeUnsafe("cmd-revert-8"), | |
| 1683 | correlationId: CorrelationId.make("cmd-revert-8"), | |
| 1684 | 1684 | metadata: {}, |
| 1685 | 1685 | payload: { |
| 1686 | threadId: ThreadId.makeUnsafe("thread-revert"), | |
| 1686 | threadId: ThreadId.make("thread-revert"), | |
| 1687 | 1687 | turnCount: 1, |
| 1688 | 1688 | }, |
| 1689 | 1689 | }); |
| ... | ... | @@ -1725,10 +1725,10 @@ it.effect("restores pending turn-start metadata across projection pipeline resta |
| 1725 | 1725 | Layer.provideMerge(persistenceLayer), |
| 1726 | 1726 | ); |
| 1727 | 1727 | |
| 1728 | const threadId = ThreadId.makeUnsafe("thread-restart"); | |
| 1729 | const turnId = TurnId.makeUnsafe("turn-restart"); | |
| 1730 | const messageId = MessageId.makeUnsafe("message-restart"); | |
| 1731 | const sourcePlanThreadId = ThreadId.makeUnsafe("thread-plan-source"); | |
| 1728 | const threadId = ThreadId.make("thread-restart"); | |
| 1729 | const turnId = TurnId.make("turn-restart"); | |
| 1730 | const messageId = MessageId.make("message-restart"); | |
| 1731 | const sourcePlanThreadId = ThreadId.make("thread-plan-source"); | |
| 1732 | 1732 | const sourcePlanId = "plan-source"; |
| 1733 | 1733 | const turnStartedAt = "2026-02-26T14:00:00.000Z"; |
| 1734 | 1734 | const sessionSetAt = "2026-02-26T14:00:05.000Z"; |
| ... | ... | @@ -1739,13 +1739,13 @@ it.effect("restores pending turn-start metadata across projection pipeline resta |
| 1739 | 1739 | |
| 1740 | 1740 | yield* eventStore.append({ |
| 1741 | 1741 | type: "thread.turn-start-requested", |
| 1742 | eventId: EventId.makeUnsafe("evt-restart-1"), | |
| 1742 | eventId: EventId.make("evt-restart-1"), | |
| 1743 | 1743 | aggregateKind: "thread", |
| 1744 | 1744 | aggregateId: threadId, |
| 1745 | 1745 | occurredAt: turnStartedAt, |
| 1746 | commandId: CommandId.makeUnsafe("cmd-restart-1"), | |
| 1746 | commandId: CommandId.make("cmd-restart-1"), | |
| 1747 | 1747 | causationEventId: null, |
| 1748 | correlationId: CorrelationId.makeUnsafe("cmd-restart-1"), | |
| 1748 | correlationId: CorrelationId.make("cmd-restart-1"), | |
| 1749 | 1749 | metadata: {}, |
| 1750 | 1750 | payload: { |
| 1751 | 1751 | threadId, |
| ... | ... | @@ -1769,13 +1769,13 @@ it.effect("restores pending turn-start metadata across projection pipeline resta |
| 1769 | 1769 | |
| 1770 | 1770 | yield* eventStore.append({ |
| 1771 | 1771 | type: "thread.session-set", |
| 1772 | eventId: EventId.makeUnsafe("evt-restart-2"), | |
| 1772 | eventId: EventId.make("evt-restart-2"), | |
| 1773 | 1773 | aggregateKind: "thread", |
| 1774 | 1774 | aggregateId: threadId, |
| 1775 | 1775 | occurredAt: sessionSetAt, |
| 1776 | commandId: CommandId.makeUnsafe("cmd-restart-2"), | |
| 1776 | commandId: CommandId.make("cmd-restart-2"), | |
| 1777 | 1777 | causationEventId: null, |
| 1778 | correlationId: CorrelationId.makeUnsafe("cmd-restart-2"), | |
| 1778 | correlationId: CorrelationId.make("cmd-restart-2"), | |
| 1779 | 1779 | metadata: {}, |
| 1780 | 1780 | payload: { |
| 1781 | 1781 | threadId, |
| ... | ... | @@ -1867,8 +1867,8 @@ engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => { |
| 1867 | 1867 | |
| 1868 | 1868 | yield* engine.dispatch({ |
| 1869 | 1869 | type: "project.create", |
| 1870 | commandId: CommandId.makeUnsafe("cmd-live-project"), | |
| 1871 | projectId: ProjectId.makeUnsafe("project-live"), | |
| 1870 | commandId: CommandId.make("cmd-live-project"), | |
| 1871 | projectId: ProjectId.make("project-live"), | |
| 1872 | 1872 | title: "Live Project", |
| 1873 | 1873 | workspaceRoot: "/tmp/project-live", |
| 1874 | 1874 | defaultModelSelection: { |
| ... | ... | @@ -1905,8 +1905,8 @@ engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => { |
| 1905 | 1905 | |
| 1906 | 1906 | yield* engine.dispatch({ |
| 1907 | 1907 | type: "project.create", |
| 1908 | commandId: CommandId.makeUnsafe("cmd-scripts-project-create"), | |
| 1909 | projectId: ProjectId.makeUnsafe("project-scripts"), | |
| 1908 | commandId: CommandId.make("cmd-scripts-project-create"), | |
| 1909 | projectId: ProjectId.make("project-scripts"), | |
| 1910 | 1910 | title: "Scripts Project", |
| 1911 | 1911 | workspaceRoot: "/tmp/project-scripts", |
| 1912 | 1912 | defaultModelSelection: { |
| ... | ... | @@ -1918,8 +1918,8 @@ engineLayer("OrchestrationProjectionPipeline via engine dispatch", (it) => { |
| 1918 | 1918 | |
| 1919 | 1919 | yield* engine.dispatch({ |
| 1920 | 1920 | type: "project.meta.update", |
| 1921 | commandId: CommandId.makeUnsafe("cmd-scripts-project-update"), | |
| 1922 | projectId: ProjectId.makeUnsafe("project-scripts"), | |
| 1921 | commandId: CommandId.make("cmd-scripts-project-update"), | |
| 1922 | projectId: ProjectId.make("project-scripts"), | |
| 1923 | 1923 | scripts: [ |
| 1924 | 1924 | { |
| 1925 | 1925 | id: "script-1", |
apps/server/src/orchestration/Layers/ProjectionPipeline.ts+1-1| ... | ... | @@ -86,7 +86,7 @@ function extractActivityRequestId(payload: unknown): ApprovalRequestId | null { |
| 86 | 86 | return null; |
| 87 | 87 | } |
| 88 | 88 | const requestId = (payload as Record<string, unknown>).requestId; |
| 89 | return typeof requestId === "string" ? ApprovalRequestId.makeUnsafe(requestId) : null; | |
| 89 | return typeof requestId === "string" ? ApprovalRequestId.make(requestId) : null; | |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | function retainProjectionMessagesAfterRevert( |
apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts+12-12| ... | ... | @@ -9,11 +9,11 @@ import { ORCHESTRATION_PROJECTOR_NAMES } from "./ProjectionPipeline.ts"; |
| 9 | 9 | import { OrchestrationProjectionSnapshotQueryLive } from "./ProjectionSnapshotQuery.ts"; |
| 10 | 10 | import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts"; |
| 11 | 11 | |
| 12 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 13 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 14 | const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value); | |
| 15 | const asEventId = (value: string): EventId => EventId.makeUnsafe(value); | |
| 16 | const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.makeUnsafe(value); | |
| 12 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 13 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 14 | const asMessageId = (value: string): MessageId => MessageId.make(value); | |
| 15 | const asEventId = (value: string): EventId => EventId.make(value); | |
| 16 | const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.make(value); | |
| 17 | 17 | |
| 18 | 18 | const projectionSnapshotLayer = it.layer( |
| 19 | 19 | OrchestrationProjectionSnapshotQueryLive.pipe( |
| ... | ... | @@ -259,7 +259,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { |
| 259 | 259 | ]); |
| 260 | 260 | assert.deepEqual(snapshot.threads, [ |
| 261 | 261 | { |
| 262 | id: ThreadId.makeUnsafe("thread-1"), | |
| 262 | id: ThreadId.make("thread-1"), | |
| 263 | 263 | projectId: asProjectId("project-1"), |
| 264 | 264 | title: "Thread 1", |
| 265 | 265 | modelSelection: { |
| ... | ... | @@ -278,7 +278,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { |
| 278 | 278 | completedAt: "2026-02-24T00:00:08.000Z", |
| 279 | 279 | assistantMessageId: asMessageId("message-1"), |
| 280 | 280 | sourceProposedPlan: { |
| 281 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 281 | threadId: ThreadId.make("thread-1"), | |
| 282 | 282 | planId: "plan-1", |
| 283 | 283 | }, |
| 284 | 284 | }, |
| ... | ... | @@ -303,7 +303,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { |
| 303 | 303 | turnId: asTurnId("turn-1"), |
| 304 | 304 | planMarkdown: "# Ship it", |
| 305 | 305 | implementedAt: "2026-02-24T00:00:05.500Z", |
| 306 | implementationThreadId: ThreadId.makeUnsafe("thread-2"), | |
| 306 | implementationThreadId: ThreadId.make("thread-2"), | |
| 307 | 307 | createdAt: "2026-02-24T00:00:05.000Z", |
| 308 | 308 | updatedAt: "2026-02-24T00:00:05.500Z", |
| 309 | 309 | }, |
| ... | ... | @@ -331,7 +331,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { |
| 331 | 331 | }, |
| 332 | 332 | ], |
| 333 | 333 | session: { |
| 334 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 334 | threadId: ThreadId.make("thread-1"), | |
| 335 | 335 | status: "running", |
| 336 | 336 | providerName: "codex", |
| 337 | 337 | runtimeMode: "approval-required", |
| ... | ... | @@ -473,7 +473,7 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { |
| 473 | 473 | ); |
| 474 | 474 | assert.equal(firstThreadId._tag, "Some"); |
| 475 | 475 | if (firstThreadId._tag === "Some") { |
| 476 | assert.equal(firstThreadId.value, ThreadId.makeUnsafe("thread-first")); | |
| 476 | assert.equal(firstThreadId.value, ThreadId.make("thread-first")); | |
| 477 | 477 | } |
| 478 | 478 | }), |
| 479 | 479 | ); |
| ... | ... | @@ -596,12 +596,12 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { |
| 596 | 596 | `; |
| 597 | 597 | |
| 598 | 598 | const context = yield* snapshotQuery.getThreadCheckpointContext( |
| 599 | ThreadId.makeUnsafe("thread-context"), | |
| 599 | ThreadId.make("thread-context"), | |
| 600 | 600 | ); |
| 601 | 601 | assert.equal(context._tag, "Some"); |
| 602 | 602 | if (context._tag === "Some") { |
| 603 | 603 | assert.deepEqual(context.value, { |
| 604 | threadId: ThreadId.makeUnsafe("thread-context"), | |
| 604 | threadId: ThreadId.make("thread-context"), | |
| 605 | 605 | projectId: asProjectId("project-context"), |
| 606 | 606 | workspaceRoot: "/tmp/context-workspace", |
| 607 | 607 | worktreePath: "/tmp/context-worktree", |
apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts+138-151| ... | ... | @@ -38,11 +38,10 @@ import { ProviderCommandReactor } from "../Services/ProviderCommandReactor.ts"; |
| 38 | 38 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 39 | 39 | import { ServerSettingsService } from "../../serverSettings.ts"; |
| 40 | 40 | |
| 41 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 42 | const asApprovalRequestId = (value: string): ApprovalRequestId => | |
| 43 | ApprovalRequestId.makeUnsafe(value); | |
| 44 | const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value); | |
| 45 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 41 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 42 | const asApprovalRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value); | |
| 43 | const asMessageId = (value: string): MessageId => MessageId.make(value); | |
| 44 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 46 | 45 | |
| 47 | 46 | const deriveServerPathsSync = (baseDir: string, devUrl: URL | undefined) => |
| 48 | 47 | Effect.runSync(deriveServerPaths(baseDir, devUrl).pipe(Effect.provide(NodeServices.layer))); |
| ... | ... | @@ -122,8 +121,8 @@ describe("ProviderCommandReactor", () => { |
| 122 | 121 | input !== null && |
| 123 | 122 | "threadId" in input && |
| 124 | 123 | typeof input.threadId === "string" |
| 125 | ? ThreadId.makeUnsafe(input.threadId) | |
| 126 | : ThreadId.makeUnsafe(`thread-${sessionIndex}`); | |
| 124 | ? ThreadId.make(input.threadId) | |
| 125 | : ThreadId.make(`thread-${sessionIndex}`); | |
| 127 | 126 | const session: ProviderSession = { |
| 128 | 127 | provider: modelSelection.provider, |
| 129 | 128 | status: "ready" as const, |
| ... | ... | @@ -145,7 +144,7 @@ describe("ProviderCommandReactor", () => { |
| 145 | 144 | }); |
| 146 | 145 | const sendTurn = vi.fn((_: unknown) => |
| 147 | 146 | Effect.succeed({ |
| 148 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 147 | threadId: ThreadId.make("thread-1"), | |
| 149 | 148 | turnId: asTurnId("turn-1"), |
| 150 | 149 | }), |
| 151 | 150 | ); |
| ... | ... | @@ -247,7 +246,7 @@ describe("ProviderCommandReactor", () => { |
| 247 | 246 | await Effect.runPromise( |
| 248 | 247 | engine.dispatch({ |
| 249 | 248 | type: "project.create", |
| 250 | commandId: CommandId.makeUnsafe("cmd-project-create"), | |
| 249 | commandId: CommandId.make("cmd-project-create"), | |
| 251 | 250 | projectId: asProjectId("project-1"), |
| 252 | 251 | title: "Provider Project", |
| 253 | 252 | workspaceRoot: "/tmp/provider-project", |
| ... | ... | @@ -258,8 +257,8 @@ describe("ProviderCommandReactor", () => { |
| 258 | 257 | await Effect.runPromise( |
| 259 | 258 | engine.dispatch({ |
| 260 | 259 | type: "thread.create", |
| 261 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 262 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 260 | commandId: CommandId.make("cmd-thread-create"), | |
| 261 | threadId: ThreadId.make("thread-1"), | |
| 263 | 262 | projectId: asProjectId("project-1"), |
| 264 | 263 | title: "Thread", |
| 265 | 264 | modelSelection: modelSelection, |
| ... | ... | @@ -294,8 +293,8 @@ describe("ProviderCommandReactor", () => { |
| 294 | 293 | await Effect.runPromise( |
| 295 | 294 | harness.engine.dispatch({ |
| 296 | 295 | type: "thread.turn.start", |
| 297 | commandId: CommandId.makeUnsafe("cmd-turn-start-1"), | |
| 298 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 296 | commandId: CommandId.make("cmd-turn-start-1"), | |
| 297 | threadId: ThreadId.make("thread-1"), | |
| 299 | 298 | message: { |
| 300 | 299 | messageId: asMessageId("user-message-1"), |
| 301 | 300 | role: "user", |
| ... | ... | @@ -310,7 +309,7 @@ describe("ProviderCommandReactor", () => { |
| 310 | 309 | |
| 311 | 310 | await waitFor(() => harness.startSession.mock.calls.length === 1); |
| 312 | 311 | await waitFor(() => harness.sendTurn.mock.calls.length === 1); |
| 313 | expect(harness.startSession.mock.calls[0]?.[0]).toEqual(ThreadId.makeUnsafe("thread-1")); | |
| 312 | expect(harness.startSession.mock.calls[0]?.[0]).toEqual(ThreadId.make("thread-1")); | |
| 314 | 313 | expect(harness.startSession.mock.calls[0]?.[1]).toMatchObject({ |
| 315 | 314 | cwd: "/tmp/provider-project", |
| 316 | 315 | modelSelection: { |
| ... | ... | @@ -321,7 +320,7 @@ describe("ProviderCommandReactor", () => { |
| 321 | 320 | }); |
| 322 | 321 | |
| 323 | 322 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 324 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 323 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 325 | 324 | expect(thread?.session?.threadId).toBe("thread-1"); |
| 326 | 325 | expect(thread?.session?.runtimeMode).toBe("approval-required"); |
| 327 | 326 | }); |
| ... | ... | @@ -335,8 +334,8 @@ describe("ProviderCommandReactor", () => { |
| 335 | 334 | await Effect.runPromise( |
| 336 | 335 | harness.engine.dispatch({ |
| 337 | 336 | type: "thread.meta.update", |
| 338 | commandId: CommandId.makeUnsafe("cmd-thread-title-seed"), | |
| 339 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 337 | commandId: CommandId.make("cmd-thread-title-seed"), | |
| 338 | threadId: ThreadId.make("thread-1"), | |
| 340 | 339 | title: seededTitle, |
| 341 | 340 | }), |
| 342 | 341 | ); |
| ... | ... | @@ -344,8 +343,8 @@ describe("ProviderCommandReactor", () => { |
| 344 | 343 | await Effect.runPromise( |
| 345 | 344 | harness.engine.dispatch({ |
| 346 | 345 | type: "thread.turn.start", |
| 347 | commandId: CommandId.makeUnsafe("cmd-turn-start-title"), | |
| 348 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 346 | commandId: CommandId.make("cmd-turn-start-title"), | |
| 347 | threadId: ThreadId.make("thread-1"), | |
| 349 | 348 | message: { |
| 350 | 349 | messageId: asMessageId("user-message-title"), |
| 351 | 350 | role: "user", |
| ... | ... | @@ -367,12 +366,12 @@ describe("ProviderCommandReactor", () => { |
| 367 | 366 | await waitFor(async () => { |
| 368 | 367 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 369 | 368 | return ( |
| 370 | readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"))?.title === | |
| 369 | readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.title === | |
| 371 | 370 | "Generated title" |
| 372 | 371 | ); |
| 373 | 372 | }); |
| 374 | 373 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 375 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 374 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 376 | 375 | expect(thread?.title).toBe("Generated title"); |
| 377 | 376 | }); |
| 378 | 377 | |
| ... | ... | @@ -384,8 +383,8 @@ describe("ProviderCommandReactor", () => { |
| 384 | 383 | await Effect.runPromise( |
| 385 | 384 | harness.engine.dispatch({ |
| 386 | 385 | type: "thread.meta.update", |
| 387 | commandId: CommandId.makeUnsafe("cmd-thread-title-custom"), | |
| 388 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 386 | commandId: CommandId.make("cmd-thread-title-custom"), | |
| 387 | threadId: ThreadId.make("thread-1"), | |
| 389 | 388 | title: "Keep this custom title", |
| 390 | 389 | }), |
| 391 | 390 | ); |
| ... | ... | @@ -393,8 +392,8 @@ describe("ProviderCommandReactor", () => { |
| 393 | 392 | await Effect.runPromise( |
| 394 | 393 | harness.engine.dispatch({ |
| 395 | 394 | type: "thread.turn.start", |
| 396 | commandId: CommandId.makeUnsafe("cmd-turn-start-title-preserve"), | |
| 397 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 395 | commandId: CommandId.make("cmd-turn-start-title-preserve"), | |
| 396 | threadId: ThreadId.make("thread-1"), | |
| 398 | 397 | message: { |
| 399 | 398 | messageId: asMessageId("user-message-title-preserve"), |
| 400 | 399 | role: "user", |
| ... | ... | @@ -412,7 +411,7 @@ describe("ProviderCommandReactor", () => { |
| 412 | 411 | expect(harness.generateThreadTitle).not.toHaveBeenCalled(); |
| 413 | 412 | |
| 414 | 413 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 415 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 414 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 416 | 415 | expect(thread?.title).toBe("Keep this custom title"); |
| 417 | 416 | }); |
| 418 | 417 | |
| ... | ... | @@ -429,8 +428,8 @@ describe("ProviderCommandReactor", () => { |
| 429 | 428 | await Effect.runPromise( |
| 430 | 429 | harness.engine.dispatch({ |
| 431 | 430 | type: "thread.meta.update", |
| 432 | commandId: CommandId.makeUnsafe("cmd-thread-title-formatted-seed"), | |
| 433 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 431 | commandId: CommandId.make("cmd-thread-title-formatted-seed"), | |
| 432 | threadId: ThreadId.make("thread-1"), | |
| 434 | 433 | title: seededTitle, |
| 435 | 434 | }), |
| 436 | 435 | ); |
| ... | ... | @@ -438,8 +437,8 @@ describe("ProviderCommandReactor", () => { |
| 438 | 437 | await Effect.runPromise( |
| 439 | 438 | harness.engine.dispatch({ |
| 440 | 439 | type: "thread.turn.start", |
| 441 | commandId: CommandId.makeUnsafe("cmd-turn-start-title-formatted"), | |
| 442 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 440 | commandId: CommandId.make("cmd-turn-start-title-formatted"), | |
| 441 | threadId: ThreadId.make("thread-1"), | |
| 443 | 442 | message: { |
| 444 | 443 | messageId: asMessageId("user-message-title-formatted"), |
| 445 | 444 | role: "user", |
| ... | ... | @@ -457,13 +456,13 @@ describe("ProviderCommandReactor", () => { |
| 457 | 456 | await waitFor(async () => { |
| 458 | 457 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 459 | 458 | return ( |
| 460 | readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1"))?.title === | |
| 459 | readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"))?.title === | |
| 461 | 460 | "Reconnect spinner resume bug" |
| 462 | 461 | ); |
| 463 | 462 | }); |
| 464 | 463 | |
| 465 | 464 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 466 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 465 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 467 | 466 | expect(thread?.title).toBe("Reconnect spinner resume bug"); |
| 468 | 467 | }); |
| 469 | 468 | |
| ... | ... | @@ -474,8 +473,8 @@ describe("ProviderCommandReactor", () => { |
| 474 | 473 | await Effect.runPromise( |
| 475 | 474 | harness.engine.dispatch({ |
| 476 | 475 | type: "thread.meta.update", |
| 477 | commandId: CommandId.makeUnsafe("cmd-thread-branch"), | |
| 478 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 476 | commandId: CommandId.make("cmd-thread-branch"), | |
| 477 | threadId: ThreadId.make("thread-1"), | |
| 479 | 478 | branch: "t3code/1234abcd", |
| 480 | 479 | worktreePath: "/tmp/provider-project-worktree", |
| 481 | 480 | }), |
| ... | ... | @@ -499,8 +498,8 @@ describe("ProviderCommandReactor", () => { |
| 499 | 498 | await Effect.runPromise( |
| 500 | 499 | harness.engine.dispatch({ |
| 501 | 500 | type: "thread.turn.start", |
| 502 | commandId: CommandId.makeUnsafe("cmd-turn-start-branch-model"), | |
| 503 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 501 | commandId: CommandId.make("cmd-turn-start-branch-model"), | |
| 502 | threadId: ThreadId.make("thread-1"), | |
| 504 | 503 | message: { |
| 505 | 504 | messageId: asMessageId("user-message-branch-model"), |
| 506 | 505 | role: "user", |
| ... | ... | @@ -526,8 +525,8 @@ describe("ProviderCommandReactor", () => { |
| 526 | 525 | await Effect.runPromise( |
| 527 | 526 | harness.engine.dispatch({ |
| 528 | 527 | type: "thread.turn.start", |
| 529 | commandId: CommandId.makeUnsafe("cmd-turn-start-fast"), | |
| 530 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 528 | commandId: CommandId.make("cmd-turn-start-fast"), | |
| 529 | threadId: ThreadId.make("thread-1"), | |
| 531 | 530 | message: { |
| 532 | 531 | messageId: asMessageId("user-message-fast"), |
| 533 | 532 | role: "user", |
| ... | ... | @@ -561,7 +560,7 @@ describe("ProviderCommandReactor", () => { |
| 561 | 560 | }, |
| 562 | 561 | }); |
| 563 | 562 | expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ |
| 564 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 563 | threadId: ThreadId.make("thread-1"), | |
| 565 | 564 | modelSelection: { |
| 566 | 565 | provider: "codex", |
| 567 | 566 | model: "gpt-5.3-codex", |
| ... | ... | @@ -582,8 +581,8 @@ describe("ProviderCommandReactor", () => { |
| 582 | 581 | await Effect.runPromise( |
| 583 | 582 | harness.engine.dispatch({ |
| 584 | 583 | type: "thread.turn.start", |
| 585 | commandId: CommandId.makeUnsafe("cmd-turn-start-claude-effort"), | |
| 586 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 584 | commandId: CommandId.make("cmd-turn-start-claude-effort"), | |
| 585 | threadId: ThreadId.make("thread-1"), | |
| 587 | 586 | message: { |
| 588 | 587 | messageId: asMessageId("user-message-claude-effort"), |
| 589 | 588 | role: "user", |
| ... | ... | @@ -615,7 +614,7 @@ describe("ProviderCommandReactor", () => { |
| 615 | 614 | }, |
| 616 | 615 | }); |
| 617 | 616 | expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ |
| 618 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 617 | threadId: ThreadId.make("thread-1"), | |
| 619 | 618 | modelSelection: { |
| 620 | 619 | provider: "claudeAgent", |
| 621 | 620 | model: "claude-sonnet-4-6", |
| ... | ... | @@ -635,8 +634,8 @@ describe("ProviderCommandReactor", () => { |
| 635 | 634 | await Effect.runPromise( |
| 636 | 635 | harness.engine.dispatch({ |
| 637 | 636 | type: "thread.turn.start", |
| 638 | commandId: CommandId.makeUnsafe("cmd-turn-start-claude-fast-mode"), | |
| 639 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 637 | commandId: CommandId.make("cmd-turn-start-claude-fast-mode"), | |
| 638 | threadId: ThreadId.make("thread-1"), | |
| 640 | 639 | message: { |
| 641 | 640 | messageId: asMessageId("user-message-claude-fast-mode"), |
| 642 | 641 | role: "user", |
| ... | ... | @@ -668,7 +667,7 @@ describe("ProviderCommandReactor", () => { |
| 668 | 667 | }, |
| 669 | 668 | }); |
| 670 | 669 | expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ |
| 671 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 670 | threadId: ThreadId.make("thread-1"), | |
| 672 | 671 | modelSelection: { |
| 673 | 672 | provider: "claudeAgent", |
| 674 | 673 | model: "claude-opus-4-6", |
| ... | ... | @@ -686,8 +685,8 @@ describe("ProviderCommandReactor", () => { |
| 686 | 685 | await Effect.runPromise( |
| 687 | 686 | harness.engine.dispatch({ |
| 688 | 687 | type: "thread.interaction-mode.set", |
| 689 | commandId: CommandId.makeUnsafe("cmd-interaction-mode-set-plan"), | |
| 690 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 688 | commandId: CommandId.make("cmd-interaction-mode-set-plan"), | |
| 689 | threadId: ThreadId.make("thread-1"), | |
| 691 | 690 | interactionMode: "plan", |
| 692 | 691 | createdAt: now, |
| 693 | 692 | }), |
| ... | ... | @@ -696,8 +695,8 @@ describe("ProviderCommandReactor", () => { |
| 696 | 695 | await Effect.runPromise( |
| 697 | 696 | harness.engine.dispatch({ |
| 698 | 697 | type: "thread.turn.start", |
| 699 | commandId: CommandId.makeUnsafe("cmd-turn-start-plan"), | |
| 700 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 698 | commandId: CommandId.make("cmd-turn-start-plan"), | |
| 699 | threadId: ThreadId.make("thread-1"), | |
| 701 | 700 | message: { |
| 702 | 701 | messageId: asMessageId("user-message-plan"), |
| 703 | 702 | role: "user", |
| ... | ... | @@ -712,7 +711,7 @@ describe("ProviderCommandReactor", () => { |
| 712 | 711 | |
| 713 | 712 | await waitFor(() => harness.sendTurn.mock.calls.length === 1); |
| 714 | 713 | expect(harness.sendTurn.mock.calls[0]?.[0]).toMatchObject({ |
| 715 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 714 | threadId: ThreadId.make("thread-1"), | |
| 716 | 715 | interactionMode: "plan", |
| 717 | 716 | }); |
| 718 | 717 | }); |
| ... | ... | @@ -726,8 +725,8 @@ describe("ProviderCommandReactor", () => { |
| 726 | 725 | await Effect.runPromise( |
| 727 | 726 | harness.engine.dispatch({ |
| 728 | 727 | type: "thread.turn.start", |
| 729 | commandId: CommandId.makeUnsafe("cmd-turn-start-provider-first"), | |
| 730 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 728 | commandId: CommandId.make("cmd-turn-start-provider-first"), | |
| 729 | threadId: ThreadId.make("thread-1"), | |
| 731 | 730 | message: { |
| 732 | 731 | messageId: asMessageId("user-message-provider-first"), |
| 733 | 732 | role: "user", |
| ... | ... | @@ -746,9 +745,7 @@ describe("ProviderCommandReactor", () => { |
| 746 | 745 | |
| 747 | 746 | await waitFor(async () => { |
| 748 | 747 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 749 | const thread = readModel.threads.find( | |
| 750 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 751 | ); | |
| 748 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 752 | 749 | return ( |
| 753 | 750 | thread?.activities.some((activity) => activity.kind === "provider.turn.start.failed") ?? |
| 754 | 751 | false |
| ... | ... | @@ -759,7 +756,7 @@ describe("ProviderCommandReactor", () => { |
| 759 | 756 | expect(harness.sendTurn).not.toHaveBeenCalled(); |
| 760 | 757 | |
| 761 | 758 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 762 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 759 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 763 | 760 | expect(thread?.session).toBeNull(); |
| 764 | 761 | expect( |
| 765 | 762 | thread?.activities.find((activity) => activity.kind === "provider.turn.start.failed"), |
| ... | ... | @@ -778,8 +775,8 @@ describe("ProviderCommandReactor", () => { |
| 778 | 775 | await Effect.runPromise( |
| 779 | 776 | harness.engine.dispatch({ |
| 780 | 777 | type: "thread.turn.start", |
| 781 | commandId: CommandId.makeUnsafe("cmd-turn-start-unsupported-1"), | |
| 782 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 778 | commandId: CommandId.make("cmd-turn-start-unsupported-1"), | |
| 779 | threadId: ThreadId.make("thread-1"), | |
| 783 | 780 | message: { |
| 784 | 781 | messageId: asMessageId("user-message-unsupported-1"), |
| 785 | 782 | role: "user", |
| ... | ... | @@ -797,8 +794,8 @@ describe("ProviderCommandReactor", () => { |
| 797 | 794 | await Effect.runPromise( |
| 798 | 795 | harness.engine.dispatch({ |
| 799 | 796 | type: "thread.turn.start", |
| 800 | commandId: CommandId.makeUnsafe("cmd-turn-start-unsupported-2"), | |
| 801 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 797 | commandId: CommandId.make("cmd-turn-start-unsupported-2"), | |
| 798 | threadId: ThreadId.make("thread-1"), | |
| 802 | 799 | message: { |
| 803 | 800 | messageId: asMessageId("user-message-unsupported-2"), |
| 804 | 801 | role: "user", |
| ... | ... | @@ -814,7 +811,7 @@ describe("ProviderCommandReactor", () => { |
| 814 | 811 | await waitFor(() => harness.sendTurn.mock.calls.length === 2); |
| 815 | 812 | |
| 816 | 813 | expect(harness.sendTurn.mock.calls[1]?.[0]).toMatchObject({ |
| 817 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 814 | threadId: ThreadId.make("thread-1"), | |
| 818 | 815 | modelSelection: { |
| 819 | 816 | provider: "codex", |
| 820 | 817 | model: "gpt-5-codex", |
| ... | ... | @@ -829,8 +826,8 @@ describe("ProviderCommandReactor", () => { |
| 829 | 826 | await Effect.runPromise( |
| 830 | 827 | harness.engine.dispatch({ |
| 831 | 828 | type: "thread.turn.start", |
| 832 | commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-1"), | |
| 833 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 829 | commandId: CommandId.make("cmd-turn-start-unchanged-1"), | |
| 830 | threadId: ThreadId.make("thread-1"), | |
| 834 | 831 | message: { |
| 835 | 832 | messageId: asMessageId("user-message-unchanged-1"), |
| 836 | 833 | role: "user", |
| ... | ... | @@ -849,8 +846,8 @@ describe("ProviderCommandReactor", () => { |
| 849 | 846 | await Effect.runPromise( |
| 850 | 847 | harness.engine.dispatch({ |
| 851 | 848 | type: "thread.turn.start", |
| 852 | commandId: CommandId.makeUnsafe("cmd-turn-start-unchanged-2"), | |
| 853 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 849 | commandId: CommandId.make("cmd-turn-start-unchanged-2"), | |
| 850 | threadId: ThreadId.make("thread-1"), | |
| 854 | 851 | message: { |
| 855 | 852 | messageId: asMessageId("user-message-unchanged-2"), |
| 856 | 853 | role: "user", |
| ... | ... | @@ -877,8 +874,8 @@ describe("ProviderCommandReactor", () => { |
| 877 | 874 | await Effect.runPromise( |
| 878 | 875 | harness.engine.dispatch({ |
| 879 | 876 | type: "thread.turn.start", |
| 880 | commandId: CommandId.makeUnsafe("cmd-turn-start-claude-effort-1"), | |
| 881 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 877 | commandId: CommandId.make("cmd-turn-start-claude-effort-1"), | |
| 878 | threadId: ThreadId.make("thread-1"), | |
| 882 | 879 | message: { |
| 883 | 880 | messageId: asMessageId("user-message-claude-effort-1"), |
| 884 | 881 | role: "user", |
| ... | ... | @@ -904,8 +901,8 @@ describe("ProviderCommandReactor", () => { |
| 904 | 901 | await Effect.runPromise( |
| 905 | 902 | harness.engine.dispatch({ |
| 906 | 903 | type: "thread.turn.start", |
| 907 | commandId: CommandId.makeUnsafe("cmd-turn-start-claude-effort-2"), | |
| 908 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 904 | commandId: CommandId.make("cmd-turn-start-claude-effort-2"), | |
| 905 | threadId: ThreadId.make("thread-1"), | |
| 909 | 906 | message: { |
| 910 | 907 | messageId: asMessageId("user-message-claude-effort-2"), |
| 911 | 908 | role: "user", |
| ... | ... | @@ -946,8 +943,8 @@ describe("ProviderCommandReactor", () => { |
| 946 | 943 | await Effect.runPromise( |
| 947 | 944 | harness.engine.dispatch({ |
| 948 | 945 | type: "thread.runtime-mode.set", |
| 949 | commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-initial-full-access"), | |
| 950 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 946 | commandId: CommandId.make("cmd-runtime-mode-set-initial-full-access"), | |
| 947 | threadId: ThreadId.make("thread-1"), | |
| 951 | 948 | runtimeMode: "full-access", |
| 952 | 949 | createdAt: now, |
| 953 | 950 | }), |
| ... | ... | @@ -956,8 +953,8 @@ describe("ProviderCommandReactor", () => { |
| 956 | 953 | await Effect.runPromise( |
| 957 | 954 | harness.engine.dispatch({ |
| 958 | 955 | type: "thread.turn.start", |
| 959 | commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-1"), | |
| 960 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 956 | commandId: CommandId.make("cmd-turn-start-runtime-mode-1"), | |
| 957 | threadId: ThreadId.make("thread-1"), | |
| 961 | 958 | message: { |
| 962 | 959 | messageId: asMessageId("user-message-runtime-mode-1"), |
| 963 | 960 | role: "user", |
| ... | ... | @@ -976,8 +973,8 @@ describe("ProviderCommandReactor", () => { |
| 976 | 973 | await Effect.runPromise( |
| 977 | 974 | harness.engine.dispatch({ |
| 978 | 975 | type: "thread.runtime-mode.set", |
| 979 | commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-1"), | |
| 980 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 976 | commandId: CommandId.make("cmd-runtime-mode-set-1"), | |
| 977 | threadId: ThreadId.make("thread-1"), | |
| 981 | 978 | runtimeMode: "approval-required", |
| 982 | 979 | createdAt: now, |
| 983 | 980 | }), |
| ... | ... | @@ -985,17 +982,15 @@ describe("ProviderCommandReactor", () => { |
| 985 | 982 | |
| 986 | 983 | await waitFor(async () => { |
| 987 | 984 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 988 | const thread = readModel.threads.find( | |
| 989 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 990 | ); | |
| 985 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 991 | 986 | return thread?.runtimeMode === "approval-required"; |
| 992 | 987 | }); |
| 993 | 988 | await waitFor(() => harness.startSession.mock.calls.length === 2); |
| 994 | 989 | await Effect.runPromise( |
| 995 | 990 | harness.engine.dispatch({ |
| 996 | 991 | type: "thread.turn.start", |
| 997 | commandId: CommandId.makeUnsafe("cmd-turn-start-runtime-mode-2"), | |
| 998 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 992 | commandId: CommandId.make("cmd-turn-start-runtime-mode-2"), | |
| 993 | threadId: ThreadId.make("thread-1"), | |
| 999 | 994 | message: { |
| 1000 | 995 | messageId: asMessageId("user-message-runtime-mode-2"), |
| 1001 | 996 | role: "user", |
| ... | ... | @@ -1012,16 +1007,16 @@ describe("ProviderCommandReactor", () => { |
| 1012 | 1007 | |
| 1013 | 1008 | expect(harness.stopSession.mock.calls.length).toBe(0); |
| 1014 | 1009 | expect(harness.startSession.mock.calls[1]?.[1]).toMatchObject({ |
| 1015 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1010 | threadId: ThreadId.make("thread-1"), | |
| 1016 | 1011 | resumeCursor: { opaque: "resume-1" }, |
| 1017 | 1012 | runtimeMode: "approval-required", |
| 1018 | 1013 | }); |
| 1019 | 1014 | expect(harness.sendTurn.mock.calls[1]?.[0]).toMatchObject({ |
| 1020 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1015 | threadId: ThreadId.make("thread-1"), | |
| 1021 | 1016 | }); |
| 1022 | 1017 | |
| 1023 | 1018 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1024 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1019 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1025 | 1020 | expect(thread?.session?.threadId).toBe("thread-1"); |
| 1026 | 1021 | expect(thread?.session?.runtimeMode).toBe("approval-required"); |
| 1027 | 1022 | }); |
| ... | ... | @@ -1035,10 +1030,10 @@ describe("ProviderCommandReactor", () => { |
| 1035 | 1030 | await Effect.runPromise( |
| 1036 | 1031 | harness.engine.dispatch({ |
| 1037 | 1032 | type: "thread.session.set", |
| 1038 | commandId: CommandId.makeUnsafe("cmd-session-set-runtime-mode-claude"), | |
| 1039 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1033 | commandId: CommandId.make("cmd-session-set-runtime-mode-claude"), | |
| 1034 | threadId: ThreadId.make("thread-1"), | |
| 1040 | 1035 | session: { |
| 1041 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1036 | threadId: ThreadId.make("thread-1"), | |
| 1042 | 1037 | status: "ready", |
| 1043 | 1038 | providerName: "claudeAgent", |
| 1044 | 1039 | runtimeMode: "full-access", |
| ... | ... | @@ -1053,8 +1048,8 @@ describe("ProviderCommandReactor", () => { |
| 1053 | 1048 | await Effect.runPromise( |
| 1054 | 1049 | harness.engine.dispatch({ |
| 1055 | 1050 | type: "thread.runtime-mode.set", |
| 1056 | commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-claude-no-options"), | |
| 1057 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1051 | commandId: CommandId.make("cmd-runtime-mode-set-claude-no-options"), | |
| 1052 | threadId: ThreadId.make("thread-1"), | |
| 1058 | 1053 | runtimeMode: "approval-required", |
| 1059 | 1054 | createdAt: now, |
| 1060 | 1055 | }), |
| ... | ... | @@ -1078,8 +1073,8 @@ describe("ProviderCommandReactor", () => { |
| 1078 | 1073 | await Effect.runPromise( |
| 1079 | 1074 | harness.engine.dispatch({ |
| 1080 | 1075 | type: "thread.turn.start", |
| 1081 | commandId: CommandId.makeUnsafe("cmd-turn-start-provider-switch-1"), | |
| 1082 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1076 | commandId: CommandId.make("cmd-turn-start-provider-switch-1"), | |
| 1077 | threadId: ThreadId.make("thread-1"), | |
| 1083 | 1078 | message: { |
| 1084 | 1079 | messageId: asMessageId("user-message-provider-switch-1"), |
| 1085 | 1080 | role: "user", |
| ... | ... | @@ -1098,8 +1093,8 @@ describe("ProviderCommandReactor", () => { |
| 1098 | 1093 | await Effect.runPromise( |
| 1099 | 1094 | harness.engine.dispatch({ |
| 1100 | 1095 | type: "thread.turn.start", |
| 1101 | commandId: CommandId.makeUnsafe("cmd-turn-start-provider-switch-2"), | |
| 1102 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1096 | commandId: CommandId.make("cmd-turn-start-provider-switch-2"), | |
| 1097 | threadId: ThreadId.make("thread-1"), | |
| 1103 | 1098 | message: { |
| 1104 | 1099 | messageId: asMessageId("user-message-provider-switch-2"), |
| 1105 | 1100 | role: "user", |
| ... | ... | @@ -1118,9 +1113,7 @@ describe("ProviderCommandReactor", () => { |
| 1118 | 1113 | |
| 1119 | 1114 | await waitFor(async () => { |
| 1120 | 1115 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1121 | const thread = readModel.threads.find( | |
| 1122 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 1123 | ); | |
| 1116 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1124 | 1117 | return ( |
| 1125 | 1118 | thread?.activities.some((activity) => activity.kind === "provider.turn.start.failed") ?? |
| 1126 | 1119 | false |
| ... | ... | @@ -1132,7 +1125,7 @@ describe("ProviderCommandReactor", () => { |
| 1132 | 1125 | expect(harness.stopSession.mock.calls.length).toBe(0); |
| 1133 | 1126 | |
| 1134 | 1127 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1135 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1128 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1136 | 1129 | expect(thread?.session?.threadId).toBe("thread-1"); |
| 1137 | 1130 | expect(thread?.session?.providerName).toBe("codex"); |
| 1138 | 1131 | expect(thread?.session?.runtimeMode).toBe("approval-required"); |
| ... | ... | @@ -1152,8 +1145,8 @@ describe("ProviderCommandReactor", () => { |
| 1152 | 1145 | await Effect.runPromise( |
| 1153 | 1146 | harness.engine.dispatch({ |
| 1154 | 1147 | type: "thread.runtime-mode.set", |
| 1155 | commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-initial-full-access-2"), | |
| 1156 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1148 | commandId: CommandId.make("cmd-runtime-mode-set-initial-full-access-2"), | |
| 1149 | threadId: ThreadId.make("thread-1"), | |
| 1157 | 1150 | runtimeMode: "full-access", |
| 1158 | 1151 | createdAt: now, |
| 1159 | 1152 | }), |
| ... | ... | @@ -1162,8 +1155,8 @@ describe("ProviderCommandReactor", () => { |
| 1162 | 1155 | await Effect.runPromise( |
| 1163 | 1156 | harness.engine.dispatch({ |
| 1164 | 1157 | type: "thread.turn.start", |
| 1165 | commandId: CommandId.makeUnsafe("cmd-turn-start-restart-failure-1"), | |
| 1166 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1158 | commandId: CommandId.make("cmd-turn-start-restart-failure-1"), | |
| 1159 | threadId: ThreadId.make("thread-1"), | |
| 1167 | 1160 | message: { |
| 1168 | 1161 | messageId: asMessageId("user-message-restart-failure-1"), |
| 1169 | 1162 | role: "user", |
| ... | ... | @@ -1186,8 +1179,8 @@ describe("ProviderCommandReactor", () => { |
| 1186 | 1179 | await Effect.runPromise( |
| 1187 | 1180 | harness.engine.dispatch({ |
| 1188 | 1181 | type: "thread.runtime-mode.set", |
| 1189 | commandId: CommandId.makeUnsafe("cmd-runtime-mode-set-restart-failure"), | |
| 1190 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1182 | commandId: CommandId.make("cmd-runtime-mode-set-restart-failure"), | |
| 1183 | threadId: ThreadId.make("thread-1"), | |
| 1191 | 1184 | runtimeMode: "approval-required", |
| 1192 | 1185 | createdAt: now, |
| 1193 | 1186 | }), |
| ... | ... | @@ -1195,9 +1188,7 @@ describe("ProviderCommandReactor", () => { |
| 1195 | 1188 | |
| 1196 | 1189 | await waitFor(async () => { |
| 1197 | 1190 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1198 | const thread = readModel.threads.find( | |
| 1199 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 1200 | ); | |
| 1191 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1201 | 1192 | return thread?.runtimeMode === "approval-required"; |
| 1202 | 1193 | }); |
| 1203 | 1194 | await waitFor(() => harness.startSession.mock.calls.length === 2); |
| ... | ... | @@ -1207,7 +1198,7 @@ describe("ProviderCommandReactor", () => { |
| 1207 | 1198 | expect(harness.sendTurn.mock.calls.length).toBe(1); |
| 1208 | 1199 | |
| 1209 | 1200 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1210 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1201 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1211 | 1202 | expect(thread?.session?.threadId).toBe("thread-1"); |
| 1212 | 1203 | expect(thread?.session?.runtimeMode).toBe("full-access"); |
| 1213 | 1204 | }); |
| ... | ... | @@ -1219,10 +1210,10 @@ describe("ProviderCommandReactor", () => { |
| 1219 | 1210 | await Effect.runPromise( |
| 1220 | 1211 | harness.engine.dispatch({ |
| 1221 | 1212 | type: "thread.session.set", |
| 1222 | commandId: CommandId.makeUnsafe("cmd-session-set"), | |
| 1223 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1213 | commandId: CommandId.make("cmd-session-set"), | |
| 1214 | threadId: ThreadId.make("thread-1"), | |
| 1224 | 1215 | session: { |
| 1225 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1216 | threadId: ThreadId.make("thread-1"), | |
| 1226 | 1217 | status: "running", |
| 1227 | 1218 | providerName: "codex", |
| 1228 | 1219 | runtimeMode: "approval-required", |
| ... | ... | @@ -1237,8 +1228,8 @@ describe("ProviderCommandReactor", () => { |
| 1237 | 1228 | await Effect.runPromise( |
| 1238 | 1229 | harness.engine.dispatch({ |
| 1239 | 1230 | type: "thread.turn.interrupt", |
| 1240 | commandId: CommandId.makeUnsafe("cmd-turn-interrupt"), | |
| 1241 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1231 | commandId: CommandId.make("cmd-turn-interrupt"), | |
| 1232 | threadId: ThreadId.make("thread-1"), | |
| 1242 | 1233 | turnId: asTurnId("turn-1"), |
| 1243 | 1234 | createdAt: now, |
| 1244 | 1235 | }), |
| ... | ... | @@ -1257,10 +1248,10 @@ describe("ProviderCommandReactor", () => { |
| 1257 | 1248 | await Effect.runPromise( |
| 1258 | 1249 | harness.engine.dispatch({ |
| 1259 | 1250 | type: "thread.session.set", |
| 1260 | commandId: CommandId.makeUnsafe("cmd-session-set-for-approval"), | |
| 1261 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1251 | commandId: CommandId.make("cmd-session-set-for-approval"), | |
| 1252 | threadId: ThreadId.make("thread-1"), | |
| 1262 | 1253 | session: { |
| 1263 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1254 | threadId: ThreadId.make("thread-1"), | |
| 1264 | 1255 | status: "running", |
| 1265 | 1256 | providerName: "codex", |
| 1266 | 1257 | runtimeMode: "approval-required", |
| ... | ... | @@ -1275,8 +1266,8 @@ describe("ProviderCommandReactor", () => { |
| 1275 | 1266 | await Effect.runPromise( |
| 1276 | 1267 | harness.engine.dispatch({ |
| 1277 | 1268 | type: "thread.approval.respond", |
| 1278 | commandId: CommandId.makeUnsafe("cmd-approval-respond"), | |
| 1279 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1269 | commandId: CommandId.make("cmd-approval-respond"), | |
| 1270 | threadId: ThreadId.make("thread-1"), | |
| 1280 | 1271 | requestId: asApprovalRequestId("approval-request-1"), |
| 1281 | 1272 | decision: "accept", |
| 1282 | 1273 | createdAt: now, |
| ... | ... | @@ -1298,10 +1289,10 @@ describe("ProviderCommandReactor", () => { |
| 1298 | 1289 | await Effect.runPromise( |
| 1299 | 1290 | harness.engine.dispatch({ |
| 1300 | 1291 | type: "thread.session.set", |
| 1301 | commandId: CommandId.makeUnsafe("cmd-session-set-for-user-input"), | |
| 1302 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1292 | commandId: CommandId.make("cmd-session-set-for-user-input"), | |
| 1293 | threadId: ThreadId.make("thread-1"), | |
| 1303 | 1294 | session: { |
| 1304 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1295 | threadId: ThreadId.make("thread-1"), | |
| 1305 | 1296 | status: "running", |
| 1306 | 1297 | providerName: "codex", |
| 1307 | 1298 | runtimeMode: "approval-required", |
| ... | ... | @@ -1316,8 +1307,8 @@ describe("ProviderCommandReactor", () => { |
| 1316 | 1307 | await Effect.runPromise( |
| 1317 | 1308 | harness.engine.dispatch({ |
| 1318 | 1309 | type: "thread.user-input.respond", |
| 1319 | commandId: CommandId.makeUnsafe("cmd-user-input-respond"), | |
| 1320 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1310 | commandId: CommandId.make("cmd-user-input-respond"), | |
| 1311 | threadId: ThreadId.make("thread-1"), | |
| 1321 | 1312 | requestId: asApprovalRequestId("user-input-request-1"), |
| 1322 | 1313 | answers: { |
| 1323 | 1314 | sandbox_mode: "workspace-write", |
| ... | ... | @@ -1352,10 +1343,10 @@ describe("ProviderCommandReactor", () => { |
| 1352 | 1343 | await Effect.runPromise( |
| 1353 | 1344 | harness.engine.dispatch({ |
| 1354 | 1345 | type: "thread.session.set", |
| 1355 | commandId: CommandId.makeUnsafe("cmd-session-set-for-approval-error"), | |
| 1356 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1346 | commandId: CommandId.make("cmd-session-set-for-approval-error"), | |
| 1347 | threadId: ThreadId.make("thread-1"), | |
| 1357 | 1348 | session: { |
| 1358 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1349 | threadId: ThreadId.make("thread-1"), | |
| 1359 | 1350 | status: "running", |
| 1360 | 1351 | providerName: "codex", |
| 1361 | 1352 | runtimeMode: "approval-required", |
| ... | ... | @@ -1370,10 +1361,10 @@ describe("ProviderCommandReactor", () => { |
| 1370 | 1361 | await Effect.runPromise( |
| 1371 | 1362 | harness.engine.dispatch({ |
| 1372 | 1363 | type: "thread.activity.append", |
| 1373 | commandId: CommandId.makeUnsafe("cmd-approval-requested"), | |
| 1374 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1364 | commandId: CommandId.make("cmd-approval-requested"), | |
| 1365 | threadId: ThreadId.make("thread-1"), | |
| 1375 | 1366 | activity: { |
| 1376 | id: EventId.makeUnsafe("activity-approval-requested"), | |
| 1367 | id: EventId.make("activity-approval-requested"), | |
| 1377 | 1368 | tone: "approval", |
| 1378 | 1369 | kind: "approval.requested", |
| 1379 | 1370 | summary: "Command approval requested", |
| ... | ... | @@ -1391,8 +1382,8 @@ describe("ProviderCommandReactor", () => { |
| 1391 | 1382 | await Effect.runPromise( |
| 1392 | 1383 | harness.engine.dispatch({ |
| 1393 | 1384 | type: "thread.approval.respond", |
| 1394 | commandId: CommandId.makeUnsafe("cmd-approval-respond-stale"), | |
| 1395 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1385 | commandId: CommandId.make("cmd-approval-respond-stale"), | |
| 1386 | threadId: ThreadId.make("thread-1"), | |
| 1396 | 1387 | requestId: asApprovalRequestId("approval-request-1"), |
| 1397 | 1388 | decision: "acceptForSession", |
| 1398 | 1389 | createdAt: now, |
| ... | ... | @@ -1401,9 +1392,7 @@ describe("ProviderCommandReactor", () => { |
| 1401 | 1392 | |
| 1402 | 1393 | await waitFor(async () => { |
| 1403 | 1394 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1404 | const thread = readModel.threads.find( | |
| 1405 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 1406 | ); | |
| 1395 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1407 | 1396 | if (!thread) return false; |
| 1408 | 1397 | return thread.activities.some( |
| 1409 | 1398 | (activity) => activity.kind === "provider.approval.respond.failed", |
| ... | ... | @@ -1411,7 +1400,7 @@ describe("ProviderCommandReactor", () => { |
| 1411 | 1400 | }); |
| 1412 | 1401 | |
| 1413 | 1402 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1414 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1403 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1415 | 1404 | expect(thread).toBeDefined(); |
| 1416 | 1405 | |
| 1417 | 1406 | const failureActivity = thread?.activities.find( |
| ... | ... | @@ -1449,10 +1438,10 @@ describe("ProviderCommandReactor", () => { |
| 1449 | 1438 | await Effect.runPromise( |
| 1450 | 1439 | harness.engine.dispatch({ |
| 1451 | 1440 | type: "thread.session.set", |
| 1452 | commandId: CommandId.makeUnsafe("cmd-session-set-for-user-input-error"), | |
| 1453 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1441 | commandId: CommandId.make("cmd-session-set-for-user-input-error"), | |
| 1442 | threadId: ThreadId.make("thread-1"), | |
| 1454 | 1443 | session: { |
| 1455 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1444 | threadId: ThreadId.make("thread-1"), | |
| 1456 | 1445 | status: "running", |
| 1457 | 1446 | providerName: "claudeAgent", |
| 1458 | 1447 | runtimeMode: "approval-required", |
| ... | ... | @@ -1467,10 +1456,10 @@ describe("ProviderCommandReactor", () => { |
| 1467 | 1456 | await Effect.runPromise( |
| 1468 | 1457 | harness.engine.dispatch({ |
| 1469 | 1458 | type: "thread.activity.append", |
| 1470 | commandId: CommandId.makeUnsafe("cmd-user-input-requested"), | |
| 1471 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1459 | commandId: CommandId.make("cmd-user-input-requested"), | |
| 1460 | threadId: ThreadId.make("thread-1"), | |
| 1472 | 1461 | activity: { |
| 1473 | id: EventId.makeUnsafe("activity-user-input-requested"), | |
| 1462 | id: EventId.make("activity-user-input-requested"), | |
| 1474 | 1463 | tone: "info", |
| 1475 | 1464 | kind: "user-input.requested", |
| 1476 | 1465 | summary: "User input requested", |
| ... | ... | @@ -1500,8 +1489,8 @@ describe("ProviderCommandReactor", () => { |
| 1500 | 1489 | await Effect.runPromise( |
| 1501 | 1490 | harness.engine.dispatch({ |
| 1502 | 1491 | type: "thread.user-input.respond", |
| 1503 | commandId: CommandId.makeUnsafe("cmd-user-input-respond-stale"), | |
| 1504 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1492 | commandId: CommandId.make("cmd-user-input-respond-stale"), | |
| 1493 | threadId: ThreadId.make("thread-1"), | |
| 1505 | 1494 | requestId: asApprovalRequestId("user-input-request-1"), |
| 1506 | 1495 | answers: { |
| 1507 | 1496 | sandbox_mode: "workspace-write", |
| ... | ... | @@ -1512,9 +1501,7 @@ describe("ProviderCommandReactor", () => { |
| 1512 | 1501 | |
| 1513 | 1502 | await waitFor(async () => { |
| 1514 | 1503 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1515 | const thread = readModel.threads.find( | |
| 1516 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 1517 | ); | |
| 1504 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1518 | 1505 | if (!thread) return false; |
| 1519 | 1506 | return thread.activities.some( |
| 1520 | 1507 | (activity) => activity.kind === "provider.user-input.respond.failed", |
| ... | ... | @@ -1522,7 +1509,7 @@ describe("ProviderCommandReactor", () => { |
| 1522 | 1509 | }); |
| 1523 | 1510 | |
| 1524 | 1511 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1525 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1512 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1526 | 1513 | expect(thread).toBeDefined(); |
| 1527 | 1514 | |
| 1528 | 1515 | const failureActivity = thread?.activities.find( |
| ... | ... | @@ -1551,10 +1538,10 @@ describe("ProviderCommandReactor", () => { |
| 1551 | 1538 | await Effect.runPromise( |
| 1552 | 1539 | harness.engine.dispatch({ |
| 1553 | 1540 | type: "thread.session.set", |
| 1554 | commandId: CommandId.makeUnsafe("cmd-session-set-for-stop"), | |
| 1555 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1541 | commandId: CommandId.make("cmd-session-set-for-stop"), | |
| 1542 | threadId: ThreadId.make("thread-1"), | |
| 1556 | 1543 | session: { |
| 1557 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1544 | threadId: ThreadId.make("thread-1"), | |
| 1558 | 1545 | status: "ready", |
| 1559 | 1546 | providerName: "codex", |
| 1560 | 1547 | runtimeMode: "approval-required", |
| ... | ... | @@ -1569,15 +1556,15 @@ describe("ProviderCommandReactor", () => { |
| 1569 | 1556 | await Effect.runPromise( |
| 1570 | 1557 | harness.engine.dispatch({ |
| 1571 | 1558 | type: "thread.session.stop", |
| 1572 | commandId: CommandId.makeUnsafe("cmd-session-stop"), | |
| 1573 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1559 | commandId: CommandId.make("cmd-session-stop"), | |
| 1560 | threadId: ThreadId.make("thread-1"), | |
| 1574 | 1561 | createdAt: now, |
| 1575 | 1562 | }), |
| 1576 | 1563 | ); |
| 1577 | 1564 | |
| 1578 | 1565 | await waitFor(() => harness.stopSession.mock.calls.length === 1); |
| 1579 | 1566 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1580 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1567 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1581 | 1568 | expect(thread?.session).not.toBeNull(); |
| 1582 | 1569 | expect(thread?.session?.status).toBe("stopped"); |
| 1583 | 1570 | expect(thread?.session?.threadId).toBe("thread-1"); |
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+2-2| ... | ... | @@ -67,7 +67,7 @@ const turnStartKeyForEvent = (event: ProviderIntentEvent): string => |
| 67 | 67 | event.commandId !== null ? `command:${event.commandId}` : `event:${event.eventId}`; |
| 68 | 68 | |
| 69 | 69 | const serverCommandId = (tag: string): CommandId => |
| 70 | CommandId.makeUnsafe(`server:${tag}:${crypto.randomUUID()}`); | |
| 70 | CommandId.make(`server:${tag}:${crypto.randomUUID()}`); | |
| 71 | 71 | |
| 72 | 72 | const HANDLED_TURN_START_KEY_MAX = 10_000; |
| 73 | 73 | const HANDLED_TURN_START_KEY_TTL = Duration.minutes(30); |
| ... | ... | @@ -186,7 +186,7 @@ const make = Effect.gen(function* () { |
| 186 | 186 | commandId: serverCommandId("provider-failure-activity"), |
| 187 | 187 | threadId: input.threadId, |
| 188 | 188 | activity: { |
| 189 | id: EventId.makeUnsafe(crypto.randomUUID()), | |
| 189 | id: EventId.make(crypto.randomUUID()), | |
| 190 | 190 | tone: "error", |
| 191 | 191 | kind: input.kind, |
| 192 | 192 | summary: input.summary, |
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts+40-48| ... | ... | @@ -47,12 +47,12 @@ function makeTestServerSettingsLayer(overrides: Partial<ServerSettings> = {}) { |
| 47 | 47 | return ServerSettingsService.layerTest(overrides); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 51 | const asItemId = (value: string): ProviderItemId => ProviderItemId.makeUnsafe(value); | |
| 52 | const asEventId = (value: string): EventId => EventId.makeUnsafe(value); | |
| 53 | const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value); | |
| 54 | const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value); | |
| 55 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 50 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 51 | const asItemId = (value: string): ProviderItemId => ProviderItemId.make(value); | |
| 52 | const asEventId = (value: string): EventId => EventId.make(value); | |
| 53 | const asMessageId = (value: string): MessageId => MessageId.make(value); | |
| 54 | const asThreadId = (value: string): ThreadId => ThreadId.make(value); | |
| 55 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 56 | 56 | |
| 57 | 57 | type LegacyProviderRuntimeEvent = { |
| 58 | 58 | readonly type: string; |
| ... | ... | @@ -227,7 +227,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 227 | 227 | await Effect.runPromise( |
| 228 | 228 | engine.dispatch({ |
| 229 | 229 | type: "project.create", |
| 230 | commandId: CommandId.makeUnsafe("cmd-provider-project-create"), | |
| 230 | commandId: CommandId.make("cmd-provider-project-create"), | |
| 231 | 231 | projectId: asProjectId("project-1"), |
| 232 | 232 | title: "Provider Project", |
| 233 | 233 | workspaceRoot, |
| ... | ... | @@ -241,8 +241,8 @@ describe("ProviderRuntimeIngestion", () => { |
| 241 | 241 | await Effect.runPromise( |
| 242 | 242 | engine.dispatch({ |
| 243 | 243 | type: "thread.create", |
| 244 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 245 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 244 | commandId: CommandId.make("cmd-thread-create"), | |
| 245 | threadId: ThreadId.make("thread-1"), | |
| 246 | 246 | projectId: asProjectId("project-1"), |
| 247 | 247 | title: "Thread", |
| 248 | 248 | modelSelection: { |
| ... | ... | @@ -259,10 +259,10 @@ describe("ProviderRuntimeIngestion", () => { |
| 259 | 259 | await Effect.runPromise( |
| 260 | 260 | engine.dispatch({ |
| 261 | 261 | type: "thread.session.set", |
| 262 | commandId: CommandId.makeUnsafe("cmd-session-seed"), | |
| 263 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 262 | commandId: CommandId.make("cmd-session-seed"), | |
| 263 | threadId: ThreadId.make("thread-1"), | |
| 264 | 264 | session: { |
| 265 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 265 | threadId: ThreadId.make("thread-1"), | |
| 266 | 266 | status: "ready", |
| 267 | 267 | providerName: "codex", |
| 268 | 268 | runtimeMode: "approval-required", |
| ... | ... | @@ -277,7 +277,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 277 | 277 | provider: "codex", |
| 278 | 278 | status: "ready", |
| 279 | 279 | runtimeMode: "approval-required", |
| 280 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 280 | threadId: ThreadId.make("thread-1"), | |
| 281 | 281 | createdAt, |
| 282 | 282 | updatedAt: createdAt, |
| 283 | 283 | }); |
| ... | ... | @@ -457,9 +457,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 457 | 457 | |
| 458 | 458 | await harness.drain(); |
| 459 | 459 | const midReadModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 460 | const midThread = midReadModel.threads.find( | |
| 461 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 462 | ); | |
| 460 | const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 463 | 461 | expect(midThread?.session?.status).toBe("running"); |
| 464 | 462 | expect(midThread?.session?.activeTurnId).toBe("turn-midturn-lifecycle"); |
| 465 | 463 | |
| ... | ... | @@ -486,10 +484,10 @@ describe("ProviderRuntimeIngestion", () => { |
| 486 | 484 | await Effect.runPromise( |
| 487 | 485 | harness.engine.dispatch({ |
| 488 | 486 | type: "thread.session.set", |
| 489 | commandId: CommandId.makeUnsafe("cmd-session-seed-claude-placeholder"), | |
| 490 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 487 | commandId: CommandId.make("cmd-session-seed-claude-placeholder"), | |
| 488 | threadId: ThreadId.make("thread-1"), | |
| 491 | 489 | session: { |
| 492 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 490 | threadId: ThreadId.make("thread-1"), | |
| 493 | 491 | status: "ready", |
| 494 | 492 | providerName: "claudeAgent", |
| 495 | 493 | runtimeMode: "approval-required", |
| ... | ... | @@ -564,9 +562,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 564 | 562 | |
| 565 | 563 | await harness.drain(); |
| 566 | 564 | const midReadModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 567 | const midThread = midReadModel.threads.find( | |
| 568 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 569 | ); | |
| 565 | const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 570 | 566 | expect(midThread?.session?.status).toBe("running"); |
| 571 | 567 | expect(midThread?.session?.activeTurnId).toBe("turn-primary"); |
| 572 | 568 | |
| ... | ... | @@ -618,9 +614,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 618 | 614 | |
| 619 | 615 | await harness.drain(); |
| 620 | 616 | const midReadModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 621 | const midThread = midReadModel.threads.find( | |
| 622 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 623 | ); | |
| 617 | const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 624 | 618 | expect(midThread?.session?.status).toBe("running"); |
| 625 | 619 | expect(midThread?.session?.activeTurnId).toBe("turn-guarded-main"); |
| 626 | 620 | |
| ... | ... | @@ -770,7 +764,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 770 | 764 | await Effect.runPromise( |
| 771 | 765 | harness.engine.dispatch({ |
| 772 | 766 | type: "thread.create", |
| 773 | commandId: CommandId.makeUnsafe("cmd-thread-create-plan-source"), | |
| 767 | commandId: CommandId.make("cmd-thread-create-plan-source"), | |
| 774 | 768 | threadId: sourceThreadId, |
| 775 | 769 | projectId: asProjectId("project-1"), |
| 776 | 770 | title: "Plan Source", |
| ... | ... | @@ -788,7 +782,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 788 | 782 | await Effect.runPromise( |
| 789 | 783 | harness.engine.dispatch({ |
| 790 | 784 | type: "thread.session.set", |
| 791 | commandId: CommandId.makeUnsafe("cmd-session-set-plan-source"), | |
| 785 | commandId: CommandId.make("cmd-session-set-plan-source"), | |
| 792 | 786 | threadId: sourceThreadId, |
| 793 | 787 | session: { |
| 794 | 788 | threadId: sourceThreadId, |
| ... | ... | @@ -805,7 +799,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 805 | 799 | await Effect.runPromise( |
| 806 | 800 | harness.engine.dispatch({ |
| 807 | 801 | type: "thread.create", |
| 808 | commandId: CommandId.makeUnsafe("cmd-thread-create-plan-target"), | |
| 802 | commandId: CommandId.make("cmd-thread-create-plan-target"), | |
| 809 | 803 | threadId: targetThreadId, |
| 810 | 804 | projectId: asProjectId("project-1"), |
| 811 | 805 | title: "Plan Target", |
| ... | ... | @@ -823,7 +817,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 823 | 817 | await Effect.runPromise( |
| 824 | 818 | harness.engine.dispatch({ |
| 825 | 819 | type: "thread.session.set", |
| 826 | commandId: CommandId.makeUnsafe("cmd-session-set-plan-target"), | |
| 820 | commandId: CommandId.make("cmd-session-set-plan-target"), | |
| 827 | 821 | threadId: targetThreadId, |
| 828 | 822 | session: { |
| 829 | 823 | threadId: targetThreadId, |
| ... | ... | @@ -882,7 +876,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 882 | 876 | await Effect.runPromise( |
| 883 | 877 | harness.engine.dispatch({ |
| 884 | 878 | type: "thread.turn.start", |
| 885 | commandId: CommandId.makeUnsafe("cmd-turn-start-plan-target"), | |
| 879 | commandId: CommandId.make("cmd-turn-start-plan-target"), | |
| 886 | 880 | threadId: targetThreadId, |
| 887 | 881 | message: { |
| 888 | 882 | messageId: asMessageId("msg-plan-target"), |
| ... | ... | @@ -957,7 +951,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 957 | 951 | await Effect.runPromise( |
| 958 | 952 | harness.engine.dispatch({ |
| 959 | 953 | type: "thread.create", |
| 960 | commandId: CommandId.makeUnsafe("cmd-thread-create-plan-source-guarded"), | |
| 954 | commandId: CommandId.make("cmd-thread-create-plan-source-guarded"), | |
| 961 | 955 | threadId: sourceThreadId, |
| 962 | 956 | projectId: asProjectId("project-1"), |
| 963 | 957 | title: "Plan Source", |
| ... | ... | @@ -975,7 +969,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 975 | 969 | await Effect.runPromise( |
| 976 | 970 | harness.engine.dispatch({ |
| 977 | 971 | type: "thread.session.set", |
| 978 | commandId: CommandId.makeUnsafe("cmd-session-set-plan-source-guarded"), | |
| 972 | commandId: CommandId.make("cmd-session-set-plan-source-guarded"), | |
| 979 | 973 | threadId: sourceThreadId, |
| 980 | 974 | session: { |
| 981 | 975 | threadId: sourceThreadId, |
| ... | ... | @@ -1051,7 +1045,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1051 | 1045 | await Effect.runPromise( |
| 1052 | 1046 | harness.engine.dispatch({ |
| 1053 | 1047 | type: "thread.turn.start", |
| 1054 | commandId: CommandId.makeUnsafe("cmd-turn-start-plan-target-guarded"), | |
| 1048 | commandId: CommandId.make("cmd-turn-start-plan-target-guarded"), | |
| 1055 | 1049 | threadId: targetThreadId, |
| 1056 | 1050 | message: { |
| 1057 | 1051 | messageId: asMessageId("msg-plan-target-guarded"), |
| ... | ... | @@ -1110,7 +1104,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1110 | 1104 | await Effect.runPromise( |
| 1111 | 1105 | harness.engine.dispatch({ |
| 1112 | 1106 | type: "thread.create", |
| 1113 | commandId: CommandId.makeUnsafe("cmd-thread-create-plan-source-unrelated"), | |
| 1107 | commandId: CommandId.make("cmd-thread-create-plan-source-unrelated"), | |
| 1114 | 1108 | threadId: sourceThreadId, |
| 1115 | 1109 | projectId: asProjectId("project-1"), |
| 1116 | 1110 | title: "Plan Source", |
| ... | ... | @@ -1128,7 +1122,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1128 | 1122 | await Effect.runPromise( |
| 1129 | 1123 | harness.engine.dispatch({ |
| 1130 | 1124 | type: "thread.session.set", |
| 1131 | commandId: CommandId.makeUnsafe("cmd-session-set-plan-source-unrelated"), | |
| 1125 | commandId: CommandId.make("cmd-session-set-plan-source-unrelated"), | |
| 1132 | 1126 | threadId: sourceThreadId, |
| 1133 | 1127 | session: { |
| 1134 | 1128 | threadId: sourceThreadId, |
| ... | ... | @@ -1145,7 +1139,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1145 | 1139 | await Effect.runPromise( |
| 1146 | 1140 | harness.engine.dispatch({ |
| 1147 | 1141 | type: "thread.create", |
| 1148 | commandId: CommandId.makeUnsafe("cmd-thread-create-plan-target-unrelated"), | |
| 1142 | commandId: CommandId.make("cmd-thread-create-plan-target-unrelated"), | |
| 1149 | 1143 | threadId: targetThreadId, |
| 1150 | 1144 | projectId: asProjectId("project-1"), |
| 1151 | 1145 | title: "Plan Target", |
| ... | ... | @@ -1163,7 +1157,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1163 | 1157 | await Effect.runPromise( |
| 1164 | 1158 | harness.engine.dispatch({ |
| 1165 | 1159 | type: "thread.session.set", |
| 1166 | commandId: CommandId.makeUnsafe("cmd-session-set-plan-target-unrelated"), | |
| 1160 | commandId: CommandId.make("cmd-session-set-plan-target-unrelated"), | |
| 1167 | 1161 | threadId: targetThreadId, |
| 1168 | 1162 | session: { |
| 1169 | 1163 | threadId: targetThreadId, |
| ... | ... | @@ -1213,7 +1207,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1213 | 1207 | await Effect.runPromise( |
| 1214 | 1208 | harness.engine.dispatch({ |
| 1215 | 1209 | type: "thread.turn.start", |
| 1216 | commandId: CommandId.makeUnsafe("cmd-turn-start-plan-target-unrelated"), | |
| 1210 | commandId: CommandId.make("cmd-turn-start-plan-target-unrelated"), | |
| 1217 | 1211 | threadId: targetThreadId, |
| 1218 | 1212 | message: { |
| 1219 | 1213 | messageId: asMessageId("msg-plan-target-unrelated"), |
| ... | ... | @@ -1364,9 +1358,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1364 | 1358 | |
| 1365 | 1359 | await harness.drain(); |
| 1366 | 1360 | const midReadModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1367 | const midThread = midReadModel.threads.find( | |
| 1368 | (entry) => entry.id === ThreadId.makeUnsafe("thread-1"), | |
| 1369 | ); | |
| 1361 | const midThread = midReadModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1370 | 1362 | expect( |
| 1371 | 1363 | midThread?.messages.some( |
| 1372 | 1364 | (message: ProviderRuntimeTestMessage) => message.id === "assistant:item-buffered", |
| ... | ... | @@ -1407,8 +1399,8 @@ describe("ProviderRuntimeIngestion", () => { |
| 1407 | 1399 | await Effect.runPromise( |
| 1408 | 1400 | harness.engine.dispatch({ |
| 1409 | 1401 | type: "thread.turn.start", |
| 1410 | commandId: CommandId.makeUnsafe("cmd-turn-start-streaming-mode"), | |
| 1411 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1402 | commandId: CommandId.make("cmd-turn-start-streaming-mode"), | |
| 1403 | threadId: ThreadId.make("thread-1"), | |
| 1412 | 1404 | message: { |
| 1413 | 1405 | messageId: asMessageId("message-streaming-mode"), |
| 1414 | 1406 | role: "user", |
| ... | ... | @@ -1649,7 +1641,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1649 | 1641 | provider: "codex", |
| 1650 | 1642 | createdAt: now, |
| 1651 | 1643 | threadId: asThreadId("thread-1"), |
| 1652 | requestId: ApprovalRequestId.makeUnsafe("req-open"), | |
| 1644 | requestId: ApprovalRequestId.make("req-open"), | |
| 1653 | 1645 | payload: { |
| 1654 | 1646 | requestType: "command_execution_approval", |
| 1655 | 1647 | detail: "pwd", |
| ... | ... | @@ -1662,7 +1654,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1662 | 1654 | provider: "codex", |
| 1663 | 1655 | createdAt: now, |
| 1664 | 1656 | threadId: asThreadId("thread-1"), |
| 1665 | requestId: ApprovalRequestId.makeUnsafe("req-open"), | |
| 1657 | requestId: ApprovalRequestId.make("req-open"), | |
| 1666 | 1658 | payload: { |
| 1667 | 1659 | requestType: "command_execution_approval", |
| 1668 | 1660 | decision: "accept", |
| ... | ... | @@ -1681,7 +1673,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 1681 | 1673 | ); |
| 1682 | 1674 | |
| 1683 | 1675 | const readModel = await Effect.runPromise(harness.engine.getReadModel()); |
| 1684 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.makeUnsafe("thread-1")); | |
| 1676 | const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); | |
| 1685 | 1677 | expect(thread).toBeDefined(); |
| 1686 | 1678 | |
| 1687 | 1679 | const requested = thread?.activities.find( |
| ... | ... | @@ -2286,7 +2278,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 2286 | 2278 | createdAt: now, |
| 2287 | 2279 | threadId: asThreadId("thread-1"), |
| 2288 | 2280 | turnId: asTurnId("turn-user-input"), |
| 2289 | requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 2281 | requestId: ApprovalRequestId.make("req-user-input-1"), | |
| 2290 | 2282 | payload: { |
| 2291 | 2283 | questions: [ |
| 2292 | 2284 | { |
| ... | ... | @@ -2311,7 +2303,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 2311 | 2303 | createdAt: new Date().toISOString(), |
| 2312 | 2304 | threadId: asThreadId("thread-1"), |
| 2313 | 2305 | turnId: asTurnId("turn-user-input"), |
| 2314 | requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 2306 | requestId: ApprovalRequestId.make("req-user-input-1"), | |
| 2315 | 2307 | payload: { |
| 2316 | 2308 | answers: { |
| 2317 | 2309 | sandbox_mode: "workspace-write", |
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts+8-10| ... | ... | @@ -30,7 +30,7 @@ import { ServerSettingsService } from "../../serverSettings.ts"; |
| 30 | 30 | |
| 31 | 31 | const providerTurnKey = (threadId: ThreadId, turnId: TurnId) => `${threadId}:${turnId}`; |
| 32 | 32 | const providerCommandId = (event: ProviderRuntimeEvent, tag: string): CommandId => |
| 33 | CommandId.makeUnsafe(`provider:${event.eventId}:${tag}:${crypto.randomUUID()}`); | |
| 33 | CommandId.make(`provider:${event.eventId}:${tag}:${crypto.randomUUID()}`); | |
| 34 | 34 | |
| 35 | 35 | const TURN_MESSAGE_IDS_BY_TURN_CACHE_CAPACITY = 10_000; |
| 36 | 36 | const TURN_MESSAGE_IDS_BY_TURN_TTL = Duration.minutes(120); |
| ... | ... | @@ -57,11 +57,11 @@ type RuntimeIngestionInput = |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | function toTurnId(value: TurnId | string | undefined): TurnId | undefined { |
| 60 | return value === undefined ? undefined : TurnId.makeUnsafe(String(value)); | |
| 60 | return value === undefined ? undefined : TurnId.make(String(value)); | |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | function toApprovalRequestId(value: string | undefined): ApprovalRequestId | undefined { |
| 64 | return value === undefined ? undefined : ApprovalRequestId.makeUnsafe(value); | |
| 64 | return value === undefined ? undefined : ApprovalRequestId.make(value); | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | function sameId(left: string | null | undefined, right: string | null | undefined): boolean { |
| ... | ... | @@ -857,7 +857,7 @@ const make = Effect.fn("make")(function* () { |
| 857 | 857 | |
| 858 | 858 | yield* orchestrationEngine.dispatch({ |
| 859 | 859 | type: "thread.proposed-plan.upsert", |
| 860 | commandId: CommandId.makeUnsafe( | |
| 860 | commandId: CommandId.make( | |
| 861 | 861 | `provider:source-proposed-plan-implemented:${implementationThreadId}:${crypto.randomUUID()}`, |
| 862 | 862 | ), |
| 863 | 863 | threadId: sourceThread.id, |
| ... | ... | @@ -1003,7 +1003,7 @@ const make = Effect.fn("make")(function* () { |
| 1003 | 1003 | event.type === "turn.proposed.delta" ? event.payload.delta : undefined; |
| 1004 | 1004 | |
| 1005 | 1005 | if (assistantDelta && assistantDelta.length > 0) { |
| 1006 | const assistantMessageId = MessageId.makeUnsafe( | |
| 1006 | const assistantMessageId = MessageId.make( | |
| 1007 | 1007 | `assistant:${event.itemId ?? event.turnId ?? event.eventId}`, |
| 1008 | 1008 | ); |
| 1009 | 1009 | const turnId = toTurnId(event.turnId); |
| ... | ... | @@ -1049,9 +1049,7 @@ const make = Effect.fn("make")(function* () { |
| 1049 | 1049 | const assistantCompletion = |
| 1050 | 1050 | event.type === "item.completed" && event.payload.itemType === "assistant_message" |
| 1051 | 1051 | ? { |
| 1052 | messageId: MessageId.makeUnsafe( | |
| 1053 | `assistant:${event.itemId ?? event.turnId ?? event.eventId}`, | |
| 1054 | ), | |
| 1052 | messageId: MessageId.make(`assistant:${event.itemId ?? event.turnId ?? event.eventId}`), | |
| 1055 | 1053 | fallbackText: event.payload.detail, |
| 1056 | 1054 | } |
| 1057 | 1055 | : undefined; |
| ... | ... | @@ -1186,7 +1184,7 @@ const make = Effect.fn("make")(function* () { |
| 1186 | 1184 | if (thread.checkpoints.some((c) => c.turnId === turnId)) { |
| 1187 | 1185 | // Already tracked; no-op. |
| 1188 | 1186 | } else { |
| 1189 | const assistantMessageId = MessageId.makeUnsafe( | |
| 1187 | const assistantMessageId = MessageId.make( | |
| 1190 | 1188 | `assistant:${event.itemId ?? event.turnId ?? event.eventId}`, |
| 1191 | 1189 | ); |
| 1192 | 1190 | const maxTurnCount = thread.checkpoints.reduce( |
| ... | ... | @@ -1199,7 +1197,7 @@ const make = Effect.fn("make")(function* () { |
| 1199 | 1197 | threadId: thread.id, |
| 1200 | 1198 | turnId, |
| 1201 | 1199 | completedAt: now, |
| 1202 | checkpointRef: CheckpointRef.makeUnsafe(`provider-diff:${event.eventId}`), | |
| 1200 | checkpointRef: CheckpointRef.make(`provider-diff:${event.eventId}`), | |
| 1203 | 1201 | status: "missing", |
| 1204 | 1202 | files: [], |
| 1205 | 1203 | assistantMessageId, |
apps/server/src/orchestration/Services/CheckpointReactor.ts+4-5| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module CheckpointReactor |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect, Scope } from "effect"; |
| 11 | 11 | |
| 12 | 12 | /** |
| ... | ... | @@ -34,7 +34,6 @@ export interface CheckpointReactorShape { |
| 34 | 34 | /** |
| 35 | 35 | * CheckpointReactor - Service tag for checkpoint reactor workers. |
| 36 | 36 | */ |
| 37 | export class CheckpointReactor extends ServiceMap.Service< | |
| 38 | CheckpointReactor, | |
| 39 | CheckpointReactorShape | |
| 40 | >()("t3/orchestration/Services/CheckpointReactor") {} | |
| 37 | export class CheckpointReactor extends Context.Service<CheckpointReactor, CheckpointReactorShape>()( | |
| 38 | "t3/orchestration/Services/CheckpointReactor", | |
| 39 | ) {} |
apps/server/src/orchestration/Services/OrchestrationEngine.ts+3-3| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | * `OrchestrationEventStore` persistence. It does not own provider process |
| 6 | 6 | * management or transport concerns (e.g. websocket request parsing). |
| 7 | 7 | * |
| 8 | * Uses Effect `ServiceMap.Service` for dependency injection. Command dispatch, | |
| 8 | * Uses Effect `Context.Service` for dependency injection. Command dispatch, | |
| 9 | 9 | * replay, and unknown-input decoding all return typed domain errors. |
| 10 | 10 | * |
| 11 | 11 | * @module OrchestrationEngineService |
| ... | ... | @@ -15,7 +15,7 @@ import type { |
| 15 | 15 | OrchestrationEvent, |
| 16 | 16 | OrchestrationReadModel, |
| 17 | 17 | } from "@t3tools/contracts"; |
| 18 | import { ServiceMap } from "effect"; | |
| 18 | import { Context } from "effect"; | |
| 19 | 19 | import type { Effect, Stream } from "effect"; |
| 20 | 20 | |
| 21 | 21 | import type { OrchestrationDispatchError } from "../Errors.ts"; |
| ... | ... | @@ -74,7 +74,7 @@ export interface OrchestrationEngineShape { |
| 74 | 74 | * }) |
| 75 | 75 | * ``` |
| 76 | 76 | */ |
| 77 | export class OrchestrationEngineService extends ServiceMap.Service< | |
| 77 | export class OrchestrationEngineService extends Context.Service< | |
| 78 | 78 | OrchestrationEngineService, |
| 79 | 79 | OrchestrationEngineShape |
| 80 | 80 | >()("t3/orchestration/Services/OrchestrationEngine/OrchestrationEngineService") {} |
apps/server/src/orchestration/Services/OrchestrationReactor.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module OrchestrationReactor |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect, Scope } from "effect"; |
| 11 | 11 | |
| 12 | 12 | /** |
| ... | ... | @@ -25,7 +25,7 @@ export interface OrchestrationReactorShape { |
| 25 | 25 | /** |
| 26 | 26 | * OrchestrationReactor - Service tag for orchestration reactor coordination. |
| 27 | 27 | */ |
| 28 | export class OrchestrationReactor extends ServiceMap.Service< | |
| 28 | export class OrchestrationReactor extends Context.Service< | |
| 29 | 29 | OrchestrationReactor, |
| 30 | 30 | OrchestrationReactorShape |
| 31 | 31 | >()("t3/orchestration/Services/OrchestrationReactor") {} |
apps/server/src/orchestration/Services/ProjectionPipeline.ts+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | * @module OrchestrationProjectionPipeline |
| 8 | 8 | */ |
| 9 | 9 | import type { OrchestrationEvent } from "@t3tools/contracts"; |
| 10 | import { ServiceMap } from "effect"; | |
| 10 | import { Context } from "effect"; | |
| 11 | 11 | import type { Effect } from "effect"; |
| 12 | 12 | |
| 13 | 13 | import type { ProjectionRepositoryError } from "../../persistence/Errors.ts"; |
| ... | ... | @@ -36,7 +36,7 @@ export interface OrchestrationProjectionPipelineShape { |
| 36 | 36 | /** |
| 37 | 37 | * OrchestrationProjectionPipeline - Service tag for orchestration projections. |
| 38 | 38 | */ |
| 39 | export class OrchestrationProjectionPipeline extends ServiceMap.Service< | |
| 39 | export class OrchestrationProjectionPipeline extends Context.Service< | |
| 40 | 40 | OrchestrationProjectionPipeline, |
| 41 | 41 | OrchestrationProjectionPipelineShape |
| 42 | 42 | >()("t3/orchestration/Services/ProjectionPipeline/OrchestrationProjectionPipeline") {} |
apps/server/src/orchestration/Services/ProjectionSnapshotQuery.ts+2-2| ... | ... | @@ -13,7 +13,7 @@ import type { |
| 13 | 13 | ProjectId, |
| 14 | 14 | ThreadId, |
| 15 | 15 | } from "@t3tools/contracts"; |
| 16 | import { ServiceMap } from "effect"; | |
| 16 | import { Context } from "effect"; | |
| 17 | 17 | import type { Option } from "effect"; |
| 18 | 18 | import type { Effect } from "effect"; |
| 19 | 19 | |
| ... | ... | @@ -74,7 +74,7 @@ export interface ProjectionSnapshotQueryShape { |
| 74 | 74 | /** |
| 75 | 75 | * ProjectionSnapshotQuery - Service tag for projection snapshot queries. |
| 76 | 76 | */ |
| 77 | export class ProjectionSnapshotQuery extends ServiceMap.Service< | |
| 77 | export class ProjectionSnapshotQuery extends Context.Service< | |
| 78 | 78 | ProjectionSnapshotQuery, |
| 79 | 79 | ProjectionSnapshotQueryShape |
| 80 | 80 | >()("t3/orchestration/Services/ProjectionSnapshotQuery") {} |
apps/server/src/orchestration/Services/ProviderCommandReactor.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module ProviderCommandReactor |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect, Scope } from "effect"; |
| 11 | 11 | |
| 12 | 12 | /** |
| ... | ... | @@ -34,7 +34,7 @@ export interface ProviderCommandReactorShape { |
| 34 | 34 | /** |
| 35 | 35 | * ProviderCommandReactor - Service tag for provider command reaction workers. |
| 36 | 36 | */ |
| 37 | export class ProviderCommandReactor extends ServiceMap.Service< | |
| 37 | export class ProviderCommandReactor extends Context.Service< | |
| 38 | 38 | ProviderCommandReactor, |
| 39 | 39 | ProviderCommandReactorShape |
| 40 | 40 | >()("t3/orchestration/Services/ProviderCommandReactor") {} |
apps/server/src/orchestration/Services/ProviderRuntimeIngestion.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module ProviderRuntimeIngestionService |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect, Scope } from "effect"; |
| 11 | 11 | |
| 12 | 12 | /** |
| ... | ... | @@ -34,7 +34,7 @@ export interface ProviderRuntimeIngestionShape { |
| 34 | 34 | /** |
| 35 | 35 | * ProviderRuntimeIngestionService - Service tag for runtime ingestion workers. |
| 36 | 36 | */ |
| 37 | export class ProviderRuntimeIngestionService extends ServiceMap.Service< | |
| 37 | export class ProviderRuntimeIngestionService extends Context.Service< | |
| 38 | 38 | ProviderRuntimeIngestionService, |
| 39 | 39 | ProviderRuntimeIngestionShape |
| 40 | 40 | >()("t3/orchestration/Services/ProviderRuntimeIngestion/ProviderRuntimeIngestionService") {} |
apps/server/src/orchestration/Services/RuntimeReceiptBus.ts+4-5| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | * @module RuntimeReceiptBus |
| 16 | 16 | */ |
| 17 | 17 | import { CheckpointRef, IsoDateTime, NonNegativeInt, ThreadId, TurnId } from "@t3tools/contracts"; |
| 18 | import { Schema, ServiceMap } from "effect"; | |
| 18 | import { Schema, Context } from "effect"; | |
| 19 | 19 | import type { Effect, Stream } from "effect"; |
| 20 | 20 | |
| 21 | 21 | export const CheckpointBaselineCapturedReceipt = Schema.Struct({ |
| ... | ... | @@ -59,7 +59,6 @@ export interface RuntimeReceiptBusShape { |
| 59 | 59 | readonly streamEventsForTest: Stream.Stream<OrchestrationRuntimeReceipt>; |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | export class RuntimeReceiptBus extends ServiceMap.Service< | |
| 63 | RuntimeReceiptBus, | |
| 64 | RuntimeReceiptBusShape | |
| 65 | >()("t3/orchestration/Services/RuntimeReceiptBus") {} | |
| 62 | export class RuntimeReceiptBus extends Context.Service<RuntimeReceiptBus, RuntimeReceiptBusShape>()( | |
| 63 | "t3/orchestration/Services/RuntimeReceiptBus", | |
| 64 | ) {} |
apps/server/src/orchestration/commandInvariants.test.ts+24-26| ... | ... | @@ -25,7 +25,7 @@ const readModel: OrchestrationReadModel = { |
| 25 | 25 | updatedAt: now, |
| 26 | 26 | projects: [ |
| 27 | 27 | { |
| 28 | id: ProjectId.makeUnsafe("project-a"), | |
| 28 | id: ProjectId.make("project-a"), | |
| 29 | 29 | title: "Project A", |
| 30 | 30 | workspaceRoot: "/tmp/project-a", |
| 31 | 31 | defaultModelSelection: { |
| ... | ... | @@ -38,7 +38,7 @@ const readModel: OrchestrationReadModel = { |
| 38 | 38 | deletedAt: null, |
| 39 | 39 | }, |
| 40 | 40 | { |
| 41 | id: ProjectId.makeUnsafe("project-b"), | |
| 41 | id: ProjectId.make("project-b"), | |
| 42 | 42 | title: "Project B", |
| 43 | 43 | workspaceRoot: "/tmp/project-b", |
| 44 | 44 | defaultModelSelection: { |
| ... | ... | @@ -53,8 +53,8 @@ const readModel: OrchestrationReadModel = { |
| 53 | 53 | ], |
| 54 | 54 | threads: [ |
| 55 | 55 | { |
| 56 | id: ThreadId.makeUnsafe("thread-1"), | |
| 57 | projectId: ProjectId.makeUnsafe("project-a"), | |
| 56 | id: ThreadId.make("thread-1"), | |
| 57 | projectId: ProjectId.make("project-a"), | |
| 58 | 58 | title: "Thread A", |
| 59 | 59 | modelSelection: { |
| 60 | 60 | provider: "codex", |
| ... | ... | @@ -76,8 +76,8 @@ const readModel: OrchestrationReadModel = { |
| 76 | 76 | deletedAt: null, |
| 77 | 77 | }, |
| 78 | 78 | { |
| 79 | id: ThreadId.makeUnsafe("thread-2"), | |
| 80 | projectId: ProjectId.makeUnsafe("project-b"), | |
| 79 | id: ThreadId.make("thread-2"), | |
| 80 | projectId: ProjectId.make("project-b"), | |
| 81 | 81 | title: "Thread B", |
| 82 | 82 | modelSelection: { |
| 83 | 83 | provider: "codex", |
| ... | ... | @@ -103,10 +103,10 @@ const readModel: OrchestrationReadModel = { |
| 103 | 103 | |
| 104 | 104 | const messageSendCommand: OrchestrationCommand = { |
| 105 | 105 | type: "thread.turn.start", |
| 106 | commandId: CommandId.makeUnsafe("cmd-1"), | |
| 107 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 106 | commandId: CommandId.make("cmd-1"), | |
| 107 | threadId: ThreadId.make("thread-1"), | |
| 108 | 108 | message: { |
| 109 | messageId: MessageId.makeUnsafe("msg-1"), | |
| 109 | messageId: MessageId.make("msg-1"), | |
| 110 | 110 | role: "user", |
| 111 | 111 | text: "hello", |
| 112 | 112 | attachments: [], |
| ... | ... | @@ -118,13 +118,11 @@ const messageSendCommand: OrchestrationCommand = { |
| 118 | 118 | |
| 119 | 119 | describe("commandInvariants", () => { |
| 120 | 120 | it("finds threads by id and project", () => { |
| 121 | expect(findThreadById(readModel, ThreadId.makeUnsafe("thread-1"))?.projectId).toBe("project-a"); | |
| 122 | expect(findThreadById(readModel, ThreadId.makeUnsafe("missing"))).toBeUndefined(); | |
| 121 | expect(findThreadById(readModel, ThreadId.make("thread-1"))?.projectId).toBe("project-a"); | |
| 122 | expect(findThreadById(readModel, ThreadId.make("missing"))).toBeUndefined(); | |
| 123 | 123 | expect( |
| 124 | listThreadsByProjectId(readModel, ProjectId.makeUnsafe("project-b")).map( | |
| 125 | (thread) => thread.id, | |
| 126 | ), | |
| 127 | ).toEqual([ThreadId.makeUnsafe("thread-2")]); | |
| 124 | listThreadsByProjectId(readModel, ProjectId.make("project-b")).map((thread) => thread.id), | |
| 125 | ).toEqual([ThreadId.make("thread-2")]); | |
| 128 | 126 | }); |
| 129 | 127 | |
| 130 | 128 | it("requires existing thread", async () => { |
| ... | ... | @@ -132,17 +130,17 @@ describe("commandInvariants", () => { |
| 132 | 130 | requireThread({ |
| 133 | 131 | readModel, |
| 134 | 132 | command: messageSendCommand, |
| 135 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 133 | threadId: ThreadId.make("thread-1"), | |
| 136 | 134 | }), |
| 137 | 135 | ); |
| 138 | expect(thread.id).toBe(ThreadId.makeUnsafe("thread-1")); | |
| 136 | expect(thread.id).toBe(ThreadId.make("thread-1")); | |
| 139 | 137 | |
| 140 | 138 | await expect( |
| 141 | 139 | Effect.runPromise( |
| 142 | 140 | requireThread({ |
| 143 | 141 | readModel, |
| 144 | 142 | command: messageSendCommand, |
| 145 | threadId: ThreadId.makeUnsafe("missing"), | |
| 143 | threadId: ThreadId.make("missing"), | |
| 146 | 144 | }), |
| 147 | 145 | ), |
| 148 | 146 | ).rejects.toThrow("does not exist"); |
| ... | ... | @@ -154,9 +152,9 @@ describe("commandInvariants", () => { |
| 154 | 152 | readModel, |
| 155 | 153 | command: { |
| 156 | 154 | type: "thread.create", |
| 157 | commandId: CommandId.makeUnsafe("cmd-2"), | |
| 158 | threadId: ThreadId.makeUnsafe("thread-3"), | |
| 159 | projectId: ProjectId.makeUnsafe("project-a"), | |
| 155 | commandId: CommandId.make("cmd-2"), | |
| 156 | threadId: ThreadId.make("thread-3"), | |
| 157 | projectId: ProjectId.make("project-a"), | |
| 160 | 158 | title: "new", |
| 161 | 159 | modelSelection: { |
| 162 | 160 | provider: "codex", |
| ... | ... | @@ -168,7 +166,7 @@ describe("commandInvariants", () => { |
| 168 | 166 | worktreePath: null, |
| 169 | 167 | createdAt: now, |
| 170 | 168 | }, |
| 171 | threadId: ThreadId.makeUnsafe("thread-3"), | |
| 169 | threadId: ThreadId.make("thread-3"), | |
| 172 | 170 | }), |
| 173 | 171 | ); |
| 174 | 172 | |
| ... | ... | @@ -178,9 +176,9 @@ describe("commandInvariants", () => { |
| 178 | 176 | readModel, |
| 179 | 177 | command: { |
| 180 | 178 | type: "thread.create", |
| 181 | commandId: CommandId.makeUnsafe("cmd-3"), | |
| 182 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 183 | projectId: ProjectId.makeUnsafe("project-a"), | |
| 179 | commandId: CommandId.make("cmd-3"), | |
| 180 | threadId: ThreadId.make("thread-1"), | |
| 181 | projectId: ProjectId.make("project-a"), | |
| 184 | 182 | title: "dup", |
| 185 | 183 | modelSelection: { |
| 186 | 184 | provider: "codex", |
| ... | ... | @@ -192,7 +190,7 @@ describe("commandInvariants", () => { |
| 192 | 190 | worktreePath: null, |
| 193 | 191 | createdAt: now, |
| 194 | 192 | }, |
| 195 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 193 | threadId: ThreadId.make("thread-1"), | |
| 196 | 194 | }), |
| 197 | 195 | ), |
| 198 | 196 | ).rejects.toThrow("already exists"); |
apps/server/src/orchestration/decider.projectScripts.test.ts+34-34| ... | ... | @@ -12,9 +12,9 @@ import { Effect } from "effect"; |
| 12 | 12 | import { decideOrchestrationCommand } from "./decider.ts"; |
| 13 | 13 | import { createEmptyReadModel, projectEvent } from "./projector.ts"; |
| 14 | 14 | |
| 15 | const asEventId = (value: string): EventId => EventId.makeUnsafe(value); | |
| 16 | const asProjectId = (value: string): ProjectId => ProjectId.makeUnsafe(value); | |
| 17 | const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value); | |
| 15 | const asEventId = (value: string): EventId => EventId.make(value); | |
| 16 | const asProjectId = (value: string): ProjectId => ProjectId.make(value); | |
| 17 | const asMessageId = (value: string): MessageId => MessageId.make(value); | |
| 18 | 18 | |
| 19 | 19 | describe("decider project scripts", () => { |
| 20 | 20 | it("emits empty scripts on project.create", async () => { |
| ... | ... | @@ -25,7 +25,7 @@ describe("decider project scripts", () => { |
| 25 | 25 | decideOrchestrationCommand({ |
| 26 | 26 | command: { |
| 27 | 27 | type: "project.create", |
| 28 | commandId: CommandId.makeUnsafe("cmd-project-create-scripts"), | |
| 28 | commandId: CommandId.make("cmd-project-create-scripts"), | |
| 29 | 29 | projectId: asProjectId("project-scripts"), |
| 30 | 30 | title: "Scripts", |
| 31 | 31 | workspaceRoot: "/tmp/scripts", |
| ... | ... | @@ -51,9 +51,9 @@ describe("decider project scripts", () => { |
| 51 | 51 | aggregateId: asProjectId("project-scripts"), |
| 52 | 52 | type: "project.created", |
| 53 | 53 | occurredAt: now, |
| 54 | commandId: CommandId.makeUnsafe("cmd-project-create-scripts"), | |
| 54 | commandId: CommandId.make("cmd-project-create-scripts"), | |
| 55 | 55 | causationEventId: null, |
| 56 | correlationId: CommandId.makeUnsafe("cmd-project-create-scripts"), | |
| 56 | correlationId: CommandId.make("cmd-project-create-scripts"), | |
| 57 | 57 | metadata: {}, |
| 58 | 58 | payload: { |
| 59 | 59 | projectId: asProjectId("project-scripts"), |
| ... | ... | @@ -81,7 +81,7 @@ describe("decider project scripts", () => { |
| 81 | 81 | decideOrchestrationCommand({ |
| 82 | 82 | command: { |
| 83 | 83 | type: "project.meta.update", |
| 84 | commandId: CommandId.makeUnsafe("cmd-project-update-scripts"), | |
| 84 | commandId: CommandId.make("cmd-project-update-scripts"), | |
| 85 | 85 | projectId: asProjectId("project-scripts"), |
| 86 | 86 | scripts: Array.from(scripts), |
| 87 | 87 | }, |
| ... | ... | @@ -105,9 +105,9 @@ describe("decider project scripts", () => { |
| 105 | 105 | aggregateId: asProjectId("project-1"), |
| 106 | 106 | type: "project.created", |
| 107 | 107 | occurredAt: now, |
| 108 | commandId: CommandId.makeUnsafe("cmd-project-create"), | |
| 108 | commandId: CommandId.make("cmd-project-create"), | |
| 109 | 109 | causationEventId: null, |
| 110 | correlationId: CommandId.makeUnsafe("cmd-project-create"), | |
| 110 | correlationId: CommandId.make("cmd-project-create"), | |
| 111 | 111 | metadata: {}, |
| 112 | 112 | payload: { |
| 113 | 113 | projectId: asProjectId("project-1"), |
| ... | ... | @@ -125,15 +125,15 @@ describe("decider project scripts", () => { |
| 125 | 125 | sequence: 2, |
| 126 | 126 | eventId: asEventId("evt-thread-create"), |
| 127 | 127 | aggregateKind: "thread", |
| 128 | aggregateId: ThreadId.makeUnsafe("thread-1"), | |
| 128 | aggregateId: ThreadId.make("thread-1"), | |
| 129 | 129 | type: "thread.created", |
| 130 | 130 | occurredAt: now, |
| 131 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 131 | commandId: CommandId.make("cmd-thread-create"), | |
| 132 | 132 | causationEventId: null, |
| 133 | correlationId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 133 | correlationId: CommandId.make("cmd-thread-create"), | |
| 134 | 134 | metadata: {}, |
| 135 | 135 | payload: { |
| 136 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 136 | threadId: ThreadId.make("thread-1"), | |
| 137 | 137 | projectId: asProjectId("project-1"), |
| 138 | 138 | title: "Thread", |
| 139 | 139 | modelSelection: { |
| ... | ... | @@ -154,8 +154,8 @@ describe("decider project scripts", () => { |
| 154 | 154 | decideOrchestrationCommand({ |
| 155 | 155 | command: { |
| 156 | 156 | type: "thread.turn.start", |
| 157 | commandId: CommandId.makeUnsafe("cmd-turn-start"), | |
| 158 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 157 | commandId: CommandId.make("cmd-turn-start"), | |
| 158 | threadId: ThreadId.make("thread-1"), | |
| 159 | 159 | message: { |
| 160 | 160 | messageId: asMessageId("message-user-1"), |
| 161 | 161 | role: "user", |
| ... | ... | @@ -189,7 +189,7 @@ describe("decider project scripts", () => { |
| 189 | 189 | return; |
| 190 | 190 | } |
| 191 | 191 | expect(turnStartEvent.payload).toMatchObject({ |
| 192 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 192 | threadId: ThreadId.make("thread-1"), | |
| 193 | 193 | messageId: asMessageId("message-user-1"), |
| 194 | 194 | modelSelection: { |
| 195 | 195 | provider: "codex", |
| ... | ... | @@ -214,9 +214,9 @@ describe("decider project scripts", () => { |
| 214 | 214 | aggregateId: asProjectId("project-1"), |
| 215 | 215 | type: "project.created", |
| 216 | 216 | occurredAt: now, |
| 217 | commandId: CommandId.makeUnsafe("cmd-project-create"), | |
| 217 | commandId: CommandId.make("cmd-project-create"), | |
| 218 | 218 | causationEventId: null, |
| 219 | correlationId: CommandId.makeUnsafe("cmd-project-create"), | |
| 219 | correlationId: CommandId.make("cmd-project-create"), | |
| 220 | 220 | metadata: {}, |
| 221 | 221 | payload: { |
| 222 | 222 | projectId: asProjectId("project-1"), |
| ... | ... | @@ -234,15 +234,15 @@ describe("decider project scripts", () => { |
| 234 | 234 | sequence: 2, |
| 235 | 235 | eventId: asEventId("evt-thread-create"), |
| 236 | 236 | aggregateKind: "thread", |
| 237 | aggregateId: ThreadId.makeUnsafe("thread-1"), | |
| 237 | aggregateId: ThreadId.make("thread-1"), | |
| 238 | 238 | type: "thread.created", |
| 239 | 239 | occurredAt: now, |
| 240 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 240 | commandId: CommandId.make("cmd-thread-create"), | |
| 241 | 241 | causationEventId: null, |
| 242 | correlationId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 242 | correlationId: CommandId.make("cmd-thread-create"), | |
| 243 | 243 | metadata: {}, |
| 244 | 244 | payload: { |
| 245 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 245 | threadId: ThreadId.make("thread-1"), | |
| 246 | 246 | projectId: asProjectId("project-1"), |
| 247 | 247 | title: "Thread", |
| 248 | 248 | modelSelection: { |
| ... | ... | @@ -263,8 +263,8 @@ describe("decider project scripts", () => { |
| 263 | 263 | decideOrchestrationCommand({ |
| 264 | 264 | command: { |
| 265 | 265 | type: "thread.runtime-mode.set", |
| 266 | commandId: CommandId.makeUnsafe("cmd-runtime-mode-set"), | |
| 267 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 266 | commandId: CommandId.make("cmd-runtime-mode-set"), | |
| 267 | threadId: ThreadId.make("thread-1"), | |
| 268 | 268 | runtimeMode: "approval-required", |
| 269 | 269 | createdAt: now, |
| 270 | 270 | }, |
| ... | ... | @@ -279,7 +279,7 @@ describe("decider project scripts", () => { |
| 279 | 279 | expect(singleResult).toMatchObject({ |
| 280 | 280 | type: "thread.runtime-mode-set", |
| 281 | 281 | payload: { |
| 282 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 282 | threadId: ThreadId.make("thread-1"), | |
| 283 | 283 | runtimeMode: "approval-required", |
| 284 | 284 | }, |
| 285 | 285 | }); |
| ... | ... | @@ -296,9 +296,9 @@ describe("decider project scripts", () => { |
| 296 | 296 | aggregateId: asProjectId("project-1"), |
| 297 | 297 | type: "project.created", |
| 298 | 298 | occurredAt: now, |
| 299 | commandId: CommandId.makeUnsafe("cmd-project-create"), | |
| 299 | commandId: CommandId.make("cmd-project-create"), | |
| 300 | 300 | causationEventId: null, |
| 301 | correlationId: CommandId.makeUnsafe("cmd-project-create"), | |
| 301 | correlationId: CommandId.make("cmd-project-create"), | |
| 302 | 302 | metadata: {}, |
| 303 | 303 | payload: { |
| 304 | 304 | projectId: asProjectId("project-1"), |
| ... | ... | @@ -316,15 +316,15 @@ describe("decider project scripts", () => { |
| 316 | 316 | sequence: 2, |
| 317 | 317 | eventId: asEventId("evt-thread-create"), |
| 318 | 318 | aggregateKind: "thread", |
| 319 | aggregateId: ThreadId.makeUnsafe("thread-1"), | |
| 319 | aggregateId: ThreadId.make("thread-1"), | |
| 320 | 320 | type: "thread.created", |
| 321 | 321 | occurredAt: now, |
| 322 | commandId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 322 | commandId: CommandId.make("cmd-thread-create"), | |
| 323 | 323 | causationEventId: null, |
| 324 | correlationId: CommandId.makeUnsafe("cmd-thread-create"), | |
| 324 | correlationId: CommandId.make("cmd-thread-create"), | |
| 325 | 325 | metadata: {}, |
| 326 | 326 | payload: { |
| 327 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 327 | threadId: ThreadId.make("thread-1"), | |
| 328 | 328 | projectId: asProjectId("project-1"), |
| 329 | 329 | title: "Thread", |
| 330 | 330 | modelSelection: { |
| ... | ... | @@ -345,8 +345,8 @@ describe("decider project scripts", () => { |
| 345 | 345 | decideOrchestrationCommand({ |
| 346 | 346 | command: { |
| 347 | 347 | type: "thread.interaction-mode.set", |
| 348 | commandId: CommandId.makeUnsafe("cmd-interaction-mode-set"), | |
| 349 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 348 | commandId: CommandId.make("cmd-interaction-mode-set"), | |
| 349 | threadId: ThreadId.make("thread-1"), | |
| 350 | 350 | interactionMode: "plan", |
| 351 | 351 | createdAt: now, |
| 352 | 352 | }, |
| ... | ... | @@ -361,7 +361,7 @@ describe("decider project scripts", () => { |
| 361 | 361 | expect(singleResult).toMatchObject({ |
| 362 | 362 | type: "thread.interaction-mode-set", |
| 363 | 363 | payload: { |
| 364 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 364 | threadId: ThreadId.make("thread-1"), | |
| 365 | 365 | interactionMode: "plan", |
| 366 | 366 | }, |
| 367 | 367 | }); |
apps/server/src/orchestration/projector.test.ts+4-4| ... | ... | @@ -21,15 +21,15 @@ function makeEvent(input: { |
| 21 | 21 | }): OrchestrationEvent { |
| 22 | 22 | return { |
| 23 | 23 | sequence: input.sequence, |
| 24 | eventId: EventId.makeUnsafe(`event-${input.sequence}`), | |
| 24 | eventId: EventId.make(`event-${input.sequence}`), | |
| 25 | 25 | type: input.type, |
| 26 | 26 | aggregateKind: input.aggregateKind, |
| 27 | 27 | aggregateId: |
| 28 | 28 | input.aggregateKind === "project" |
| 29 | ? ProjectId.makeUnsafe(input.aggregateId) | |
| 30 | : ThreadId.makeUnsafe(input.aggregateId), | |
| 29 | ? ProjectId.make(input.aggregateId) | |
| 30 | : ThreadId.make(input.aggregateId), | |
| 31 | 31 | occurredAt: input.occurredAt, |
| 32 | commandId: input.commandId === null ? null : CommandId.makeUnsafe(input.commandId), | |
| 32 | commandId: input.commandId === null ? null : CommandId.make(input.commandId), | |
| 33 | 33 | causationEventId: null, |
| 34 | 34 | correlationId: null, |
| 35 | 35 | metadata: {}, |
apps/server/src/persistence/Layers/OrchestrationEventStore.test.ts+8-8| ... | ... | @@ -21,18 +21,18 @@ layer("OrchestrationEventStore", (it) => { |
| 21 | 21 | |
| 22 | 22 | const appended = yield* eventStore.append({ |
| 23 | 23 | type: "project.created", |
| 24 | eventId: EventId.makeUnsafe("evt-store-roundtrip"), | |
| 24 | eventId: EventId.make("evt-store-roundtrip"), | |
| 25 | 25 | aggregateKind: "project", |
| 26 | aggregateId: ProjectId.makeUnsafe("project-roundtrip"), | |
| 26 | aggregateId: ProjectId.make("project-roundtrip"), | |
| 27 | 27 | occurredAt: now, |
| 28 | commandId: CommandId.makeUnsafe("cmd-store-roundtrip"), | |
| 28 | commandId: CommandId.make("cmd-store-roundtrip"), | |
| 29 | 29 | causationEventId: null, |
| 30 | correlationId: CommandId.makeUnsafe("cmd-store-roundtrip"), | |
| 30 | correlationId: CommandId.make("cmd-store-roundtrip"), | |
| 31 | 31 | metadata: { |
| 32 | 32 | adapterKey: "codex", |
| 33 | 33 | }, |
| 34 | 34 | payload: { |
| 35 | projectId: ProjectId.makeUnsafe("project-roundtrip"), | |
| 35 | projectId: ProjectId.make("project-roundtrip"), | |
| 36 | 36 | title: "Roundtrip Project", |
| 37 | 37 | workspaceRoot: "/tmp/project-roundtrip", |
| 38 | 38 | defaultModelSelection: null, |
| ... | ... | @@ -87,13 +87,13 @@ layer("OrchestrationEventStore", (it) => { |
| 87 | 87 | metadata_json |
| 88 | 88 | ) |
| 89 | 89 | VALUES ( |
| 90 | ${EventId.makeUnsafe("evt-store-invalid-json")}, | |
| 90 | ${EventId.make("evt-store-invalid-json")}, | |
| 91 | 91 | ${"project"}, |
| 92 | ${ProjectId.makeUnsafe("project-invalid-json")}, | |
| 92 | ${ProjectId.make("project-invalid-json")}, | |
| 93 | 93 | ${0}, |
| 94 | 94 | ${"project.created"}, |
| 95 | 95 | ${now}, |
| 96 | ${CommandId.makeUnsafe("cmd-store-invalid-json")}, | |
| 96 | ${CommandId.make("cmd-store-invalid-json")}, | |
| 97 | 97 | ${null}, |
| 98 | 98 | ${null}, |
| 99 | 99 | ${"server"}, |
apps/server/src/persistence/Layers/ProjectionRepositories.test.ts+5-5| ... | ... | @@ -24,7 +24,7 @@ projectionRepositoriesLayer("Projection repositories", (it) => { |
| 24 | 24 | const sql = yield* SqlClient.SqlClient; |
| 25 | 25 | |
| 26 | 26 | yield* projects.upsert({ |
| 27 | projectId: ProjectId.makeUnsafe("project-null-options"), | |
| 27 | projectId: ProjectId.make("project-null-options"), | |
| 28 | 28 | title: "Null options project", |
| 29 | 29 | workspaceRoot: "/tmp/project-null-options", |
| 30 | 30 | defaultModelSelection: { |
| ... | ... | @@ -58,7 +58,7 @@ projectionRepositoriesLayer("Projection repositories", (it) => { |
| 58 | 58 | ); |
| 59 | 59 | |
| 60 | 60 | const persisted = yield* projects.getById({ |
| 61 | projectId: ProjectId.makeUnsafe("project-null-options"), | |
| 61 | projectId: ProjectId.make("project-null-options"), | |
| 62 | 62 | }); |
| 63 | 63 | assert.deepStrictEqual(Option.getOrNull(persisted)?.defaultModelSelection, { |
| 64 | 64 | provider: "codex", |
| ... | ... | @@ -73,8 +73,8 @@ projectionRepositoriesLayer("Projection repositories", (it) => { |
| 73 | 73 | const sql = yield* SqlClient.SqlClient; |
| 74 | 74 | |
| 75 | 75 | yield* threads.upsert({ |
| 76 | threadId: ThreadId.makeUnsafe("thread-null-options"), | |
| 77 | projectId: ProjectId.makeUnsafe("project-null-options"), | |
| 76 | threadId: ThreadId.make("thread-null-options"), | |
| 77 | projectId: ProjectId.make("project-null-options"), | |
| 78 | 78 | title: "Null options thread", |
| 79 | 79 | modelSelection: { |
| 80 | 80 | provider: "claudeAgent", |
| ... | ... | @@ -112,7 +112,7 @@ projectionRepositoriesLayer("Projection repositories", (it) => { |
| 112 | 112 | ); |
| 113 | 113 | |
| 114 | 114 | const persisted = yield* threads.getById({ |
| 115 | threadId: ThreadId.makeUnsafe("thread-null-options"), | |
| 115 | threadId: ThreadId.make("thread-null-options"), | |
| 116 | 116 | }); |
| 117 | 117 | assert.deepStrictEqual(Option.getOrNull(persisted)?.modelSelection, { |
| 118 | 118 | provider: "claudeAgent", |
apps/server/src/persistence/Layers/ProjectionThreadMessages.test.ts+4-4| ... | ... | @@ -14,8 +14,8 @@ layer("ProjectionThreadMessageRepository", (it) => { |
| 14 | 14 | it.effect("preserves existing attachments when upsert omits attachments", () => |
| 15 | 15 | Effect.gen(function* () { |
| 16 | 16 | const repository = yield* ProjectionThreadMessageRepository; |
| 17 | const threadId = ThreadId.makeUnsafe("thread-preserve-attachments"); | |
| 18 | const messageId = MessageId.makeUnsafe("message-preserve-attachments"); | |
| 17 | const threadId = ThreadId.make("thread-preserve-attachments"); | |
| 18 | const messageId = MessageId.make("message-preserve-attachments"); | |
| 19 | 19 | const createdAt = "2026-02-28T19:00:00.000Z"; |
| 20 | 20 | const updatedAt = "2026-02-28T19:00:01.000Z"; |
| 21 | 21 | const persistedAttachments = [ |
| ... | ... | @@ -68,8 +68,8 @@ layer("ProjectionThreadMessageRepository", (it) => { |
| 68 | 68 | it.effect("allows explicit attachment clearing with an empty array", () => |
| 69 | 69 | Effect.gen(function* () { |
| 70 | 70 | const repository = yield* ProjectionThreadMessageRepository; |
| 71 | const threadId = ThreadId.makeUnsafe("thread-clear-attachments"); | |
| 72 | const messageId = MessageId.makeUnsafe("message-clear-attachments"); | |
| 71 | const threadId = ThreadId.make("thread-clear-attachments"); | |
| 72 | const messageId = MessageId.make("message-clear-attachments"); | |
| 73 | 73 | const createdAt = "2026-02-28T19:10:00.000Z"; |
| 74 | 74 | |
| 75 | 75 | yield* repository.upsert({ |
apps/server/src/persistence/NodeSqliteClient.ts+10-10| ... | ... | @@ -15,7 +15,7 @@ import { identity } from "effect/Function"; |
| 15 | 15 | import * as Layer from "effect/Layer"; |
| 16 | 16 | import * as Scope from "effect/Scope"; |
| 17 | 17 | import * as Semaphore from "effect/Semaphore"; |
| 18 | import * as ServiceMap from "effect/ServiceMap"; | |
| 18 | import * as Context from "effect/Context"; | |
| 19 | 19 | import * as Stream from "effect/Stream"; |
| 20 | 20 | import * as Reactivity from "effect/unstable/reactivity/Reactivity"; |
| 21 | 21 | import * as Client from "effect/unstable/sql/SqlClient"; |
| ... | ... | @@ -32,7 +32,7 @@ export type TypeId = "~local/sqlite-node/SqliteClient"; |
| 32 | 32 | /** |
| 33 | 33 | * SqliteClient - Effect service tag for the sqlite SQL client. |
| 34 | 34 | */ |
| 35 | export const SqliteClient = ServiceMap.Service<Client.SqlClient>("t3/persistence/NodeSqliteClient"); | |
| 35 | export const SqliteClient = Context.Service<Client.SqlClient>("t3/persistence/NodeSqliteClient"); | |
| 36 | 36 | |
| 37 | 37 | export interface SqliteClientConfig { |
| 38 | 38 | readonly filename: string; |
| ... | ... | @@ -120,7 +120,7 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( |
| 120 | 120 | |
| 121 | 121 | const runStatement = (statement: StatementSync, params: ReadonlyArray<unknown>, raw: boolean) => |
| 122 | 122 | Effect.withFiber<ReadonlyArray<any>, SqlError>((fiber) => { |
| 123 | statement.setReadBigInts(Boolean(ServiceMap.get(fiber.services, Client.SafeIntegers))); | |
| 123 | statement.setReadBigInts(Boolean(Context.get(fiber.context, Client.SafeIntegers))); | |
| 124 | 124 | try { |
| 125 | 125 | if (hasRows(statement)) { |
| 126 | 126 | return Effect.succeed(statement.all(...(params as any))); |
| ... | ... | @@ -200,7 +200,7 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( |
| 200 | 200 | const acquirer = semaphore.withPermits(1)(Effect.succeed(connection)); |
| 201 | 201 | const transactionAcquirer = Effect.uninterruptibleMask((restore) => { |
| 202 | 202 | const fiber = Fiber.getCurrent()!; |
| 203 | const scope = ServiceMap.getUnsafe(fiber.services, Scope.Scope); | |
| 203 | const scope = Context.getUnsafe(fiber.context, Scope.Scope); | |
| 204 | 204 | return Effect.as( |
| 205 | 205 | Effect.tap(restore(semaphore.take(1)), () => Scope.addFinalizer(scope, semaphore.release(1))), |
| 206 | 206 | connection, |
| ... | ... | @@ -251,27 +251,27 @@ const makeMemory = ( |
| 251 | 251 | export const layerConfig = ( |
| 252 | 252 | config: Config.Wrap<SqliteClientConfig>, |
| 253 | 253 | ): Layer.Layer<Client.SqlClient, Config.ConfigError> => |
| 254 | Layer.effectServices( | |
| 254 | Layer.effectContext( | |
| 255 | 255 | Config.unwrap(config) |
| 256 | 256 | .asEffect() |
| 257 | 257 | .pipe( |
| 258 | 258 | Effect.flatMap(make), |
| 259 | 259 | Effect.map((client) => |
| 260 | ServiceMap.make(SqliteClient, client).pipe(ServiceMap.add(Client.SqlClient, client)), | |
| 260 | Context.make(SqliteClient, client).pipe(Context.add(Client.SqlClient, client)), | |
| 261 | 261 | ), |
| 262 | 262 | ), |
| 263 | 263 | ).pipe(Layer.provide(Reactivity.layer)); |
| 264 | 264 | |
| 265 | 265 | export const layer = (config: SqliteClientConfig): Layer.Layer<Client.SqlClient> => |
| 266 | Layer.effectServices( | |
| 266 | Layer.effectContext( | |
| 267 | 267 | Effect.map(make(config), (client) => |
| 268 | ServiceMap.make(SqliteClient, client).pipe(ServiceMap.add(Client.SqlClient, client)), | |
| 268 | Context.make(SqliteClient, client).pipe(Context.add(Client.SqlClient, client)), | |
| 269 | 269 | ), |
| 270 | 270 | ).pipe(Layer.provide(Reactivity.layer)); |
| 271 | 271 | |
| 272 | 272 | export const layerMemory = (config: SqliteMemoryClientConfig = {}): Layer.Layer<Client.SqlClient> => |
| 273 | Layer.effectServices( | |
| 273 | Layer.effectContext( | |
| 274 | 274 | Effect.map(makeMemory(config), (client) => |
| 275 | ServiceMap.make(SqliteClient, client).pipe(ServiceMap.add(Client.SqlClient, client)), | |
| 275 | Context.make(SqliteClient, client).pipe(Context.add(Client.SqlClient, client)), | |
| 276 | 276 | ), |
| 277 | 277 | ).pipe(Layer.provide(Reactivity.layer)); |
apps/server/src/persistence/Services/AuthPairingLinks.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { Option, Schema, ServiceMap } from "effect"; | |
| 1 | import { Option, Schema, Context } from "effect"; | |
| 2 | 2 | import type { Effect } from "effect"; |
| 3 | 3 | |
| 4 | 4 | import type { AuthPairingLinkRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -70,7 +70,7 @@ export interface AuthPairingLinkRepositoryShape { |
| 70 | 70 | ) => Effect.Effect<Option.Option<AuthPairingLinkRecord>, AuthPairingLinkRepositoryError>; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | export class AuthPairingLinkRepository extends ServiceMap.Service< | |
| 73 | export class AuthPairingLinkRepository extends Context.Service< | |
| 74 | 74 | AuthPairingLinkRepository, |
| 75 | 75 | AuthPairingLinkRepositoryShape |
| 76 | 76 | >()("t3/persistence/Services/AuthPairingLinks/AuthPairingLinkRepository") {} |
apps/server/src/persistence/Services/AuthSessions.ts+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | import { AuthClientMetadataDeviceType, AuthSessionId } from "@t3tools/contracts"; |
| 2 | import { Option, Schema, ServiceMap } from "effect"; | |
| 2 | import { Option, Schema, Context } from "effect"; | |
| 3 | 3 | import type { Effect } from "effect"; |
| 4 | 4 | |
| 5 | 5 | import type { AuthSessionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -87,7 +87,7 @@ export interface AuthSessionRepositoryShape { |
| 87 | 87 | ) => Effect.Effect<void, AuthSessionRepositoryError>; |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | export class AuthSessionRepository extends ServiceMap.Service< | |
| 90 | export class AuthSessionRepository extends Context.Service< | |
| 91 | 91 | AuthSessionRepository, |
| 92 | 92 | AuthSessionRepositoryShape |
| 93 | 93 | >()("t3/persistence/Services/AuthSessions/AuthSessionRepository") {} |
apps/server/src/persistence/Services/OrchestrationCommandReceipts.ts+2-2| ... | ... | @@ -15,7 +15,7 @@ import { |
| 15 | 15 | ProjectId, |
| 16 | 16 | ThreadId, |
| 17 | 17 | } from "@t3tools/contracts"; |
| 18 | import { Option, Schema, ServiceMap } from "effect"; | |
| 18 | import { Option, Schema, Context } from "effect"; | |
| 19 | 19 | import type { Effect } from "effect"; |
| 20 | 20 | |
| 21 | 21 | import type { OrchestrationCommandReceiptRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -63,7 +63,7 @@ export interface OrchestrationCommandReceiptRepositoryShape { |
| 63 | 63 | /** |
| 64 | 64 | * OrchestrationCommandReceiptRepository - Service tag for command receipt persistence. |
| 65 | 65 | */ |
| 66 | export class OrchestrationCommandReceiptRepository extends ServiceMap.Service< | |
| 66 | export class OrchestrationCommandReceiptRepository extends Context.Service< | |
| 67 | 67 | OrchestrationCommandReceiptRepository, |
| 68 | 68 | OrchestrationCommandReceiptRepositoryShape |
| 69 | 69 | >()("t3/persistence/Services/OrchestrationCommandReceipts/OrchestrationCommandReceiptRepository") {} |
apps/server/src/persistence/Services/OrchestrationEventStore.ts+3-3| ... | ... | @@ -4,13 +4,13 @@ |
| 4 | 4 | * Owns durable append/replay access to the orchestration event stream. It does |
| 5 | 5 | * not reduce events into read models or apply command validation rules. |
| 6 | 6 | * |
| 7 | * Uses Effect `ServiceMap.Service` for dependency injection and exposes typed | |
| 7 | * Uses Effect `Context.Service` for dependency injection and exposes typed | |
| 8 | 8 | * persistence/decode errors for event append and replay operations. |
| 9 | 9 | * |
| 10 | 10 | * @module OrchestrationEventStore |
| 11 | 11 | */ |
| 12 | 12 | import { OrchestrationEvent } from "@t3tools/contracts"; |
| 13 | import { ServiceMap } from "effect"; | |
| 13 | import { Context } from "effect"; | |
| 14 | 14 | import type { Effect, Stream } from "effect"; |
| 15 | 15 | |
| 16 | 16 | import type { OrchestrationEventStoreError } from "../Errors.ts"; |
| ... | ... | @@ -64,7 +64,7 @@ export interface OrchestrationEventStoreShape { |
| 64 | 64 | * }) |
| 65 | 65 | * ``` |
| 66 | 66 | */ |
| 67 | export class OrchestrationEventStore extends ServiceMap.Service< | |
| 67 | export class OrchestrationEventStore extends Context.Service< | |
| 68 | 68 | OrchestrationEventStore, |
| 69 | 69 | OrchestrationEventStoreShape |
| 70 | 70 | >()("t3/persistence/Services/OrchestrationEventStore") {} |
apps/server/src/persistence/Services/ProjectionCheckpoints.ts+2-2| ... | ... | @@ -16,7 +16,7 @@ import { |
| 16 | 16 | ThreadId, |
| 17 | 17 | TurnId, |
| 18 | 18 | } from "@t3tools/contracts"; |
| 19 | import { Option, ServiceMap, Schema } from "effect"; | |
| 19 | import { Option, Context, Schema } from "effect"; | |
| 20 | 20 | import type { Effect } from "effect"; |
| 21 | 21 | |
| 22 | 22 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -87,7 +87,7 @@ export interface ProjectionCheckpointRepositoryShape { |
| 87 | 87 | /** |
| 88 | 88 | * ProjectionCheckpointRepository - Service tag for checkpoint projection persistence. |
| 89 | 89 | */ |
| 90 | export class ProjectionCheckpointRepository extends ServiceMap.Service< | |
| 90 | export class ProjectionCheckpointRepository extends Context.Service< | |
| 91 | 91 | ProjectionCheckpointRepository, |
| 92 | 92 | ProjectionCheckpointRepositoryShape |
| 93 | 93 | >()("t3/persistence/Services/ProjectionCheckpoints/ProjectionCheckpointRepository") {} |
apps/server/src/persistence/Services/ProjectionPendingApprovals.ts+2-2| ... | ... | @@ -14,7 +14,7 @@ import { |
| 14 | 14 | ThreadId, |
| 15 | 15 | TurnId, |
| 16 | 16 | } from "@t3tools/contracts"; |
| 17 | import { Option, Schema, ServiceMap } from "effect"; | |
| 17 | import { Option, Schema, Context } from "effect"; | |
| 18 | 18 | import type { Effect } from "effect"; |
| 19 | 19 | |
| 20 | 20 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -85,7 +85,7 @@ export interface ProjectionPendingApprovalRepositoryShape { |
| 85 | 85 | /** |
| 86 | 86 | * ProjectionPendingApprovalRepository - Service tag for pending approval persistence. |
| 87 | 87 | */ |
| 88 | export class ProjectionPendingApprovalRepository extends ServiceMap.Service< | |
| 88 | export class ProjectionPendingApprovalRepository extends Context.Service< | |
| 89 | 89 | ProjectionPendingApprovalRepository, |
| 90 | 90 | ProjectionPendingApprovalRepositoryShape |
| 91 | 91 | >()("t3/persistence/Services/ProjectionPendingApprovals/ProjectionPendingApprovalRepository") {} |
apps/server/src/persistence/Services/ProjectionProjects.ts+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | * @module ProjectionProjectRepository |
| 8 | 8 | */ |
| 9 | 9 | import { IsoDateTime, ModelSelection, ProjectId, ProjectScript } from "@t3tools/contracts"; |
| 10 | import { Option, Schema, ServiceMap } from "effect"; | |
| 10 | import { Option, Schema, Context } from "effect"; | |
| 11 | 11 | import type { Effect } from "effect"; |
| 12 | 12 | |
| 13 | 13 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -73,7 +73,7 @@ export interface ProjectionProjectRepositoryShape { |
| 73 | 73 | /** |
| 74 | 74 | * ProjectionProjectRepository - Service tag for project projection persistence. |
| 75 | 75 | */ |
| 76 | export class ProjectionProjectRepository extends ServiceMap.Service< | |
| 76 | export class ProjectionProjectRepository extends Context.Service< | |
| 77 | 77 | ProjectionProjectRepository, |
| 78 | 78 | ProjectionProjectRepositoryShape |
| 79 | 79 | >()("t3/persistence/Services/ProjectionProjects/ProjectionProjectRepository") {} |
apps/server/src/persistence/Services/ProjectionState.ts+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | * @module ProjectionStateRepository |
| 8 | 8 | */ |
| 9 | 9 | import { IsoDateTime, NonNegativeInt } from "@t3tools/contracts"; |
| 10 | import { Option, Schema, ServiceMap } from "effect"; | |
| 10 | import { Option, Schema, Context } from "effect"; | |
| 11 | 11 | import type { Effect } from "effect"; |
| 12 | 12 | |
| 13 | 13 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -58,7 +58,7 @@ export interface ProjectionStateRepositoryShape { |
| 58 | 58 | /** |
| 59 | 59 | * ProjectionStateRepository - Service tag for projection cursor persistence. |
| 60 | 60 | */ |
| 61 | export class ProjectionStateRepository extends ServiceMap.Service< | |
| 61 | export class ProjectionStateRepository extends Context.Service< | |
| 62 | 62 | ProjectionStateRepository, |
| 63 | 63 | ProjectionStateRepositoryShape |
| 64 | 64 | >()("t3/persistence/Services/ProjectionState/ProjectionStateRepository") {} |
apps/server/src/persistence/Services/ProjectionThreadActivities.ts+2-2| ... | ... | @@ -14,7 +14,7 @@ import { |
| 14 | 14 | ThreadId, |
| 15 | 15 | TurnId, |
| 16 | 16 | } from "@t3tools/contracts"; |
| 17 | import { Schema, ServiceMap } from "effect"; | |
| 17 | import { Schema, Context } from "effect"; | |
| 18 | 18 | import type { Effect } from "effect"; |
| 19 | 19 | |
| 20 | 20 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -77,7 +77,7 @@ export interface ProjectionThreadActivityRepositoryShape { |
| 77 | 77 | /** |
| 78 | 78 | * ProjectionThreadActivityRepository - Service tag for thread activity persistence. |
| 79 | 79 | */ |
| 80 | export class ProjectionThreadActivityRepository extends ServiceMap.Service< | |
| 80 | export class ProjectionThreadActivityRepository extends Context.Service< | |
| 81 | 81 | ProjectionThreadActivityRepository, |
| 82 | 82 | ProjectionThreadActivityRepositoryShape |
| 83 | 83 | >()("t3/persistence/Services/ProjectionThreadActivities/ProjectionThreadActivityRepository") {} |
apps/server/src/persistence/Services/ProjectionThreadMessages.ts+2-2| ... | ... | @@ -14,7 +14,7 @@ import { |
| 14 | 14 | TurnId, |
| 15 | 15 | IsoDateTime, |
| 16 | 16 | } from "@t3tools/contracts"; |
| 17 | import { Schema, ServiceMap } from "effect"; | |
| 17 | import { Schema, Context } from "effect"; | |
| 18 | 18 | import type { Option } from "effect"; |
| 19 | 19 | import type { Effect } from "effect"; |
| 20 | 20 | |
| ... | ... | @@ -88,7 +88,7 @@ export interface ProjectionThreadMessageRepositoryShape { |
| 88 | 88 | /** |
| 89 | 89 | * ProjectionThreadMessageRepository - Service tag for message projection persistence. |
| 90 | 90 | */ |
| 91 | export class ProjectionThreadMessageRepository extends ServiceMap.Service< | |
| 91 | export class ProjectionThreadMessageRepository extends Context.Service< | |
| 92 | 92 | ProjectionThreadMessageRepository, |
| 93 | 93 | ProjectionThreadMessageRepositoryShape |
| 94 | 94 | >()("t3/persistence/Services/ProjectionThreadMessages/ProjectionThreadMessageRepository") {} |
apps/server/src/persistence/Services/ProjectionThreadProposedPlans.ts+2-2| ... | ... | @@ -5,7 +5,7 @@ import { |
| 5 | 5 | TrimmedNonEmptyString, |
| 6 | 6 | TurnId, |
| 7 | 7 | } from "@t3tools/contracts"; |
| 8 | import { Schema, ServiceMap } from "effect"; | |
| 8 | import { Schema, Context } from "effect"; | |
| 9 | 9 | import type { Effect } from "effect"; |
| 10 | 10 | |
| 11 | 11 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -46,7 +46,7 @@ export interface ProjectionThreadProposedPlanRepositoryShape { |
| 46 | 46 | ) => Effect.Effect<void, ProjectionRepositoryError>; |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | export class ProjectionThreadProposedPlanRepository extends ServiceMap.Service< | |
| 49 | export class ProjectionThreadProposedPlanRepository extends Context.Service< | |
| 50 | 50 | ProjectionThreadProposedPlanRepository, |
| 51 | 51 | ProjectionThreadProposedPlanRepositoryShape |
| 52 | 52 | >()( |
apps/server/src/persistence/Services/ProjectionThreadSessions.ts+2-2| ... | ... | @@ -13,7 +13,7 @@ import { |
| 13 | 13 | ThreadId, |
| 14 | 14 | TurnId, |
| 15 | 15 | } from "@t3tools/contracts"; |
| 16 | import { Option, Schema, ServiceMap } from "effect"; | |
| 16 | import { Option, Schema, Context } from "effect"; | |
| 17 | 17 | import type { Effect } from "effect"; |
| 18 | 18 | |
| 19 | 19 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -68,7 +68,7 @@ export interface ProjectionThreadSessionRepositoryShape { |
| 68 | 68 | /** |
| 69 | 69 | * ProjectionThreadSessionRepository - Service tag for thread-session persistence. |
| 70 | 70 | */ |
| 71 | export class ProjectionThreadSessionRepository extends ServiceMap.Service< | |
| 71 | export class ProjectionThreadSessionRepository extends Context.Service< | |
| 72 | 72 | ProjectionThreadSessionRepository, |
| 73 | 73 | ProjectionThreadSessionRepositoryShape |
| 74 | 74 | >()("t3/persistence/Services/ProjectionThreadSessions/ProjectionThreadSessionRepository") {} |
apps/server/src/persistence/Services/ProjectionThreads.ts+2-2| ... | ... | @@ -15,7 +15,7 @@ import { |
| 15 | 15 | ThreadId, |
| 16 | 16 | TurnId, |
| 17 | 17 | } from "@t3tools/contracts"; |
| 18 | import { Option, Schema, ServiceMap } from "effect"; | |
| 18 | import { Option, Schema, Context } from "effect"; | |
| 19 | 19 | import type { Effect } from "effect"; |
| 20 | 20 | |
| 21 | 21 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -90,7 +90,7 @@ export interface ProjectionThreadRepositoryShape { |
| 90 | 90 | /** |
| 91 | 91 | * ProjectionThreadRepository - Service tag for thread projection persistence. |
| 92 | 92 | */ |
| 93 | export class ProjectionThreadRepository extends ServiceMap.Service< | |
| 93 | export class ProjectionThreadRepository extends Context.Service< | |
| 94 | 94 | ProjectionThreadRepository, |
| 95 | 95 | ProjectionThreadRepositoryShape |
| 96 | 96 | >()("t3/persistence/Services/ProjectionThreads/ProjectionThreadRepository") {} |
apps/server/src/persistence/Services/ProjectionTurns.ts+2-2| ... | ... | @@ -17,7 +17,7 @@ import { |
| 17 | 17 | ThreadId, |
| 18 | 18 | TurnId, |
| 19 | 19 | } from "@t3tools/contracts"; |
| 20 | import { Option, Schema, ServiceMap } from "effect"; | |
| 20 | import { Option, Schema, Context } from "effect"; | |
| 21 | 21 | import type { Effect } from "effect"; |
| 22 | 22 | |
| 23 | 23 | import type { ProjectionRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -162,7 +162,7 @@ export interface ProjectionTurnRepositoryShape { |
| 162 | 162 | ) => Effect.Effect<void, ProjectionRepositoryError>; |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | export class ProjectionTurnRepository extends ServiceMap.Service< | |
| 165 | export class ProjectionTurnRepository extends Context.Service< | |
| 166 | 166 | ProjectionTurnRepository, |
| 167 | 167 | ProjectionTurnRepositoryShape |
| 168 | 168 | >()("t3/persistence/Services/ProjectionTurns/ProjectionTurnRepository") {} |
apps/server/src/persistence/Services/ProviderSessionRuntime.ts+2-2| ... | ... | @@ -11,7 +11,7 @@ import { |
| 11 | 11 | RuntimeMode, |
| 12 | 12 | ThreadId, |
| 13 | 13 | } from "@t3tools/contracts"; |
| 14 | import { Option, Schema, ServiceMap } from "effect"; | |
| 14 | import { Option, Schema, Context } from "effect"; | |
| 15 | 15 | import type { Effect } from "effect"; |
| 16 | 16 | |
| 17 | 17 | import type { ProviderSessionRuntimeRepositoryError } from "../Errors.ts"; |
| ... | ... | @@ -75,7 +75,7 @@ export interface ProviderSessionRuntimeRepositoryShape { |
| 75 | 75 | /** |
| 76 | 76 | * ProviderSessionRuntimeRepository - Service tag for provider runtime persistence. |
| 77 | 77 | */ |
| 78 | export class ProviderSessionRuntimeRepository extends ServiceMap.Service< | |
| 78 | export class ProviderSessionRuntimeRepository extends Context.Service< | |
| 79 | 79 | ProviderSessionRuntimeRepository, |
| 80 | 80 | ProviderSessionRuntimeRepositoryShape |
| 81 | 81 | >()("t3/persistence/Services/ProviderSessionRuntime/ProviderSessionRuntimeRepository") {} |
apps/server/src/project/Layers/RepositoryIdentityResolver.ts+13-11| ... | ... | @@ -116,17 +116,19 @@ async function resolveRepositoryIdentityFromCacheKey( |
| 116 | 116 | |
| 117 | 117 | export const makeRepositoryIdentityResolver = Effect.fn("makeRepositoryIdentityResolver")( |
| 118 | 118 | function* (options: RepositoryIdentityResolverOptions = {}) { |
| 119 | const repositoryIdentityCache = yield* Cache.makeWith<string, RepositoryIdentity | null>({ | |
| 120 | capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY, | |
| 121 | lookup: (cacheKey) => Effect.promise(() => resolveRepositoryIdentityFromCacheKey(cacheKey)), | |
| 122 | timeToLive: Exit.match({ | |
| 123 | onSuccess: (value) => | |
| 124 | value === null | |
| 125 | ? (options.negativeCacheTtl ?? DEFAULT_NEGATIVE_CACHE_TTL) | |
| 126 | : (options.positiveCacheTtl ?? DEFAULT_POSITIVE_CACHE_TTL), | |
| 127 | onFailure: () => Duration.zero, | |
| 128 | }), | |
| 129 | }); | |
| 119 | const repositoryIdentityCache = yield* Cache.makeWith<string, RepositoryIdentity | null>( | |
| 120 | (cacheKey) => Effect.promise(() => resolveRepositoryIdentityFromCacheKey(cacheKey)), | |
| 121 | { | |
| 122 | capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY, | |
| 123 | timeToLive: Exit.match({ | |
| 124 | onSuccess: (value) => | |
| 125 | value === null | |
| 126 | ? (options.negativeCacheTtl ?? DEFAULT_NEGATIVE_CACHE_TTL) | |
| 127 | : (options.positiveCacheTtl ?? DEFAULT_POSITIVE_CACHE_TTL), | |
| 128 | onFailure: () => Duration.zero, | |
| 129 | }), | |
| 130 | }, | |
| 131 | ); | |
| 130 | 132 | |
| 131 | 133 | const resolve: RepositoryIdentityResolverShape["resolve"] = Effect.fn( |
| 132 | 134 | "RepositoryIdentityResolver.resolve", |
apps/server/src/project/Services/ProjectFaviconResolver.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module ProjectFaviconResolver |
| 8 | 8 | */ |
| 9 | import { ServiceMap } from "effect"; | |
| 9 | import { Context } from "effect"; | |
| 10 | 10 | import type { Effect } from "effect"; |
| 11 | 11 | |
| 12 | 12 | /** |
| ... | ... | @@ -24,7 +24,7 @@ export interface ProjectFaviconResolverShape { |
| 24 | 24 | /** |
| 25 | 25 | * ProjectFaviconResolver - Service tag for project favicon resolution. |
| 26 | 26 | */ |
| 27 | export class ProjectFaviconResolver extends ServiceMap.Service< | |
| 27 | export class ProjectFaviconResolver extends Context.Service< | |
| 28 | 28 | ProjectFaviconResolver, |
| 29 | 29 | ProjectFaviconResolverShape |
| 30 | 30 | >()("t3/project/Services/ProjectFaviconResolver") {} |
apps/server/src/project/Services/ProjectSetupScriptRunner.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { ServiceMap } from "effect"; | |
| 1 | import { Context } from "effect"; | |
| 2 | 2 | import type { Effect } from "effect"; |
| 3 | 3 | |
| 4 | 4 | export interface ProjectSetupScriptRunnerResultNoScript { |
| ... | ... | @@ -31,7 +31,7 @@ export interface ProjectSetupScriptRunnerShape { |
| 31 | 31 | ) => Effect.Effect<ProjectSetupScriptRunnerResult, Error>; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | export class ProjectSetupScriptRunner extends ServiceMap.Service< | |
| 34 | export class ProjectSetupScriptRunner extends Context.Service< | |
| 35 | 35 | ProjectSetupScriptRunner, |
| 36 | 36 | ProjectSetupScriptRunnerShape |
| 37 | 37 | >()("t3/project/ProjectSetupScriptRunner") {} |
apps/server/src/project/Services/RepositoryIdentityResolver.ts+2-2| ... | ... | @@ -1,12 +1,12 @@ |
| 1 | 1 | import type { RepositoryIdentity } from "@t3tools/contracts"; |
| 2 | import { ServiceMap } from "effect"; | |
| 2 | import { Context } from "effect"; | |
| 3 | 3 | import type { Effect } from "effect"; |
| 4 | 4 | |
| 5 | 5 | export interface RepositoryIdentityResolverShape { |
| 6 | 6 | readonly resolve: (cwd: string) => Effect.Effect<RepositoryIdentity | null>; |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | export class RepositoryIdentityResolver extends ServiceMap.Service< | |
| 9 | export class RepositoryIdentityResolver extends Context.Service< | |
| 10 | 10 | RepositoryIdentityResolver, |
| 11 | 11 | RepositoryIdentityResolverShape |
| 12 | 12 | >()("t3/project/Services/RepositoryIdentityResolver") {} |
apps/server/src/provider/Layers/ClaudeAdapter.test.ts+21-25| ... | ... | @@ -237,8 +237,8 @@ async function readFirstPromptMessage( |
| 237 | 237 | return next.value; |
| 238 | 238 | } |
| 239 | 239 | |
| 240 | const THREAD_ID = ThreadId.makeUnsafe("thread-claude-1"); | |
| 241 | const RESUME_THREAD_ID = ThreadId.makeUnsafe("thread-claude-resume"); | |
| 240 | const THREAD_ID = ThreadId.make("thread-claude-1"); | |
| 241 | const RESUME_THREAD_ID = ThreadId.make("thread-claude-resume"); | |
| 242 | 242 | |
| 243 | 243 | describe("ClaudeAdapterLive", () => { |
| 244 | 244 | it.effect("returns validation error for non-claude provider on startSession", () => { |
| ... | ... | @@ -1104,8 +1104,8 @@ describe("ClaudeAdapterLive", () => { |
| 1104 | 1104 | it.effect("closes the session when the Claude stream aborts after a turn starts", () => { |
| 1105 | 1105 | const harness = makeHarness(); |
| 1106 | 1106 | return Effect.gen(function* () { |
| 1107 | const services = yield* Effect.services(); | |
| 1108 | const runFork = Effect.runForkWith(services); | |
| 1107 | const context = yield* Effect.context<never>(); | |
| 1108 | const runFork = Effect.runForkWith(context); | |
| 1109 | 1109 | |
| 1110 | 1110 | const adapter = yield* ClaudeAdapter; |
| 1111 | 1111 | const runtimeEvents: Array<ProviderRuntimeEvent> = []; |
| ... | ... | @@ -1204,8 +1204,8 @@ describe("ClaudeAdapterLive", () => { |
| 1204 | 1204 | ); |
| 1205 | 1205 | |
| 1206 | 1206 | return Effect.gen(function* () { |
| 1207 | const services = yield* Effect.services(); | |
| 1208 | const runFork = Effect.runForkWith(services); | |
| 1207 | const context = yield* Effect.context<never>(); | |
| 1208 | const runFork = Effect.runForkWith(context); | |
| 1209 | 1209 | |
| 1210 | 1210 | const adapter = yield* ClaudeAdapter; |
| 1211 | 1211 | |
| ... | ... | @@ -2108,7 +2108,7 @@ describe("ClaudeAdapterLive", () => { |
| 2108 | 2108 | return; |
| 2109 | 2109 | } |
| 2110 | 2110 | assert.deepEqual(requested.value.providerRefs, { |
| 2111 | providerItemId: ProviderItemId.makeUnsafe("tool-use-1"), | |
| 2111 | providerItemId: ProviderItemId.make("tool-use-1"), | |
| 2112 | 2112 | }); |
| 2113 | 2113 | const runtimeRequestId = requested.value.requestId; |
| 2114 | 2114 | assert.equal(typeof runtimeRequestId, "string"); |
| ... | ... | @@ -2118,7 +2118,7 @@ describe("ClaudeAdapterLive", () => { |
| 2118 | 2118 | |
| 2119 | 2119 | yield* adapter.respondToRequest( |
| 2120 | 2120 | session.threadId, |
| 2121 | ApprovalRequestId.makeUnsafe(runtimeRequestId), | |
| 2121 | ApprovalRequestId.make(runtimeRequestId), | |
| 2122 | 2122 | "accept", |
| 2123 | 2123 | ); |
| 2124 | 2124 | |
| ... | ... | @@ -2134,7 +2134,7 @@ describe("ClaudeAdapterLive", () => { |
| 2134 | 2134 | assert.equal(resolved.value.requestId, requested.value.requestId); |
| 2135 | 2135 | assert.equal(resolved.value.payload.decision, "accept"); |
| 2136 | 2136 | assert.deepEqual(resolved.value.providerRefs, { |
| 2137 | providerItemId: ProviderItemId.makeUnsafe("tool-use-1"), | |
| 2137 | providerItemId: ProviderItemId.make("tool-use-1"), | |
| 2138 | 2138 | }); |
| 2139 | 2139 | |
| 2140 | 2140 | const permissionResult = yield* Effect.promise(() => permissionPromise); |
| ... | ... | @@ -2183,7 +2183,7 @@ describe("ClaudeAdapterLive", () => { |
| 2183 | 2183 | |
| 2184 | 2184 | yield* adapter.respondToRequest( |
| 2185 | 2185 | session.threadId, |
| 2186 | ApprovalRequestId.makeUnsafe(String(agentRequested.value.requestId)), | |
| 2186 | ApprovalRequestId.make(String(agentRequested.value.requestId)), | |
| 2187 | 2187 | "accept", |
| 2188 | 2188 | ); |
| 2189 | 2189 | yield* Stream.runHead(adapter.streamEvents); |
| ... | ... | @@ -2207,7 +2207,7 @@ describe("ClaudeAdapterLive", () => { |
| 2207 | 2207 | |
| 2208 | 2208 | yield* adapter.respondToRequest( |
| 2209 | 2209 | session.threadId, |
| 2210 | ApprovalRequestId.makeUnsafe(String(grepRequested.value.requestId)), | |
| 2210 | ApprovalRequestId.make(String(grepRequested.value.requestId)), | |
| 2211 | 2211 | "accept", |
| 2212 | 2212 | ); |
| 2213 | 2213 | yield* Stream.runHead(adapter.streamEvents); |
| ... | ... | @@ -2629,7 +2629,7 @@ describe("ClaudeAdapterLive", () => { |
| 2629 | 2629 | } |
| 2630 | 2630 | assert.equal(proposedEvent.value.payload.planMarkdown, "# Ship it\n\n- one\n- two"); |
| 2631 | 2631 | assert.deepEqual(proposedEvent.value.providerRefs, { |
| 2632 | providerItemId: ProviderItemId.makeUnsafe("tool-exit-1"), | |
| 2632 | providerItemId: ProviderItemId.make("tool-exit-1"), | |
| 2633 | 2633 | }); |
| 2634 | 2634 | |
| 2635 | 2635 | const permissionResult = yield* Effect.promise(() => permissionPromise); |
| ... | ... | @@ -2707,7 +2707,7 @@ describe("ClaudeAdapterLive", () => { |
| 2707 | 2707 | } |
| 2708 | 2708 | assert.equal(proposedEvent.value.payload.planMarkdown, "# Final plan\n\n- capture it"); |
| 2709 | 2709 | assert.deepEqual(proposedEvent.value.providerRefs, { |
| 2710 | providerItemId: ProviderItemId.makeUnsafe("tool-exit-2"), | |
| 2710 | providerItemId: ProviderItemId.make("tool-exit-2"), | |
| 2711 | 2711 | }); |
| 2712 | 2712 | }).pipe( |
| 2713 | 2713 | Effect.provideService(Random.Random, makeDeterministicRandomService()), |
| ... | ... | @@ -2798,15 +2798,13 @@ describe("ClaudeAdapterLive", () => { |
| 2798 | 2798 | assert.equal(requestedEvent.value.payload.questions.length, 1); |
| 2799 | 2799 | assert.equal(requestedEvent.value.payload.questions[0]?.question, "Which framework?"); |
| 2800 | 2800 | assert.deepEqual(requestedEvent.value.providerRefs, { |
| 2801 | providerItemId: ProviderItemId.makeUnsafe("tool-ask-1"), | |
| 2801 | providerItemId: ProviderItemId.make("tool-ask-1"), | |
| 2802 | 2802 | }); |
| 2803 | 2803 | |
| 2804 | 2804 | // Respond with the user's answers. |
| 2805 | yield* adapter.respondToUserInput( | |
| 2806 | session.threadId, | |
| 2807 | ApprovalRequestId.makeUnsafe(requestId!), | |
| 2808 | { "Which framework?": "React" }, | |
| 2809 | ); | |
| 2805 | yield* adapter.respondToUserInput(session.threadId, ApprovalRequestId.make(requestId!), { | |
| 2806 | "Which framework?": "React", | |
| 2807 | }); | |
| 2810 | 2808 | |
| 2811 | 2809 | // The adapter should emit a user-input.resolved event. |
| 2812 | 2810 | const resolvedEvent = yield* Stream.runHead(adapter.streamEvents); |
| ... | ... | @@ -2822,7 +2820,7 @@ describe("ClaudeAdapterLive", () => { |
| 2822 | 2820 | "Which framework?": "React", |
| 2823 | 2821 | }); |
| 2824 | 2822 | assert.deepEqual(resolvedEvent.value.providerRefs, { |
| 2825 | providerItemId: ProviderItemId.makeUnsafe("tool-ask-1"), | |
| 2823 | providerItemId: ProviderItemId.make("tool-ask-1"), | |
| 2826 | 2824 | }); |
| 2827 | 2825 | |
| 2828 | 2826 | // The canUseTool promise should resolve with the answers in SDK format. |
| ... | ... | @@ -2889,11 +2887,9 @@ describe("ClaudeAdapterLive", () => { |
| 2889 | 2887 | } |
| 2890 | 2888 | const requestId = requestedEvent.value.requestId; |
| 2891 | 2889 | |
| 2892 | yield* adapter.respondToUserInput( | |
| 2893 | session.threadId, | |
| 2894 | ApprovalRequestId.makeUnsafe(requestId!), | |
| 2895 | { "Deploy to which env?": "Staging" }, | |
| 2896 | ); | |
| 2890 | yield* adapter.respondToUserInput(session.threadId, ApprovalRequestId.make(requestId!), { | |
| 2891 | "Deploy to which env?": "Staging", | |
| 2892 | }); | |
| 2897 | 2893 | |
| 2898 | 2894 | // Drain the resolved event. |
| 2899 | 2895 | yield* Stream.runHead(adapter.streamEvents); |
apps/server/src/provider/Layers/ClaudeAdapter.ts+16-16| ... | ... | @@ -269,7 +269,7 @@ function isInterruptedResult(result: SDKResultMessage): boolean { |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | function asRuntimeItemId(value: string): RuntimeItemId { |
| 272 | return RuntimeItemId.makeUnsafe(value); | |
| 272 | return RuntimeItemId.make(value); | |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | 275 | function maxClaudeContextWindowFromModelUsage(modelUsage: unknown): number | undefined { |
| ... | ... | @@ -353,7 +353,7 @@ function asCanonicalTurnId(value: TurnId): TurnId { |
| 353 | 353 | } |
| 354 | 354 | |
| 355 | 355 | function asRuntimeRequestId(value: ApprovalRequestId): RuntimeRequestId { |
| 356 | return RuntimeRequestId.makeUnsafe(value); | |
| 356 | return RuntimeRequestId.make(value); | |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | 359 | function readClaudeResumeState(resumeCursor: unknown): ClaudeResumeState | undefined { |
| ... | ... | @@ -371,7 +371,7 @@ function readClaudeResumeState(resumeCursor: unknown): ClaudeResumeState | undef |
| 371 | 371 | const threadIdCandidate = typeof cursor.threadId === "string" ? cursor.threadId : undefined; |
| 372 | 372 | const threadId = |
| 373 | 373 | threadIdCandidate && !isSyntheticClaudeThreadId(threadIdCandidate) |
| 374 | ? ThreadId.makeUnsafe(threadIdCandidate) | |
| 374 | ? ThreadId.make(threadIdCandidate) | |
| 375 | 375 | : undefined; |
| 376 | 376 | const resumeCandidate = |
| 377 | 377 | typeof cursor.resume === "string" |
| ... | ... | @@ -641,7 +641,7 @@ function nativeProviderRefs( |
| 641 | 641 | ): NonNullable<ProviderRuntimeEvent["providerRefs"]> { |
| 642 | 642 | if (options?.providerItemId) { |
| 643 | 643 | return { |
| 644 | providerItemId: ProviderItemId.makeUnsafe(options.providerItemId), | |
| 644 | providerItemId: ProviderItemId.make(options.providerItemId), | |
| 645 | 645 | }; |
| 646 | 646 | } |
| 647 | 647 | return {}; |
| ... | ... | @@ -934,7 +934,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 934 | 934 | const serverSettingsService = yield* ServerSettingsService; |
| 935 | 935 | |
| 936 | 936 | const nowIso = Effect.map(DateTime.now, DateTime.formatIso); |
| 937 | const nextEventId = Effect.map(Random.nextUUIDv4, (id) => EventId.makeUnsafe(id)); | |
| 937 | const nextEventId = Effect.map(Random.nextUUIDv4, (id) => EventId.make(id)); | |
| 938 | 938 | const makeEventStamp = () => Effect.all({ eventId: nextEventId, createdAt: nowIso }); |
| 939 | 939 | |
| 940 | 940 | const offerRuntimeEvent = (event: ProviderRuntimeEvent): Effect.Effect<void> => |
| ... | ... | @@ -967,7 +967,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 967 | 967 | ? { providerThreadId: message.session_id } |
| 968 | 968 | : {}), |
| 969 | 969 | ...(context.turnState ? { turnId: asCanonicalTurnId(context.turnState.turnId) } : {}), |
| 970 | ...(itemId ? { itemId: ProviderItemId.makeUnsafe(itemId) } : {}), | |
| 970 | ...(itemId ? { itemId: ProviderItemId.make(itemId) } : {}), | |
| 971 | 971 | payload: message, |
| 972 | 972 | }, |
| 973 | 973 | }, |
| ... | ... | @@ -1822,7 +1822,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 1822 | 1822 | // Auto-start a synthetic turn for assistant messages that arrive without |
| 1823 | 1823 | // an active turn (e.g., background agent/subagent responses between user prompts). |
| 1824 | 1824 | if (!context.turnState) { |
| 1825 | const turnId = TurnId.makeUnsafe(yield* Random.nextUUIDv4); | |
| 1825 | const turnId = TurnId.make(yield* Random.nextUUIDv4); | |
| 1826 | 1826 | const startedAt = yield* nowIso; |
| 1827 | 1827 | context.turnState = { |
| 1828 | 1828 | turnId, |
| ... | ... | @@ -2013,7 +2013,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2013 | 2013 | ...base, |
| 2014 | 2014 | type: "task.started", |
| 2015 | 2015 | payload: { |
| 2016 | taskId: RuntimeTaskId.makeUnsafe(message.task_id), | |
| 2016 | taskId: RuntimeTaskId.make(message.task_id), | |
| 2017 | 2017 | description: message.description, |
| 2018 | 2018 | ...(message.task_type ? { taskType: message.task_type } : {}), |
| 2019 | 2019 | }, |
| ... | ... | @@ -2043,7 +2043,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2043 | 2043 | ...base, |
| 2044 | 2044 | type: "task.progress", |
| 2045 | 2045 | payload: { |
| 2046 | taskId: RuntimeTaskId.makeUnsafe(message.task_id), | |
| 2046 | taskId: RuntimeTaskId.make(message.task_id), | |
| 2047 | 2047 | description: message.description, |
| 2048 | 2048 | ...(message.summary ? { summary: message.summary } : {}), |
| 2049 | 2049 | ...(message.usage ? { usage: message.usage } : {}), |
| ... | ... | @@ -2075,7 +2075,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2075 | 2075 | ...base, |
| 2076 | 2076 | type: "task.completed", |
| 2077 | 2077 | payload: { |
| 2078 | taskId: RuntimeTaskId.makeUnsafe(message.task_id), | |
| 2078 | taskId: RuntimeTaskId.make(message.task_id), | |
| 2079 | 2079 | status: message.status, |
| 2080 | 2080 | ...(message.summary ? { summary: message.summary } : {}), |
| 2081 | 2081 | ...(message.usage ? { usage: message.usage } : {}), |
| ... | ... | @@ -2380,9 +2380,9 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2380 | 2380 | existingResumeSessionId === undefined ? yield* Random.nextUUIDv4 : undefined; |
| 2381 | 2381 | const sessionId = existingResumeSessionId ?? newSessionId; |
| 2382 | 2382 | |
| 2383 | const services = yield* Effect.services(); | |
| 2384 | const runFork = Effect.runForkWith(services); | |
| 2385 | const runPromise = Effect.runPromiseWith(services); | |
| 2383 | const runtimeContext = yield* Effect.context<never>(); | |
| 2384 | const runFork = Effect.runForkWith(runtimeContext); | |
| 2385 | const runPromise = Effect.runPromiseWith(runtimeContext); | |
| 2386 | 2386 | |
| 2387 | 2387 | const promptQueue = yield* Queue.unbounded<PromptQueueItem>(); |
| 2388 | 2388 | const prompt = Stream.fromQueue(promptQueue).pipe( |
| ... | ... | @@ -2409,7 +2409,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2409 | 2409 | toolInput: Record<string, unknown>, |
| 2410 | 2410 | callbackOptions: { readonly signal: AbortSignal; readonly toolUseID?: string }, |
| 2411 | 2411 | ) { |
| 2412 | const requestId = ApprovalRequestId.makeUnsafe(yield* Random.nextUUIDv4); | |
| 2412 | const requestId = ApprovalRequestId.make(yield* Random.nextUUIDv4); | |
| 2413 | 2413 | |
| 2414 | 2414 | // Parse questions from the SDK's AskUserQuestion input. |
| 2415 | 2415 | const rawQuestions = Array.isArray(toolInput.questions) ? toolInput.questions : []; |
| ... | ... | @@ -2562,7 +2562,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2562 | 2562 | } satisfies PermissionResult; |
| 2563 | 2563 | } |
| 2564 | 2564 | |
| 2565 | const requestId = ApprovalRequestId.makeUnsafe(yield* Random.nextUUIDv4); | |
| 2565 | const requestId = ApprovalRequestId.make(yield* Random.nextUUIDv4); | |
| 2566 | 2566 | const requestType = classifyRequestType(toolName); |
| 2567 | 2567 | const detail = summarizeToolRequest(toolName, toolInput); |
| 2568 | 2568 | const decisionDeferred = yield* Deferred.make<ProviderApprovalDecision>(); |
| ... | ... | @@ -2890,7 +2890,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( |
| 2890 | 2890 | }); |
| 2891 | 2891 | } |
| 2892 | 2892 | |
| 2893 | const turnId = TurnId.makeUnsafe(yield* Random.nextUUIDv4); | |
| 2893 | const turnId = TurnId.make(yield* Random.nextUUIDv4); | |
| 2894 | 2894 | const turnState: ClaudeTurnState = { |
| 2895 | 2895 | turnId, |
| 2896 | 2896 | startedAt: yield* nowIso, |
apps/server/src/provider/Layers/CodexAdapter.test.ts+8-8| ... | ... | @@ -28,10 +28,10 @@ import { CodexAdapter } from "../Services/CodexAdapter.ts"; |
| 28 | 28 | import { ProviderSessionDirectory } from "../Services/ProviderSessionDirectory.ts"; |
| 29 | 29 | import { makeCodexAdapterLive } from "./CodexAdapter.ts"; |
| 30 | 30 | |
| 31 | const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value); | |
| 32 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 33 | const asEventId = (value: string): EventId => EventId.makeUnsafe(value); | |
| 34 | const asItemId = (value: string): ProviderItemId => ProviderItemId.makeUnsafe(value); | |
| 31 | const asThreadId = (value: string): ThreadId => ThreadId.make(value); | |
| 32 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 33 | const asEventId = (value: string): EventId => EventId.make(value); | |
| 34 | const asItemId = (value: string): ProviderItemId => ProviderItemId.make(value); | |
| 35 | 35 | |
| 36 | 36 | class FakeCodexManager extends CodexAppServerManager { |
| 37 | 37 | public startSessionImpl = vi.fn( |
| ... | ... | @@ -556,7 +556,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 556 | 556 | threadId: asThreadId("thread-1"), |
| 557 | 557 | createdAt: new Date().toISOString(), |
| 558 | 558 | method: "serverRequest/resolved", |
| 559 | requestId: ApprovalRequestId.makeUnsafe("req-1"), | |
| 559 | requestId: ApprovalRequestId.make("req-1"), | |
| 560 | 560 | payload: { |
| 561 | 561 | request: { |
| 562 | 562 | method: "item/commandExecution/requestApproval", |
| ... | ... | @@ -592,7 +592,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 592 | 592 | threadId: asThreadId("thread-1"), |
| 593 | 593 | createdAt: new Date().toISOString(), |
| 594 | 594 | method: "serverRequest/resolved", |
| 595 | requestId: ApprovalRequestId.makeUnsafe("req-file-read-1"), | |
| 595 | requestId: ApprovalRequestId.make("req-file-read-1"), | |
| 596 | 596 | payload: { |
| 597 | 597 | request: { |
| 598 | 598 | method: "item/fileRead/requestApproval", |
| ... | ... | @@ -710,7 +710,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 710 | 710 | threadId: asThreadId("thread-1"), |
| 711 | 711 | createdAt: new Date().toISOString(), |
| 712 | 712 | method: "item/tool/requestUserInput", |
| 713 | requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 713 | requestId: ApprovalRequestId.make("req-user-input-1"), | |
| 714 | 714 | payload: { |
| 715 | 715 | questions: [ |
| 716 | 716 | { |
| ... | ... | @@ -735,7 +735,7 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 735 | 735 | threadId: asThreadId("thread-1"), |
| 736 | 736 | createdAt: new Date().toISOString(), |
| 737 | 737 | method: "item/tool/requestUserInput/answered", |
| 738 | requestId: ApprovalRequestId.makeUnsafe("req-user-input-1"), | |
| 738 | requestId: ApprovalRequestId.make("req-user-input-1"), | |
| 739 | 739 | payload: { |
| 740 | 740 | answers: { |
| 741 | 741 | sandbox_mode: { |
apps/server/src/provider/Layers/CodexAdapter.ts+9-9| ... | ... | @@ -22,7 +22,7 @@ import { |
| 22 | 22 | TurnId, |
| 23 | 23 | ProviderSendTurnInput, |
| 24 | 24 | } from "@t3tools/contracts"; |
| 25 | import { Effect, FileSystem, Layer, Queue, Schema, ServiceMap, Stream } from "effect"; | |
| 25 | import { Effect, FileSystem, Layer, Queue, Schema, Context, Stream } from "effect"; | |
| 26 | 26 | |
| 27 | 27 | import { |
| 28 | 28 | ProviderAdapterProcessError, |
| ... | ... | @@ -46,7 +46,7 @@ const PROVIDER = "codex" as const; |
| 46 | 46 | |
| 47 | 47 | export interface CodexAdapterLiveOptions { |
| 48 | 48 | readonly manager?: CodexAppServerManager; |
| 49 | readonly makeManager?: (services?: ServiceMap.ServiceMap<never>) => CodexAppServerManager; | |
| 49 | readonly makeManager?: (services?: Context.Context<never>) => CodexAppServerManager; | |
| 50 | 50 | readonly nativeEventLogPath?: string; |
| 51 | 51 | readonly nativeEventLogger?: EventNdjsonLogger; |
| 52 | 52 | } |
| ... | ... | @@ -162,11 +162,11 @@ function normalizeCodexTokenUsage(value: unknown): ThreadTokenUsageSnapshot | un |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | function toTurnId(value: string | undefined): TurnId | undefined { |
| 165 | return value?.trim() ? TurnId.makeUnsafe(value) : undefined; | |
| 165 | return value?.trim() ? TurnId.make(value) : undefined; | |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | 168 | function toProviderItemId(value: string | undefined): ProviderItemId | undefined { |
| 169 | return value?.trim() ? ProviderItemId.makeUnsafe(value) : undefined; | |
| 169 | return value?.trim() ? ProviderItemId.make(value) : undefined; | |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | function toTurnStatus(value: unknown): "completed" | "failed" | "cancelled" | "interrupted" { |
| ... | ... | @@ -454,15 +454,15 @@ function extractProposedPlanMarkdown(text: string | undefined): string | undefin |
| 454 | 454 | } |
| 455 | 455 | |
| 456 | 456 | function asRuntimeItemId(itemId: ProviderItemId): RuntimeItemId { |
| 457 | return RuntimeItemId.makeUnsafe(itemId); | |
| 457 | return RuntimeItemId.make(itemId); | |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | 460 | function asRuntimeRequestId(requestId: string): RuntimeRequestId { |
| 461 | return RuntimeRequestId.makeUnsafe(requestId); | |
| 461 | return RuntimeRequestId.make(requestId); | |
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | function asRuntimeTaskId(taskId: string): RuntimeTaskId { |
| 465 | return RuntimeTaskId.makeUnsafe(taskId); | |
| 465 | return RuntimeTaskId.make(taskId); | |
| 466 | 466 | } |
| 467 | 467 | |
| 468 | 468 | function codexEventMessage( |
| ... | ... | @@ -1366,7 +1366,7 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* ( |
| 1366 | 1366 | if (options?.manager) { |
| 1367 | 1367 | return options.manager; |
| 1368 | 1368 | } |
| 1369 | const services = yield* Effect.services<never>(); | |
| 1369 | const services = yield* Effect.context<never>(); | |
| 1370 | 1370 | return options?.makeManager?.(services) ?? new CodexAppServerManager(services); |
| 1371 | 1371 | }); |
| 1372 | 1372 | |
| ... | ... | @@ -1585,7 +1585,7 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* ( |
| 1585 | 1585 | }); |
| 1586 | 1586 | |
| 1587 | 1587 | const registerListener = Effect.fn("registerListener")(function* () { |
| 1588 | const services = yield* Effect.services<never>(); | |
| 1588 | const services = yield* Effect.context<never>(); | |
| 1589 | 1589 | const listenerEffect = Effect.fn("listener")(function* (event: ProviderEvent) { |
| 1590 | 1590 | yield* writeNativeEvent(event); |
| 1591 | 1591 | const runtimeEvents = mapToRuntimeEvents(event, event.threadId); |
apps/server/src/provider/Layers/EventNdjsonLogger.test.ts+3-3| ... | ... | @@ -42,11 +42,11 @@ describe("EventNdjsonLogger", () => { |
| 42 | 42 | |
| 43 | 43 | yield* logger.write( |
| 44 | 44 | { threadId: "provider-thread-1", id: "evt-1" }, |
| 45 | ThreadId.makeUnsafe("thread-1"), | |
| 45 | ThreadId.make("thread-1"), | |
| 46 | 46 | ); |
| 47 | 47 | yield* logger.write( |
| 48 | 48 | { type: "turn.completed", threadId: "provider-thread-2", id: "evt-2" }, |
| 49 | ThreadId.makeUnsafe("thread-2"), | |
| 49 | ThreadId.make("thread-2"), | |
| 50 | 50 | ); |
| 51 | 51 | yield* logger.close(); |
| 52 | 52 | |
| ... | ... | @@ -178,7 +178,7 @@ describe("EventNdjsonLogger", () => { |
| 178 | 178 | id: `evt-${index}`, |
| 179 | 179 | payload: "x".repeat(40), |
| 180 | 180 | }, |
| 181 | ThreadId.makeUnsafe("thread-rotate"), | |
| 181 | ThreadId.make("thread-rotate"), | |
| 182 | 182 | ); |
| 183 | 183 | } |
| 184 | 184 | yield* logger.close(); |
apps/server/src/provider/Layers/ProviderRegistry.test.ts+1| ... | ... | @@ -44,6 +44,7 @@ function mockHandle(result: { stdout: string; stderr: string; code: number }) { |
| 44 | 44 | exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(result.code)), |
| 45 | 45 | isRunning: Effect.succeed(false), |
| 46 | 46 | kill: () => Effect.void, |
| 47 | unref: Effect.succeed(Effect.void), | |
| 47 | 48 | stdin: Sink.drain, |
| 48 | 49 | stdout: Stream.make(encoder.encode(result.stdout)), |
| 49 | 50 | stderr: Stream.make(encoder.encode(result.stderr)), |
apps/server/src/provider/Layers/ProviderService.test.ts+6-6| ... | ... | @@ -47,10 +47,10 @@ import { AnalyticsService } from "../../telemetry/Services/AnalyticsService.ts"; |
| 47 | 47 | |
| 48 | 48 | const defaultServerSettingsLayer = ServerSettingsService.layerTest(); |
| 49 | 49 | |
| 50 | const asRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.makeUnsafe(value); | |
| 51 | const asEventId = (value: string): EventId => EventId.makeUnsafe(value); | |
| 52 | const asThreadId = (value: string): ThreadId => ThreadId.makeUnsafe(value); | |
| 53 | const asTurnId = (value: string): TurnId => TurnId.makeUnsafe(value); | |
| 50 | const asRequestId = (value: string): ApprovalRequestId => ApprovalRequestId.make(value); | |
| 51 | const asEventId = (value: string): EventId => EventId.make(value); | |
| 52 | const asThreadId = (value: string): ThreadId => ThreadId.make(value); | |
| 53 | const asTurnId = (value: string): TurnId => TurnId.make(value); | |
| 54 | 54 | |
| 55 | 55 | type LegacyProviderRuntimeEvent = { |
| 56 | 56 | readonly type: string; |
| ... | ... | @@ -102,7 +102,7 @@ function makeFakeCodexAdapter(provider: ProviderKind = "codex") { |
| 102 | 102 | |
| 103 | 103 | return Effect.succeed({ |
| 104 | 104 | threadId: input.threadId, |
| 105 | turnId: TurnId.makeUnsafe(`turn-${String(input.threadId)}`), | |
| 105 | turnId: TurnId.make(`turn-${String(input.threadId)}`), | |
| 106 | 106 | }); |
| 107 | 107 | }, |
| 108 | 108 | ); |
| ... | ... | @@ -358,7 +358,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", ( |
| 358 | 358 | const directory = yield* ProviderSessionDirectory; |
| 359 | 359 | yield* directory.upsert({ |
| 360 | 360 | provider: "codex", |
| 361 | threadId: ThreadId.makeUnsafe("thread-stale"), | |
| 361 | threadId: ThreadId.make("thread-stale"), | |
| 362 | 362 | }); |
| 363 | 363 | }).pipe(Effect.provide(directoryLayer)); |
| 364 | 364 |
apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts+5-5| ... | ... | @@ -36,7 +36,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 36 | 36 | const directory = yield* ProviderSessionDirectory; |
| 37 | 37 | const runtimeRepository = yield* ProviderSessionRuntimeRepository; |
| 38 | 38 | |
| 39 | const initialThreadId = ThreadId.makeUnsafe("thread-1"); | |
| 39 | const initialThreadId = ThreadId.make("thread-1"); | |
| 40 | 40 | |
| 41 | 41 | yield* directory.upsert({ |
| 42 | 42 | provider: "codex", |
| ... | ... | @@ -54,7 +54,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 54 | 54 | assert.equal(resolvedBinding.value.threadId, initialThreadId); |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | const nextThreadId = ThreadId.makeUnsafe("thread-2"); | |
| 57 | const nextThreadId = ThreadId.make("thread-2"); | |
| 58 | 58 | |
| 59 | 59 | yield* directory.upsert({ |
| 60 | 60 | provider: "codex", |
| ... | ... | @@ -93,7 +93,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 93 | 93 | const directory = yield* ProviderSessionDirectory; |
| 94 | 94 | const runtimeRepository = yield* ProviderSessionRuntimeRepository; |
| 95 | 95 | |
| 96 | const threadId = ThreadId.makeUnsafe("thread-runtime"); | |
| 96 | const threadId = ThreadId.make("thread-runtime"); | |
| 97 | 97 | |
| 98 | 98 | yield* directory.upsert({ |
| 99 | 99 | provider: "codex", |
| ... | ... | @@ -137,7 +137,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 137 | 137 | Effect.gen(function* () { |
| 138 | 138 | const directory = yield* ProviderSessionDirectory; |
| 139 | 139 | const runtimeRepository = yield* ProviderSessionRuntimeRepository; |
| 140 | const threadId = ThreadId.makeUnsafe("thread-provider-change"); | |
| 140 | const threadId = ThreadId.make("thread-provider-change"); | |
| 141 | 141 | |
| 142 | 142 | yield* runtimeRepository.upsert({ |
| 143 | 143 | threadId, |
| ... | ... | @@ -169,7 +169,7 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 169 | 169 | const dbPath = path.join(tempDir, "orchestration.sqlite"); |
| 170 | 170 | const directoryLayer = makeDirectoryLayer(makeSqlitePersistenceLive(dbPath)); |
| 171 | 171 | |
| 172 | const threadId = ThreadId.makeUnsafe("thread-restart"); | |
| 172 | const threadId = ThreadId.make("thread-restart"); | |
| 173 | 173 | |
| 174 | 174 | yield* Effect.gen(function* () { |
| 175 | 175 | const directory = yield* ProviderSessionDirectory; |
apps/server/src/provider/Services/ClaudeAdapter.ts+3-3| ... | ... | @@ -5,12 +5,12 @@ |
| 5 | 5 | * provider runtime events. It does not perform cross-provider routing, shared |
| 6 | 6 | * event fan-out, or checkpoint orchestration. |
| 7 | 7 | * |
| 8 | * Uses Effect `ServiceMap.Service` for dependency injection and returns the | |
| 8 | * Uses Effect `Context.Service` for dependency injection and returns the | |
| 9 | 9 | * shared provider-adapter error channel with `provider: "claudeAgent"` context. |
| 10 | 10 | * |
| 11 | 11 | * @module ClaudeAdapter |
| 12 | 12 | */ |
| 13 | import { ServiceMap } from "effect"; | |
| 13 | import { Context } from "effect"; | |
| 14 | 14 | |
| 15 | 15 | import type { ProviderAdapterError } from "../Errors.ts"; |
| 16 | 16 | import type { ProviderAdapterShape } from "./ProviderAdapter.ts"; |
| ... | ... | @@ -25,6 +25,6 @@ export interface ClaudeAdapterShape extends ProviderAdapterShape<ProviderAdapter |
| 25 | 25 | /** |
| 26 | 26 | * ClaudeAdapter - Service tag for Claude Agent provider adapter operations. |
| 27 | 27 | */ |
| 28 | export class ClaudeAdapter extends ServiceMap.Service<ClaudeAdapter, ClaudeAdapterShape>()( | |
| 28 | export class ClaudeAdapter extends Context.Service<ClaudeAdapter, ClaudeAdapterShape>()( | |
| 29 | 29 | "t3/provider/Services/ClaudeAdapter", |
| 30 | 30 | ) {} |
apps/server/src/provider/Services/ClaudeProvider.ts+2-2| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | import { ServiceMap } from "effect"; | |
| 1 | import { Context } from "effect"; | |
| 2 | 2 | |
| 3 | 3 | import type { ServerProviderShape } from "./ServerProvider"; |
| 4 | 4 | |
| 5 | 5 | export interface ClaudeProviderShape extends ServerProviderShape {} |
| 6 | 6 | |
| 7 | export class ClaudeProvider extends ServiceMap.Service<ClaudeProvider, ClaudeProviderShape>()( | |
| 7 | export class ClaudeProvider extends Context.Service<ClaudeProvider, ClaudeProviderShape>()( | |
| 8 | 8 | "t3/provider/Services/ClaudeProvider", |
| 9 | 9 | ) {} |
apps/server/src/provider/Services/CodexAdapter.ts+3-3| ... | ... | @@ -5,12 +5,12 @@ |
| 5 | 5 | * Codex provider events. It does not perform cross-provider routing, shared |
| 6 | 6 | * event fan-out, or checkpoint orchestration. |
| 7 | 7 | * |
| 8 | * Uses Effect `ServiceMap.Service` for dependency injection and returns the | |
| 8 | * Uses Effect `Context.Service` for dependency injection and returns the | |
| 9 | 9 | * shared provider-adapter error channel with `provider: "codex"` context. |
| 10 | 10 | * |
| 11 | 11 | * @module CodexAdapter |
| 12 | 12 | */ |
| 13 | import { ServiceMap } from "effect"; | |
| 13 | import { Context } from "effect"; | |
| 14 | 14 | |
| 15 | 15 | import type { ProviderAdapterError } from "../Errors.ts"; |
| 16 | 16 | import type { ProviderAdapterShape } from "./ProviderAdapter.ts"; |
| ... | ... | @@ -25,6 +25,6 @@ export interface CodexAdapterShape extends ProviderAdapterShape<ProviderAdapterE |
| 25 | 25 | /** |
| 26 | 26 | * CodexAdapter - Service tag for Codex provider adapter operations. |
| 27 | 27 | */ |
| 28 | export class CodexAdapter extends ServiceMap.Service<CodexAdapter, CodexAdapterShape>()( | |
| 28 | export class CodexAdapter extends Context.Service<CodexAdapter, CodexAdapterShape>()( | |
| 29 | 29 | "t3/provider/Services/CodexAdapter", |
| 30 | 30 | ) {} |
apps/server/src/provider/Services/CodexProvider.ts+2-2| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | import { ServiceMap } from "effect"; | |
| 1 | import { Context } from "effect"; | |
| 2 | 2 | |
| 3 | 3 | import type { ServerProviderShape } from "./ServerProvider"; |
| 4 | 4 | |
| 5 | 5 | export interface CodexProviderShape extends ServerProviderShape {} |
| 6 | 6 | |
| 7 | export class CodexProvider extends ServiceMap.Service<CodexProvider, CodexProviderShape>()( | |
| 7 | export class CodexProvider extends Context.Service<CodexProvider, CodexProviderShape>()( | |
| 8 | 8 | "t3/provider/Services/CodexProvider", |
| 9 | 9 | ) {} |
apps/server/src/provider/Services/ProviderAdapterRegistry.ts+2-2| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | * @module ProviderAdapterRegistry |
| 9 | 9 | */ |
| 10 | 10 | import type { ProviderKind } from "@t3tools/contracts"; |
| 11 | import { ServiceMap } from "effect"; | |
| 11 | import { Context } from "effect"; | |
| 12 | 12 | import type { Effect } from "effect"; |
| 13 | 13 | |
| 14 | 14 | import type { ProviderAdapterError, ProviderUnsupportedError } from "../Errors.ts"; |
| ... | ... | @@ -34,7 +34,7 @@ export interface ProviderAdapterRegistryShape { |
| 34 | 34 | /** |
| 35 | 35 | * ProviderAdapterRegistry - Service tag for provider adapter lookup. |
| 36 | 36 | */ |
| 37 | export class ProviderAdapterRegistry extends ServiceMap.Service< | |
| 37 | export class ProviderAdapterRegistry extends Context.Service< | |
| 38 | 38 | ProviderAdapterRegistry, |
| 39 | 39 | ProviderAdapterRegistryShape |
| 40 | 40 | >()("t3/provider/Services/ProviderAdapterRegistry") {} |
apps/server/src/provider/Services/ProviderRegistry.ts+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | * @module ProviderRegistry |
| 8 | 8 | */ |
| 9 | 9 | import type { ProviderKind, ServerProvider } from "@t3tools/contracts"; |
| 10 | import { ServiceMap } from "effect"; | |
| 10 | import { Context } from "effect"; | |
| 11 | 11 | import type { Effect, Stream } from "effect"; |
| 12 | 12 | |
| 13 | 13 | export interface ProviderRegistryShape { |
| ... | ... | @@ -27,6 +27,6 @@ export interface ProviderRegistryShape { |
| 27 | 27 | readonly streamChanges: Stream.Stream<ReadonlyArray<ServerProvider>>; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | export class ProviderRegistry extends ServiceMap.Service<ProviderRegistry, ProviderRegistryShape>()( | |
| 30 | export class ProviderRegistry extends Context.Service<ProviderRegistry, ProviderRegistryShape>()( | |
| 31 | 31 | "t3/provider/Services/ProviderRegistry", |
| 32 | 32 | ) {} |
apps/server/src/provider/Services/ProviderService.ts+3-3| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * session-scoped calls via `ProviderSessionDirectory`, and exposes one unified |
| 7 | 7 | * provider event stream to callers. |
| 8 | 8 | * |
| 9 | * Uses Effect `ServiceMap.Service` for dependency injection and returns typed | |
| 9 | * Uses Effect `Context.Service` for dependency injection and returns typed | |
| 10 | 10 | * domain errors for validation, session, codex, and checkpoint workflows. |
| 11 | 11 | * |
| 12 | 12 | * @module ProviderService |
| ... | ... | @@ -24,7 +24,7 @@ import type { |
| 24 | 24 | ThreadId, |
| 25 | 25 | ProviderTurnStartResult, |
| 26 | 26 | } from "@t3tools/contracts"; |
| 27 | import { ServiceMap } from "effect"; | |
| 27 | import { Context } from "effect"; | |
| 28 | 28 | import type { Effect, Stream } from "effect"; |
| 29 | 29 | |
| 30 | 30 | import type { ProviderServiceError } from "../Errors.ts"; |
| ... | ... | @@ -110,6 +110,6 @@ export interface ProviderServiceShape { |
| 110 | 110 | /** |
| 111 | 111 | * ProviderService - Service tag for provider orchestration. |
| 112 | 112 | */ |
| 113 | export class ProviderService extends ServiceMap.Service<ProviderService, ProviderServiceShape>()( | |
| 113 | export class ProviderService extends Context.Service<ProviderService, ProviderServiceShape>()( | |
| 114 | 114 | "t3/provider/Services/ProviderService", |
| 115 | 115 | ) {} |
apps/server/src/provider/Services/ProviderSessionDirectory.ts+2-2| ... | ... | @@ -4,7 +4,7 @@ import type { |
| 4 | 4 | RuntimeMode, |
| 5 | 5 | ThreadId, |
| 6 | 6 | } from "@t3tools/contracts"; |
| 7 | import { Option, ServiceMap } from "effect"; | |
| 7 | import { Option, Context } from "effect"; | |
| 8 | 8 | import type { Effect } from "effect"; |
| 9 | 9 | |
| 10 | 10 | import type { |
| ... | ... | @@ -51,7 +51,7 @@ export interface ProviderSessionDirectoryShape { |
| 51 | 51 | >; |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | export class ProviderSessionDirectory extends ServiceMap.Service< | |
| 54 | export class ProviderSessionDirectory extends Context.Service< | |
| 55 | 55 | ProviderSessionDirectory, |
| 56 | 56 | ProviderSessionDirectoryShape |
| 57 | 57 | >()("t3/provider/Services/ProviderSessionDirectory") {} |
apps/server/src/server.test.ts+32-32| ... | ... | @@ -101,15 +101,15 @@ import { WorkspacePathsLive } from "./workspace/Layers/WorkspacePaths.ts"; |
| 101 | 101 | import { ServerSecretStoreLive } from "./auth/Layers/ServerSecretStore.ts"; |
| 102 | 102 | import { ServerAuthLive } from "./auth/Layers/ServerAuth.ts"; |
| 103 | 103 | |
| 104 | const defaultProjectId = ProjectId.makeUnsafe("project-default"); | |
| 105 | const defaultThreadId = ThreadId.makeUnsafe("thread-default"); | |
| 104 | const defaultProjectId = ProjectId.make("project-default"); | |
| 105 | const defaultThreadId = ThreadId.make("thread-default"); | |
| 106 | 106 | const defaultDesktopBootstrapToken = "test-desktop-bootstrap-token"; |
| 107 | 107 | const defaultModelSelection = { |
| 108 | 108 | provider: "codex", |
| 109 | 109 | model: "gpt-5-codex", |
| 110 | 110 | } as const; |
| 111 | 111 | const testEnvironmentDescriptor = { |
| 112 | environmentId: EnvironmentId.makeUnsafe("environment-test"), | |
| 112 | environmentId: EnvironmentId.make("environment-test"), | |
| 113 | 113 | label: "Test environment", |
| 114 | 114 | platform: { |
| 115 | 115 | os: "darwin" as const, |
| ... | ... | @@ -1307,7 +1307,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 1307 | 1307 | ); |
| 1308 | 1308 | |
| 1309 | 1309 | assert.equal(error._tag, "RpcClientError"); |
| 1310 | assertInclude(String(error), "401"); | |
| 1310 | assertInclude(String(error), "SocketOpenError"); | |
| 1311 | 1311 | }).pipe(Effect.provide(NodeHttpServer.layerTest)), |
| 1312 | 1312 | ); |
| 1313 | 1313 | |
| ... | ... | @@ -2685,7 +2685,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2685 | 2685 | updatedAt: now, |
| 2686 | 2686 | projects: [ |
| 2687 | 2687 | { |
| 2688 | id: ProjectId.makeUnsafe("project-a"), | |
| 2688 | id: ProjectId.make("project-a"), | |
| 2689 | 2689 | title: "Project A", |
| 2690 | 2690 | workspaceRoot: "/tmp/project-a", |
| 2691 | 2691 | defaultModelSelection, |
| ... | ... | @@ -2697,8 +2697,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2697 | 2697 | ], |
| 2698 | 2698 | threads: [ |
| 2699 | 2699 | { |
| 2700 | id: ThreadId.makeUnsafe("thread-1"), | |
| 2701 | projectId: ProjectId.makeUnsafe("project-a"), | |
| 2700 | id: ThreadId.make("thread-1"), | |
| 2701 | projectId: ProjectId.make("project-a"), | |
| 2702 | 2702 | title: "Thread A", |
| 2703 | 2703 | modelSelection: defaultModelSelection, |
| 2704 | 2704 | interactionMode: "default" as const, |
| ... | ... | @@ -2731,14 +2731,14 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2731 | 2731 | checkpointDiffQuery: { |
| 2732 | 2732 | getTurnDiff: () => |
| 2733 | 2733 | Effect.succeed({ |
| 2734 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 2734 | threadId: ThreadId.make("thread-1"), | |
| 2735 | 2735 | fromTurnCount: 0, |
| 2736 | 2736 | toTurnCount: 1, |
| 2737 | 2737 | diff: "turn-diff", |
| 2738 | 2738 | }), |
| 2739 | 2739 | getFullThreadDiff: () => |
| 2740 | 2740 | Effect.succeed({ |
| 2741 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 2741 | threadId: ThreadId.make("thread-1"), | |
| 2742 | 2742 | fromTurnCount: 0, |
| 2743 | 2743 | toTurnCount: 1, |
| 2744 | 2744 | diff: "full-diff", |
| ... | ... | @@ -2757,8 +2757,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2757 | 2757 | withWsRpcClient(wsUrl, (client) => |
| 2758 | 2758 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 2759 | 2759 | type: "thread.session.stop", |
| 2760 | commandId: CommandId.makeUnsafe("cmd-1"), | |
| 2761 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 2760 | commandId: CommandId.make("cmd-1"), | |
| 2761 | threadId: ThreadId.make("thread-1"), | |
| 2762 | 2762 | createdAt: now, |
| 2763 | 2763 | }), |
| 2764 | 2764 | ), |
| ... | ... | @@ -2768,7 +2768,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2768 | 2768 | const turnDiffResult = yield* Effect.scoped( |
| 2769 | 2769 | withWsRpcClient(wsUrl, (client) => |
| 2770 | 2770 | client[ORCHESTRATION_WS_METHODS.getTurnDiff]({ |
| 2771 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 2771 | threadId: ThreadId.make("thread-1"), | |
| 2772 | 2772 | fromTurnCount: 0, |
| 2773 | 2773 | toTurnCount: 1, |
| 2774 | 2774 | }), |
| ... | ... | @@ -2779,7 +2779,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2779 | 2779 | const fullDiffResult = yield* Effect.scoped( |
| 2780 | 2780 | withWsRpcClient(wsUrl, (client) => |
| 2781 | 2781 | client[ORCHESTRATION_WS_METHODS.getFullThreadDiff]({ |
| 2782 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 2782 | threadId: ThreadId.make("thread-1"), | |
| 2783 | 2783 | toTurnCount: 1, |
| 2784 | 2784 | }), |
| 2785 | 2785 | ), |
| ... | ... | @@ -2818,7 +2818,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2818 | 2818 | readEvents: (_fromSequenceExclusive) => |
| 2819 | 2819 | Stream.make({ |
| 2820 | 2820 | sequence: 1, |
| 2821 | eventId: EventId.makeUnsafe("event-1"), | |
| 2821 | eventId: EventId.make("event-1"), | |
| 2822 | 2822 | aggregateKind: "project", |
| 2823 | 2823 | aggregateId: defaultProjectId, |
| 2824 | 2824 | occurredAt: "2026-04-05T00:00:00.000Z", |
| ... | ... | @@ -2866,7 +2866,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2866 | 2866 | |
| 2867 | 2867 | it.effect("closes thread terminals after a successful archive command", () => |
| 2868 | 2868 | Effect.gen(function* () { |
| 2869 | const threadId = ThreadId.makeUnsafe("thread-archive"); | |
| 2869 | const threadId = ThreadId.make("thread-archive"); | |
| 2870 | 2870 | const closeInputs: Array<Parameters<TerminalManagerShape["close"]>[0]> = []; |
| 2871 | 2871 | |
| 2872 | 2872 | yield* buildAppUnderTest({ |
| ... | ... | @@ -2888,7 +2888,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2888 | 2888 | withWsRpcClient(wsUrl, (client) => |
| 2889 | 2889 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 2890 | 2890 | type: "thread.archive", |
| 2891 | commandId: CommandId.makeUnsafe("cmd-thread-archive"), | |
| 2891 | commandId: CommandId.make("cmd-thread-archive"), | |
| 2892 | 2892 | threadId, |
| 2893 | 2893 | }), |
| 2894 | 2894 | ), |
| ... | ... | @@ -2948,10 +2948,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2948 | 2948 | withWsRpcClient(wsUrl, (client) => |
| 2949 | 2949 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 2950 | 2950 | type: "thread.turn.start", |
| 2951 | commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start"), | |
| 2952 | threadId: ThreadId.makeUnsafe("thread-bootstrap"), | |
| 2951 | commandId: CommandId.make("cmd-bootstrap-turn-start"), | |
| 2952 | threadId: ThreadId.make("thread-bootstrap"), | |
| 2953 | 2953 | message: { |
| 2954 | messageId: MessageId.makeUnsafe("msg-bootstrap"), | |
| 2954 | messageId: MessageId.make("msg-bootstrap"), | |
| 2955 | 2955 | role: "user", |
| 2956 | 2956 | text: "hello", |
| 2957 | 2957 | attachments: [], |
| ... | ... | @@ -3000,7 +3000,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3000 | 3000 | path: null, |
| 3001 | 3001 | }); |
| 3002 | 3002 | assert.deepEqual(runForThread.mock.calls[0]?.[0], { |
| 3003 | threadId: ThreadId.makeUnsafe("thread-bootstrap"), | |
| 3003 | threadId: ThreadId.make("thread-bootstrap"), | |
| 3004 | 3004 | projectId: defaultProjectId, |
| 3005 | 3005 | projectCwd: "/tmp/project", |
| 3006 | 3006 | worktreePath: "/tmp/bootstrap-worktree", |
| ... | ... | @@ -3063,10 +3063,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3063 | 3063 | withWsRpcClient(wsUrl, (client) => |
| 3064 | 3064 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 3065 | 3065 | type: "thread.turn.start", |
| 3066 | commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start-setup-failure"), | |
| 3067 | threadId: ThreadId.makeUnsafe("thread-bootstrap-setup-failure"), | |
| 3066 | commandId: CommandId.make("cmd-bootstrap-turn-start-setup-failure"), | |
| 3067 | threadId: ThreadId.make("thread-bootstrap-setup-failure"), | |
| 3068 | 3068 | message: { |
| 3069 | messageId: MessageId.makeUnsafe("msg-bootstrap-setup-failure"), | |
| 3069 | messageId: MessageId.make("msg-bootstrap-setup-failure"), | |
| 3070 | 3070 | role: "user", |
| 3071 | 3071 | text: "hello", |
| 3072 | 3072 | attachments: [], |
| ... | ... | @@ -3179,10 +3179,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3179 | 3179 | withWsRpcClient(wsUrl, (client) => |
| 3180 | 3180 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 3181 | 3181 | type: "thread.turn.start", |
| 3182 | commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start-setup-activity-failure"), | |
| 3183 | threadId: ThreadId.makeUnsafe("thread-bootstrap-setup-activity-failure"), | |
| 3182 | commandId: CommandId.make("cmd-bootstrap-turn-start-setup-activity-failure"), | |
| 3183 | threadId: ThreadId.make("thread-bootstrap-setup-activity-failure"), | |
| 3184 | 3184 | message: { |
| 3185 | messageId: MessageId.makeUnsafe("msg-bootstrap-setup-activity-failure"), | |
| 3185 | messageId: MessageId.make("msg-bootstrap-setup-activity-failure"), | |
| 3186 | 3186 | role: "user", |
| 3187 | 3187 | text: "hello", |
| 3188 | 3188 | attachments: [], |
| ... | ... | @@ -3262,10 +3262,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3262 | 3262 | withWsRpcClient(wsUrl, (client) => |
| 3263 | 3263 | client[ORCHESTRATION_WS_METHODS.dispatchCommand]({ |
| 3264 | 3264 | type: "thread.turn.start", |
| 3265 | commandId: CommandId.makeUnsafe("cmd-bootstrap-turn-start-defect"), | |
| 3266 | threadId: ThreadId.makeUnsafe("thread-bootstrap-defect"), | |
| 3265 | commandId: CommandId.make("cmd-bootstrap-turn-start-defect"), | |
| 3266 | threadId: ThreadId.make("thread-bootstrap-defect"), | |
| 3267 | 3267 | message: { |
| 3268 | messageId: MessageId.makeUnsafe("msg-bootstrap-defect"), | |
| 3268 | messageId: MessageId.make("msg-bootstrap-defect"), | |
| 3269 | 3269 | role: "user", |
| 3270 | 3270 | text: "hello", |
| 3271 | 3271 | attachments: [], |
| ... | ... | @@ -3311,7 +3311,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3311 | 3311 | () => |
| 3312 | 3312 | Effect.gen(function* () { |
| 3313 | 3313 | const now = new Date().toISOString(); |
| 3314 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 3314 | const threadId = ThreadId.make("thread-1"); | |
| 3315 | 3315 | let replayCursor: number | null = null; |
| 3316 | 3316 | const makeEvent = (sequence: number): OrchestrationEvent => |
| 3317 | 3317 | ({ |
| ... | ... | @@ -3393,7 +3393,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3393 | 3393 | readEvents: () => |
| 3394 | 3394 | Stream.make({ |
| 3395 | 3395 | sequence: 1, |
| 3396 | eventId: EventId.makeUnsafe("event-1"), | |
| 3396 | eventId: EventId.make("event-1"), | |
| 3397 | 3397 | aggregateKind: "project", |
| 3398 | 3398 | aggregateId: defaultProjectId, |
| 3399 | 3399 | occurredAt: "2026-04-06T00:00:00.000Z", |
| ... | ... | @@ -3464,7 +3464,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3464 | 3464 | }), |
| 3465 | 3465 | streamDomainEvents: Stream.make({ |
| 3466 | 3466 | sequence: 1, |
| 3467 | eventId: EventId.makeUnsafe("event-1"), | |
| 3467 | eventId: EventId.make("event-1"), | |
| 3468 | 3468 | aggregateKind: "project", |
| 3469 | 3469 | aggregateId: defaultProjectId, |
| 3470 | 3470 | occurredAt: "2026-04-05T00:00:00.000Z", |
apps/server/src/serverLifecycleEvents.test.ts+1-1| ... | ... | @@ -11,7 +11,7 @@ it.effect( |
| 11 | 11 | Effect.gen(function* () { |
| 12 | 12 | const lifecycleEvents = yield* ServerLifecycleEvents; |
| 13 | 13 | const environment = { |
| 14 | environmentId: EnvironmentId.makeUnsafe("environment-test"), | |
| 14 | environmentId: EnvironmentId.make("environment-test"), | |
| 15 | 15 | label: "Test environment", |
| 16 | 16 | platform: { os: "darwin" as const, arch: "arm64" as const }, |
| 17 | 17 | serverVersion: "0.0.0-test", |
apps/server/src/serverLifecycleEvents.ts+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | import type { ServerLifecycleStreamEvent } from "@t3tools/contracts"; |
| 2 | import { Effect, Layer, PubSub, Ref, ServiceMap, Stream } from "effect"; | |
| 2 | import { Effect, Layer, PubSub, Ref, Context, Stream } from "effect"; | |
| 3 | 3 | |
| 4 | 4 | type LifecycleEventInput = |
| 5 | 5 | | Omit<Extract<ServerLifecycleStreamEvent, { type: "welcome" }>, "sequence"> |
| ... | ... | @@ -16,7 +16,7 @@ export interface ServerLifecycleEventsShape { |
| 16 | 16 | readonly stream: Stream.Stream<ServerLifecycleStreamEvent>; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | export class ServerLifecycleEvents extends ServiceMap.Service< | |
| 19 | export class ServerLifecycleEvents extends Context.Service< | |
| 20 | 20 | ServerLifecycleEvents, |
| 21 | 21 | ServerLifecycleEventsShape |
| 22 | 22 | >()("t3/serverLifecycleEvents") {} |
apps/server/src/serverRuntimeStartup.ts+6-6| ... | ... | @@ -17,7 +17,7 @@ import { |
| 17 | 17 | Queue, |
| 18 | 18 | Ref, |
| 19 | 19 | Scope, |
| 20 | ServiceMap, | |
| 20 | Context, | |
| 21 | 21 | Console, |
| 22 | 22 | } from "effect"; |
| 23 | 23 | |
| ... | ... | @@ -52,7 +52,7 @@ export interface ServerRuntimeStartupShape { |
| 52 | 52 | ) => Effect.Effect<A, E | ServerRuntimeStartupError>; |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | export class ServerRuntimeStartup extends ServiceMap.Service< | |
| 55 | export class ServerRuntimeStartup extends Context.Service< | |
| 56 | 56 | ServerRuntimeStartup, |
| 57 | 57 | ServerRuntimeStartupShape |
| 58 | 58 | >()("t3/serverRuntimeStartup") {} |
| ... | ... | @@ -176,12 +176,12 @@ const autoBootstrapWelcome = Effect.gen(function* () { |
| 176 | 176 | |
| 177 | 177 | if (Option.isNone(existingProject)) { |
| 178 | 178 | const createdAt = new Date().toISOString(); |
| 179 | nextProjectId = ProjectId.makeUnsafe(crypto.randomUUID()); | |
| 179 | nextProjectId = ProjectId.make(crypto.randomUUID()); | |
| 180 | 180 | const bootstrapProjectTitle = path.basename(serverConfig.cwd) || "project"; |
| 181 | 181 | nextProjectDefaultModelSelection = getAutoBootstrapDefaultModelSelection(); |
| 182 | 182 | yield* orchestrationEngine.dispatch({ |
| 183 | 183 | type: "project.create", |
| 184 | commandId: CommandId.makeUnsafe(crypto.randomUUID()), | |
| 184 | commandId: CommandId.make(crypto.randomUUID()), | |
| 185 | 185 | projectId: nextProjectId, |
| 186 | 186 | title: bootstrapProjectTitle, |
| 187 | 187 | workspaceRoot: serverConfig.cwd, |
| ... | ... | @@ -198,10 +198,10 @@ const autoBootstrapWelcome = Effect.gen(function* () { |
| 198 | 198 | yield* projectionReadModelQuery.getFirstActiveThreadIdByProjectId(nextProjectId); |
| 199 | 199 | if (Option.isNone(existingThreadId)) { |
| 200 | 200 | const createdAt = new Date().toISOString(); |
| 201 | const createdThreadId = ThreadId.makeUnsafe(crypto.randomUUID()); | |
| 201 | const createdThreadId = ThreadId.make(crypto.randomUUID()); | |
| 202 | 202 | yield* orchestrationEngine.dispatch({ |
| 203 | 203 | type: "thread.create", |
| 204 | commandId: CommandId.makeUnsafe(crypto.randomUUID()), | |
| 204 | commandId: CommandId.make(crypto.randomUUID()), | |
| 205 | 205 | threadId: createdThreadId, |
| 206 | 206 | projectId: nextProjectId, |
| 207 | 207 | title: "New thread", |
apps/server/src/serverSettings.ts+2-2| ... | ... | @@ -34,7 +34,7 @@ import { |
| 34 | 34 | Schema, |
| 35 | 35 | SchemaIssue, |
| 36 | 36 | Scope, |
| 37 | ServiceMap, | |
| 37 | Context, | |
| 38 | 38 | Stream, |
| 39 | 39 | Cause, |
| 40 | 40 | } from "effect"; |
| ... | ... | @@ -62,7 +62,7 @@ export interface ServerSettingsShape { |
| 62 | 62 | readonly streamChanges: Stream.Stream<ServerSettings>; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | export class ServerSettingsService extends ServiceMap.Service< | |
| 65 | export class ServerSettingsService extends Context.Service< | |
| 66 | 66 | ServerSettingsService, |
| 67 | 67 | ServerSettingsShape |
| 68 | 68 | >()("t3/serverSettings/ServerSettingsService") { |
apps/server/src/telemetry/Services/AnalyticsService.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module AnalyticsService |
| 8 | 8 | */ |
| 9 | import { Effect, Layer, ServiceMap } from "effect"; | |
| 9 | import { Effect, Layer, Context } from "effect"; | |
| 10 | 10 | |
| 11 | 11 | export interface AnalyticsServiceShape { |
| 12 | 12 | /** |
| ... | ... | @@ -23,7 +23,7 @@ export interface AnalyticsServiceShape { |
| 23 | 23 | readonly flush: Effect.Effect<void, never>; |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | export class AnalyticsService extends ServiceMap.Service<AnalyticsService, AnalyticsServiceShape>()( | |
| 26 | export class AnalyticsService extends Context.Service<AnalyticsService, AnalyticsServiceShape>()( | |
| 27 | 27 | "t3/telemetry/Services/AnalyticsService", |
| 28 | 28 | ) { |
| 29 | 29 | static readonly layerTest = Layer.succeed(AnalyticsService, { |
apps/server/src/terminal/Layers/Manager.ts+2-2| ... | ... | @@ -664,8 +664,8 @@ const makeTerminalManager = Effect.fn("makeTerminalManager")(function* () { |
| 664 | 664 | export const makeTerminalManagerWithOptions = Effect.fn("makeTerminalManagerWithOptions")( |
| 665 | 665 | function* (options: TerminalManagerOptions) { |
| 666 | 666 | const fileSystem = yield* FileSystem.FileSystem; |
| 667 | const services = yield* Effect.services(); | |
| 668 | const runFork = Effect.runForkWith(services); | |
| 667 | const context = yield* Effect.context<never>(); | |
| 668 | const runFork = Effect.runForkWith(context); | |
| 669 | 669 | |
| 670 | 670 | const logsDir = options.logsDir; |
| 671 | 671 | const historyLineLimit = options.historyLineLimit ?? DEFAULT_HISTORY_LINE_LIMIT; |
apps/server/src/terminal/Services/Manager.ts+2-2| ... | ... | @@ -23,7 +23,7 @@ import { |
| 23 | 23 | TerminalWriteInput, |
| 24 | 24 | } from "@t3tools/contracts"; |
| 25 | 25 | import { PtyProcess } from "./PTY"; |
| 26 | import { Effect, ServiceMap } from "effect"; | |
| 26 | import { Effect, Context } from "effect"; | |
| 27 | 27 | |
| 28 | 28 | export { |
| 29 | 29 | TerminalCwdError, |
| ... | ... | @@ -122,6 +122,6 @@ export interface TerminalManagerShape { |
| 122 | 122 | /** |
| 123 | 123 | * TerminalManager - Service tag for terminal session orchestration. |
| 124 | 124 | */ |
| 125 | export class TerminalManager extends ServiceMap.Service<TerminalManager, TerminalManagerShape>()( | |
| 125 | export class TerminalManager extends Context.Service<TerminalManager, TerminalManagerShape>()( | |
| 126 | 126 | "t3/terminal/Services/Manager/TerminalManager", |
| 127 | 127 | ) {} |
apps/server/src/terminal/Services/PTY.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module PtyAdapter |
| 8 | 8 | */ |
| 9 | import { Effect, Schema, ServiceMap } from "effect"; | |
| 9 | import { Effect, Schema, Context } from "effect"; | |
| 10 | 10 | |
| 11 | 11 | /** |
| 12 | 12 | * PtyError - Error type for PTY adapter operations. |
| ... | ... | @@ -53,6 +53,6 @@ export interface PtyAdapterShape { |
| 53 | 53 | /** |
| 54 | 54 | * PtyAdapter - Service tag for PTY process integration. |
| 55 | 55 | */ |
| 56 | export class PtyAdapter extends ServiceMap.Service<PtyAdapter, PtyAdapterShape>()( | |
| 56 | export class PtyAdapter extends Context.Service<PtyAdapter, PtyAdapterShape>()( | |
| 57 | 57 | "t3/terminal/Services/PTY/PtyAdapter", |
| 58 | 58 | ) {} |
apps/server/src/workspace/Layers/WorkspaceEntries.ts+8-6| ... | ... | @@ -430,12 +430,14 @@ export const makeWorkspaceEntries = Effect.gen(function* () { |
| 430 | 430 | return yield* buildWorkspaceIndexFromFilesystem(cwd); |
| 431 | 431 | }); |
| 432 | 432 | |
| 433 | const workspaceIndexCache = yield* Cache.makeWith<string, WorkspaceIndex, WorkspaceEntriesError>({ | |
| 434 | capacity: WORKSPACE_CACHE_MAX_KEYS, | |
| 435 | lookup: buildWorkspaceIndex, | |
| 436 | timeToLive: (exit) => | |
| 437 | Exit.isSuccess(exit) ? Duration.millis(WORKSPACE_CACHE_TTL_MS) : Duration.zero, | |
| 438 | }); | |
| 433 | const workspaceIndexCache = yield* Cache.makeWith<string, WorkspaceIndex, WorkspaceEntriesError>( | |
| 434 | buildWorkspaceIndex, | |
| 435 | { | |
| 436 | capacity: WORKSPACE_CACHE_MAX_KEYS, | |
| 437 | timeToLive: (exit) => | |
| 438 | Exit.isSuccess(exit) ? Duration.millis(WORKSPACE_CACHE_TTL_MS) : Duration.zero, | |
| 439 | }, | |
| 440 | ); | |
| 439 | 441 | |
| 440 | 442 | const normalizeWorkspaceRoot = Effect.fn("WorkspaceEntries.normalizeWorkspaceRoot")(function* ( |
| 441 | 443 | cwd: string, |
apps/server/src/workspace/Services/WorkspaceEntries.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module WorkspaceEntries |
| 8 | 8 | */ |
| 9 | import { Schema, ServiceMap } from "effect"; | |
| 9 | import { Schema, Context } from "effect"; | |
| 10 | 10 | import type { Effect } from "effect"; |
| 11 | 11 | |
| 12 | 12 | import type { ProjectSearchEntriesInput, ProjectSearchEntriesResult } from "@t3tools/contracts"; |
| ... | ... | @@ -43,6 +43,6 @@ export interface WorkspaceEntriesShape { |
| 43 | 43 | /** |
| 44 | 44 | * WorkspaceEntries - Service tag for cached workspace entry search. |
| 45 | 45 | */ |
| 46 | export class WorkspaceEntries extends ServiceMap.Service<WorkspaceEntries, WorkspaceEntriesShape>()( | |
| 46 | export class WorkspaceEntries extends Context.Service<WorkspaceEntries, WorkspaceEntriesShape>()( | |
| 47 | 47 | "t3/workspace/Services/WorkspaceEntries", |
| 48 | 48 | ) {} |
apps/server/src/workspace/Services/WorkspaceFileSystem.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module WorkspaceFileSystem |
| 8 | 8 | */ |
| 9 | import { Schema, ServiceMap } from "effect"; | |
| 9 | import { Schema, Context } from "effect"; | |
| 10 | 10 | import type { Effect } from "effect"; |
| 11 | 11 | |
| 12 | 12 | import type { ProjectWriteFileInput, ProjectWriteFileResult } from "@t3tools/contracts"; |
| ... | ... | @@ -44,7 +44,7 @@ export interface WorkspaceFileSystemShape { |
| 44 | 44 | /** |
| 45 | 45 | * WorkspaceFileSystem - Service tag for workspace file operations. |
| 46 | 46 | */ |
| 47 | export class WorkspaceFileSystem extends ServiceMap.Service< | |
| 47 | export class WorkspaceFileSystem extends Context.Service< | |
| 48 | 48 | WorkspaceFileSystem, |
| 49 | 49 | WorkspaceFileSystemShape |
| 50 | 50 | >()("t3/workspace/Services/WorkspaceFileSystem") {} |
apps/server/src/workspace/Services/WorkspacePaths.ts+2-2| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | * |
| 7 | 7 | * @module WorkspacePaths |
| 8 | 8 | */ |
| 9 | import { Schema, ServiceMap } from "effect"; | |
| 9 | import { Schema, Context } from "effect"; | |
| 10 | 10 | import type { Effect } from "effect"; |
| 11 | 11 | |
| 12 | 12 | export class WorkspaceRootNotExistsError extends Schema.TaggedErrorClass<WorkspaceRootNotExistsError>()( |
| ... | ... | @@ -80,6 +80,6 @@ export interface WorkspacePathsShape { |
| 80 | 80 | /** |
| 81 | 81 | * WorkspacePaths - Service tag for workspace path normalization and resolution. |
| 82 | 82 | */ |
| 83 | export class WorkspacePaths extends ServiceMap.Service<WorkspacePaths, WorkspacePathsShape>()( | |
| 83 | export class WorkspacePaths extends Context.Service<WorkspacePaths, WorkspacePathsShape>()( | |
| 84 | 84 | "t3/workspace/Services/WorkspacePaths", |
| 85 | 85 | ) {} |
apps/server/src/ws.ts+2-2| ... | ... | @@ -128,7 +128,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => |
| 128 | 128 | const bootstrapCredentials = yield* BootstrapCredentialService; |
| 129 | 129 | const sessions = yield* SessionCredentialService; |
| 130 | 130 | const serverCommandId = (tag: string) => |
| 131 | CommandId.makeUnsafe(`server:${tag}:${crypto.randomUUID()}`); | |
| 131 | CommandId.make(`server:${tag}:${crypto.randomUUID()}`); | |
| 132 | 132 | |
| 133 | 133 | const loadAuthAccessSnapshot = () => |
| 134 | 134 | Effect.all({ |
| ... | ... | @@ -149,7 +149,7 @@ const makeWsRpcLayer = (currentSessionId: AuthSessionId) => |
| 149 | 149 | commandId: serverCommandId("setup-script-activity"), |
| 150 | 150 | threadId: input.threadId, |
| 151 | 151 | activity: { |
| 152 | id: EventId.makeUnsafe(crypto.randomUUID()), | |
| 152 | id: EventId.make(crypto.randomUUID()), | |
| 153 | 153 | tone: input.tone, |
| 154 | 154 | kind: input.kind, |
| 155 | 155 | summary: input.summary, |
apps/web/src/clientPersistenceStorage.test.ts+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | import { EnvironmentId, type PersistedSavedEnvironmentRecord } from "@t3tools/contracts"; |
| 2 | 2 | import { afterEach, describe, expect, it, vi } from "vitest"; |
| 3 | 3 | |
| 4 | const testEnvironmentId = EnvironmentId.makeUnsafe("environment-1"); | |
| 4 | const testEnvironmentId = EnvironmentId.make("environment-1"); | |
| 5 | 5 | |
| 6 | 6 | const savedRegistryRecord: PersistedSavedEnvironmentRecord = { |
| 7 | 7 | environmentId: testEnvironmentId, |
apps/web/src/components/BranchToolbar.logic.test.ts+2-2| ... | ... | @@ -13,8 +13,8 @@ import { |
| 13 | 13 | shouldIncludeBranchPickerItem, |
| 14 | 14 | } from "./BranchToolbar.logic"; |
| 15 | 15 | |
| 16 | const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local"); | |
| 17 | const remoteEnvironmentId = EnvironmentId.makeUnsafe("environment-remote"); | |
| 16 | const localEnvironmentId = EnvironmentId.make("environment-local"); | |
| 17 | const remoteEnvironmentId = EnvironmentId.make("environment-remote"); | |
| 18 | 18 | |
| 19 | 19 | describe("resolveDraftEnvModeAfterBranchChange", () => { |
| 20 | 20 | it("switches to local mode when returning from an existing worktree to the main worktree", () => { |
apps/web/src/components/ChatView.browser.tsx+7-7| ... | ... | @@ -58,7 +58,7 @@ vi.mock("../lib/gitStatusState", () => ({ |
| 58 | 58 | |
| 59 | 59 | const THREAD_ID = "thread-browser-test" as ThreadId; |
| 60 | 60 | const PROJECT_ID = "project-1" as ProjectId; |
| 61 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local"); | |
| 61 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | |
| 62 | 62 | const THREAD_REF = scopeThreadRef(LOCAL_ENVIRONMENT_ID, THREAD_ID); |
| 63 | 63 | const THREAD_KEY = scopedThreadKey(THREAD_REF); |
| 64 | 64 | const UUID_ROUTE_RE = /^\/draft\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/; |
| ... | ... | @@ -143,7 +143,7 @@ function isoAt(offsetSeconds: number): string { |
| 143 | 143 | function createBaseServerConfig(): ServerConfig { |
| 144 | 144 | return { |
| 145 | 145 | environment: { |
| 146 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 146 | environmentId: EnvironmentId.make("environment-local"), | |
| 147 | 147 | label: "Local environment", |
| 148 | 148 | platform: { os: "darwin" as const, arch: "arm64" as const }, |
| 149 | 149 | serverVersion: "0.0.0-test", |
| ... | ... | @@ -341,7 +341,7 @@ function buildFixture(snapshot: OrchestrationReadModel): TestFixture { |
| 341 | 341 | serverConfig: createBaseServerConfig(), |
| 342 | 342 | welcome: { |
| 343 | 343 | environment: { |
| 344 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 344 | environmentId: EnvironmentId.make("environment-local"), | |
| 345 | 345 | label: "Local environment", |
| 346 | 346 | platform: { os: "darwin" as const, arch: "arm64" as const }, |
| 347 | 347 | serverVersion: "0.0.0-test", |
| ... | ... | @@ -402,7 +402,7 @@ function addThreadToSnapshot( |
| 402 | 402 | function createThreadCreatedEvent(threadId: ThreadId, sequence: number): OrchestrationEvent { |
| 403 | 403 | return { |
| 404 | 404 | sequence, |
| 405 | eventId: EventId.makeUnsafe(`event-thread-created-${sequence}`), | |
| 405 | eventId: EventId.make(`event-thread-created-${sequence}`), | |
| 406 | 406 | aggregateKind: "thread", |
| 407 | 407 | aggregateId: threadId, |
| 408 | 408 | occurredAt: NOW_ISO, |
| ... | ... | @@ -432,7 +432,7 @@ function createThreadCreatedEvent(threadId: ThreadId, sequence: number): Orchest |
| 432 | 432 | function createThreadSessionSetEvent(threadId: ThreadId, sequence: number): OrchestrationEvent { |
| 433 | 433 | return { |
| 434 | 434 | sequence, |
| 435 | eventId: EventId.makeUnsafe(`event-thread-session-set-${sequence}`), | |
| 435 | eventId: EventId.make(`event-thread-session-set-${sequence}`), | |
| 436 | 436 | aggregateKind: "thread", |
| 437 | 437 | aggregateId: threadId, |
| 438 | 438 | occurredAt: NOW_ISO, |
| ... | ... | @@ -498,7 +498,7 @@ function draftIdFromPath(pathname: string) { |
| 498 | 498 | if (!draftId) { |
| 499 | 499 | throw new Error(`Expected thread path, received "${pathname}".`); |
| 500 | 500 | } |
| 501 | return DraftId.makeUnsafe(draftId); | |
| 501 | return DraftId.make(draftId); | |
| 502 | 502 | } |
| 503 | 503 | |
| 504 | 504 | function draftThreadIdFor(draftId: ReturnType<typeof draftIdFromPath>): ThreadId { |
| ... | ... | @@ -666,7 +666,7 @@ function createSnapshotWithPendingUserInput(): OrchestrationReadModel { |
| 666 | 666 | interactionMode: "plan", |
| 667 | 667 | activities: [ |
| 668 | 668 | { |
| 669 | id: EventId.makeUnsafe("activity-user-input-requested"), | |
| 669 | id: EventId.make("activity-user-input-requested"), | |
| 670 | 670 | tone: "info", |
| 671 | 671 | kind: "user-input.requested", |
| 672 | 672 | summary: "User input requested", |
apps/web/src/components/ChatView.logic.test.ts+45-56| ... | ... | @@ -15,7 +15,7 @@ import { |
| 15 | 15 | waitForStartedServerThread, |
| 16 | 16 | } from "./ChatView.logic"; |
| 17 | 17 | |
| 18 | const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local"); | |
| 18 | const localEnvironmentId = EnvironmentId.make("environment-local"); | |
| 19 | 19 | |
| 20 | 20 | describe("deriveComposerSendState", () => { |
| 21 | 21 | it("treats expired terminal pills as non-sendable content", () => { |
| ... | ... | @@ -25,7 +25,7 @@ describe("deriveComposerSendState", () => { |
| 25 | 25 | terminalContexts: [ |
| 26 | 26 | { |
| 27 | 27 | id: "ctx-expired", |
| 28 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 28 | threadId: ThreadId.make("thread-1"), | |
| 29 | 29 | terminalId: "default", |
| 30 | 30 | terminalLabel: "Terminal 1", |
| 31 | 31 | lineStart: 4, |
| ... | ... | @@ -49,7 +49,7 @@ describe("deriveComposerSendState", () => { |
| 49 | 49 | terminalContexts: [ |
| 50 | 50 | { |
| 51 | 51 | id: "ctx-expired", |
| 52 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 52 | threadId: ThreadId.make("thread-1"), | |
| 53 | 53 | terminalId: "default", |
| 54 | 54 | terminalLabel: "Terminal 1", |
| 55 | 55 | lineStart: 4, |
| ... | ... | @@ -86,23 +86,20 @@ describe("reconcileMountedTerminalThreadIds", () => { |
| 86 | 86 | it("keeps previously mounted open threads and adds the active open thread", () => { |
| 87 | 87 | expect( |
| 88 | 88 | reconcileMountedTerminalThreadIds({ |
| 89 | currentThreadIds: [ | |
| 90 | ThreadId.makeUnsafe("thread-hidden"), | |
| 91 | ThreadId.makeUnsafe("thread-stale"), | |
| 92 | ], | |
| 93 | openThreadIds: [ThreadId.makeUnsafe("thread-hidden"), ThreadId.makeUnsafe("thread-active")], | |
| 94 | activeThreadId: ThreadId.makeUnsafe("thread-active"), | |
| 89 | currentThreadIds: [ThreadId.make("thread-hidden"), ThreadId.make("thread-stale")], | |
| 90 | openThreadIds: [ThreadId.make("thread-hidden"), ThreadId.make("thread-active")], | |
| 91 | activeThreadId: ThreadId.make("thread-active"), | |
| 95 | 92 | activeThreadTerminalOpen: true, |
| 96 | 93 | }), |
| 97 | ).toEqual([ThreadId.makeUnsafe("thread-hidden"), ThreadId.makeUnsafe("thread-active")]); | |
| 94 | ).toEqual([ThreadId.make("thread-hidden"), ThreadId.make("thread-active")]); | |
| 98 | 95 | }); |
| 99 | 96 | |
| 100 | 97 | it("drops mounted threads once their terminal drawer is no longer open", () => { |
| 101 | 98 | expect( |
| 102 | 99 | reconcileMountedTerminalThreadIds({ |
| 103 | currentThreadIds: [ThreadId.makeUnsafe("thread-closed")], | |
| 100 | currentThreadIds: [ThreadId.make("thread-closed")], | |
| 104 | 101 | openThreadIds: [], |
| 105 | activeThreadId: ThreadId.makeUnsafe("thread-closed"), | |
| 102 | activeThreadId: ThreadId.make("thread-closed"), | |
| 106 | 103 | activeThreadTerminalOpen: false, |
| 107 | 104 | }), |
| 108 | 105 | ).toEqual([]); |
| ... | ... | @@ -112,55 +109,47 @@ describe("reconcileMountedTerminalThreadIds", () => { |
| 112 | 109 | expect( |
| 113 | 110 | reconcileMountedTerminalThreadIds({ |
| 114 | 111 | currentThreadIds: [ |
| 115 | ThreadId.makeUnsafe("thread-1"), | |
| 116 | ThreadId.makeUnsafe("thread-2"), | |
| 117 | ThreadId.makeUnsafe("thread-3"), | |
| 112 | ThreadId.make("thread-1"), | |
| 113 | ThreadId.make("thread-2"), | |
| 114 | ThreadId.make("thread-3"), | |
| 118 | 115 | ], |
| 119 | 116 | openThreadIds: [ |
| 120 | ThreadId.makeUnsafe("thread-1"), | |
| 121 | ThreadId.makeUnsafe("thread-2"), | |
| 122 | ThreadId.makeUnsafe("thread-3"), | |
| 123 | ThreadId.makeUnsafe("thread-4"), | |
| 117 | ThreadId.make("thread-1"), | |
| 118 | ThreadId.make("thread-2"), | |
| 119 | ThreadId.make("thread-3"), | |
| 120 | ThreadId.make("thread-4"), | |
| 124 | 121 | ], |
| 125 | activeThreadId: ThreadId.makeUnsafe("thread-4"), | |
| 122 | activeThreadId: ThreadId.make("thread-4"), | |
| 126 | 123 | activeThreadTerminalOpen: true, |
| 127 | 124 | maxHiddenThreadCount: 2, |
| 128 | 125 | }), |
| 129 | ).toEqual([ | |
| 130 | ThreadId.makeUnsafe("thread-2"), | |
| 131 | ThreadId.makeUnsafe("thread-3"), | |
| 132 | ThreadId.makeUnsafe("thread-4"), | |
| 133 | ]); | |
| 126 | ).toEqual([ThreadId.make("thread-2"), ThreadId.make("thread-3"), ThreadId.make("thread-4")]); | |
| 134 | 127 | }); |
| 135 | 128 | |
| 136 | 129 | it("moves the active thread to the end so it is treated as most recently used", () => { |
| 137 | 130 | expect( |
| 138 | 131 | reconcileMountedTerminalThreadIds({ |
| 139 | 132 | currentThreadIds: [ |
| 140 | ThreadId.makeUnsafe("thread-a"), | |
| 141 | ThreadId.makeUnsafe("thread-b"), | |
| 142 | ThreadId.makeUnsafe("thread-c"), | |
| 133 | ThreadId.make("thread-a"), | |
| 134 | ThreadId.make("thread-b"), | |
| 135 | ThreadId.make("thread-c"), | |
| 143 | 136 | ], |
| 144 | 137 | openThreadIds: [ |
| 145 | ThreadId.makeUnsafe("thread-a"), | |
| 146 | ThreadId.makeUnsafe("thread-b"), | |
| 147 | ThreadId.makeUnsafe("thread-c"), | |
| 138 | ThreadId.make("thread-a"), | |
| 139 | ThreadId.make("thread-b"), | |
| 140 | ThreadId.make("thread-c"), | |
| 148 | 141 | ], |
| 149 | activeThreadId: ThreadId.makeUnsafe("thread-a"), | |
| 142 | activeThreadId: ThreadId.make("thread-a"), | |
| 150 | 143 | activeThreadTerminalOpen: true, |
| 151 | 144 | maxHiddenThreadCount: 2, |
| 152 | 145 | }), |
| 153 | ).toEqual([ | |
| 154 | ThreadId.makeUnsafe("thread-b"), | |
| 155 | ThreadId.makeUnsafe("thread-c"), | |
| 156 | ThreadId.makeUnsafe("thread-a"), | |
| 157 | ]); | |
| 146 | ).toEqual([ThreadId.make("thread-b"), ThreadId.make("thread-c"), ThreadId.make("thread-a")]); | |
| 158 | 147 | }); |
| 159 | 148 | |
| 160 | 149 | it("defaults to the hidden mounted terminal cap", () => { |
| 161 | 150 | const currentThreadIds = Array.from( |
| 162 | 151 | { length: MAX_HIDDEN_MOUNTED_TERMINAL_THREADS + 2 }, |
| 163 | (_, index) => ThreadId.makeUnsafe(`thread-${index + 1}`), | |
| 152 | (_, index) => ThreadId.make(`thread-${index + 1}`), | |
| 164 | 153 | ); |
| 165 | 154 | |
| 166 | 155 | expect( |
| ... | ... | @@ -176,7 +165,7 @@ describe("reconcileMountedTerminalThreadIds", () => { |
| 176 | 165 | |
| 177 | 166 | describe("shouldWriteThreadErrorToCurrentServerThread", () => { |
| 178 | 167 | it("routes errors to the active server thread when route and target match", () => { |
| 179 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 168 | const threadId = ThreadId.make("thread-1"); | |
| 180 | 169 | const routeThreadRef = scopeThreadRef(localEnvironmentId, threadId); |
| 181 | 170 | |
| 182 | 171 | expect( |
| ... | ... | @@ -192,7 +181,7 @@ describe("shouldWriteThreadErrorToCurrentServerThread", () => { |
| 192 | 181 | }); |
| 193 | 182 | |
| 194 | 183 | it("does not route draft-thread errors into server-backed state", () => { |
| 195 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 184 | const threadId = ThreadId.make("thread-1"); | |
| 196 | 185 | |
| 197 | 186 | expect( |
| 198 | 187 | shouldWriteThreadErrorToCurrentServerThread({ |
| ... | ... | @@ -214,10 +203,10 @@ const makeThread = (input?: { |
| 214 | 203 | completedAt: string | null; |
| 215 | 204 | } | null; |
| 216 | 205 | }): Thread => ({ |
| 217 | id: input?.id ?? ThreadId.makeUnsafe("thread-1"), | |
| 206 | id: input?.id ?? ThreadId.make("thread-1"), | |
| 218 | 207 | environmentId: localEnvironmentId, |
| 219 | 208 | codexThreadId: null, |
| 220 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 209 | projectId: ProjectId.make("project-1"), | |
| 221 | 210 | title: "Thread", |
| 222 | 211 | modelSelection: { provider: "codex" as const, model: "gpt-5.4" }, |
| 223 | 212 | runtimeMode: "full-access" as const, |
| ... | ... | @@ -242,7 +231,7 @@ const makeThread = (input?: { |
| 242 | 231 | }); |
| 243 | 232 | |
| 244 | 233 | function setStoreThreads(threads: ReadonlyArray<ReturnType<typeof makeThread>>) { |
| 245 | const projectId = ProjectId.makeUnsafe("project-1"); | |
| 234 | const projectId = ProjectId.make("project-1"); | |
| 246 | 235 | const environmentState: EnvironmentState = { |
| 247 | 236 | projectIds: [projectId], |
| 248 | 237 | projectById: { |
| ... | ... | @@ -355,12 +344,12 @@ afterEach(() => { |
| 355 | 344 | |
| 356 | 345 | describe("waitForStartedServerThread", () => { |
| 357 | 346 | it("resolves immediately when the thread is already started", async () => { |
| 358 | const threadId = ThreadId.makeUnsafe("thread-started"); | |
| 347 | const threadId = ThreadId.make("thread-started"); | |
| 359 | 348 | setStoreThreads([ |
| 360 | 349 | makeThread({ |
| 361 | 350 | id: threadId, |
| 362 | 351 | latestTurn: { |
| 363 | turnId: TurnId.makeUnsafe("turn-started"), | |
| 352 | turnId: TurnId.make("turn-started"), | |
| 364 | 353 | state: "running", |
| 365 | 354 | requestedAt: "2026-03-29T00:00:01.000Z", |
| 366 | 355 | startedAt: "2026-03-29T00:00:01.000Z", |
| ... | ... | @@ -375,7 +364,7 @@ describe("waitForStartedServerThread", () => { |
| 375 | 364 | }); |
| 376 | 365 | |
| 377 | 366 | it("waits for the thread to start via subscription updates", async () => { |
| 378 | const threadId = ThreadId.makeUnsafe("thread-wait"); | |
| 367 | const threadId = ThreadId.make("thread-wait"); | |
| 379 | 368 | setStoreThreads([makeThread({ id: threadId })]); |
| 380 | 369 | |
| 381 | 370 | const promise = waitForStartedServerThread(scopeThreadRef(localEnvironmentId, threadId), 500); |
| ... | ... | @@ -384,7 +373,7 @@ describe("waitForStartedServerThread", () => { |
| 384 | 373 | makeThread({ |
| 385 | 374 | id: threadId, |
| 386 | 375 | latestTurn: { |
| 387 | turnId: TurnId.makeUnsafe("turn-started"), | |
| 376 | turnId: TurnId.make("turn-started"), | |
| 388 | 377 | state: "running", |
| 389 | 378 | requestedAt: "2026-03-29T00:00:01.000Z", |
| 390 | 379 | startedAt: "2026-03-29T00:00:01.000Z", |
| ... | ... | @@ -397,7 +386,7 @@ describe("waitForStartedServerThread", () => { |
| 397 | 386 | }); |
| 398 | 387 | |
| 399 | 388 | it("handles the thread starting between the initial read and subscription setup", async () => { |
| 400 | const threadId = ThreadId.makeUnsafe("thread-race"); | |
| 389 | const threadId = ThreadId.make("thread-race"); | |
| 401 | 390 | setStoreThreads([makeThread({ id: threadId })]); |
| 402 | 391 | |
| 403 | 392 | const originalSubscribe = useStore.subscribe.bind(useStore); |
| ... | ... | @@ -409,7 +398,7 @@ describe("waitForStartedServerThread", () => { |
| 409 | 398 | makeThread({ |
| 410 | 399 | id: threadId, |
| 411 | 400 | latestTurn: { |
| 412 | turnId: TurnId.makeUnsafe("turn-race"), | |
| 401 | turnId: TurnId.make("turn-race"), | |
| 413 | 402 | state: "running", |
| 414 | 403 | requestedAt: "2026-03-29T00:00:01.000Z", |
| 415 | 404 | startedAt: "2026-03-29T00:00:01.000Z", |
| ... | ... | @@ -429,7 +418,7 @@ describe("waitForStartedServerThread", () => { |
| 429 | 418 | it("returns false after the timeout when the thread never starts", async () => { |
| 430 | 419 | vi.useFakeTimers(); |
| 431 | 420 | |
| 432 | const threadId = ThreadId.makeUnsafe("thread-timeout"); | |
| 421 | const threadId = ThreadId.make("thread-timeout"); | |
| 433 | 422 | setStoreThreads([makeThread({ id: threadId })]); |
| 434 | 423 | const promise = waitForStartedServerThread(scopeThreadRef(localEnvironmentId, threadId), 500); |
| 435 | 424 | |
| ... | ... | @@ -440,9 +429,9 @@ describe("waitForStartedServerThread", () => { |
| 440 | 429 | }); |
| 441 | 430 | |
| 442 | 431 | describe("hasServerAcknowledgedLocalDispatch", () => { |
| 443 | const projectId = ProjectId.makeUnsafe("project-1"); | |
| 432 | const projectId = ProjectId.make("project-1"); | |
| 444 | 433 | const previousLatestTurn = { |
| 445 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 434 | turnId: TurnId.make("turn-1"), | |
| 446 | 435 | state: "completed" as const, |
| 447 | 436 | requestedAt: "2026-03-29T00:00:00.000Z", |
| 448 | 437 | startedAt: "2026-03-29T00:00:01.000Z", |
| ... | ... | @@ -460,7 +449,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => { |
| 460 | 449 | |
| 461 | 450 | it("does not clear local dispatch before server state changes", () => { |
| 462 | 451 | const localDispatch = createLocalDispatchSnapshot({ |
| 463 | id: ThreadId.makeUnsafe("thread-1"), | |
| 452 | id: ThreadId.make("thread-1"), | |
| 464 | 453 | environmentId: localEnvironmentId, |
| 465 | 454 | codexThreadId: null, |
| 466 | 455 | projectId, |
| ... | ... | @@ -497,7 +486,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => { |
| 497 | 486 | |
| 498 | 487 | it("clears local dispatch when a new turn is already settled", () => { |
| 499 | 488 | const localDispatch = createLocalDispatchSnapshot({ |
| 500 | id: ThreadId.makeUnsafe("thread-1"), | |
| 489 | id: ThreadId.make("thread-1"), | |
| 501 | 490 | environmentId: localEnvironmentId, |
| 502 | 491 | codexThreadId: null, |
| 503 | 492 | projectId, |
| ... | ... | @@ -525,7 +514,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => { |
| 525 | 514 | phase: "ready", |
| 526 | 515 | latestTurn: { |
| 527 | 516 | ...previousLatestTurn, |
| 528 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 517 | turnId: TurnId.make("turn-2"), | |
| 529 | 518 | requestedAt: "2026-03-29T00:01:00.000Z", |
| 530 | 519 | startedAt: "2026-03-29T00:01:01.000Z", |
| 531 | 520 | completedAt: "2026-03-29T00:01:30.000Z", |
| ... | ... | @@ -543,7 +532,7 @@ describe("hasServerAcknowledgedLocalDispatch", () => { |
| 543 | 532 | |
| 544 | 533 | it("clears local dispatch when the session changes without an observed running phase", () => { |
| 545 | 534 | const localDispatch = createLocalDispatchSnapshot({ |
| 546 | id: ThreadId.makeUnsafe("thread-1"), | |
| 535 | id: ThreadId.make("thread-1"), | |
| 547 | 536 | environmentId: localEnvironmentId, |
| 548 | 537 | codexThreadId: null, |
| 549 | 538 | projectId, |
apps/web/src/components/GitActionsControl.browser.tsx+1-1| ... | ... | @@ -4,7 +4,7 @@ import { useState } from "react"; |
| 4 | 4 | import { afterEach, describe, expect, it, vi } from "vitest"; |
| 5 | 5 | import { render } from "vitest-browser-react"; |
| 6 | 6 | |
| 7 | const SHARED_THREAD_ID = ThreadId.makeUnsafe("thread-shared"); | |
| 7 | const SHARED_THREAD_ID = ThreadId.make("thread-shared"); | |
| 8 | 8 | const ENVIRONMENT_A = "environment-local" as never; |
| 9 | 9 | const ENVIRONMENT_B = "environment-remote" as never; |
| 10 | 10 | const GIT_CWD = "/repo/project"; |
apps/web/src/components/KeybindingsToast.browser.tsx+1-1| ... | ... | @@ -37,7 +37,7 @@ vi.mock("../lib/gitStatusState", () => ({ |
| 37 | 37 | |
| 38 | 38 | const THREAD_ID = "thread-kb-toast-test" as ThreadId; |
| 39 | 39 | const PROJECT_ID = "project-1" as ProjectId; |
| 40 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local"); | |
| 40 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | |
| 41 | 41 | const NOW_ISO = "2026-03-04T12:00:00.000Z"; |
| 42 | 42 | |
| 43 | 43 | interface TestFixture { |
apps/web/src/components/Sidebar.logic.test.ts+109-117| ... | ... | @@ -28,7 +28,7 @@ import { |
| 28 | 28 | type Thread, |
| 29 | 29 | } from "../types"; |
| 30 | 30 | |
| 31 | const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local"); | |
| 31 | const localEnvironmentId = EnvironmentId.make("environment-local"); | |
| 32 | 32 | |
| 33 | 33 | function makeLatestTurn(overrides?: { |
| 34 | 34 | completedAt?: string | null; |
| ... | ... | @@ -235,42 +235,42 @@ describe("orderItemsByPreferredIds", () => { |
| 235 | 235 | it("keeps preferred ids first, skips stale ids, and preserves the relative order of remaining items", () => { |
| 236 | 236 | const ordered = orderItemsByPreferredIds({ |
| 237 | 237 | items: [ |
| 238 | { id: ProjectId.makeUnsafe("project-1"), name: "One" }, | |
| 239 | { id: ProjectId.makeUnsafe("project-2"), name: "Two" }, | |
| 240 | { id: ProjectId.makeUnsafe("project-3"), name: "Three" }, | |
| 238 | { id: ProjectId.make("project-1"), name: "One" }, | |
| 239 | { id: ProjectId.make("project-2"), name: "Two" }, | |
| 240 | { id: ProjectId.make("project-3"), name: "Three" }, | |
| 241 | 241 | ], |
| 242 | 242 | preferredIds: [ |
| 243 | ProjectId.makeUnsafe("project-3"), | |
| 244 | ProjectId.makeUnsafe("project-missing"), | |
| 245 | ProjectId.makeUnsafe("project-1"), | |
| 243 | ProjectId.make("project-3"), | |
| 244 | ProjectId.make("project-missing"), | |
| 245 | ProjectId.make("project-1"), | |
| 246 | 246 | ], |
| 247 | 247 | getId: (project) => project.id, |
| 248 | 248 | }); |
| 249 | 249 | |
| 250 | 250 | expect(ordered.map((project) => project.id)).toEqual([ |
| 251 | ProjectId.makeUnsafe("project-3"), | |
| 252 | ProjectId.makeUnsafe("project-1"), | |
| 253 | ProjectId.makeUnsafe("project-2"), | |
| 251 | ProjectId.make("project-3"), | |
| 252 | ProjectId.make("project-1"), | |
| 253 | ProjectId.make("project-2"), | |
| 254 | 254 | ]); |
| 255 | 255 | }); |
| 256 | 256 | |
| 257 | 257 | it("does not duplicate items when preferred ids repeat", () => { |
| 258 | 258 | const ordered = orderItemsByPreferredIds({ |
| 259 | 259 | items: [ |
| 260 | { id: ProjectId.makeUnsafe("project-1"), name: "One" }, | |
| 261 | { id: ProjectId.makeUnsafe("project-2"), name: "Two" }, | |
| 260 | { id: ProjectId.make("project-1"), name: "One" }, | |
| 261 | { id: ProjectId.make("project-2"), name: "Two" }, | |
| 262 | 262 | ], |
| 263 | 263 | preferredIds: [ |
| 264 | ProjectId.makeUnsafe("project-2"), | |
| 265 | ProjectId.makeUnsafe("project-1"), | |
| 266 | ProjectId.makeUnsafe("project-2"), | |
| 264 | ProjectId.make("project-2"), | |
| 265 | ProjectId.make("project-1"), | |
| 266 | ProjectId.make("project-2"), | |
| 267 | 267 | ], |
| 268 | 268 | getId: (project) => project.id, |
| 269 | 269 | }); |
| 270 | 270 | |
| 271 | 271 | expect(ordered.map((project) => project.id)).toEqual([ |
| 272 | ProjectId.makeUnsafe("project-2"), | |
| 273 | ProjectId.makeUnsafe("project-1"), | |
| 272 | ProjectId.make("project-2"), | |
| 273 | ProjectId.make("project-1"), | |
| 274 | 274 | ]); |
| 275 | 275 | }); |
| 276 | 276 | }); |
| ... | ... | @@ -278,9 +278,9 @@ describe("orderItemsByPreferredIds", () => { |
| 278 | 278 | describe("resolveAdjacentThreadId", () => { |
| 279 | 279 | it("resolves adjacent thread ids in ordered sidebar traversal", () => { |
| 280 | 280 | const threads = [ |
| 281 | ThreadId.makeUnsafe("thread-1"), | |
| 282 | ThreadId.makeUnsafe("thread-2"), | |
| 283 | ThreadId.makeUnsafe("thread-3"), | |
| 281 | ThreadId.make("thread-1"), | |
| 282 | ThreadId.make("thread-2"), | |
| 283 | ThreadId.make("thread-3"), | |
| 284 | 284 | ]; |
| 285 | 285 | |
| 286 | 286 | expect( |
| ... | ... | @@ -327,21 +327,21 @@ describe("getVisibleSidebarThreadIds", () => { |
| 327 | 327 | getVisibleSidebarThreadIds([ |
| 328 | 328 | { |
| 329 | 329 | renderedThreadIds: [ |
| 330 | ThreadId.makeUnsafe("thread-12"), | |
| 331 | ThreadId.makeUnsafe("thread-11"), | |
| 332 | ThreadId.makeUnsafe("thread-10"), | |
| 330 | ThreadId.make("thread-12"), | |
| 331 | ThreadId.make("thread-11"), | |
| 332 | ThreadId.make("thread-10"), | |
| 333 | 333 | ], |
| 334 | 334 | }, |
| 335 | 335 | { |
| 336 | renderedThreadIds: [ThreadId.makeUnsafe("thread-8"), ThreadId.makeUnsafe("thread-6")], | |
| 336 | renderedThreadIds: [ThreadId.make("thread-8"), ThreadId.make("thread-6")], | |
| 337 | 337 | }, |
| 338 | 338 | ]), |
| 339 | 339 | ).toEqual([ |
| 340 | ThreadId.makeUnsafe("thread-12"), | |
| 341 | ThreadId.makeUnsafe("thread-11"), | |
| 342 | ThreadId.makeUnsafe("thread-10"), | |
| 343 | ThreadId.makeUnsafe("thread-8"), | |
| 344 | ThreadId.makeUnsafe("thread-6"), | |
| 340 | ThreadId.make("thread-12"), | |
| 341 | ThreadId.make("thread-11"), | |
| 342 | ThreadId.make("thread-10"), | |
| 343 | ThreadId.make("thread-8"), | |
| 344 | ThreadId.make("thread-6"), | |
| 345 | 345 | ]); |
| 346 | 346 | }); |
| 347 | 347 | |
| ... | ... | @@ -350,17 +350,14 @@ describe("getVisibleSidebarThreadIds", () => { |
| 350 | 350 | getVisibleSidebarThreadIds([ |
| 351 | 351 | { |
| 352 | 352 | shouldShowThreadPanel: false, |
| 353 | renderedThreadIds: [ | |
| 354 | ThreadId.makeUnsafe("thread-hidden-2"), | |
| 355 | ThreadId.makeUnsafe("thread-hidden-1"), | |
| 356 | ], | |
| 353 | renderedThreadIds: [ThreadId.make("thread-hidden-2"), ThreadId.make("thread-hidden-1")], | |
| 357 | 354 | }, |
| 358 | 355 | { |
| 359 | 356 | shouldShowThreadPanel: true, |
| 360 | renderedThreadIds: [ThreadId.makeUnsafe("thread-12"), ThreadId.makeUnsafe("thread-11")], | |
| 357 | renderedThreadIds: [ThreadId.make("thread-12"), ThreadId.make("thread-11")], | |
| 361 | 358 | }, |
| 362 | 359 | ]), |
| 363 | ).toEqual([ThreadId.makeUnsafe("thread-12"), ThreadId.makeUnsafe("thread-11")]); | |
| 360 | ).toEqual([ThreadId.make("thread-12"), ThreadId.make("thread-11")]); | |
| 364 | 361 | }); |
| 365 | 362 | }); |
| 366 | 363 | |
| ... | ... | @@ -574,43 +571,41 @@ describe("getVisibleThreadsForProject", () => { |
| 574 | 571 | it("includes the active thread even when it falls below the folded preview", () => { |
| 575 | 572 | const threads = Array.from({ length: 8 }, (_, index) => |
| 576 | 573 | makeThread({ |
| 577 | id: ThreadId.makeUnsafe(`thread-${index + 1}`), | |
| 574 | id: ThreadId.make(`thread-${index + 1}`), | |
| 578 | 575 | title: `Thread ${index + 1}`, |
| 579 | 576 | }), |
| 580 | 577 | ); |
| 581 | 578 | |
| 582 | 579 | const result = getVisibleThreadsForProject({ |
| 583 | 580 | threads, |
| 584 | activeThreadId: ThreadId.makeUnsafe("thread-8"), | |
| 581 | activeThreadId: ThreadId.make("thread-8"), | |
| 585 | 582 | isThreadListExpanded: false, |
| 586 | 583 | previewLimit: 6, |
| 587 | 584 | }); |
| 588 | 585 | |
| 589 | 586 | expect(result.hasHiddenThreads).toBe(true); |
| 590 | 587 | expect(result.visibleThreads.map((thread) => thread.id)).toEqual([ |
| 591 | ThreadId.makeUnsafe("thread-1"), | |
| 592 | ThreadId.makeUnsafe("thread-2"), | |
| 593 | ThreadId.makeUnsafe("thread-3"), | |
| 594 | ThreadId.makeUnsafe("thread-4"), | |
| 595 | ThreadId.makeUnsafe("thread-5"), | |
| 596 | ThreadId.makeUnsafe("thread-6"), | |
| 597 | ThreadId.makeUnsafe("thread-8"), | |
| 598 | ]); | |
| 599 | expect(result.hiddenThreads.map((thread) => thread.id)).toEqual([ | |
| 600 | ThreadId.makeUnsafe("thread-7"), | |
| 588 | ThreadId.make("thread-1"), | |
| 589 | ThreadId.make("thread-2"), | |
| 590 | ThreadId.make("thread-3"), | |
| 591 | ThreadId.make("thread-4"), | |
| 592 | ThreadId.make("thread-5"), | |
| 593 | ThreadId.make("thread-6"), | |
| 594 | ThreadId.make("thread-8"), | |
| 601 | 595 | ]); |
| 596 | expect(result.hiddenThreads.map((thread) => thread.id)).toEqual([ThreadId.make("thread-7")]); | |
| 602 | 597 | }); |
| 603 | 598 | |
| 604 | 599 | it("returns all threads when the list is expanded", () => { |
| 605 | 600 | const threads = Array.from({ length: 8 }, (_, index) => |
| 606 | 601 | makeThread({ |
| 607 | id: ThreadId.makeUnsafe(`thread-${index + 1}`), | |
| 602 | id: ThreadId.make(`thread-${index + 1}`), | |
| 608 | 603 | }), |
| 609 | 604 | ); |
| 610 | 605 | |
| 611 | 606 | const result = getVisibleThreadsForProject({ |
| 612 | 607 | threads, |
| 613 | activeThreadId: ThreadId.makeUnsafe("thread-8"), | |
| 608 | activeThreadId: ThreadId.make("thread-8"), | |
| 614 | 609 | isThreadListExpanded: true, |
| 615 | 610 | previewLimit: 6, |
| 616 | 611 | }); |
| ... | ... | @@ -626,7 +621,7 @@ describe("getVisibleThreadsForProject", () => { |
| 626 | 621 | function makeProject(overrides: Partial<Project> = {}): Project { |
| 627 | 622 | const { defaultModelSelection, ...rest } = overrides; |
| 628 | 623 | return { |
| 629 | id: ProjectId.makeUnsafe("project-1"), | |
| 624 | id: ProjectId.make("project-1"), | |
| 630 | 625 | environmentId: localEnvironmentId, |
| 631 | 626 | name: "Project", |
| 632 | 627 | cwd: "/tmp/project", |
| ... | ... | @@ -644,10 +639,10 @@ function makeProject(overrides: Partial<Project> = {}): Project { |
| 644 | 639 | |
| 645 | 640 | function makeThread(overrides: Partial<Thread> = {}): Thread { |
| 646 | 641 | return { |
| 647 | id: ThreadId.makeUnsafe("thread-1"), | |
| 642 | id: ThreadId.make("thread-1"), | |
| 648 | 643 | environmentId: localEnvironmentId, |
| 649 | 644 | codexThreadId: null, |
| 650 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 645 | projectId: ProjectId.make("project-1"), | |
| 651 | 646 | title: "Thread", |
| 652 | 647 | modelSelection: { |
| 653 | 648 | provider: "codex", |
| ... | ... | @@ -677,7 +672,7 @@ describe("sortThreadsForSidebar", () => { |
| 677 | 672 | const sorted = sortThreadsForSidebar( |
| 678 | 673 | [ |
| 679 | 674 | makeThread({ |
| 680 | id: ThreadId.makeUnsafe("thread-1"), | |
| 675 | id: ThreadId.make("thread-1"), | |
| 681 | 676 | createdAt: "2026-03-09T10:00:00.000Z", |
| 682 | 677 | updatedAt: "2026-03-09T10:10:00.000Z", |
| 683 | 678 | messages: [ |
| ... | ... | @@ -692,7 +687,7 @@ describe("sortThreadsForSidebar", () => { |
| 692 | 687 | ], |
| 693 | 688 | }), |
| 694 | 689 | makeThread({ |
| 695 | id: ThreadId.makeUnsafe("thread-2"), | |
| 690 | id: ThreadId.make("thread-2"), | |
| 696 | 691 | createdAt: "2026-03-09T10:05:00.000Z", |
| 697 | 692 | updatedAt: "2026-03-09T10:05:00.000Z", |
| 698 | 693 | messages: [ |
| ... | ... | @@ -711,8 +706,8 @@ describe("sortThreadsForSidebar", () => { |
| 711 | 706 | ); |
| 712 | 707 | |
| 713 | 708 | expect(sorted.map((thread) => thread.id)).toEqual([ |
| 714 | ThreadId.makeUnsafe("thread-2"), | |
| 715 | ThreadId.makeUnsafe("thread-1"), | |
| 709 | ThreadId.make("thread-2"), | |
| 710 | ThreadId.make("thread-1"), | |
| 716 | 711 | ]); |
| 717 | 712 | }); |
| 718 | 713 | |
| ... | ... | @@ -720,7 +715,7 @@ describe("sortThreadsForSidebar", () => { |
| 720 | 715 | const sorted = sortThreadsForSidebar( |
| 721 | 716 | [ |
| 722 | 717 | makeThread({ |
| 723 | id: ThreadId.makeUnsafe("thread-1"), | |
| 718 | id: ThreadId.make("thread-1"), | |
| 724 | 719 | createdAt: "2026-03-09T10:00:00.000Z", |
| 725 | 720 | updatedAt: "2026-03-09T10:01:00.000Z", |
| 726 | 721 | messages: [ |
| ... | ... | @@ -735,7 +730,7 @@ describe("sortThreadsForSidebar", () => { |
| 735 | 730 | ], |
| 736 | 731 | }), |
| 737 | 732 | makeThread({ |
| 738 | id: ThreadId.makeUnsafe("thread-2"), | |
| 733 | id: ThreadId.make("thread-2"), | |
| 739 | 734 | createdAt: "2026-03-09T10:05:00.000Z", |
| 740 | 735 | updatedAt: "2026-03-09T10:05:00.000Z", |
| 741 | 736 | messages: [], |
| ... | ... | @@ -745,8 +740,8 @@ describe("sortThreadsForSidebar", () => { |
| 745 | 740 | ); |
| 746 | 741 | |
| 747 | 742 | expect(sorted.map((thread) => thread.id)).toEqual([ |
| 748 | ThreadId.makeUnsafe("thread-2"), | |
| 749 | ThreadId.makeUnsafe("thread-1"), | |
| 743 | ThreadId.make("thread-2"), | |
| 744 | ThreadId.make("thread-1"), | |
| 750 | 745 | ]); |
| 751 | 746 | }); |
| 752 | 747 | |
| ... | ... | @@ -754,13 +749,13 @@ describe("sortThreadsForSidebar", () => { |
| 754 | 749 | const sorted = sortThreadsForSidebar( |
| 755 | 750 | [ |
| 756 | 751 | makeThread({ |
| 757 | id: ThreadId.makeUnsafe("thread-1"), | |
| 752 | id: ThreadId.make("thread-1"), | |
| 758 | 753 | createdAt: "" as never, |
| 759 | 754 | updatedAt: undefined, |
| 760 | 755 | messages: [], |
| 761 | 756 | }), |
| 762 | 757 | makeThread({ |
| 763 | id: ThreadId.makeUnsafe("thread-2"), | |
| 758 | id: ThreadId.make("thread-2"), | |
| 764 | 759 | createdAt: "" as never, |
| 765 | 760 | updatedAt: undefined, |
| 766 | 761 | messages: [], |
| ... | ... | @@ -770,8 +765,8 @@ describe("sortThreadsForSidebar", () => { |
| 770 | 765 | ); |
| 771 | 766 | |
| 772 | 767 | expect(sorted.map((thread) => thread.id)).toEqual([ |
| 773 | ThreadId.makeUnsafe("thread-2"), | |
| 774 | ThreadId.makeUnsafe("thread-1"), | |
| 768 | ThreadId.make("thread-2"), | |
| 769 | ThreadId.make("thread-1"), | |
| 775 | 770 | ]); |
| 776 | 771 | }); |
| 777 | 772 | |
| ... | ... | @@ -779,12 +774,12 @@ describe("sortThreadsForSidebar", () => { |
| 779 | 774 | const sorted = sortThreadsForSidebar( |
| 780 | 775 | [ |
| 781 | 776 | makeThread({ |
| 782 | id: ThreadId.makeUnsafe("thread-1"), | |
| 777 | id: ThreadId.make("thread-1"), | |
| 783 | 778 | createdAt: "2026-03-09T10:05:00.000Z", |
| 784 | 779 | updatedAt: "2026-03-09T10:05:00.000Z", |
| 785 | 780 | }), |
| 786 | 781 | makeThread({ |
| 787 | id: ThreadId.makeUnsafe("thread-2"), | |
| 782 | id: ThreadId.make("thread-2"), | |
| 788 | 783 | createdAt: "2026-03-09T10:00:00.000Z", |
| 789 | 784 | updatedAt: "2026-03-09T10:10:00.000Z", |
| 790 | 785 | }), |
| ... | ... | @@ -793,8 +788,8 @@ describe("sortThreadsForSidebar", () => { |
| 793 | 788 | ); |
| 794 | 789 | |
| 795 | 790 | expect(sorted.map((thread) => thread.id)).toEqual([ |
| 796 | ThreadId.makeUnsafe("thread-1"), | |
| 797 | ThreadId.makeUnsafe("thread-2"), | |
| 791 | ThreadId.make("thread-1"), | |
| 792 | ThreadId.make("thread-2"), | |
| 798 | 793 | ]); |
| 799 | 794 | }); |
| 800 | 795 | }); |
| ... | ... | @@ -804,80 +799,77 @@ describe("getFallbackThreadIdAfterDelete", () => { |
| 804 | 799 | const fallbackThreadId = getFallbackThreadIdAfterDelete({ |
| 805 | 800 | threads: [ |
| 806 | 801 | makeThread({ |
| 807 | id: ThreadId.makeUnsafe("thread-oldest"), | |
| 808 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 802 | id: ThreadId.make("thread-oldest"), | |
| 803 | projectId: ProjectId.make("project-1"), | |
| 809 | 804 | createdAt: "2026-03-09T10:00:00.000Z", |
| 810 | 805 | messages: [], |
| 811 | 806 | }), |
| 812 | 807 | makeThread({ |
| 813 | id: ThreadId.makeUnsafe("thread-active"), | |
| 814 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 808 | id: ThreadId.make("thread-active"), | |
| 809 | projectId: ProjectId.make("project-1"), | |
| 815 | 810 | createdAt: "2026-03-09T10:05:00.000Z", |
| 816 | 811 | messages: [], |
| 817 | 812 | }), |
| 818 | 813 | makeThread({ |
| 819 | id: ThreadId.makeUnsafe("thread-newest"), | |
| 820 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 814 | id: ThreadId.make("thread-newest"), | |
| 815 | projectId: ProjectId.make("project-1"), | |
| 821 | 816 | createdAt: "2026-03-09T10:10:00.000Z", |
| 822 | 817 | messages: [], |
| 823 | 818 | }), |
| 824 | 819 | makeThread({ |
| 825 | id: ThreadId.makeUnsafe("thread-other-project"), | |
| 826 | projectId: ProjectId.makeUnsafe("project-2"), | |
| 820 | id: ThreadId.make("thread-other-project"), | |
| 821 | projectId: ProjectId.make("project-2"), | |
| 827 | 822 | createdAt: "2026-03-09T10:20:00.000Z", |
| 828 | 823 | messages: [], |
| 829 | 824 | }), |
| 830 | 825 | ], |
| 831 | deletedThreadId: ThreadId.makeUnsafe("thread-active"), | |
| 826 | deletedThreadId: ThreadId.make("thread-active"), | |
| 832 | 827 | sortOrder: "created_at", |
| 833 | 828 | }); |
| 834 | 829 | |
| 835 | expect(fallbackThreadId).toBe(ThreadId.makeUnsafe("thread-newest")); | |
| 830 | expect(fallbackThreadId).toBe(ThreadId.make("thread-newest")); | |
| 836 | 831 | }); |
| 837 | 832 | |
| 838 | 833 | it("skips other threads being deleted in the same action", () => { |
| 839 | 834 | const fallbackThreadId = getFallbackThreadIdAfterDelete({ |
| 840 | 835 | threads: [ |
| 841 | 836 | makeThread({ |
| 842 | id: ThreadId.makeUnsafe("thread-active"), | |
| 843 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 837 | id: ThreadId.make("thread-active"), | |
| 838 | projectId: ProjectId.make("project-1"), | |
| 844 | 839 | createdAt: "2026-03-09T10:05:00.000Z", |
| 845 | 840 | messages: [], |
| 846 | 841 | }), |
| 847 | 842 | makeThread({ |
| 848 | id: ThreadId.makeUnsafe("thread-newest"), | |
| 849 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 843 | id: ThreadId.make("thread-newest"), | |
| 844 | projectId: ProjectId.make("project-1"), | |
| 850 | 845 | createdAt: "2026-03-09T10:10:00.000Z", |
| 851 | 846 | messages: [], |
| 852 | 847 | }), |
| 853 | 848 | makeThread({ |
| 854 | id: ThreadId.makeUnsafe("thread-next"), | |
| 855 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 849 | id: ThreadId.make("thread-next"), | |
| 850 | projectId: ProjectId.make("project-1"), | |
| 856 | 851 | createdAt: "2026-03-09T10:07:00.000Z", |
| 857 | 852 | messages: [], |
| 858 | 853 | }), |
| 859 | 854 | ], |
| 860 | deletedThreadId: ThreadId.makeUnsafe("thread-active"), | |
| 861 | deletedThreadIds: new Set([ | |
| 862 | ThreadId.makeUnsafe("thread-active"), | |
| 863 | ThreadId.makeUnsafe("thread-newest"), | |
| 864 | ]), | |
| 855 | deletedThreadId: ThreadId.make("thread-active"), | |
| 856 | deletedThreadIds: new Set([ThreadId.make("thread-active"), ThreadId.make("thread-newest")]), | |
| 865 | 857 | sortOrder: "created_at", |
| 866 | 858 | }); |
| 867 | 859 | |
| 868 | expect(fallbackThreadId).toBe(ThreadId.makeUnsafe("thread-next")); | |
| 860 | expect(fallbackThreadId).toBe(ThreadId.make("thread-next")); | |
| 869 | 861 | }); |
| 870 | 862 | }); |
| 871 | 863 | |
| 872 | 864 | describe("sortProjectsForSidebar", () => { |
| 873 | 865 | it("sorts projects by the most recent user message across their threads", () => { |
| 874 | 866 | const projects = [ |
| 875 | makeProject({ id: ProjectId.makeUnsafe("project-1"), name: "Older project" }), | |
| 876 | makeProject({ id: ProjectId.makeUnsafe("project-2"), name: "Newer project" }), | |
| 867 | makeProject({ id: ProjectId.make("project-1"), name: "Older project" }), | |
| 868 | makeProject({ id: ProjectId.make("project-2"), name: "Newer project" }), | |
| 877 | 869 | ]; |
| 878 | 870 | const threads = [ |
| 879 | 871 | makeThread({ |
| 880 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 872 | projectId: ProjectId.make("project-1"), | |
| 881 | 873 | updatedAt: "2026-03-09T10:20:00.000Z", |
| 882 | 874 | messages: [ |
| 883 | 875 | { |
| ... | ... | @@ -891,8 +883,8 @@ describe("sortProjectsForSidebar", () => { |
| 891 | 883 | ], |
| 892 | 884 | }), |
| 893 | 885 | makeThread({ |
| 894 | id: ThreadId.makeUnsafe("thread-2"), | |
| 895 | projectId: ProjectId.makeUnsafe("project-2"), | |
| 886 | id: ThreadId.make("thread-2"), | |
| 887 | projectId: ProjectId.make("project-2"), | |
| 896 | 888 | updatedAt: "2026-03-09T10:05:00.000Z", |
| 897 | 889 | messages: [ |
| 898 | 890 | { |
| ... | ... | @@ -910,8 +902,8 @@ describe("sortProjectsForSidebar", () => { |
| 910 | 902 | const sorted = sortProjectsForSidebar(projects, threads, "updated_at"); |
| 911 | 903 | |
| 912 | 904 | expect(sorted.map((project) => project.id)).toEqual([ |
| 913 | ProjectId.makeUnsafe("project-2"), | |
| 914 | ProjectId.makeUnsafe("project-1"), | |
| 905 | ProjectId.make("project-2"), | |
| 906 | ProjectId.make("project-1"), | |
| 915 | 907 | ]); |
| 916 | 908 | }); |
| 917 | 909 | |
| ... | ... | @@ -919,12 +911,12 @@ describe("sortProjectsForSidebar", () => { |
| 919 | 911 | const sorted = sortProjectsForSidebar( |
| 920 | 912 | [ |
| 921 | 913 | makeProject({ |
| 922 | id: ProjectId.makeUnsafe("project-1"), | |
| 914 | id: ProjectId.make("project-1"), | |
| 923 | 915 | name: "Older project", |
| 924 | 916 | updatedAt: "2026-03-09T10:01:00.000Z", |
| 925 | 917 | }), |
| 926 | 918 | makeProject({ |
| 927 | id: ProjectId.makeUnsafe("project-2"), | |
| 919 | id: ProjectId.make("project-2"), | |
| 928 | 920 | name: "Newer project", |
| 929 | 921 | updatedAt: "2026-03-09T10:05:00.000Z", |
| 930 | 922 | }), |
| ... | ... | @@ -934,8 +926,8 @@ describe("sortProjectsForSidebar", () => { |
| 934 | 926 | ); |
| 935 | 927 | |
| 936 | 928 | expect(sorted.map((project) => project.id)).toEqual([ |
| 937 | ProjectId.makeUnsafe("project-2"), | |
| 938 | ProjectId.makeUnsafe("project-1"), | |
| 929 | ProjectId.make("project-2"), | |
| 930 | ProjectId.make("project-1"), | |
| 939 | 931 | ]); |
| 940 | 932 | }); |
| 941 | 933 | |
| ... | ... | @@ -943,13 +935,13 @@ describe("sortProjectsForSidebar", () => { |
| 943 | 935 | const sorted = sortProjectsForSidebar( |
| 944 | 936 | [ |
| 945 | 937 | makeProject({ |
| 946 | id: ProjectId.makeUnsafe("project-2"), | |
| 938 | id: ProjectId.make("project-2"), | |
| 947 | 939 | name: "Beta", |
| 948 | 940 | createdAt: undefined, |
| 949 | 941 | updatedAt: undefined, |
| 950 | 942 | }), |
| 951 | 943 | makeProject({ |
| 952 | id: ProjectId.makeUnsafe("project-1"), | |
| 944 | id: ProjectId.make("project-1"), | |
| 953 | 945 | name: "Alpha", |
| 954 | 946 | createdAt: undefined, |
| 955 | 947 | updatedAt: undefined, |
| ... | ... | @@ -960,22 +952,22 @@ describe("sortProjectsForSidebar", () => { |
| 960 | 952 | ); |
| 961 | 953 | |
| 962 | 954 | expect(sorted.map((project) => project.id)).toEqual([ |
| 963 | ProjectId.makeUnsafe("project-1"), | |
| 964 | ProjectId.makeUnsafe("project-2"), | |
| 955 | ProjectId.make("project-1"), | |
| 956 | ProjectId.make("project-2"), | |
| 965 | 957 | ]); |
| 966 | 958 | }); |
| 967 | 959 | |
| 968 | 960 | it("preserves manual project ordering", () => { |
| 969 | 961 | const projects = [ |
| 970 | makeProject({ id: ProjectId.makeUnsafe("project-2"), name: "Second" }), | |
| 971 | makeProject({ id: ProjectId.makeUnsafe("project-1"), name: "First" }), | |
| 962 | makeProject({ id: ProjectId.make("project-2"), name: "Second" }), | |
| 963 | makeProject({ id: ProjectId.make("project-1"), name: "First" }), | |
| 972 | 964 | ]; |
| 973 | 965 | |
| 974 | 966 | const sorted = sortProjectsForSidebar(projects, [], "manual"); |
| 975 | 967 | |
| 976 | 968 | expect(sorted.map((project) => project.id)).toEqual([ |
| 977 | ProjectId.makeUnsafe("project-2"), | |
| 978 | ProjectId.makeUnsafe("project-1"), | |
| 969 | ProjectId.make("project-2"), | |
| 970 | ProjectId.make("project-1"), | |
| 979 | 971 | ]); |
| 980 | 972 | }); |
| 981 | 973 | |
| ... | ... | @@ -983,26 +975,26 @@ describe("sortProjectsForSidebar", () => { |
| 983 | 975 | const sorted = sortProjectsForSidebar( |
| 984 | 976 | [ |
| 985 | 977 | makeProject({ |
| 986 | id: ProjectId.makeUnsafe("project-1"), | |
| 978 | id: ProjectId.make("project-1"), | |
| 987 | 979 | name: "Visible project", |
| 988 | 980 | updatedAt: "2026-03-09T10:01:00.000Z", |
| 989 | 981 | }), |
| 990 | 982 | makeProject({ |
| 991 | id: ProjectId.makeUnsafe("project-2"), | |
| 983 | id: ProjectId.make("project-2"), | |
| 992 | 984 | name: "Archived-only project", |
| 993 | 985 | updatedAt: "2026-03-09T10:00:00.000Z", |
| 994 | 986 | }), |
| 995 | 987 | ], |
| 996 | 988 | [ |
| 997 | 989 | makeThread({ |
| 998 | id: ThreadId.makeUnsafe("thread-visible"), | |
| 999 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 990 | id: ThreadId.make("thread-visible"), | |
| 991 | projectId: ProjectId.make("project-1"), | |
| 1000 | 992 | updatedAt: "2026-03-09T10:02:00.000Z", |
| 1001 | 993 | archivedAt: null, |
| 1002 | 994 | }), |
| 1003 | 995 | makeThread({ |
| 1004 | id: ThreadId.makeUnsafe("thread-archived"), | |
| 1005 | projectId: ProjectId.makeUnsafe("project-2"), | |
| 996 | id: ThreadId.make("thread-archived"), | |
| 997 | projectId: ProjectId.make("project-2"), | |
| 1006 | 998 | updatedAt: "2026-03-09T10:10:00.000Z", |
| 1007 | 999 | archivedAt: "2026-03-09T10:11:00.000Z", |
| 1008 | 1000 | }), |
| ... | ... | @@ -1011,8 +1003,8 @@ describe("sortProjectsForSidebar", () => { |
| 1011 | 1003 | ); |
| 1012 | 1004 | |
| 1013 | 1005 | expect(sorted.map((project) => project.id)).toEqual([ |
| 1014 | ProjectId.makeUnsafe("project-1"), | |
| 1015 | ProjectId.makeUnsafe("project-2"), | |
| 1006 | ProjectId.make("project-1"), | |
| 1007 | ProjectId.make("project-2"), | |
| 1016 | 1008 | ]); |
| 1017 | 1009 | }); |
| 1018 | 1010 |
apps/web/src/components/ThreadTerminalDrawer.browser.tsx+1-1| ... | ... | @@ -121,7 +121,7 @@ vi.mock("~/localApi", () => ({ |
| 121 | 121 | |
| 122 | 122 | import { TerminalViewport } from "./ThreadTerminalDrawer"; |
| 123 | 123 | |
| 124 | const THREAD_ID = ThreadId.makeUnsafe("thread-terminal-browser"); | |
| 124 | const THREAD_ID = ThreadId.make("thread-terminal-browser"); | |
| 125 | 125 | |
| 126 | 126 | function createEnvironmentApi() { |
| 127 | 127 | return { |
apps/web/src/components/chat/ChangedFilesTree.test.tsx+2-2| ... | ... | @@ -39,7 +39,7 @@ describe("ChangedFilesTree", () => { |
| 39 | 39 | ({ files, visibleLabels, hiddenLabels }) => { |
| 40 | 40 | const markup = renderToStaticMarkup( |
| 41 | 41 | <ChangedFilesTree |
| 42 | turnId={TurnId.makeUnsafe("turn-1")} | |
| 42 | turnId={TurnId.make("turn-1")} | |
| 43 | 43 | files={files} |
| 44 | 44 | allDirectoriesExpanded={false} |
| 45 | 45 | resolvedTheme="light" |
| ... | ... | @@ -100,7 +100,7 @@ describe("ChangedFilesTree", () => { |
| 100 | 100 | ({ files, visibleLabels }) => { |
| 101 | 101 | const markup = renderToStaticMarkup( |
| 102 | 102 | <ChangedFilesTree |
| 103 | turnId={TurnId.makeUnsafe("turn-1")} | |
| 103 | turnId={TurnId.make("turn-1")} | |
| 104 | 104 | files={files} |
| 105 | 105 | allDirectoriesExpanded |
| 106 | 106 | resolvedTheme="light" |
apps/web/src/components/chat/CompactComposerControlsMenu.browser.tsx+2-2| ... | ... | @@ -15,10 +15,10 @@ import { CompactComposerControlsMenu } from "./CompactComposerControlsMenu"; |
| 15 | 15 | import { TraitsMenuContent } from "./TraitsPicker"; |
| 16 | 16 | import { useComposerDraftStore } from "../../composerDraftStore"; |
| 17 | 17 | |
| 18 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local"); | |
| 18 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | |
| 19 | 19 | |
| 20 | 20 | async function mountMenu(props?: { modelSelection?: ModelSelection; prompt?: string }) { |
| 21 | const threadId = ThreadId.makeUnsafe("thread-compact-menu"); | |
| 21 | const threadId = ThreadId.make("thread-compact-menu"); | |
| 22 | 22 | const threadRef = scopeThreadRef(LOCAL_ENVIRONMENT_ID, threadId); |
| 23 | 23 | const threadKey = scopedThreadKey(threadRef); |
| 24 | 24 | const provider = props?.modelSelection?.provider ?? "claudeAgent"; |
apps/web/src/components/chat/ComposerPendingTerminalContexts.test.tsx+1-1| ... | ... | @@ -10,7 +10,7 @@ describe("ComposerPendingTerminalContextChip", () => { |
| 10 | 10 | <ComposerPendingTerminalContextChip |
| 11 | 11 | context={{ |
| 12 | 12 | id: "ctx-expired", |
| 13 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 13 | threadId: ThreadId.make("thread-1"), | |
| 14 | 14 | terminalId: "default", |
| 15 | 15 | terminalLabel: "Terminal 1", |
| 16 | 16 | lineStart: 2, |
apps/web/src/components/chat/MessagesTimeline.test.tsx+1-1| ... | ... | @@ -60,7 +60,7 @@ describe("MessagesTimeline", () => { |
| 60 | 60 | kind: "message", |
| 61 | 61 | createdAt: "2026-03-17T19:12:28.000Z", |
| 62 | 62 | message: { |
| 63 | id: MessageId.makeUnsafe("message-2"), | |
| 63 | id: MessageId.make("message-2"), | |
| 64 | 64 | role: "user", |
| 65 | 65 | text: [ |
| 66 | 66 | "yoo what's @terminal-1:1-5 mean", |
apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx+1-1| ... | ... | @@ -101,7 +101,7 @@ function createMessage(input: { |
| 101 | 101 | attachments?: ChatMessage["attachments"]; |
| 102 | 102 | }): ChatMessage { |
| 103 | 103 | return { |
| 104 | id: MessageId.makeUnsafe(input.id), | |
| 104 | id: MessageId.make(input.id), | |
| 105 | 105 | role: input.role, |
| 106 | 106 | text: input.text, |
| 107 | 107 | ...(input.attachments ? { attachments: input.attachments } : {}), |
apps/web/src/components/chat/TraitsPicker.browser.tsx+3-3| ... | ... | @@ -28,11 +28,11 @@ import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings"; |
| 28 | 28 | |
| 29 | 29 | // ── Claude TraitsPicker tests ───────────────────────────────────────── |
| 30 | 30 | |
| 31 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local"); | |
| 32 | const CLAUDE_THREAD_ID = ThreadId.makeUnsafe("thread-claude-traits"); | |
| 31 | const LOCAL_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | |
| 32 | const CLAUDE_THREAD_ID = ThreadId.make("thread-claude-traits"); | |
| 33 | 33 | const CLAUDE_THREAD_REF = scopeThreadRef(LOCAL_ENVIRONMENT_ID, CLAUDE_THREAD_ID); |
| 34 | 34 | const CLAUDE_THREAD_KEY = scopedThreadKey(CLAUDE_THREAD_REF); |
| 35 | const CODEX_THREAD_ID = ThreadId.makeUnsafe("thread-codex-traits"); | |
| 35 | const CODEX_THREAD_ID = ThreadId.make("thread-codex-traits"); | |
| 36 | 36 | const CODEX_THREAD_REF = scopeThreadRef(LOCAL_ENVIRONMENT_ID, CODEX_THREAD_ID); |
| 37 | 37 | const CODEX_THREAD_KEY = scopedThreadKey(CODEX_THREAD_REF); |
| 38 | 38 | const TEST_PROVIDERS: ReadonlyArray<ServerProvider> = [ |
apps/web/src/components/settings/SettingsPanels.browser.tsx+5-5| ... | ... | @@ -92,7 +92,7 @@ const authAccessHarness = vi.hoisted(() => { |
| 92 | 92 | revision, |
| 93 | 93 | type: "clientRemoved", |
| 94 | 94 | payload: { |
| 95 | sessionId: AuthSessionId.makeUnsafe(sessionId), | |
| 95 | sessionId: AuthSessionId.make(sessionId), | |
| 96 | 96 | }, |
| 97 | 97 | }); |
| 98 | 98 | revision += 1; |
| ... | ... | @@ -119,13 +119,13 @@ vi.mock("../../environments/runtime", () => { |
| 119 | 119 | id: "environment-local", |
| 120 | 120 | label: "Local environment", |
| 121 | 121 | source: "manual" as const, |
| 122 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 122 | environmentId: EnvironmentId.make("environment-local"), | |
| 123 | 123 | target: { |
| 124 | 124 | httpBaseUrl: "http://localhost:3000", |
| 125 | 125 | wsBaseUrl: "ws://localhost:3000", |
| 126 | 126 | }, |
| 127 | 127 | }, |
| 128 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 128 | environmentId: EnvironmentId.make("environment-local"), | |
| 129 | 129 | client: { |
| 130 | 130 | server: { |
| 131 | 131 | subscribeAuthAccess: (listener: Parameters<typeof authAccessHarness.subscribe>[0]) => |
| ... | ... | @@ -171,7 +171,7 @@ vi.mock("../../environments/runtime", () => { |
| 171 | 171 | function createBaseServerConfig(): ServerConfig { |
| 172 | 172 | return { |
| 173 | 173 | environment: { |
| 174 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 174 | environmentId: EnvironmentId.make("environment-local"), | |
| 175 | 175 | label: "Local environment", |
| 176 | 176 | platform: { os: "darwin" as const, arch: "arm64" as const }, |
| 177 | 177 | serverVersion: "0.0.0-test", |
| ... | ... | @@ -245,7 +245,7 @@ function makeClientSession(input: { |
| 245 | 245 | deviceType: "unknown", |
| 246 | 246 | ...input.client, |
| 247 | 247 | }, |
| 248 | sessionId: AuthSessionId.makeUnsafe(input.sessionId), | |
| 248 | sessionId: AuthSessionId.make(input.sessionId), | |
| 249 | 249 | issuedAt: makeUtc(input.issuedAt), |
| 250 | 250 | expiresAt: makeUtc(input.expiresAt), |
| 251 | 251 | lastConnectedAt: |
apps/web/src/composerDraftStore.test.ts+22-22| ... | ... | @@ -70,7 +70,7 @@ function makeTerminalContext(input: { |
| 70 | 70 | }): TerminalContextDraft { |
| 71 | 71 | return { |
| 72 | 72 | id: input.id, |
| 73 | threadId: ThreadId.makeUnsafe("thread-dedupe"), | |
| 73 | threadId: ThreadId.make("thread-dedupe"), | |
| 74 | 74 | terminalId: input.terminalId ?? "default", |
| 75 | 75 | terminalLabel: input.terminalLabel ?? "Terminal 1", |
| 76 | 76 | lineStart: input.lineStart ?? 4, |
| ... | ... | @@ -106,9 +106,9 @@ function providerModelOptions(options: ProviderModelOptions): ProviderModelOptio |
| 106 | 106 | return options; |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | const TEST_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local"); | |
| 110 | const OTHER_TEST_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-remote"); | |
| 111 | const LEGACY_TEST_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("__legacy__"); | |
| 109 | const TEST_ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | |
| 110 | const OTHER_TEST_ENVIRONMENT_ID = EnvironmentId.make("environment-remote"); | |
| 111 | const LEGACY_TEST_ENVIRONMENT_ID = EnvironmentId.make("__legacy__"); | |
| 112 | 112 | |
| 113 | 113 | function threadKeyFor( |
| 114 | 114 | threadId: ThreadId, |
| ... | ... | @@ -130,7 +130,7 @@ function draftByKey(key: string) { |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | describe("composerDraftStore addImages", () => { |
| 133 | const threadId = ThreadId.makeUnsafe("thread-dedupe"); | |
| 133 | const threadId = ThreadId.make("thread-dedupe"); | |
| 134 | 134 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 135 | 135 | let originalRevokeObjectUrl: typeof URL.revokeObjectURL; |
| 136 | 136 | let revokeSpy: ReturnType<typeof vi.fn<(url: string) => void>>; |
| ... | ... | @@ -216,7 +216,7 @@ describe("composerDraftStore addImages", () => { |
| 216 | 216 | }); |
| 217 | 217 | |
| 218 | 218 | describe("composerDraftStore clearComposerContent", () => { |
| 219 | const threadId = ThreadId.makeUnsafe("thread-clear"); | |
| 219 | const threadId = ThreadId.make("thread-clear"); | |
| 220 | 220 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 221 | 221 | let originalRevokeObjectUrl: typeof URL.revokeObjectURL; |
| 222 | 222 | let revokeSpy: ReturnType<typeof vi.fn<(url: string) => void>>; |
| ... | ... | @@ -248,7 +248,7 @@ describe("composerDraftStore clearComposerContent", () => { |
| 248 | 248 | }); |
| 249 | 249 | |
| 250 | 250 | describe("composerDraftStore syncPersistedAttachments", () => { |
| 251 | const threadId = ThreadId.makeUnsafe("thread-sync-persisted"); | |
| 251 | const threadId = ThreadId.make("thread-sync-persisted"); | |
| 252 | 252 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 253 | 253 | |
| 254 | 254 | beforeEach(() => { |
| ... | ... | @@ -304,7 +304,7 @@ describe("composerDraftStore syncPersistedAttachments", () => { |
| 304 | 304 | }); |
| 305 | 305 | |
| 306 | 306 | describe("composerDraftStore terminal contexts", () => { |
| 307 | const threadId = ThreadId.makeUnsafe("thread-dedupe"); | |
| 307 | const threadId = ThreadId.make("thread-dedupe"); | |
| 308 | 308 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 309 | 309 | |
| 310 | 310 | beforeEach(() => { |
| ... | ... | @@ -482,18 +482,18 @@ describe("composerDraftStore terminal contexts", () => { |
| 482 | 482 | }); |
| 483 | 483 | |
| 484 | 484 | describe("composerDraftStore project draft thread mapping", () => { |
| 485 | const projectId = ProjectId.makeUnsafe("project-a"); | |
| 486 | const otherProjectId = ProjectId.makeUnsafe("project-b"); | |
| 485 | const projectId = ProjectId.make("project-a"); | |
| 486 | const otherProjectId = ProjectId.make("project-b"); | |
| 487 | 487 | const projectRef = scopeProjectRef(TEST_ENVIRONMENT_ID, projectId); |
| 488 | 488 | const otherProjectRef = scopeProjectRef(TEST_ENVIRONMENT_ID, otherProjectId); |
| 489 | 489 | const remoteProjectRef = scopeProjectRef(OTHER_TEST_ENVIRONMENT_ID, projectId); |
| 490 | const threadId = ThreadId.makeUnsafe("thread-a"); | |
| 491 | const otherThreadId = ThreadId.makeUnsafe("thread-b"); | |
| 492 | const draftId = DraftId.makeUnsafe("draft-a"); | |
| 493 | const otherDraftId = DraftId.makeUnsafe("draft-b"); | |
| 494 | const sharedDraftId = DraftId.makeUnsafe("draft-shared"); | |
| 495 | const localDraftId = DraftId.makeUnsafe("draft-local"); | |
| 496 | const remoteDraftId = DraftId.makeUnsafe("draft-remote"); | |
| 490 | const threadId = ThreadId.make("thread-a"); | |
| 491 | const otherThreadId = ThreadId.make("thread-b"); | |
| 492 | const draftId = DraftId.make("draft-a"); | |
| 493 | const otherDraftId = DraftId.make("draft-b"); | |
| 494 | const sharedDraftId = DraftId.make("draft-shared"); | |
| 495 | const localDraftId = DraftId.make("draft-local"); | |
| 496 | const remoteDraftId = DraftId.make("draft-remote"); | |
| 497 | 497 | |
| 498 | 498 | beforeEach(() => { |
| 499 | 499 | resetComposerDraftStore(); |
| ... | ... | @@ -847,7 +847,7 @@ describe("composerDraftStore project draft thread mapping", () => { |
| 847 | 847 | }); |
| 848 | 848 | |
| 849 | 849 | describe("composerDraftStore modelSelection", () => { |
| 850 | const threadId = ThreadId.makeUnsafe("thread-model-options"); | |
| 850 | const threadId = ThreadId.make("thread-model-options"); | |
| 851 | 851 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 852 | 852 | |
| 853 | 853 | beforeEach(() => { |
| ... | ... | @@ -1078,7 +1078,7 @@ describe("composerDraftStore modelSelection", () => { |
| 1078 | 1078 | }); |
| 1079 | 1079 | |
| 1080 | 1080 | describe("composerDraftStore setModelSelection", () => { |
| 1081 | const threadId = ThreadId.makeUnsafe("thread-model"); | |
| 1081 | const threadId = ThreadId.make("thread-model"); | |
| 1082 | 1082 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 1083 | 1083 | |
| 1084 | 1084 | beforeEach(() => { |
| ... | ... | @@ -1133,7 +1133,7 @@ describe("composerDraftStore sticky composer settings", () => { |
| 1133 | 1133 | |
| 1134 | 1134 | it("applies sticky activeProvider to new drafts", () => { |
| 1135 | 1135 | const store = useComposerDraftStore.getState(); |
| 1136 | const threadId = ThreadId.makeUnsafe("thread-sticky-active-provider"); | |
| 1136 | const threadId = ThreadId.make("thread-sticky-active-provider"); | |
| 1137 | 1137 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 1138 | 1138 | |
| 1139 | 1139 | store.setStickyModelSelection(modelSelection("claudeAgent", "claude-opus-4-6")); |
| ... | ... | @@ -1149,7 +1149,7 @@ describe("composerDraftStore sticky composer settings", () => { |
| 1149 | 1149 | }); |
| 1150 | 1150 | |
| 1151 | 1151 | describe("composerDraftStore provider-scoped option updates", () => { |
| 1152 | const threadId = ThreadId.makeUnsafe("thread-provider"); | |
| 1152 | const threadId = ThreadId.make("thread-provider"); | |
| 1153 | 1153 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 1154 | 1154 | |
| 1155 | 1155 | beforeEach(() => { |
| ... | ... | @@ -1175,7 +1175,7 @@ describe("composerDraftStore provider-scoped option updates", () => { |
| 1175 | 1175 | }); |
| 1176 | 1176 | |
| 1177 | 1177 | describe("composerDraftStore runtime and interaction settings", () => { |
| 1178 | const threadId = ThreadId.makeUnsafe("thread-settings"); | |
| 1178 | const threadId = ThreadId.make("thread-settings"); | |
| 1179 | 1179 | const threadRef = scopeThreadRef(TEST_ENVIRONMENT_ID, threadId); |
| 1180 | 1180 | |
| 1181 | 1181 | beforeEach(() => { |
apps/web/src/composerDraftStore.ts+13-16| ... | ... | @@ -926,7 +926,7 @@ function normalizeComposerTarget( |
| 926 | 926 | ): ComposerThreadTarget | null { |
| 927 | 927 | if (typeof target === "string") { |
| 928 | 928 | const draftId = target.trim(); |
| 929 | return draftId.length > 0 ? DraftId.makeUnsafe(draftId) : null; | |
| 929 | return draftId.length > 0 ? DraftId.make(draftId) : null; | |
| 930 | 930 | } |
| 931 | 931 | return target; |
| 932 | 932 | } |
| ... | ... | @@ -1804,7 +1804,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()( |
| 1804 | 1804 | if (!draftThread || isDraftThreadPromoting(draftThread)) { |
| 1805 | 1805 | return null; |
| 1806 | 1806 | } |
| 1807 | return toProjectDraftSession(DraftId.makeUnsafe(draftId), draftThread); | |
| 1807 | return toProjectDraftSession(DraftId.make(draftId), draftThread); | |
| 1808 | 1808 | }, |
| 1809 | 1809 | getDraftThreadByProjectRef: (projectRef) => { |
| 1810 | 1810 | return get().getDraftSessionByProjectRef(projectRef); |
| ... | ... | @@ -1818,7 +1818,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()( |
| 1818 | 1818 | draftThread.projectId === projectRef.projectId && |
| 1819 | 1819 | draftThread.environmentId === projectRef.environmentId |
| 1820 | 1820 | ) { |
| 1821 | return toProjectDraftSession(DraftId.makeUnsafe(draftId), draftThread); | |
| 1821 | return toProjectDraftSession(DraftId.make(draftId), draftThread); | |
| 1822 | 1822 | } |
| 1823 | 1823 | } |
| 1824 | 1824 | return null; |
| ... | ... | @@ -1837,7 +1837,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()( |
| 1837 | 1837 | }, |
| 1838 | 1838 | getDraftThread: (threadRef) => { |
| 1839 | 1839 | if (typeof threadRef === "string") { |
| 1840 | return get().getDraftSession(DraftId.makeUnsafe(threadRef)); | |
| 1840 | return get().getDraftSession(DraftId.make(threadRef)); | |
| 1841 | 1841 | } |
| 1842 | 1842 | return get().getDraftSessionByRef(threadRef); |
| 1843 | 1843 | }, |
| ... | ... | @@ -1863,7 +1863,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()( |
| 1863 | 1863 | state.logicalProjectDraftThreadKeyByLogicalProjectKey[normalizedLogicalProjectKey]; |
| 1864 | 1864 | const nextDraftThread = createDraftThreadState( |
| 1865 | 1865 | projectRef, |
| 1866 | options?.threadId ?? existingThread?.threadId ?? ThreadId.makeUnsafe(draftId), | |
| 1866 | options?.threadId ?? existingThread?.threadId ?? ThreadId.make(draftId), | |
| 1867 | 1867 | normalizedLogicalProjectKey, |
| 1868 | 1868 | existingThread, |
| 1869 | 1869 | options, |
| ... | ... | @@ -2438,10 +2438,9 @@ const composerDraftStore = create<ComposerDraftStoreState>()( |
| 2438 | 2438 | if (!threadKey || !threadId) { |
| 2439 | 2439 | return; |
| 2440 | 2440 | } |
| 2441 | get().addImages( | |
| 2442 | typeof threadRef === "string" ? DraftId.makeUnsafe(threadKey) : threadRef, | |
| 2443 | [image], | |
| 2444 | ); | |
| 2441 | get().addImages(typeof threadRef === "string" ? DraftId.make(threadKey) : threadRef, [ | |
| 2442 | image, | |
| 2443 | ]); | |
| 2445 | 2444 | }, |
| 2446 | 2445 | addImages: (threadRef, images) => { |
| 2447 | 2446 | const threadKey = resolveComposerDraftKey(get(), threadRef) ?? ""; |
| ... | ... | @@ -2566,7 +2565,7 @@ const composerDraftStore = create<ComposerDraftStoreState>()( |
| 2566 | 2565 | return; |
| 2567 | 2566 | } |
| 2568 | 2567 | get().addTerminalContexts( |
| 2569 | typeof threadRef === "string" ? DraftId.makeUnsafe(threadKey) : threadRef, | |
| 2568 | typeof threadRef === "string" ? DraftId.make(threadKey) : threadRef, | |
| 2570 | 2569 | [context], |
| 2571 | 2570 | ); |
| 2572 | 2571 | }, |
| ... | ... | @@ -2799,9 +2798,7 @@ export function useEffectiveComposerModelState(input: { |
| 2799 | 2798 | projectModelSelection: ModelSelection | null | undefined; |
| 2800 | 2799 | settings: UnifiedSettings; |
| 2801 | 2800 | }): EffectiveComposerModelState { |
| 2802 | const draft = useComposerDraftModelState( | |
| 2803 | input.threadRef ?? input.draftId ?? DraftId.makeUnsafe(""), | |
| 2804 | ); | |
| 2801 | const draft = useComposerDraftModelState(input.threadRef ?? input.draftId ?? DraftId.make("")); | |
| 2805 | 2802 | |
| 2806 | 2803 | return useMemo( |
| 2807 | 2804 | () => |
| ... | ... | @@ -2836,7 +2833,7 @@ export function markPromotedDraftThread(threadId: ThreadId): void { |
| 2836 | 2833 | const draftThreadTargets: ComposerThreadTarget[] = []; |
| 2837 | 2834 | for (const [draftId, draftThread] of Object.entries(store.draftThreadsByThreadKey)) { |
| 2838 | 2835 | if (draftThread.threadId === threadId) { |
| 2839 | draftThreadTargets.push(DraftId.makeUnsafe(draftId)); | |
| 2836 | draftThreadTargets.push(DraftId.make(draftId)); | |
| 2840 | 2837 | } |
| 2841 | 2838 | } |
| 2842 | 2839 | if (draftThreadTargets.length === 0) { |
| ... | ... | @@ -2854,7 +2851,7 @@ export function markPromotedDraftThreadByRef(threadRef: ScopedThreadRef): void { |
| 2854 | 2851 | draftThread.environmentId === threadRef.environmentId && |
| 2855 | 2852 | draftThread.threadId === threadRef.threadId |
| 2856 | 2853 | ) { |
| 2857 | draftStore.markDraftThreadPromoting(DraftId.makeUnsafe(draftId), threadRef); | |
| 2854 | draftStore.markDraftThreadPromoting(DraftId.make(draftId), threadRef); | |
| 2858 | 2855 | } |
| 2859 | 2856 | } |
| 2860 | 2857 | } |
| ... | ... | @@ -2879,7 +2876,7 @@ export function finalizePromotedDraftThreadByRef(threadRef: ScopedThreadRef): vo |
| 2879 | 2876 | draftThread.promotedTo.environmentId === threadRef.environmentId && |
| 2880 | 2877 | draftThread.promotedTo.threadId === threadRef.threadId |
| 2881 | 2878 | ) { |
| 2882 | draftStore.finalizePromotedDraftThread(DraftId.makeUnsafe(draftId)); | |
| 2879 | draftStore.finalizePromotedDraftThread(DraftId.make(draftId)); | |
| 2883 | 2880 | } |
| 2884 | 2881 | } |
| 2885 | 2882 | } |
apps/web/src/diffRouteSearch.ts+1-1| ... | ... | @@ -28,7 +28,7 @@ export function stripDiffSearchParams<T extends Record<string, unknown>>( |
| 28 | 28 | export function parseDiffRouteSearch(search: Record<string, unknown>): DiffRouteSearch { |
| 29 | 29 | const diff = isDiffOpenValue(search.diff) ? "1" : undefined; |
| 30 | 30 | const diffTurnIdRaw = diff ? normalizeSearchString(search.diffTurnId) : undefined; |
| 31 | const diffTurnId = diffTurnIdRaw ? TurnId.makeUnsafe(diffTurnIdRaw) : undefined; | |
| 31 | const diffTurnId = diffTurnIdRaw ? TurnId.make(diffTurnIdRaw) : undefined; | |
| 32 | 32 | const diffFilePath = diff && diffTurnId ? normalizeSearchString(search.diffFilePath) : undefined; |
| 33 | 33 | |
| 34 | 34 | return { |
apps/web/src/environmentGrouping.test.ts+13-13| ... | ... | @@ -16,19 +16,19 @@ import { DEFAULT_INTERACTION_MODE } from "./types"; |
| 16 | 16 | |
| 17 | 17 | // ── Fixture Identifiers ────────────────────────────────────────────── |
| 18 | 18 | |
| 19 | const primaryEnvId = EnvironmentId.makeUnsafe("env-primary"); | |
| 20 | const remoteEnvId = EnvironmentId.makeUnsafe("env-remote"); | |
| 19 | const primaryEnvId = EnvironmentId.make("env-primary"); | |
| 20 | const remoteEnvId = EnvironmentId.make("env-remote"); | |
| 21 | 21 | |
| 22 | const sharedProjectPrimaryId = ProjectId.makeUnsafe("shared-proj-primary"); | |
| 23 | const sharedProjectRemoteId = ProjectId.makeUnsafe("shared-proj-remote"); | |
| 24 | const localOnlyProjectId = ProjectId.makeUnsafe("local-only-proj"); | |
| 25 | const remoteOnlyProjectId = ProjectId.makeUnsafe("remote-only-proj"); | |
| 22 | const sharedProjectPrimaryId = ProjectId.make("shared-proj-primary"); | |
| 23 | const sharedProjectRemoteId = ProjectId.make("shared-proj-remote"); | |
| 24 | const localOnlyProjectId = ProjectId.make("local-only-proj"); | |
| 25 | const remoteOnlyProjectId = ProjectId.make("remote-only-proj"); | |
| 26 | 26 | |
| 27 | const threadP1 = ThreadId.makeUnsafe("thread-shared-primary-1"); | |
| 28 | const threadP2 = ThreadId.makeUnsafe("thread-shared-primary-2"); | |
| 29 | const threadR1 = ThreadId.makeUnsafe("thread-shared-remote-1"); | |
| 30 | const threadL1 = ThreadId.makeUnsafe("thread-local-only-1"); | |
| 31 | const threadRO1 = ThreadId.makeUnsafe("thread-remote-only-1"); | |
| 27 | const threadP1 = ThreadId.make("thread-shared-primary-1"); | |
| 28 | const threadP2 = ThreadId.make("thread-shared-primary-2"); | |
| 29 | const threadR1 = ThreadId.make("thread-shared-remote-1"); | |
| 30 | const threadL1 = ThreadId.make("thread-local-only-1"); | |
| 31 | const threadRO1 = ThreadId.make("thread-remote-only-1"); | |
| 32 | 32 | |
| 33 | 33 | const SHARED_REPO_CANONICAL_KEY = "github.com/example/shared-repo"; |
| 34 | 34 | |
| ... | ... | @@ -328,7 +328,7 @@ describe("environment grouping", () => { |
| 328 | 328 | |
| 329 | 329 | it("returns empty array for nonexistent environment", () => { |
| 330 | 330 | const state = makeFixtureState(); |
| 331 | const ref = scopeProjectRef(EnvironmentId.makeUnsafe("nonexistent"), sharedProjectPrimaryId); | |
| 331 | const ref = scopeProjectRef(EnvironmentId.make("nonexistent"), sharedProjectPrimaryId); | |
| 332 | 332 | expect(selectSidebarThreadsForProjectRef(state, ref)).toEqual([]); |
| 333 | 333 | }); |
| 334 | 334 | }); |
| ... | ... | @@ -381,7 +381,7 @@ describe("environment grouping", () => { |
| 381 | 381 | const state = makeFixtureState(); |
| 382 | 382 | const refs = [ |
| 383 | 383 | scopeProjectRef(primaryEnvId, sharedProjectPrimaryId), |
| 384 | scopeProjectRef(EnvironmentId.makeUnsafe("nonexistent"), ProjectId.makeUnsafe("nope")), | |
| 384 | scopeProjectRef(EnvironmentId.make("nonexistent"), ProjectId.make("nope")), | |
| 385 | 385 | ]; |
| 386 | 386 | const threads = selectSidebarThreadsForProjectRefs(state, refs); |
| 387 | 387 | // Only returns threads from the valid ref |
apps/web/src/environments/primary/bootstrap.test.ts+1-1| ... | ... | @@ -63,7 +63,7 @@ describe("environmentBootstrap", () => { |
| 63 | 63 | desktopBridge: undefined, |
| 64 | 64 | }); |
| 65 | 65 | writePrimaryEnvironmentDescriptor({ |
| 66 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 66 | environmentId: EnvironmentId.make("environment-local"), | |
| 67 | 67 | label: "Bootstrapped environment", |
| 68 | 68 | platform: { |
| 69 | 69 | os: "darwin", |
apps/web/src/environments/runtime/catalog.test.ts+4-4| ... | ... | @@ -41,7 +41,7 @@ describe("environment runtime catalog stores", () => { |
| 41 | 41 | }); |
| 42 | 42 | |
| 43 | 43 | it("resets the saved environment registry store state", () => { |
| 44 | const environmentId = EnvironmentId.makeUnsafe("environment-1"); | |
| 44 | const environmentId = EnvironmentId.make("environment-1"); | |
| 45 | 45 | |
| 46 | 46 | useSavedEnvironmentRegistryStore.getState().upsert({ |
| 47 | 47 | environmentId, |
| ... | ... | @@ -60,7 +60,7 @@ describe("environment runtime catalog stores", () => { |
| 60 | 60 | }); |
| 61 | 61 | |
| 62 | 62 | it("resets the saved environment runtime store state", () => { |
| 63 | const environmentId = EnvironmentId.makeUnsafe("environment-1"); | |
| 63 | const environmentId = EnvironmentId.make("environment-1"); | |
| 64 | 64 | |
| 65 | 65 | useSavedEnvironmentRuntimeStore.getState().patch(environmentId, { |
| 66 | 66 | connectionState: "connected", |
| ... | ... | @@ -82,7 +82,7 @@ describe("environment runtime catalog stores", () => { |
| 82 | 82 | |
| 83 | 83 | expect(() => |
| 84 | 84 | useSavedEnvironmentRegistryStore.getState().upsert({ |
| 85 | environmentId: EnvironmentId.makeUnsafe("environment-1"), | |
| 85 | environmentId: EnvironmentId.make("environment-1"), | |
| 86 | 86 | label: "Remote environment", |
| 87 | 87 | httpBaseUrl: "https://remote.example.com/", |
| 88 | 88 | wsBaseUrl: "wss://remote.example.com/", |
| ... | ... | @@ -121,7 +121,7 @@ describe("environment runtime catalog stores", () => { |
| 121 | 121 | |
| 122 | 122 | const hydrationPromise = waitForSavedEnvironmentRegistryHydration(); |
| 123 | 123 | |
| 124 | const environmentId = EnvironmentId.makeUnsafe("environment-1"); | |
| 124 | const environmentId = EnvironmentId.make("environment-1"); | |
| 125 | 125 | const record = { |
| 126 | 126 | environmentId, |
| 127 | 127 | label: "Remote environment", |
apps/web/src/environments/runtime/connection.test.ts+7-7| ... | ... | @@ -30,7 +30,7 @@ function createTestClient(options?: { |
| 30 | 30 | server: { |
| 31 | 31 | getConfig: vi.fn(async () => ({ |
| 32 | 32 | environment: { |
| 33 | environmentId: EnvironmentId.makeUnsafe("env-1"), | |
| 33 | environmentId: EnvironmentId.make("env-1"), | |
| 34 | 34 | }, |
| 35 | 35 | })), |
| 36 | 36 | subscribeConfig: (listener: (event: any) => void) => { |
| ... | ... | @@ -133,7 +133,7 @@ function createTestClient(options?: { |
| 133 | 133 | |
| 134 | 134 | describe("createEnvironmentConnection", () => { |
| 135 | 135 | it("bootstraps a snapshot immediately for a new connection", async () => { |
| 136 | const environmentId = EnvironmentId.makeUnsafe("env-1"); | |
| 136 | const environmentId = EnvironmentId.make("env-1"); | |
| 137 | 137 | const { client, getSnapshot } = createTestClient(); |
| 138 | 138 | const syncSnapshot = vi.fn(); |
| 139 | 139 | |
| ... | ... | @@ -168,7 +168,7 @@ describe("createEnvironmentConnection", () => { |
| 168 | 168 | }); |
| 169 | 169 | |
| 170 | 170 | it("rejects welcome/config identity drift", async () => { |
| 171 | const environmentId = EnvironmentId.makeUnsafe("env-1"); | |
| 171 | const environmentId = EnvironmentId.make("env-1"); | |
| 172 | 172 | const { client, emitWelcome } = createTestClient(); |
| 173 | 173 | |
| 174 | 174 | const connection = createEnvironmentConnection({ |
| ... | ... | @@ -189,7 +189,7 @@ describe("createEnvironmentConnection", () => { |
| 189 | 189 | applyTerminalEvent: vi.fn(), |
| 190 | 190 | }); |
| 191 | 191 | |
| 192 | expect(() => emitWelcome(EnvironmentId.makeUnsafe("env-2"))).toThrow( | |
| 192 | expect(() => emitWelcome(EnvironmentId.make("env-2"))).toThrow( | |
| 193 | 193 | "Environment connection env-1 changed identity to env-2 via server lifecycle welcome.", |
| 194 | 194 | ); |
| 195 | 195 | |
| ... | ... | @@ -197,7 +197,7 @@ describe("createEnvironmentConnection", () => { |
| 197 | 197 | }); |
| 198 | 198 | |
| 199 | 199 | it("rejects ensureBootstrapped when snapshot recovery fails", async () => { |
| 200 | const environmentId = EnvironmentId.makeUnsafe("env-1"); | |
| 200 | const environmentId = EnvironmentId.make("env-1"); | |
| 201 | 201 | const snapshotError = new Error("snapshot failed"); |
| 202 | 202 | const { client } = createTestClient({ |
| 203 | 203 | getSnapshot: async () => { |
| ... | ... | @@ -229,7 +229,7 @@ describe("createEnvironmentConnection", () => { |
| 229 | 229 | }); |
| 230 | 230 | |
| 231 | 231 | it("retries replay recovery after transport disconnects during resubscribe", async () => { |
| 232 | const environmentId = EnvironmentId.makeUnsafe("env-1"); | |
| 232 | const environmentId = EnvironmentId.make("env-1"); | |
| 233 | 233 | let replayAttempts = 0; |
| 234 | 234 | const applyEventBatch = vi.fn(); |
| 235 | 235 | const { client, replayEvents, triggerDomainResubscribe } = createTestClient({ |
| ... | ... | @@ -287,7 +287,7 @@ describe("createEnvironmentConnection", () => { |
| 287 | 287 | await connection.dispose(); |
| 288 | 288 | }); |
| 289 | 289 | it("swallows replay recovery failures triggered by resubscribe", async () => { |
| 290 | const environmentId = EnvironmentId.makeUnsafe("env-1"); | |
| 290 | const environmentId = EnvironmentId.make("env-1"); | |
| 291 | 291 | const snapshotError = new Error("snapshot failed"); |
| 292 | 292 | let snapshotCalls = 0; |
| 293 | 293 | const { client, triggerDomainResubscribe } = createTestClient({ |
apps/web/src/environments/runtime/service.addSavedEnvironment.test.ts+2-2| ... | ... | @@ -68,7 +68,7 @@ describe("addSavedEnvironment", () => { |
| 68 | 68 | credential: "pairing-code", |
| 69 | 69 | }); |
| 70 | 70 | mockFetchRemoteEnvironmentDescriptor.mockResolvedValue({ |
| 71 | environmentId: EnvironmentId.makeUnsafe("environment-1"), | |
| 71 | environmentId: EnvironmentId.make("environment-1"), | |
| 72 | 72 | label: "Remote environment", |
| 73 | 73 | }); |
| 74 | 74 | mockBootstrapRemoteBearerSession.mockResolvedValue({ |
| ... | ... | @@ -94,7 +94,7 @@ describe("addSavedEnvironment", () => { |
| 94 | 94 | |
| 95 | 95 | expect(mockPersistSavedEnvironmentRecord).toHaveBeenCalledTimes(1); |
| 96 | 96 | expect(mockWriteSavedEnvironmentBearerToken).toHaveBeenCalledWith( |
| 97 | EnvironmentId.makeUnsafe("environment-1"), | |
| 97 | EnvironmentId.make("environment-1"), | |
| 98 | 98 | "bearer-token", |
| 99 | 99 | ); |
| 100 | 100 | expect(mockSetSavedEnvironmentRegistry).toHaveBeenCalledWith([]); |
apps/web/src/environments/runtime/service.ts+1-1| ... | ... | @@ -281,7 +281,7 @@ function createEnvironmentConnectionHandlers() { |
| 281 | 281 | reconcileSnapshotDerivedState(); |
| 282 | 282 | }, |
| 283 | 283 | applyTerminalEvent: (event: TerminalEvent, environmentId: EnvironmentId) => { |
| 284 | const threadRef = scopeThreadRef(environmentId, ThreadId.makeUnsafe(event.threadId)); | |
| 284 | const threadRef = scopeThreadRef(environmentId, ThreadId.make(event.threadId)); | |
| 285 | 285 | const serverThread = selectThreadByRef(useStore.getState(), threadRef); |
| 286 | 286 | const hasDraftThread = |
| 287 | 287 | useComposerDraftStore.getState().getDraftThreadByRef(threadRef) !== null; |
apps/web/src/historyBootstrap.test.ts+1-1| ... | ... | @@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest"; |
| 3 | 3 | |
| 4 | 4 | import { buildBootstrapInput } from "./historyBootstrap"; |
| 5 | 5 | |
| 6 | const messageId = (value: string) => MessageId.makeUnsafe(value); | |
| 6 | const messageId = (value: string) => MessageId.make(value); | |
| 7 | 7 | |
| 8 | 8 | describe("buildBootstrapInput", () => { |
| 9 | 9 | it("includes full transcript when under budget", () => { |
apps/web/src/lib/contextWindow.test.ts+2-2| ... | ... | @@ -5,12 +5,12 @@ import { deriveLatestContextWindowSnapshot, formatContextWindowTokens } from "./ |
| 5 | 5 | |
| 6 | 6 | function makeActivity(id: string, kind: string, payload: unknown): OrchestrationThreadActivity { |
| 7 | 7 | return { |
| 8 | id: EventId.makeUnsafe(id), | |
| 8 | id: EventId.make(id), | |
| 9 | 9 | tone: "info", |
| 10 | 10 | kind, |
| 11 | 11 | summary: kind, |
| 12 | 12 | payload, |
| 13 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 13 | turnId: TurnId.make("turn-1"), | |
| 14 | 14 | createdAt: "2026-03-23T00:00:00.000Z", |
| 15 | 15 | }; |
| 16 | 16 | } |
apps/web/src/lib/gitReactQuery.test.ts+2-2| ... | ... | @@ -34,8 +34,8 @@ const BRANCH_SEARCH_RESULT: InfiniteData<GitListBranchesResult, number> = { |
| 34 | 34 | pages: [BRANCH_QUERY_RESULT], |
| 35 | 35 | pageParams: [0], |
| 36 | 36 | }; |
| 37 | const ENVIRONMENT_A = EnvironmentId.makeUnsafe("environment-a"); | |
| 38 | const ENVIRONMENT_B = EnvironmentId.makeUnsafe("environment-b"); | |
| 37 | const ENVIRONMENT_A = EnvironmentId.make("environment-a"); | |
| 38 | const ENVIRONMENT_B = EnvironmentId.make("environment-b"); | |
| 39 | 39 | |
| 40 | 40 | describe("gitMutationKeys", () => { |
| 41 | 41 | it("scopes stacked action keys by cwd", () => { |
apps/web/src/lib/gitStatusState.test.ts+2-2| ... | ... | @@ -34,8 +34,8 @@ function registerListener<T>(listeners: Set<(event: T) => void>, listener: (even |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | const gitStatusListeners = new Set<(event: GitStatusResult) => void>(); |
| 37 | const ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-local"); | |
| 38 | const OTHER_ENVIRONMENT_ID = EnvironmentId.makeUnsafe("environment-remote"); | |
| 37 | const ENVIRONMENT_ID = EnvironmentId.make("environment-local"); | |
| 38 | const OTHER_ENVIRONMENT_ID = EnvironmentId.make("environment-remote"); | |
| 39 | 39 | const TARGET = { environmentId: ENVIRONMENT_ID, cwd: "/repo" } as const; |
| 40 | 40 | const FRESH_TARGET = { environmentId: ENVIRONMENT_ID, cwd: "/fresh" } as const; |
| 41 | 41 |
apps/web/src/lib/providerReactQuery.test.ts+2-2| ... | ... | @@ -4,8 +4,8 @@ import { afterEach, describe, expect, it, vi } from "vitest"; |
| 4 | 4 | import { checkpointDiffQueryOptions, providerQueryKeys } from "./providerReactQuery"; |
| 5 | 5 | import * as environmentApi from "../environmentApi"; |
| 6 | 6 | |
| 7 | const threadId = ThreadId.makeUnsafe("thread-id"); | |
| 8 | const environmentId = EnvironmentId.makeUnsafe("environment-local"); | |
| 7 | const threadId = ThreadId.make("thread-id"); | |
| 8 | const environmentId = EnvironmentId.make("environment-local"); | |
| 9 | 9 | |
| 10 | 10 | function mockNativeApi(input: { |
| 11 | 11 | getTurnDiff: ReturnType<typeof vi.fn>; |
apps/web/src/lib/terminalContext.test.ts+1-1| ... | ... | @@ -25,7 +25,7 @@ import { |
| 25 | 25 | function makeContext(overrides?: Partial<TerminalContextDraft>): TerminalContextDraft { |
| 26 | 26 | return { |
| 27 | 27 | id: "context-1", |
| 28 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 28 | threadId: ThreadId.make("thread-1"), | |
| 29 | 29 | terminalId: "default", |
| 30 | 30 | terminalLabel: "Terminal 1", |
| 31 | 31 | lineStart: 12, |
apps/web/src/lib/terminalStateCleanup.test.ts+1-1| ... | ... | @@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest"; |
| 4 | 4 | |
| 5 | 5 | import { collectActiveTerminalThreadIds } from "./terminalStateCleanup"; |
| 6 | 6 | |
| 7 | const threadId = (id: string): ThreadId => ThreadId.makeUnsafe(id); | |
| 7 | const threadId = (id: string): ThreadId => ThreadId.make(id); | |
| 8 | 8 | const threadKey = (environmentId: string, id: string): string => |
| 9 | 9 | scopedThreadKey(scopeThreadRef(environmentId as never, threadId(id))); |
| 10 | 10 |
apps/web/src/lib/utils.ts+5-5| ... | ... | @@ -28,12 +28,12 @@ export function randomUUID(): string { |
| 28 | 28 | return Effect.runSync(Random.nextUUIDv4); |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | export const newCommandId = (): CommandId => CommandId.makeUnsafe(randomUUID()); | |
| 31 | export const newCommandId = (): CommandId => CommandId.make(randomUUID()); | |
| 32 | 32 | |
| 33 | export const newProjectId = (): ProjectId => ProjectId.makeUnsafe(randomUUID()); | |
| 33 | export const newProjectId = (): ProjectId => ProjectId.make(randomUUID()); | |
| 34 | 34 | |
| 35 | export const newThreadId = (): ThreadId => ThreadId.makeUnsafe(randomUUID()); | |
| 35 | export const newThreadId = (): ThreadId => ThreadId.make(randomUUID()); | |
| 36 | 36 | |
| 37 | export const newDraftId = (): DraftId => DraftId.makeUnsafe(randomUUID()); | |
| 37 | export const newDraftId = (): DraftId => DraftId.make(randomUUID()); | |
| 38 | 38 | |
| 39 | export const newMessageId = (): MessageId => MessageId.makeUnsafe(randomUUID()); | |
| 39 | export const newMessageId = (): MessageId => MessageId.make(randomUUID()); |
apps/web/src/localApi.test.ts+18-22| ... | ... | @@ -104,10 +104,10 @@ vi.mock("./environments/runtime", () => ({ |
| 104 | 104 | httpBaseUrl: "http://localhost:3000", |
| 105 | 105 | wsBaseUrl: "ws://localhost:3000", |
| 106 | 106 | }, |
| 107 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 107 | environmentId: EnvironmentId.make("environment-local"), | |
| 108 | 108 | }, |
| 109 | 109 | client: rpcClientMock, |
| 110 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 110 | environmentId: EnvironmentId.make("environment-local"), | |
| 111 | 111 | ensureBootstrapped: async () => undefined, |
| 112 | 112 | reconnect: async () => undefined, |
| 113 | 113 | dispose: async () => undefined, |
| ... | ... | @@ -214,7 +214,7 @@ const defaultProviders: ReadonlyArray<ServerProvider> = [ |
| 214 | 214 | ]; |
| 215 | 215 | |
| 216 | 216 | const baseEnvironment = { |
| 217 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 217 | environmentId: EnvironmentId.make("environment-local"), | |
| 218 | 218 | label: "Local environment", |
| 219 | 219 | platform: { |
| 220 | 220 | os: "darwin" as const, |
| ... | ... | @@ -315,9 +315,9 @@ describe("wsApi", () => { |
| 315 | 315 | |
| 316 | 316 | const orchestrationEvent = { |
| 317 | 317 | sequence: 1, |
| 318 | eventId: EventId.makeUnsafe("event-1"), | |
| 318 | eventId: EventId.make("event-1"), | |
| 319 | 319 | aggregateKind: "project", |
| 320 | aggregateId: ProjectId.makeUnsafe("project-1"), | |
| 320 | aggregateId: ProjectId.make("project-1"), | |
| 321 | 321 | occurredAt: "2026-02-24T00:00:00.000Z", |
| 322 | 322 | commandId: null, |
| 323 | 323 | causationEventId: null, |
| ... | ... | @@ -325,7 +325,7 @@ describe("wsApi", () => { |
| 325 | 325 | metadata: {}, |
| 326 | 326 | type: "project.created", |
| 327 | 327 | payload: { |
| 328 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 328 | projectId: ProjectId.make("project-1"), | |
| 329 | 329 | title: "Project", |
| 330 | 330 | workspaceRoot: "/tmp/workspace", |
| 331 | 331 | defaultModelSelection: { |
| ... | ... | @@ -390,8 +390,8 @@ describe("wsApi", () => { |
| 390 | 390 | const api = createEnvironmentApi(rpcClientMock as never); |
| 391 | 391 | const command = { |
| 392 | 392 | type: "project.create", |
| 393 | commandId: CommandId.makeUnsafe("cmd-1"), | |
| 394 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 393 | commandId: CommandId.make("cmd-1"), | |
| 394 | projectId: ProjectId.make("project-1"), | |
| 395 | 395 | title: "Project", |
| 396 | 396 | workspaceRoot: "/tmp/project", |
| 397 | 397 | defaultModelSelection: { |
| ... | ... | @@ -429,7 +429,7 @@ describe("wsApi", () => { |
| 429 | 429 | |
| 430 | 430 | const api = createEnvironmentApi(rpcClientMock as never); |
| 431 | 431 | await api.orchestration.getFullThreadDiff({ |
| 432 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 432 | threadId: ThreadId.make("thread-1"), | |
| 433 | 433 | toTurnCount: 1, |
| 434 | 434 | }); |
| 435 | 435 | |
| ... | ... | @@ -535,14 +535,12 @@ describe("wsApi", () => { |
| 535 | 535 | }); |
| 536 | 536 | await api.persistence.getSavedEnvironmentRegistry(); |
| 537 | 537 | await api.persistence.setSavedEnvironmentRegistry([]); |
| 538 | await api.persistence.getSavedEnvironmentSecret(EnvironmentId.makeUnsafe("environment-local")); | |
| 538 | await api.persistence.getSavedEnvironmentSecret(EnvironmentId.make("environment-local")); | |
| 539 | 539 | await api.persistence.setSavedEnvironmentSecret( |
| 540 | EnvironmentId.makeUnsafe("environment-local"), | |
| 540 | EnvironmentId.make("environment-local"), | |
| 541 | 541 | "bearer-token", |
| 542 | 542 | ); |
| 543 | await api.persistence.removeSavedEnvironmentSecret( | |
| 544 | EnvironmentId.makeUnsafe("environment-local"), | |
| 545 | ); | |
| 543 | await api.persistence.removeSavedEnvironmentSecret(EnvironmentId.make("environment-local")); | |
| 546 | 544 | |
| 547 | 545 | expect(getClientSettings).toHaveBeenCalledWith(); |
| 548 | 546 | expect(setClientSettings).toHaveBeenCalledWith({ |
| ... | ... | @@ -574,7 +572,7 @@ describe("wsApi", () => { |
| 574 | 572 | }); |
| 575 | 573 | await api.persistence.setSavedEnvironmentRegistry([ |
| 576 | 574 | { |
| 577 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 575 | environmentId: EnvironmentId.make("environment-local"), | |
| 578 | 576 | label: "Primary", |
| 579 | 577 | httpBaseUrl: "http://localhost:3000", |
| 580 | 578 | wsBaseUrl: "ws://localhost:3000", |
| ... | ... | @@ -583,7 +581,7 @@ describe("wsApi", () => { |
| 583 | 581 | }, |
| 584 | 582 | ]); |
| 585 | 583 | await api.persistence.setSavedEnvironmentSecret( |
| 586 | EnvironmentId.makeUnsafe("environment-local"), | |
| 584 | EnvironmentId.make("environment-local"), | |
| 587 | 585 | "bearer-token", |
| 588 | 586 | ); |
| 589 | 587 | |
| ... | ... | @@ -597,7 +595,7 @@ describe("wsApi", () => { |
| 597 | 595 | }); |
| 598 | 596 | await expect(api.persistence.getSavedEnvironmentRegistry()).resolves.toEqual([ |
| 599 | 597 | { |
| 600 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 598 | environmentId: EnvironmentId.make("environment-local"), | |
| 601 | 599 | label: "Primary", |
| 602 | 600 | httpBaseUrl: "http://localhost:3000", |
| 603 | 601 | wsBaseUrl: "ws://localhost:3000", |
| ... | ... | @@ -606,15 +604,13 @@ describe("wsApi", () => { |
| 606 | 604 | }, |
| 607 | 605 | ]); |
| 608 | 606 | await expect( |
| 609 | api.persistence.getSavedEnvironmentSecret(EnvironmentId.makeUnsafe("environment-local")), | |
| 607 | api.persistence.getSavedEnvironmentSecret(EnvironmentId.make("environment-local")), | |
| 610 | 608 | ).resolves.toBe("bearer-token"); |
| 611 | 609 | |
| 612 | await api.persistence.removeSavedEnvironmentSecret( | |
| 613 | EnvironmentId.makeUnsafe("environment-local"), | |
| 614 | ); | |
| 610 | await api.persistence.removeSavedEnvironmentSecret(EnvironmentId.make("environment-local")); | |
| 615 | 611 | |
| 616 | 612 | await expect( |
| 617 | api.persistence.getSavedEnvironmentSecret(EnvironmentId.makeUnsafe("environment-local")), | |
| 613 | api.persistence.getSavedEnvironmentSecret(EnvironmentId.make("environment-local")), | |
| 618 | 614 | ).resolves.toBeNull(); |
| 619 | 615 | }); |
| 620 | 616 | }); |
apps/web/src/orchestrationEventEffects.test.ts+12-12| ... | ... | @@ -19,14 +19,14 @@ function makeEvent<T extends OrchestrationEvent["type"]>( |
| 19 | 19 | const sequence = overrides.sequence ?? 1; |
| 20 | 20 | return { |
| 21 | 21 | sequence, |
| 22 | eventId: EventId.makeUnsafe(`event-${sequence}`), | |
| 22 | eventId: EventId.make(`event-${sequence}`), | |
| 23 | 23 | aggregateKind: "thread", |
| 24 | 24 | aggregateId: |
| 25 | 25 | "threadId" in payload |
| 26 | 26 | ? payload.threadId |
| 27 | 27 | : "projectId" in payload |
| 28 | 28 | ? payload.projectId |
| 29 | : ProjectId.makeUnsafe("project-1"), | |
| 29 | : ProjectId.make("project-1"), | |
| 30 | 30 | occurredAt: "2026-02-27T00:00:00.000Z", |
| 31 | 31 | commandId: null, |
| 32 | 32 | causationEventId: null, |
| ... | ... | @@ -40,14 +40,14 @@ function makeEvent<T extends OrchestrationEvent["type"]>( |
| 40 | 40 | |
| 41 | 41 | describe("deriveOrchestrationBatchEffects", () => { |
| 42 | 42 | it("targets draft promotion and terminal cleanup from thread lifecycle events", () => { |
| 43 | const createdThreadId = ThreadId.makeUnsafe("thread-created"); | |
| 44 | const deletedThreadId = ThreadId.makeUnsafe("thread-deleted"); | |
| 45 | const archivedThreadId = ThreadId.makeUnsafe("thread-archived"); | |
| 43 | const createdThreadId = ThreadId.make("thread-created"); | |
| 44 | const deletedThreadId = ThreadId.make("thread-deleted"); | |
| 45 | const archivedThreadId = ThreadId.make("thread-archived"); | |
| 46 | 46 | |
| 47 | 47 | const effects = deriveOrchestrationBatchEffects([ |
| 48 | 48 | makeEvent("thread.created", { |
| 49 | 49 | threadId: createdThreadId, |
| 50 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 50 | projectId: ProjectId.make("project-1"), | |
| 51 | 51 | title: "Created thread", |
| 52 | 52 | modelSelection: { provider: "codex", model: "gpt-5-codex" }, |
| 53 | 53 | runtimeMode: "full-access", |
| ... | ... | @@ -75,7 +75,7 @@ describe("deriveOrchestrationBatchEffects", () => { |
| 75 | 75 | }); |
| 76 | 76 | |
| 77 | 77 | it("keeps only the final lifecycle outcome for a thread within one batch", () => { |
| 78 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 78 | const threadId = ThreadId.make("thread-1"); | |
| 79 | 79 | |
| 80 | 80 | const effects = deriveOrchestrationBatchEffects([ |
| 81 | 81 | makeEvent("thread.deleted", { |
| ... | ... | @@ -84,7 +84,7 @@ describe("deriveOrchestrationBatchEffects", () => { |
| 84 | 84 | }), |
| 85 | 85 | makeEvent("thread.created", { |
| 86 | 86 | threadId, |
| 87 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 87 | projectId: ProjectId.make("project-1"), | |
| 88 | 88 | title: "Recreated thread", |
| 89 | 89 | modelSelection: { provider: "codex", model: "gpt-5-codex" }, |
| 90 | 90 | runtimeMode: "full-access", |
| ... | ... | @@ -96,12 +96,12 @@ describe("deriveOrchestrationBatchEffects", () => { |
| 96 | 96 | }), |
| 97 | 97 | makeEvent("thread.turn-diff-completed", { |
| 98 | 98 | threadId, |
| 99 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 99 | turnId: TurnId.make("turn-1"), | |
| 100 | 100 | checkpointTurnCount: 1, |
| 101 | checkpointRef: CheckpointRef.makeUnsafe("checkpoint-1"), | |
| 101 | checkpointRef: CheckpointRef.make("checkpoint-1"), | |
| 102 | 102 | status: "ready", |
| 103 | 103 | files: [], |
| 104 | assistantMessageId: MessageId.makeUnsafe("assistant-1"), | |
| 104 | assistantMessageId: MessageId.make("assistant-1"), | |
| 105 | 105 | completedAt: "2026-02-27T00:00:03.000Z", |
| 106 | 106 | }), |
| 107 | 107 | ]); |
| ... | ... | @@ -113,7 +113,7 @@ describe("deriveOrchestrationBatchEffects", () => { |
| 113 | 113 | }); |
| 114 | 114 | |
| 115 | 115 | it("does not retain archive cleanup when a thread is unarchived later in the same batch", () => { |
| 116 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 116 | const threadId = ThreadId.make("thread-1"); | |
| 117 | 117 | |
| 118 | 118 | const effects = deriveOrchestrationBatchEffects([ |
| 119 | 119 | makeEvent("thread.archived", { |
apps/web/src/projectScripts.ts+1-1| ... | ... | @@ -22,7 +22,7 @@ function normalizeScriptId(value: string): string { |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | export const commandForProjectScript = (scriptId: string): KeybindingCommand => |
| 25 | SCRIPT_RUN_COMMAND_PATTERN.makeUnsafe(`script.${scriptId}.run`); | |
| 25 | SCRIPT_RUN_COMMAND_PATTERN.make(`script.${scriptId}.run`); | |
| 26 | 26 | |
| 27 | 27 | export function projectScriptIdFromCommand(command: string): string | null { |
| 28 | 28 | const trimmed = command.trim(); |
apps/web/src/routes/_chat.draft.$draftId.tsx+1-1| ... | ... | @@ -11,7 +11,7 @@ import { buildThreadRouteParams } from "../threadRoutes"; |
| 11 | 11 | function DraftChatThreadRouteView() { |
| 12 | 12 | const navigate = useNavigate(); |
| 13 | 13 | const { draftId: rawDraftId } = Route.useParams(); |
| 14 | const draftId = DraftId.makeUnsafe(rawDraftId); | |
| 14 | const draftId = DraftId.make(rawDraftId); | |
| 15 | 15 | const draftSession = useComposerDraftStore((store) => store.getDraftSession(draftId)); |
| 16 | 16 | const serverThread = useStore( |
| 17 | 17 | useMemo( |
apps/web/src/rpc/protocol.ts+4-4| ... | ... | @@ -154,8 +154,8 @@ export function createWsRpcProtocolLayer( |
| 154 | 154 | }), |
| 155 | 155 | (protocol) => ({ |
| 156 | 156 | ...protocol, |
| 157 | run: (writeResponse) => | |
| 158 | protocol.run((response) => { | |
| 157 | run: (clientId, writeResponse) => | |
| 158 | protocol.run(clientId, (response) => { | |
| 159 | 159 | if (response._tag === "Chunk" || response._tag === "Exit") { |
| 160 | 160 | acknowledgeRpcRequest(response.requestId); |
| 161 | 161 | } else if (response._tag === "ClientProtocolError" || response._tag === "Defect") { |
| ... | ... | @@ -163,11 +163,11 @@ export function createWsRpcProtocolLayer( |
| 163 | 163 | } |
| 164 | 164 | return writeResponse(response); |
| 165 | 165 | }), |
| 166 | send: (request, transferables) => { | |
| 166 | send: (clientId, request, transferables) => { | |
| 167 | 167 | if (request._tag === "Request") { |
| 168 | 168 | trackRpcRequestSent(request.id, request.tag); |
| 169 | 169 | } |
| 170 | return protocol.send(request, transferables); | |
| 170 | return protocol.send(clientId, request, transferables); | |
| 171 | 171 | }, |
| 172 | 172 | }), |
| 173 | 173 | ), |
apps/web/src/rpc/serverState.test.ts+7-7| ... | ... | @@ -52,7 +52,7 @@ const defaultProviders: ReadonlyArray<ServerProvider> = [ |
| 52 | 52 | ]; |
| 53 | 53 | |
| 54 | 54 | const baseEnvironment = { |
| 55 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 55 | environmentId: EnvironmentId.make("environment-local"), | |
| 56 | 56 | label: "Local environment", |
| 57 | 57 | platform: { |
| 58 | 58 | os: "darwin" as const, |
| ... | ... | @@ -217,8 +217,8 @@ describe("serverState", () => { |
| 217 | 217 | environment: baseEnvironment, |
| 218 | 218 | cwd: "/tmp/workspace", |
| 219 | 219 | projectName: "t3-code", |
| 220 | bootstrapProjectId: ProjectId.makeUnsafe("project-1"), | |
| 221 | bootstrapThreadId: ThreadId.makeUnsafe("thread-1"), | |
| 220 | bootstrapProjectId: ProjectId.make("project-1"), | |
| 221 | bootstrapThreadId: ThreadId.make("thread-1"), | |
| 222 | 222 | }, |
| 223 | 223 | }); |
| 224 | 224 | |
| ... | ... | @@ -226,8 +226,8 @@ describe("serverState", () => { |
| 226 | 226 | environment: baseEnvironment, |
| 227 | 227 | cwd: "/tmp/workspace", |
| 228 | 228 | projectName: "t3-code", |
| 229 | bootstrapProjectId: ProjectId.makeUnsafe("project-1"), | |
| 230 | bootstrapThreadId: ThreadId.makeUnsafe("thread-1"), | |
| 229 | bootstrapProjectId: ProjectId.make("project-1"), | |
| 230 | bootstrapThreadId: ThreadId.make("thread-1"), | |
| 231 | 231 | }); |
| 232 | 232 | |
| 233 | 233 | const lateListener = vi.fn(); |
| ... | ... | @@ -236,8 +236,8 @@ describe("serverState", () => { |
| 236 | 236 | environment: baseEnvironment, |
| 237 | 237 | cwd: "/tmp/workspace", |
| 238 | 238 | projectName: "t3-code", |
| 239 | bootstrapProjectId: ProjectId.makeUnsafe("project-1"), | |
| 240 | bootstrapThreadId: ThreadId.makeUnsafe("thread-1"), | |
| 239 | bootstrapProjectId: ProjectId.make("project-1"), | |
| 240 | bootstrapThreadId: ThreadId.make("thread-1"), | |
| 241 | 241 | }); |
| 242 | 242 | |
| 243 | 243 | unsubscribeLate(); |
apps/web/src/session-logic.test.ts+43-43| ... | ... | @@ -35,13 +35,13 @@ function makeActivity(overrides: { |
| 35 | 35 | }): OrchestrationThreadActivity { |
| 36 | 36 | const payload = overrides.payload ?? {}; |
| 37 | 37 | return { |
| 38 | id: EventId.makeUnsafe(overrides.id ?? crypto.randomUUID()), | |
| 38 | id: EventId.make(overrides.id ?? crypto.randomUUID()), | |
| 39 | 39 | createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z", |
| 40 | 40 | kind: overrides.kind ?? "tool.started", |
| 41 | 41 | summary: overrides.summary ?? "Tool call", |
| 42 | 42 | tone: overrides.tone ?? "tool", |
| 43 | 43 | payload, |
| 44 | turnId: overrides.turnId ? TurnId.makeUnsafe(overrides.turnId) : null, | |
| 44 | turnId: overrides.turnId ? TurnId.make(overrides.turnId) : null, | |
| 45 | 45 | ...(overrides.sequence !== undefined ? { sequence: overrides.sequence } : {}), |
| 46 | 46 | }; |
| 47 | 47 | } |
| ... | ... | @@ -336,7 +336,7 @@ describe("deriveActivePlanState", () => { |
| 336 | 336 | }), |
| 337 | 337 | ]; |
| 338 | 338 | |
| 339 | expect(deriveActivePlanState(activities, TurnId.makeUnsafe("turn-1"))).toEqual({ | |
| 339 | expect(deriveActivePlanState(activities, TurnId.make("turn-1"))).toEqual({ | |
| 340 | 340 | createdAt: "2026-02-23T00:00:02.000Z", |
| 341 | 341 | turnId: "turn-1", |
| 342 | 342 | explanation: "Refined plan", |
| ... | ... | @@ -352,7 +352,7 @@ describe("findLatestProposedPlan", () => { |
| 352 | 352 | [ |
| 353 | 353 | { |
| 354 | 354 | id: "plan:thread-1:turn:turn-1", |
| 355 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 355 | turnId: TurnId.make("turn-1"), | |
| 356 | 356 | planMarkdown: "# Older", |
| 357 | 357 | implementedAt: null, |
| 358 | 358 | implementationThreadId: null, |
| ... | ... | @@ -361,7 +361,7 @@ describe("findLatestProposedPlan", () => { |
| 361 | 361 | }, |
| 362 | 362 | { |
| 363 | 363 | id: "plan:thread-1:turn:turn-1", |
| 364 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 364 | turnId: TurnId.make("turn-1"), | |
| 365 | 365 | planMarkdown: "# Latest", |
| 366 | 366 | implementedAt: null, |
| 367 | 367 | implementationThreadId: null, |
| ... | ... | @@ -370,7 +370,7 @@ describe("findLatestProposedPlan", () => { |
| 370 | 370 | }, |
| 371 | 371 | { |
| 372 | 372 | id: "plan:thread-1:turn:turn-2", |
| 373 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 373 | turnId: TurnId.make("turn-2"), | |
| 374 | 374 | planMarkdown: "# Different turn", |
| 375 | 375 | implementedAt: null, |
| 376 | 376 | implementationThreadId: null, |
| ... | ... | @@ -378,7 +378,7 @@ describe("findLatestProposedPlan", () => { |
| 378 | 378 | updatedAt: "2026-02-23T00:00:03.000Z", |
| 379 | 379 | }, |
| 380 | 380 | ], |
| 381 | TurnId.makeUnsafe("turn-1"), | |
| 381 | TurnId.make("turn-1"), | |
| 382 | 382 | ), |
| 383 | 383 | ).toEqual({ |
| 384 | 384 | id: "plan:thread-1:turn:turn-1", |
| ... | ... | @@ -396,7 +396,7 @@ describe("findLatestProposedPlan", () => { |
| 396 | 396 | [ |
| 397 | 397 | { |
| 398 | 398 | id: "plan:thread-1:turn:turn-1", |
| 399 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 399 | turnId: TurnId.make("turn-1"), | |
| 400 | 400 | planMarkdown: "# First", |
| 401 | 401 | implementedAt: null, |
| 402 | 402 | implementationThreadId: null, |
| ... | ... | @@ -405,7 +405,7 @@ describe("findLatestProposedPlan", () => { |
| 405 | 405 | }, |
| 406 | 406 | { |
| 407 | 407 | id: "plan:thread-1:turn:turn-2", |
| 408 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 408 | turnId: TurnId.make("turn-2"), | |
| 409 | 409 | planMarkdown: "# Latest", |
| 410 | 410 | implementedAt: null, |
| 411 | 411 | implementationThreadId: null, |
| ... | ... | @@ -425,7 +425,7 @@ describe("hasActionableProposedPlan", () => { |
| 425 | 425 | expect( |
| 426 | 426 | hasActionableProposedPlan({ |
| 427 | 427 | id: "plan-1", |
| 428 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 428 | turnId: TurnId.make("turn-1"), | |
| 429 | 429 | planMarkdown: "# Plan", |
| 430 | 430 | implementedAt: null, |
| 431 | 431 | implementationThreadId: null, |
| ... | ... | @@ -439,10 +439,10 @@ describe("hasActionableProposedPlan", () => { |
| 439 | 439 | expect( |
| 440 | 440 | hasActionableProposedPlan({ |
| 441 | 441 | id: "plan-1", |
| 442 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 442 | turnId: TurnId.make("turn-1"), | |
| 443 | 443 | planMarkdown: "# Plan", |
| 444 | 444 | implementedAt: "2026-02-23T00:00:02.000Z", |
| 445 | implementationThreadId: ThreadId.makeUnsafe("thread-implement"), | |
| 445 | implementationThreadId: ThreadId.make("thread-implement"), | |
| 446 | 446 | createdAt: "2026-02-23T00:00:00.000Z", |
| 447 | 447 | updatedAt: "2026-02-23T00:00:02.000Z", |
| 448 | 448 | }), |
| ... | ... | @@ -456,25 +456,25 @@ describe("findSidebarProposedPlan", () => { |
| 456 | 456 | findSidebarProposedPlan({ |
| 457 | 457 | threads: [ |
| 458 | 458 | { |
| 459 | id: ThreadId.makeUnsafe("thread-1"), | |
| 459 | id: ThreadId.make("thread-1"), | |
| 460 | 460 | proposedPlans: [ |
| 461 | 461 | { |
| 462 | 462 | id: "plan-1", |
| 463 | turnId: TurnId.makeUnsafe("turn-plan"), | |
| 463 | turnId: TurnId.make("turn-plan"), | |
| 464 | 464 | planMarkdown: "# Source plan", |
| 465 | 465 | implementedAt: "2026-02-23T00:00:03.000Z", |
| 466 | implementationThreadId: ThreadId.makeUnsafe("thread-2"), | |
| 466 | implementationThreadId: ThreadId.make("thread-2"), | |
| 467 | 467 | createdAt: "2026-02-23T00:00:01.000Z", |
| 468 | 468 | updatedAt: "2026-02-23T00:00:02.000Z", |
| 469 | 469 | }, |
| 470 | 470 | ], |
| 471 | 471 | }, |
| 472 | 472 | { |
| 473 | id: ThreadId.makeUnsafe("thread-2"), | |
| 473 | id: ThreadId.make("thread-2"), | |
| 474 | 474 | proposedPlans: [ |
| 475 | 475 | { |
| 476 | 476 | id: "plan-2", |
| 477 | turnId: TurnId.makeUnsafe("turn-other"), | |
| 477 | turnId: TurnId.make("turn-other"), | |
| 478 | 478 | planMarkdown: "# Latest elsewhere", |
| 479 | 479 | implementedAt: null, |
| 480 | 480 | implementationThreadId: null, |
| ... | ... | @@ -485,14 +485,14 @@ describe("findSidebarProposedPlan", () => { |
| 485 | 485 | }, |
| 486 | 486 | ], |
| 487 | 487 | latestTurn: { |
| 488 | turnId: TurnId.makeUnsafe("turn-implementation"), | |
| 488 | turnId: TurnId.make("turn-implementation"), | |
| 489 | 489 | sourceProposedPlan: { |
| 490 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 490 | threadId: ThreadId.make("thread-1"), | |
| 491 | 491 | planId: "plan-1", |
| 492 | 492 | }, |
| 493 | 493 | }, |
| 494 | 494 | latestTurnSettled: false, |
| 495 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 495 | threadId: ThreadId.make("thread-1"), | |
| 496 | 496 | }), |
| 497 | 497 | ).toEqual({ |
| 498 | 498 | id: "plan-1", |
| ... | ... | @@ -510,11 +510,11 @@ describe("findSidebarProposedPlan", () => { |
| 510 | 510 | findSidebarProposedPlan({ |
| 511 | 511 | threads: [ |
| 512 | 512 | { |
| 513 | id: ThreadId.makeUnsafe("thread-1"), | |
| 513 | id: ThreadId.make("thread-1"), | |
| 514 | 514 | proposedPlans: [ |
| 515 | 515 | { |
| 516 | 516 | id: "plan-1", |
| 517 | turnId: TurnId.makeUnsafe("turn-plan"), | |
| 517 | turnId: TurnId.make("turn-plan"), | |
| 518 | 518 | planMarkdown: "# Older", |
| 519 | 519 | implementedAt: null, |
| 520 | 520 | implementationThreadId: null, |
| ... | ... | @@ -523,7 +523,7 @@ describe("findSidebarProposedPlan", () => { |
| 523 | 523 | }, |
| 524 | 524 | { |
| 525 | 525 | id: "plan-2", |
| 526 | turnId: TurnId.makeUnsafe("turn-latest"), | |
| 526 | turnId: TurnId.make("turn-latest"), | |
| 527 | 527 | planMarkdown: "# Latest", |
| 528 | 528 | implementedAt: null, |
| 529 | 529 | implementationThreadId: null, |
| ... | ... | @@ -534,14 +534,14 @@ describe("findSidebarProposedPlan", () => { |
| 534 | 534 | }, |
| 535 | 535 | ], |
| 536 | 536 | latestTurn: { |
| 537 | turnId: TurnId.makeUnsafe("turn-implementation"), | |
| 537 | turnId: TurnId.make("turn-implementation"), | |
| 538 | 538 | sourceProposedPlan: { |
| 539 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 539 | threadId: ThreadId.make("thread-1"), | |
| 540 | 540 | planId: "plan-1", |
| 541 | 541 | }, |
| 542 | 542 | }, |
| 543 | 543 | latestTurnSettled: true, |
| 544 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 544 | threadId: ThreadId.make("thread-1"), | |
| 545 | 545 | })?.planMarkdown, |
| 546 | 546 | ).toBe("# Latest"); |
| 547 | 547 | }); |
| ... | ... | @@ -609,7 +609,7 @@ describe("deriveWorkLogEntries", () => { |
| 609 | 609 | makeActivity({ id: "no-turn", summary: "Checkpoint captured", tone: "info" }), |
| 610 | 610 | ]; |
| 611 | 611 | |
| 612 | const entries = deriveWorkLogEntries(activities, TurnId.makeUnsafe("turn-2")); | |
| 612 | const entries = deriveWorkLogEntries(activities, TurnId.make("turn-2")); | |
| 613 | 613 | expect(entries.map((entry) => entry.id)).toEqual(["turn-2"]); |
| 614 | 614 | }); |
| 615 | 615 | |
| ... | ... | @@ -1022,7 +1022,7 @@ describe("deriveTimelineEntries", () => { |
| 1022 | 1022 | const entries = deriveTimelineEntries( |
| 1023 | 1023 | [ |
| 1024 | 1024 | { |
| 1025 | id: MessageId.makeUnsafe("message-1"), | |
| 1025 | id: MessageId.make("message-1"), | |
| 1026 | 1026 | role: "assistant", |
| 1027 | 1027 | text: "hello", |
| 1028 | 1028 | createdAt: "2026-02-23T00:00:01.000Z", |
| ... | ... | @@ -1032,7 +1032,7 @@ describe("deriveTimelineEntries", () => { |
| 1032 | 1032 | [ |
| 1033 | 1033 | { |
| 1034 | 1034 | id: "plan:thread-1:turn:turn-1", |
| 1035 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1035 | turnId: TurnId.make("turn-1"), | |
| 1036 | 1036 | planMarkdown: "# Ship it", |
| 1037 | 1037 | implementedAt: null, |
| 1038 | 1038 | implementationThreadId: null, |
| ... | ... | @@ -1065,14 +1065,14 @@ describe("deriveTimelineEntries", () => { |
| 1065 | 1065 | const entries = deriveTimelineEntries( |
| 1066 | 1066 | [ |
| 1067 | 1067 | { |
| 1068 | id: MessageId.makeUnsafe("assistant-earlier"), | |
| 1068 | id: MessageId.make("assistant-earlier"), | |
| 1069 | 1069 | role: "assistant", |
| 1070 | 1070 | text: "progress update", |
| 1071 | 1071 | createdAt: "2026-02-23T00:00:01.000Z", |
| 1072 | 1072 | streaming: false, |
| 1073 | 1073 | }, |
| 1074 | 1074 | { |
| 1075 | id: MessageId.makeUnsafe("assistant-final"), | |
| 1075 | id: MessageId.make("assistant-final"), | |
| 1076 | 1076 | role: "assistant", |
| 1077 | 1077 | text: "final answer", |
| 1078 | 1078 | createdAt: "2026-02-23T00:00:01.000Z", |
| ... | ... | @@ -1085,7 +1085,7 @@ describe("deriveTimelineEntries", () => { |
| 1085 | 1085 | |
| 1086 | 1086 | expect( |
| 1087 | 1087 | deriveCompletionDividerBeforeEntryId(entries, { |
| 1088 | assistantMessageId: MessageId.makeUnsafe("assistant-final"), | |
| 1088 | assistantMessageId: MessageId.make("assistant-final"), | |
| 1089 | 1089 | startedAt: "2026-02-23T00:00:00.000Z", |
| 1090 | 1090 | completedAt: "2026-02-23T00:00:02.000Z", |
| 1091 | 1091 | }), |
| ... | ... | @@ -1112,7 +1112,7 @@ describe("deriveWorkLogEntries context window handling", () => { |
| 1112 | 1112 | tone: "tool", |
| 1113 | 1113 | }), |
| 1114 | 1114 | ], |
| 1115 | TurnId.makeUnsafe("turn-1"), | |
| 1115 | TurnId.make("turn-1"), | |
| 1116 | 1116 | ); |
| 1117 | 1117 | |
| 1118 | 1118 | expect(entries).toHaveLength(1); |
| ... | ... | @@ -1130,7 +1130,7 @@ describe("deriveWorkLogEntries context window handling", () => { |
| 1130 | 1130 | tone: "info", |
| 1131 | 1131 | }), |
| 1132 | 1132 | ], |
| 1133 | TurnId.makeUnsafe("turn-1"), | |
| 1133 | TurnId.make("turn-1"), | |
| 1134 | 1134 | ); |
| 1135 | 1135 | |
| 1136 | 1136 | expect(entries).toHaveLength(1); |
| ... | ... | @@ -1154,14 +1154,14 @@ describe("hasToolActivityForTurn", () => { |
| 1154 | 1154 | makeActivity({ id: "info-1", turnId: "turn-2", kind: "turn.completed", tone: "info" }), |
| 1155 | 1155 | ]; |
| 1156 | 1156 | |
| 1157 | expect(hasToolActivityForTurn(activities, TurnId.makeUnsafe("turn-1"))).toBe(true); | |
| 1158 | expect(hasToolActivityForTurn(activities, TurnId.makeUnsafe("turn-2"))).toBe(false); | |
| 1157 | expect(hasToolActivityForTurn(activities, TurnId.make("turn-1"))).toBe(true); | |
| 1158 | expect(hasToolActivityForTurn(activities, TurnId.make("turn-2"))).toBe(false); | |
| 1159 | 1159 | }); |
| 1160 | 1160 | }); |
| 1161 | 1161 | |
| 1162 | 1162 | describe("isLatestTurnSettled", () => { |
| 1163 | 1163 | const latestTurn = { |
| 1164 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1164 | turnId: TurnId.make("turn-1"), | |
| 1165 | 1165 | startedAt: "2026-02-27T21:10:00.000Z", |
| 1166 | 1166 | completedAt: "2026-02-27T21:10:06.000Z", |
| 1167 | 1167 | } as const; |
| ... | ... | @@ -1170,7 +1170,7 @@ describe("isLatestTurnSettled", () => { |
| 1170 | 1170 | expect( |
| 1171 | 1171 | isLatestTurnSettled(latestTurn, { |
| 1172 | 1172 | orchestrationStatus: "running", |
| 1173 | activeTurnId: TurnId.makeUnsafe("turn-1"), | |
| 1173 | activeTurnId: TurnId.make("turn-1"), | |
| 1174 | 1174 | }), |
| 1175 | 1175 | ).toBe(false); |
| 1176 | 1176 | }); |
| ... | ... | @@ -1179,7 +1179,7 @@ describe("isLatestTurnSettled", () => { |
| 1179 | 1179 | expect( |
| 1180 | 1180 | isLatestTurnSettled(latestTurn, { |
| 1181 | 1181 | orchestrationStatus: "running", |
| 1182 | activeTurnId: TurnId.makeUnsafe("turn-2"), | |
| 1182 | activeTurnId: TurnId.make("turn-2"), | |
| 1183 | 1183 | }), |
| 1184 | 1184 | ).toBe(false); |
| 1185 | 1185 | }); |
| ... | ... | @@ -1197,7 +1197,7 @@ describe("isLatestTurnSettled", () => { |
| 1197 | 1197 | expect( |
| 1198 | 1198 | isLatestTurnSettled( |
| 1199 | 1199 | { |
| 1200 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1200 | turnId: TurnId.make("turn-1"), | |
| 1201 | 1201 | startedAt: null, |
| 1202 | 1202 | completedAt: "2026-02-27T21:10:06.000Z", |
| 1203 | 1203 | }, |
| ... | ... | @@ -1209,7 +1209,7 @@ describe("isLatestTurnSettled", () => { |
| 1209 | 1209 | |
| 1210 | 1210 | describe("deriveActiveWorkStartedAt", () => { |
| 1211 | 1211 | const latestTurn = { |
| 1212 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1212 | turnId: TurnId.make("turn-1"), | |
| 1213 | 1213 | startedAt: "2026-02-27T21:10:00.000Z", |
| 1214 | 1214 | completedAt: "2026-02-27T21:10:06.000Z", |
| 1215 | 1215 | } as const; |
| ... | ... | @@ -1220,7 +1220,7 @@ describe("deriveActiveWorkStartedAt", () => { |
| 1220 | 1220 | latestTurn, |
| 1221 | 1221 | { |
| 1222 | 1222 | orchestrationStatus: "running", |
| 1223 | activeTurnId: TurnId.makeUnsafe("turn-1"), | |
| 1223 | activeTurnId: TurnId.make("turn-1"), | |
| 1224 | 1224 | }, |
| 1225 | 1225 | "2026-02-27T21:11:00.000Z", |
| 1226 | 1226 | ), |
| ... | ... | @@ -1244,7 +1244,7 @@ describe("deriveActiveWorkStartedAt", () => { |
| 1244 | 1244 | expect( |
| 1245 | 1245 | deriveActiveWorkStartedAt( |
| 1246 | 1246 | { |
| 1247 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1247 | turnId: TurnId.make("turn-1"), | |
| 1248 | 1248 | startedAt: "2026-02-27T21:10:00.000Z", |
| 1249 | 1249 | completedAt: "2026-02-27T21:10:06.000Z", |
| 1250 | 1250 | }, |
apps/web/src/session-logic.ts+2-2| ... | ... | @@ -193,7 +193,7 @@ export function derivePendingApprovals( |
| 193 | 193 | : null; |
| 194 | 194 | const requestId = |
| 195 | 195 | payload && typeof payload.requestId === "string" |
| 196 | ? ApprovalRequestId.makeUnsafe(payload.requestId) | |
| 196 | ? ApprovalRequestId.make(payload.requestId) | |
| 197 | 197 | : null; |
| 198 | 198 | const requestKind = |
| 199 | 199 | payload && |
| ... | ... | @@ -299,7 +299,7 @@ export function derivePendingUserInputs( |
| 299 | 299 | : null; |
| 300 | 300 | const requestId = |
| 301 | 301 | payload && typeof payload.requestId === "string" |
| 302 | ? ApprovalRequestId.makeUnsafe(payload.requestId) | |
| 302 | ? ApprovalRequestId.make(payload.requestId) | |
| 303 | 303 | : null; |
| 304 | 304 | const detail = payload && typeof payload.detail === "string" ? payload.detail : undefined; |
| 305 | 305 |
apps/web/src/store.test.ts+76-76| ... | ... | @@ -26,8 +26,8 @@ import { |
| 26 | 26 | } from "./store"; |
| 27 | 27 | import { DEFAULT_INTERACTION_MODE, DEFAULT_RUNTIME_MODE, type Thread } from "./types"; |
| 28 | 28 | |
| 29 | const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local"); | |
| 30 | const remoteEnvironmentId = EnvironmentId.makeUnsafe("environment-remote"); | |
| 29 | const localEnvironmentId = EnvironmentId.make("environment-local"); | |
| 30 | const remoteEnvironmentId = EnvironmentId.make("environment-remote"); | |
| 31 | 31 | |
| 32 | 32 | function withActiveEnvironmentState( |
| 33 | 33 | environmentState: EnvironmentState, |
| ... | ... | @@ -59,10 +59,10 @@ function withActiveEnvironmentState( |
| 59 | 59 | |
| 60 | 60 | function makeThread(overrides: Partial<Thread> = {}): Thread { |
| 61 | 61 | return { |
| 62 | id: ThreadId.makeUnsafe("thread-1"), | |
| 62 | id: ThreadId.make("thread-1"), | |
| 63 | 63 | environmentId: localEnvironmentId, |
| 64 | 64 | codexThreadId: null, |
| 65 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 65 | projectId: ProjectId.make("project-1"), | |
| 66 | 66 | title: "Thread", |
| 67 | 67 | modelSelection: { |
| 68 | 68 | provider: "codex", |
| ... | ... | @@ -86,7 +86,7 @@ function makeThread(overrides: Partial<Thread> = {}): Thread { |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | function makeState(thread: Thread): AppState { |
| 89 | const projectId = ProjectId.makeUnsafe("project-1"); | |
| 89 | const projectId = ProjectId.make("project-1"); | |
| 90 | 90 | const project = { |
| 91 | 91 | id: projectId, |
| 92 | 92 | environmentId: thread.environmentId, |
| ... | ... | @@ -226,14 +226,14 @@ function makeEvent<T extends OrchestrationEvent["type"]>( |
| 226 | 226 | const sequence = overrides.sequence ?? 1; |
| 227 | 227 | return { |
| 228 | 228 | sequence, |
| 229 | eventId: EventId.makeUnsafe(`event-${sequence}`), | |
| 229 | eventId: EventId.make(`event-${sequence}`), | |
| 230 | 230 | aggregateKind: "thread", |
| 231 | 231 | aggregateId: |
| 232 | 232 | "threadId" in payload |
| 233 | 233 | ? payload.threadId |
| 234 | 234 | : "projectId" in payload |
| 235 | 235 | ? payload.projectId |
| 236 | : ProjectId.makeUnsafe("project-1"), | |
| 236 | : ProjectId.make("project-1"), | |
| 237 | 237 | occurredAt: "2026-02-27T00:00:00.000Z", |
| 238 | 238 | commandId: null, |
| 239 | 239 | causationEventId: null, |
| ... | ... | @@ -247,8 +247,8 @@ function makeEvent<T extends OrchestrationEvent["type"]>( |
| 247 | 247 | |
| 248 | 248 | function makeReadModelThread(overrides: Partial<OrchestrationReadModel["threads"][number]>) { |
| 249 | 249 | return { |
| 250 | id: ThreadId.makeUnsafe("thread-1"), | |
| 251 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 250 | id: ThreadId.make("thread-1"), | |
| 251 | projectId: ProjectId.make("project-1"), | |
| 252 | 252 | title: "Thread", |
| 253 | 253 | modelSelection: { |
| 254 | 254 | provider: "codex", |
| ... | ... | @@ -278,7 +278,7 @@ function makeReadModel(thread: OrchestrationReadModel["threads"][number]): Orche |
| 278 | 278 | updatedAt: "2026-02-27T00:00:00.000Z", |
| 279 | 279 | projects: [ |
| 280 | 280 | { |
| 281 | id: ProjectId.makeUnsafe("project-1"), | |
| 281 | id: ProjectId.make("project-1"), | |
| 282 | 282 | title: "Project", |
| 283 | 283 | workspaceRoot: "/tmp/project", |
| 284 | 284 | defaultModelSelection: { |
| ... | ... | @@ -299,7 +299,7 @@ function makeReadModelProject( |
| 299 | 299 | overrides: Partial<OrchestrationReadModel["projects"][number]>, |
| 300 | 300 | ): OrchestrationReadModel["projects"][number] { |
| 301 | 301 | return { |
| 302 | id: ProjectId.makeUnsafe("project-1"), | |
| 302 | id: ProjectId.make("project-1"), | |
| 303 | 303 | title: "Project", |
| 304 | 304 | workspaceRoot: "/tmp/project", |
| 305 | 305 | defaultModelSelection: { |
| ... | ... | @@ -316,7 +316,7 @@ function makeReadModelProject( |
| 316 | 316 | |
| 317 | 317 | describe("setThreadBranch", () => { |
| 318 | 318 | it("updates only the scoped thread environment", () => { |
| 319 | const sharedThreadId = ThreadId.makeUnsafe("thread-shared"); | |
| 319 | const sharedThreadId = ThreadId.make("thread-shared"); | |
| 320 | 320 | const localThread = makeThread({ |
| 321 | 321 | id: sharedThreadId, |
| 322 | 322 | environmentId: localEnvironmentId, |
| ... | ... | @@ -397,7 +397,7 @@ describe("store read model sync", () => { |
| 397 | 397 | model: "sonnet", |
| 398 | 398 | }, |
| 399 | 399 | session: { |
| 400 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 400 | threadId: ThreadId.make("thread-1"), | |
| 401 | 401 | status: "ready", |
| 402 | 402 | providerName: "claudeAgent", |
| 403 | 403 | runtimeMode: "approval-required", |
| ... | ... | @@ -444,9 +444,9 @@ describe("store read model sync", () => { |
| 444 | 444 | }); |
| 445 | 445 | |
| 446 | 446 | it("replaces projects using snapshot order during recovery", () => { |
| 447 | const project1 = ProjectId.makeUnsafe("project-1"); | |
| 448 | const project2 = ProjectId.makeUnsafe("project-2"); | |
| 449 | const project3 = ProjectId.makeUnsafe("project-3"); | |
| 447 | const project1 = ProjectId.make("project-1"); | |
| 448 | const project2 = ProjectId.make("project-2"); | |
| 449 | const project3 = ProjectId.make("project-3"); | |
| 450 | 450 | const initialState: AppState = makeEmptyState({ |
| 451 | 451 | projectIds: [project2, project1], |
| 452 | 452 | projectById: { |
| ... | ... | @@ -516,7 +516,7 @@ describe("incremental orchestration updates", () => { |
| 516 | 516 | const next = applyOrchestrationEvent( |
| 517 | 517 | state, |
| 518 | 518 | makeEvent("thread.meta-updated", { |
| 519 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 519 | threadId: ThreadId.make("thread-1"), | |
| 520 | 520 | title: "Updated title", |
| 521 | 521 | updatedAt: "2026-02-27T00:00:01.000Z", |
| 522 | 522 | }), |
| ... | ... | @@ -533,7 +533,7 @@ describe("incremental orchestration updates", () => { |
| 533 | 533 | const nextAfterProjectDelete = applyOrchestrationEvent( |
| 534 | 534 | state, |
| 535 | 535 | makeEvent("project.deleted", { |
| 536 | projectId: ProjectId.makeUnsafe("project-missing"), | |
| 536 | projectId: ProjectId.make("project-missing"), | |
| 537 | 537 | deletedAt: "2026-02-27T00:00:01.000Z", |
| 538 | 538 | }), |
| 539 | 539 | localEnvironmentId, |
| ... | ... | @@ -541,7 +541,7 @@ describe("incremental orchestration updates", () => { |
| 541 | 541 | const nextAfterThreadDelete = applyOrchestrationEvent( |
| 542 | 542 | state, |
| 543 | 543 | makeEvent("thread.deleted", { |
| 544 | threadId: ThreadId.makeUnsafe("thread-missing"), | |
| 544 | threadId: ThreadId.make("thread-missing"), | |
| 545 | 545 | deletedAt: "2026-02-27T00:00:01.000Z", |
| 546 | 546 | }), |
| 547 | 547 | localEnvironmentId, |
| ... | ... | @@ -552,8 +552,8 @@ describe("incremental orchestration updates", () => { |
| 552 | 552 | }); |
| 553 | 553 | |
| 554 | 554 | it("reuses an existing project row when project.created arrives with a new id for the same cwd", () => { |
| 555 | const originalProjectId = ProjectId.makeUnsafe("project-1"); | |
| 556 | const recreatedProjectId = ProjectId.makeUnsafe("project-2"); | |
| 555 | const originalProjectId = ProjectId.make("project-1"); | |
| 556 | const recreatedProjectId = ProjectId.make("project-2"); | |
| 557 | 557 | const state: AppState = makeEmptyState({ |
| 558 | 558 | projectIds: [originalProjectId], |
| 559 | 559 | projectById: { |
| ... | ... | @@ -602,9 +602,9 @@ describe("incremental orchestration updates", () => { |
| 602 | 602 | }); |
| 603 | 603 | |
| 604 | 604 | it("removes stale project index entries when thread.created recreates a thread under a new project", () => { |
| 605 | const originalProjectId = ProjectId.makeUnsafe("project-1"); | |
| 606 | const recreatedProjectId = ProjectId.makeUnsafe("project-2"); | |
| 607 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 605 | const originalProjectId = ProjectId.make("project-1"); | |
| 606 | const recreatedProjectId = ProjectId.make("project-2"); | |
| 607 | const threadId = ThreadId.make("thread-1"); | |
| 608 | 608 | const thread = makeThread({ |
| 609 | 609 | id: threadId, |
| 610 | 610 | projectId: originalProjectId, |
| ... | ... | @@ -671,20 +671,20 @@ describe("incremental orchestration updates", () => { |
| 671 | 671 | |
| 672 | 672 | it("updates only the affected thread for message events", () => { |
| 673 | 673 | const thread1 = makeThread({ |
| 674 | id: ThreadId.makeUnsafe("thread-1"), | |
| 674 | id: ThreadId.make("thread-1"), | |
| 675 | 675 | messages: [ |
| 676 | 676 | { |
| 677 | id: MessageId.makeUnsafe("message-1"), | |
| 677 | id: MessageId.make("message-1"), | |
| 678 | 678 | role: "assistant", |
| 679 | 679 | text: "hello", |
| 680 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 680 | turnId: TurnId.make("turn-1"), | |
| 681 | 681 | createdAt: "2026-02-27T00:00:00.000Z", |
| 682 | 682 | completedAt: "2026-02-27T00:00:00.000Z", |
| 683 | 683 | streaming: false, |
| 684 | 684 | }, |
| 685 | 685 | ], |
| 686 | 686 | }); |
| 687 | const thread2 = makeThread({ id: ThreadId.makeUnsafe("thread-2") }); | |
| 687 | const thread2 = makeThread({ id: ThreadId.make("thread-2") }); | |
| 688 | 688 | const baseState = makeState(thread1); |
| 689 | 689 | const baseEnvironmentState = localEnvironmentStateOf(baseState); |
| 690 | 690 | const state = withActiveEnvironmentState(baseEnvironmentState, { |
| ... | ... | @@ -762,10 +762,10 @@ describe("incremental orchestration updates", () => { |
| 762 | 762 | state, |
| 763 | 763 | makeEvent("thread.message-sent", { |
| 764 | 764 | threadId: thread1.id, |
| 765 | messageId: MessageId.makeUnsafe("message-1"), | |
| 765 | messageId: MessageId.make("message-1"), | |
| 766 | 766 | role: "assistant", |
| 767 | 767 | text: " world", |
| 768 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 768 | turnId: TurnId.make("turn-1"), | |
| 769 | 769 | streaming: true, |
| 770 | 770 | createdAt: "2026-02-27T00:00:01.000Z", |
| 771 | 771 | updatedAt: "2026-02-27T00:00:01.000Z", |
| ... | ... | @@ -794,7 +794,7 @@ describe("incremental orchestration updates", () => { |
| 794 | 794 | it("applies replay batches in sequence and updates session state", () => { |
| 795 | 795 | const thread = makeThread({ |
| 796 | 796 | latestTurn: { |
| 797 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 797 | turnId: TurnId.make("turn-1"), | |
| 798 | 798 | state: "running", |
| 799 | 799 | requestedAt: "2026-02-27T00:00:00.000Z", |
| 800 | 800 | startedAt: "2026-02-27T00:00:00.000Z", |
| ... | ... | @@ -816,7 +816,7 @@ describe("incremental orchestration updates", () => { |
| 816 | 816 | status: "running", |
| 817 | 817 | providerName: "codex", |
| 818 | 818 | runtimeMode: "full-access", |
| 819 | activeTurnId: TurnId.makeUnsafe("turn-1"), | |
| 819 | activeTurnId: TurnId.make("turn-1"), | |
| 820 | 820 | lastError: null, |
| 821 | 821 | updatedAt: "2026-02-27T00:00:02.000Z", |
| 822 | 822 | }, |
| ... | ... | @@ -827,10 +827,10 @@ describe("incremental orchestration updates", () => { |
| 827 | 827 | "thread.message-sent", |
| 828 | 828 | { |
| 829 | 829 | threadId: thread.id, |
| 830 | messageId: MessageId.makeUnsafe("assistant-1"), | |
| 830 | messageId: MessageId.make("assistant-1"), | |
| 831 | 831 | role: "assistant", |
| 832 | 832 | text: "done", |
| 833 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 833 | turnId: TurnId.make("turn-1"), | |
| 834 | 834 | streaming: false, |
| 835 | 835 | createdAt: "2026-02-27T00:00:03.000Z", |
| 836 | 836 | updatedAt: "2026-02-27T00:00:03.000Z", |
| ... | ... | @@ -850,7 +850,7 @@ describe("incremental orchestration updates", () => { |
| 850 | 850 | const state = makeState( |
| 851 | 851 | makeThread({ |
| 852 | 852 | latestTurn: { |
| 853 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 853 | turnId: TurnId.make("turn-2"), | |
| 854 | 854 | state: "running", |
| 855 | 855 | requestedAt: "2026-02-27T00:00:02.000Z", |
| 856 | 856 | startedAt: "2026-02-27T00:00:03.000Z", |
| ... | ... | @@ -863,13 +863,13 @@ describe("incremental orchestration updates", () => { |
| 863 | 863 | const next = applyOrchestrationEvent( |
| 864 | 864 | state, |
| 865 | 865 | makeEvent("thread.turn-diff-completed", { |
| 866 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 867 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 866 | threadId: ThreadId.make("thread-1"), | |
| 867 | turnId: TurnId.make("turn-1"), | |
| 868 | 868 | checkpointTurnCount: 1, |
| 869 | checkpointRef: CheckpointRef.makeUnsafe("checkpoint-1"), | |
| 869 | checkpointRef: CheckpointRef.make("checkpoint-1"), | |
| 870 | 870 | status: "ready", |
| 871 | 871 | files: [], |
| 872 | assistantMessageId: MessageId.makeUnsafe("assistant-1"), | |
| 872 | assistantMessageId: MessageId.make("assistant-1"), | |
| 873 | 873 | completedAt: "2026-02-27T00:00:04.000Z", |
| 874 | 874 | }), |
| 875 | 875 | localEnvironmentId, |
| ... | ... | @@ -880,7 +880,7 @@ describe("incremental orchestration updates", () => { |
| 880 | 880 | }); |
| 881 | 881 | |
| 882 | 882 | it("rebinds live turn diffs to the authoritative assistant message when it arrives later", () => { |
| 883 | const turnId = TurnId.makeUnsafe("turn-1"); | |
| 883 | const turnId = TurnId.make("turn-1"); | |
| 884 | 884 | const state = makeState( |
| 885 | 885 | makeThread({ |
| 886 | 886 | latestTurn: { |
| ... | ... | @@ -889,7 +889,7 @@ describe("incremental orchestration updates", () => { |
| 889 | 889 | requestedAt: "2026-02-27T00:00:00.000Z", |
| 890 | 890 | startedAt: "2026-02-27T00:00:00.000Z", |
| 891 | 891 | completedAt: "2026-02-27T00:00:02.000Z", |
| 892 | assistantMessageId: MessageId.makeUnsafe("assistant:turn-1"), | |
| 892 | assistantMessageId: MessageId.make("assistant:turn-1"), | |
| 893 | 893 | }, |
| 894 | 894 | turnDiffSummaries: [ |
| 895 | 895 | { |
| ... | ... | @@ -897,8 +897,8 @@ describe("incremental orchestration updates", () => { |
| 897 | 897 | completedAt: "2026-02-27T00:00:02.000Z", |
| 898 | 898 | status: "ready", |
| 899 | 899 | checkpointTurnCount: 1, |
| 900 | checkpointRef: CheckpointRef.makeUnsafe("checkpoint-1"), | |
| 901 | assistantMessageId: MessageId.makeUnsafe("assistant:turn-1"), | |
| 900 | checkpointRef: CheckpointRef.make("checkpoint-1"), | |
| 901 | assistantMessageId: MessageId.make("assistant:turn-1"), | |
| 902 | 902 | files: [{ path: "src/app.ts", additions: 1, deletions: 0 }], |
| 903 | 903 | }, |
| 904 | 904 | ], |
| ... | ... | @@ -908,8 +908,8 @@ describe("incremental orchestration updates", () => { |
| 908 | 908 | const next = applyOrchestrationEvent( |
| 909 | 909 | state, |
| 910 | 910 | makeEvent("thread.message-sent", { |
| 911 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 912 | messageId: MessageId.makeUnsafe("assistant-real"), | |
| 911 | threadId: ThreadId.make("thread-1"), | |
| 912 | messageId: MessageId.make("assistant-real"), | |
| 913 | 913 | role: "assistant", |
| 914 | 914 | text: "final answer", |
| 915 | 915 | turnId, |
| ... | ... | @@ -921,10 +921,10 @@ describe("incremental orchestration updates", () => { |
| 921 | 921 | ); |
| 922 | 922 | |
| 923 | 923 | expect(threadsOf(next)[0]?.turnDiffSummaries[0]?.assistantMessageId).toBe( |
| 924 | MessageId.makeUnsafe("assistant-real"), | |
| 924 | MessageId.make("assistant-real"), | |
| 925 | 925 | ); |
| 926 | 926 | expect(threadsOf(next)[0]?.latestTurn?.assistantMessageId).toBe( |
| 927 | MessageId.makeUnsafe("assistant-real"), | |
| 927 | MessageId.make("assistant-real"), | |
| 928 | 928 | ); |
| 929 | 929 | }); |
| 930 | 930 | |
| ... | ... | @@ -933,28 +933,28 @@ describe("incremental orchestration updates", () => { |
| 933 | 933 | makeThread({ |
| 934 | 934 | messages: [ |
| 935 | 935 | { |
| 936 | id: MessageId.makeUnsafe("user-1"), | |
| 936 | id: MessageId.make("user-1"), | |
| 937 | 937 | role: "user", |
| 938 | 938 | text: "first", |
| 939 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 939 | turnId: TurnId.make("turn-1"), | |
| 940 | 940 | createdAt: "2026-02-27T00:00:00.000Z", |
| 941 | 941 | completedAt: "2026-02-27T00:00:00.000Z", |
| 942 | 942 | streaming: false, |
| 943 | 943 | }, |
| 944 | 944 | { |
| 945 | id: MessageId.makeUnsafe("assistant-1"), | |
| 945 | id: MessageId.make("assistant-1"), | |
| 946 | 946 | role: "assistant", |
| 947 | 947 | text: "first reply", |
| 948 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 948 | turnId: TurnId.make("turn-1"), | |
| 949 | 949 | createdAt: "2026-02-27T00:00:01.000Z", |
| 950 | 950 | completedAt: "2026-02-27T00:00:01.000Z", |
| 951 | 951 | streaming: false, |
| 952 | 952 | }, |
| 953 | 953 | { |
| 954 | id: MessageId.makeUnsafe("user-2"), | |
| 954 | id: MessageId.make("user-2"), | |
| 955 | 955 | role: "user", |
| 956 | 956 | text: "second", |
| 957 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 957 | turnId: TurnId.make("turn-2"), | |
| 958 | 958 | createdAt: "2026-02-27T00:00:02.000Z", |
| 959 | 959 | completedAt: "2026-02-27T00:00:02.000Z", |
| 960 | 960 | streaming: false, |
| ... | ... | @@ -963,7 +963,7 @@ describe("incremental orchestration updates", () => { |
| 963 | 963 | proposedPlans: [ |
| 964 | 964 | { |
| 965 | 965 | id: "plan-1", |
| 966 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 966 | turnId: TurnId.make("turn-1"), | |
| 967 | 967 | planMarkdown: "plan 1", |
| 968 | 968 | implementedAt: null, |
| 969 | 969 | implementationThreadId: null, |
| ... | ... | @@ -972,7 +972,7 @@ describe("incremental orchestration updates", () => { |
| 972 | 972 | }, |
| 973 | 973 | { |
| 974 | 974 | id: "plan-2", |
| 975 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 975 | turnId: TurnId.make("turn-2"), | |
| 976 | 976 | planMarkdown: "plan 2", |
| 977 | 977 | implementedAt: null, |
| 978 | 978 | implementationThreadId: null, |
| ... | ... | @@ -982,39 +982,39 @@ describe("incremental orchestration updates", () => { |
| 982 | 982 | ], |
| 983 | 983 | activities: [ |
| 984 | 984 | { |
| 985 | id: EventId.makeUnsafe("activity-1"), | |
| 985 | id: EventId.make("activity-1"), | |
| 986 | 986 | tone: "info", |
| 987 | 987 | kind: "step", |
| 988 | 988 | summary: "one", |
| 989 | 989 | payload: {}, |
| 990 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 990 | turnId: TurnId.make("turn-1"), | |
| 991 | 991 | createdAt: "2026-02-27T00:00:00.000Z", |
| 992 | 992 | }, |
| 993 | 993 | { |
| 994 | id: EventId.makeUnsafe("activity-2"), | |
| 994 | id: EventId.make("activity-2"), | |
| 995 | 995 | tone: "info", |
| 996 | 996 | kind: "step", |
| 997 | 997 | summary: "two", |
| 998 | 998 | payload: {}, |
| 999 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 999 | turnId: TurnId.make("turn-2"), | |
| 1000 | 1000 | createdAt: "2026-02-27T00:00:02.000Z", |
| 1001 | 1001 | }, |
| 1002 | 1002 | ], |
| 1003 | 1003 | turnDiffSummaries: [ |
| 1004 | 1004 | { |
| 1005 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1005 | turnId: TurnId.make("turn-1"), | |
| 1006 | 1006 | completedAt: "2026-02-27T00:00:01.000Z", |
| 1007 | 1007 | status: "ready", |
| 1008 | 1008 | checkpointTurnCount: 1, |
| 1009 | checkpointRef: CheckpointRef.makeUnsafe("ref-1"), | |
| 1009 | checkpointRef: CheckpointRef.make("ref-1"), | |
| 1010 | 1010 | files: [], |
| 1011 | 1011 | }, |
| 1012 | 1012 | { |
| 1013 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 1013 | turnId: TurnId.make("turn-2"), | |
| 1014 | 1014 | completedAt: "2026-02-27T00:00:03.000Z", |
| 1015 | 1015 | status: "ready", |
| 1016 | 1016 | checkpointTurnCount: 2, |
| 1017 | checkpointRef: CheckpointRef.makeUnsafe("ref-2"), | |
| 1017 | checkpointRef: CheckpointRef.make("ref-2"), | |
| 1018 | 1018 | files: [], |
| 1019 | 1019 | }, |
| 1020 | 1020 | ], |
| ... | ... | @@ -1024,7 +1024,7 @@ describe("incremental orchestration updates", () => { |
| 1024 | 1024 | const next = applyOrchestrationEvent( |
| 1025 | 1025 | state, |
| 1026 | 1026 | makeEvent("thread.reverted", { |
| 1027 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 1027 | threadId: ThreadId.make("thread-1"), | |
| 1028 | 1028 | turnCount: 1, |
| 1029 | 1029 | }), |
| 1030 | 1030 | localEnvironmentId, |
| ... | ... | @@ -1036,46 +1036,46 @@ describe("incremental orchestration updates", () => { |
| 1036 | 1036 | ]); |
| 1037 | 1037 | expect(threadsOf(next)[0]?.proposedPlans.map((plan) => plan.id)).toEqual(["plan-1"]); |
| 1038 | 1038 | expect(threadsOf(next)[0]?.activities.map((activity) => activity.id)).toEqual([ |
| 1039 | EventId.makeUnsafe("activity-1"), | |
| 1039 | EventId.make("activity-1"), | |
| 1040 | 1040 | ]); |
| 1041 | 1041 | expect(threadsOf(next)[0]?.turnDiffSummaries.map((summary) => summary.turnId)).toEqual([ |
| 1042 | TurnId.makeUnsafe("turn-1"), | |
| 1042 | TurnId.make("turn-1"), | |
| 1043 | 1043 | ]); |
| 1044 | 1044 | }); |
| 1045 | 1045 | |
| 1046 | 1046 | it("clears pending source proposed plans after revert before a new session-set event", () => { |
| 1047 | 1047 | const thread = makeThread({ |
| 1048 | 1048 | latestTurn: { |
| 1049 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 1049 | turnId: TurnId.make("turn-2"), | |
| 1050 | 1050 | state: "completed", |
| 1051 | 1051 | requestedAt: "2026-02-27T00:00:02.000Z", |
| 1052 | 1052 | startedAt: "2026-02-27T00:00:02.000Z", |
| 1053 | 1053 | completedAt: "2026-02-27T00:00:03.000Z", |
| 1054 | assistantMessageId: MessageId.makeUnsafe("assistant-2"), | |
| 1054 | assistantMessageId: MessageId.make("assistant-2"), | |
| 1055 | 1055 | sourceProposedPlan: { |
| 1056 | threadId: ThreadId.makeUnsafe("thread-source"), | |
| 1056 | threadId: ThreadId.make("thread-source"), | |
| 1057 | 1057 | planId: "plan-2" as never, |
| 1058 | 1058 | }, |
| 1059 | 1059 | }, |
| 1060 | 1060 | pendingSourceProposedPlan: { |
| 1061 | threadId: ThreadId.makeUnsafe("thread-source"), | |
| 1061 | threadId: ThreadId.make("thread-source"), | |
| 1062 | 1062 | planId: "plan-2" as never, |
| 1063 | 1063 | }, |
| 1064 | 1064 | turnDiffSummaries: [ |
| 1065 | 1065 | { |
| 1066 | turnId: TurnId.makeUnsafe("turn-1"), | |
| 1066 | turnId: TurnId.make("turn-1"), | |
| 1067 | 1067 | completedAt: "2026-02-27T00:00:01.000Z", |
| 1068 | 1068 | status: "ready", |
| 1069 | 1069 | checkpointTurnCount: 1, |
| 1070 | checkpointRef: CheckpointRef.makeUnsafe("ref-1"), | |
| 1070 | checkpointRef: CheckpointRef.make("ref-1"), | |
| 1071 | 1071 | files: [], |
| 1072 | 1072 | }, |
| 1073 | 1073 | { |
| 1074 | turnId: TurnId.makeUnsafe("turn-2"), | |
| 1074 | turnId: TurnId.make("turn-2"), | |
| 1075 | 1075 | completedAt: "2026-02-27T00:00:03.000Z", |
| 1076 | 1076 | status: "ready", |
| 1077 | 1077 | checkpointTurnCount: 2, |
| 1078 | checkpointRef: CheckpointRef.makeUnsafe("ref-2"), | |
| 1078 | checkpointRef: CheckpointRef.make("ref-2"), | |
| 1079 | 1079 | files: [], |
| 1080 | 1080 | }, |
| 1081 | 1081 | ], |
| ... | ... | @@ -1100,7 +1100,7 @@ describe("incremental orchestration updates", () => { |
| 1100 | 1100 | status: "running", |
| 1101 | 1101 | providerName: "codex", |
| 1102 | 1102 | runtimeMode: "full-access", |
| 1103 | activeTurnId: TurnId.makeUnsafe("turn-3"), | |
| 1103 | activeTurnId: TurnId.make("turn-3"), | |
| 1104 | 1104 | lastError: null, |
| 1105 | 1105 | updatedAt: "2026-02-27T00:00:04.000Z", |
| 1106 | 1106 | }, |
| ... | ... | @@ -1109,7 +1109,7 @@ describe("incremental orchestration updates", () => { |
| 1109 | 1109 | ); |
| 1110 | 1110 | |
| 1111 | 1111 | expect(threadsOf(next)[0]?.latestTurn).toMatchObject({ |
| 1112 | turnId: TurnId.makeUnsafe("turn-3"), | |
| 1112 | turnId: TurnId.make("turn-3"), | |
| 1113 | 1113 | state: "running", |
| 1114 | 1114 | }); |
| 1115 | 1115 | expect(threadsOf(next)[0]?.latestTurn?.sourceProposedPlan).toBeUndefined(); |
apps/web/src/terminalStateStore.test.ts+1-1| ... | ... | @@ -9,7 +9,7 @@ import { |
| 9 | 9 | useTerminalStateStore, |
| 10 | 10 | } from "./terminalStateStore"; |
| 11 | 11 | |
| 12 | const THREAD_ID = ThreadId.makeUnsafe("thread-1"); | |
| 12 | const THREAD_ID = ThreadId.make("thread-1"); | |
| 13 | 13 | const THREAD_REF = scopeThreadRef("environment-a" as never, THREAD_ID); |
| 14 | 14 | const OTHER_THREAD_REF = scopeThreadRef("environment-b" as never, THREAD_ID); |
| 15 | 15 |
apps/web/src/threadRoutes.test.ts+2-2| ... | ... | @@ -12,7 +12,7 @@ import { |
| 12 | 12 | |
| 13 | 13 | describe("threadRoutes", () => { |
| 14 | 14 | it("builds canonical thread route params from a scoped ref", () => { |
| 15 | const ref = scopeThreadRef("env-1" as never, ThreadId.makeUnsafe("thread-1")); | |
| 15 | const ref = scopeThreadRef("env-1" as never, ThreadId.make("thread-1")); | |
| 16 | 16 | |
| 17 | 17 | expect(buildThreadRouteParams(ref)).toEqual({ |
| 18 | 18 | environmentId: "env-1", |
| ... | ... | @@ -36,7 +36,7 @@ describe("threadRoutes", () => { |
| 36 | 36 | }); |
| 37 | 37 | |
| 38 | 38 | it("builds canonical draft route params from a draft id", () => { |
| 39 | expect(buildDraftThreadRouteParams(DraftId.makeUnsafe("draft-1"))).toEqual({ | |
| 39 | expect(buildDraftThreadRouteParams(DraftId.make("draft-1"))).toEqual({ | |
| 40 | 40 | draftId: "draft-1", |
| 41 | 41 | }); |
| 42 | 42 | }); |
apps/web/src/threadSelectionStore.test.ts+6-6| ... | ... | @@ -3,11 +3,11 @@ import { beforeEach, describe, expect, it } from "vitest"; |
| 3 | 3 | |
| 4 | 4 | import { useThreadSelectionStore } from "./threadSelectionStore"; |
| 5 | 5 | |
| 6 | const THREAD_A = ThreadId.makeUnsafe("thread-a"); | |
| 7 | const THREAD_B = ThreadId.makeUnsafe("thread-b"); | |
| 8 | const THREAD_C = ThreadId.makeUnsafe("thread-c"); | |
| 9 | const THREAD_D = ThreadId.makeUnsafe("thread-d"); | |
| 10 | const THREAD_E = ThreadId.makeUnsafe("thread-e"); | |
| 6 | const THREAD_A = ThreadId.make("thread-a"); | |
| 7 | const THREAD_B = ThreadId.make("thread-b"); | |
| 8 | const THREAD_C = ThreadId.make("thread-c"); | |
| 9 | const THREAD_D = ThreadId.make("thread-d"); | |
| 10 | const THREAD_E = ThreadId.make("thread-e"); | |
| 11 | 11 | |
| 12 | 12 | const ORDERED = [THREAD_A, THREAD_B, THREAD_C, THREAD_D, THREAD_E] as const; |
| 13 | 13 | |
| ... | ... | @@ -173,7 +173,7 @@ describe("threadSelectionStore", () => { |
| 173 | 173 | it("falls back to toggle when target is not in the ordered list", () => { |
| 174 | 174 | const store = useThreadSelectionStore.getState(); |
| 175 | 175 | store.toggleThread(THREAD_B); // anchor = B |
| 176 | const unknownThread = ThreadId.makeUnsafe("thread-unknown"); | |
| 176 | const unknownThread = ThreadId.make("thread-unknown"); | |
| 177 | 177 | store.rangeSelectTo(unknownThread, ORDERED); |
| 178 | 178 | |
| 179 | 179 | const state = useThreadSelectionStore.getState(); |
apps/web/src/uiStateStore.test.ts+17-17| ... | ... | @@ -22,7 +22,7 @@ function makeUiState(overrides: Partial<UiState> = {}): UiState { |
| 22 | 22 | |
| 23 | 23 | describe("uiStateStore pure functions", () => { |
| 24 | 24 | it("markThreadUnread moves lastVisitedAt before completion for a completed thread", () => { |
| 25 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 25 | const threadId = ThreadId.make("thread-1"); | |
| 26 | 26 | const latestTurnCompletedAt = "2026-02-25T12:30:00.000Z"; |
| 27 | 27 | const initialState = makeUiState({ |
| 28 | 28 | threadLastVisitedAtById: { |
| ... | ... | @@ -36,7 +36,7 @@ describe("uiStateStore pure functions", () => { |
| 36 | 36 | }); |
| 37 | 37 | |
| 38 | 38 | it("markThreadUnread does not change a thread without a completed turn", () => { |
| 39 | const threadId = ThreadId.makeUnsafe("thread-1"); | |
| 39 | const threadId = ThreadId.make("thread-1"); | |
| 40 | 40 | const initialState = makeUiState({ |
| 41 | 41 | threadLastVisitedAtById: { |
| 42 | 42 | [threadId]: "2026-02-25T12:35:00.000Z", |
| ... | ... | @@ -49,9 +49,9 @@ describe("uiStateStore pure functions", () => { |
| 49 | 49 | }); |
| 50 | 50 | |
| 51 | 51 | it("reorderProjects moves a project to a target index", () => { |
| 52 | const project1 = ProjectId.makeUnsafe("project-1"); | |
| 53 | const project2 = ProjectId.makeUnsafe("project-2"); | |
| 54 | const project3 = ProjectId.makeUnsafe("project-3"); | |
| 52 | const project1 = ProjectId.make("project-1"); | |
| 53 | const project2 = ProjectId.make("project-2"); | |
| 54 | const project3 = ProjectId.make("project-3"); | |
| 55 | 55 | const initialState = makeUiState({ |
| 56 | 56 | projectOrder: [project1, project2, project3], |
| 57 | 57 | }); |
| ... | ... | @@ -62,9 +62,9 @@ describe("uiStateStore pure functions", () => { |
| 62 | 62 | }); |
| 63 | 63 | |
| 64 | 64 | it("syncProjects preserves current project order during snapshot recovery", () => { |
| 65 | const project1 = ProjectId.makeUnsafe("project-1"); | |
| 66 | const project2 = ProjectId.makeUnsafe("project-2"); | |
| 67 | const project3 = ProjectId.makeUnsafe("project-3"); | |
| 65 | const project1 = ProjectId.make("project-1"); | |
| 66 | const project2 = ProjectId.make("project-2"); | |
| 67 | const project3 = ProjectId.make("project-3"); | |
| 68 | 68 | const initialState = makeUiState({ |
| 69 | 69 | projectExpandedById: { |
| 70 | 70 | [project1]: true, |
| ... | ... | @@ -84,9 +84,9 @@ describe("uiStateStore pure functions", () => { |
| 84 | 84 | }); |
| 85 | 85 | |
| 86 | 86 | it("syncProjects preserves manual order when a project is recreated with the same cwd", () => { |
| 87 | const oldProject1 = ProjectId.makeUnsafe("project-1"); | |
| 88 | const oldProject2 = ProjectId.makeUnsafe("project-2"); | |
| 89 | const recreatedProject2 = ProjectId.makeUnsafe("project-2b"); | |
| 87 | const oldProject1 = ProjectId.make("project-1"); | |
| 88 | const oldProject2 = ProjectId.make("project-2"); | |
| 89 | const recreatedProject2 = ProjectId.make("project-2b"); | |
| 90 | 90 | const initialState = syncProjects( |
| 91 | 91 | makeUiState({ |
| 92 | 92 | projectExpandedById: { |
| ... | ... | @@ -111,7 +111,7 @@ describe("uiStateStore pure functions", () => { |
| 111 | 111 | }); |
| 112 | 112 | |
| 113 | 113 | it("syncProjects returns a new state when only project cwd changes", () => { |
| 114 | const project1 = ProjectId.makeUnsafe("project-1"); | |
| 114 | const project1 = ProjectId.make("project-1"); | |
| 115 | 115 | const initialState = syncProjects( |
| 116 | 116 | makeUiState({ |
| 117 | 117 | projectExpandedById: { |
| ... | ... | @@ -130,8 +130,8 @@ describe("uiStateStore pure functions", () => { |
| 130 | 130 | }); |
| 131 | 131 | |
| 132 | 132 | it("syncThreads prunes missing thread UI state", () => { |
| 133 | const thread1 = ThreadId.makeUnsafe("thread-1"); | |
| 134 | const thread2 = ThreadId.makeUnsafe("thread-2"); | |
| 133 | const thread1 = ThreadId.make("thread-1"); | |
| 134 | const thread2 = ThreadId.make("thread-2"); | |
| 135 | 135 | const initialState = makeUiState({ |
| 136 | 136 | threadLastVisitedAtById: { |
| 137 | 137 | [thread1]: "2026-02-25T12:35:00.000Z", |
| ... | ... | @@ -147,7 +147,7 @@ describe("uiStateStore pure functions", () => { |
| 147 | 147 | }); |
| 148 | 148 | |
| 149 | 149 | it("syncThreads seeds visit state for unseen snapshot threads", () => { |
| 150 | const thread1 = ThreadId.makeUnsafe("thread-1"); | |
| 150 | const thread1 = ThreadId.make("thread-1"); | |
| 151 | 151 | const initialState = makeUiState(); |
| 152 | 152 | |
| 153 | 153 | const next = syncThreads(initialState, [ |
| ... | ... | @@ -163,7 +163,7 @@ describe("uiStateStore pure functions", () => { |
| 163 | 163 | }); |
| 164 | 164 | |
| 165 | 165 | it("setProjectExpanded updates expansion without touching order", () => { |
| 166 | const project1 = ProjectId.makeUnsafe("project-1"); | |
| 166 | const project1 = ProjectId.make("project-1"); | |
| 167 | 167 | const initialState = makeUiState({ |
| 168 | 168 | projectExpandedById: { |
| 169 | 169 | [project1]: true, |
| ... | ... | @@ -178,7 +178,7 @@ describe("uiStateStore pure functions", () => { |
| 178 | 178 | }); |
| 179 | 179 | |
| 180 | 180 | it("clearThreadUi removes visit state for deleted threads", () => { |
| 181 | const thread1 = ThreadId.makeUnsafe("thread-1"); | |
| 181 | const thread1 = ThreadId.make("thread-1"); | |
| 182 | 182 | const initialState = makeUiState({ |
| 183 | 183 | threadLastVisitedAtById: { |
| 184 | 184 | [thread1]: "2026-02-25T12:35:00.000Z", |
apps/web/src/worktreeCleanup.test.ts+12-12| ... | ... | @@ -4,14 +4,14 @@ import { describe, expect, it } from "vitest"; |
| 4 | 4 | import { DEFAULT_INTERACTION_MODE, DEFAULT_RUNTIME_MODE, type Thread } from "./types"; |
| 5 | 5 | import { formatWorktreePathForDisplay, getOrphanedWorktreePathForThread } from "./worktreeCleanup"; |
| 6 | 6 | |
| 7 | const localEnvironmentId = EnvironmentId.makeUnsafe("environment-local"); | |
| 7 | const localEnvironmentId = EnvironmentId.make("environment-local"); | |
| 8 | 8 | |
| 9 | 9 | function makeThread(overrides: Partial<Thread> = {}): Thread { |
| 10 | 10 | return { |
| 11 | id: ThreadId.makeUnsafe("thread-1"), | |
| 11 | id: ThreadId.make("thread-1"), | |
| 12 | 12 | environmentId: localEnvironmentId, |
| 13 | 13 | codexThreadId: null, |
| 14 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 14 | projectId: ProjectId.make("project-1"), | |
| 15 | 15 | title: "Thread", |
| 16 | 16 | modelSelection: { |
| 17 | 17 | provider: "codex", |
| ... | ... | @@ -36,49 +36,49 @@ function makeThread(overrides: Partial<Thread> = {}): Thread { |
| 36 | 36 | |
| 37 | 37 | describe("getOrphanedWorktreePathForThread", () => { |
| 38 | 38 | it("returns null when the target thread does not exist", () => { |
| 39 | const result = getOrphanedWorktreePathForThread([], ThreadId.makeUnsafe("missing-thread")); | |
| 39 | const result = getOrphanedWorktreePathForThread([], ThreadId.make("missing-thread")); | |
| 40 | 40 | expect(result).toBeNull(); |
| 41 | 41 | }); |
| 42 | 42 | |
| 43 | 43 | it("returns null when the target thread has no worktree", () => { |
| 44 | 44 | const threads = [makeThread()]; |
| 45 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1")); | |
| 45 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1")); | |
| 46 | 46 | expect(result).toBeNull(); |
| 47 | 47 | }); |
| 48 | 48 | |
| 49 | 49 | it("returns the path when no other thread links to that worktree", () => { |
| 50 | 50 | const threads = [makeThread({ worktreePath: "/tmp/repo/worktrees/feature-a" })]; |
| 51 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1")); | |
| 51 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1")); | |
| 52 | 52 | expect(result).toBe("/tmp/repo/worktrees/feature-a"); |
| 53 | 53 | }); |
| 54 | 54 | |
| 55 | 55 | it("returns null when another thread links to the same worktree", () => { |
| 56 | 56 | const threads = [ |
| 57 | 57 | makeThread({ |
| 58 | id: ThreadId.makeUnsafe("thread-1"), | |
| 58 | id: ThreadId.make("thread-1"), | |
| 59 | 59 | worktreePath: "/tmp/repo/worktrees/feature-a", |
| 60 | 60 | }), |
| 61 | 61 | makeThread({ |
| 62 | id: ThreadId.makeUnsafe("thread-2"), | |
| 62 | id: ThreadId.make("thread-2"), | |
| 63 | 63 | worktreePath: "/tmp/repo/worktrees/feature-a", |
| 64 | 64 | }), |
| 65 | 65 | ]; |
| 66 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1")); | |
| 66 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1")); | |
| 67 | 67 | expect(result).toBeNull(); |
| 68 | 68 | }); |
| 69 | 69 | |
| 70 | 70 | it("ignores threads linked to different worktrees", () => { |
| 71 | 71 | const threads = [ |
| 72 | 72 | makeThread({ |
| 73 | id: ThreadId.makeUnsafe("thread-1"), | |
| 73 | id: ThreadId.make("thread-1"), | |
| 74 | 74 | worktreePath: "/tmp/repo/worktrees/feature-a", |
| 75 | 75 | }), |
| 76 | 76 | makeThread({ |
| 77 | id: ThreadId.makeUnsafe("thread-2"), | |
| 77 | id: ThreadId.make("thread-2"), | |
| 78 | 78 | worktreePath: "/tmp/repo/worktrees/feature-b", |
| 79 | 79 | }), |
| 80 | 80 | ]; |
| 81 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.makeUnsafe("thread-1")); | |
| 81 | const result = getOrphanedWorktreePathForThread(threads, ThreadId.make("thread-1")); | |
| 82 | 82 | expect(result).toBe("/tmp/repo/worktrees/feature-a"); |
| 83 | 83 | }); |
| 84 | 84 | }); |
apps/web/test/authHttpHandlers.ts+1-1| ... | ... | @@ -7,7 +7,7 @@ import { HttpResponse, http } from "msw"; |
| 7 | 7 | |
| 8 | 8 | const TEST_SESSION_EXPIRES_AT = "2026-05-01T12:00:00.000Z"; |
| 9 | 9 | const TEST_ENVIRONMENT_DESCRIPTOR: ExecutionEnvironmentDescriptor = { |
| 10 | environmentId: EnvironmentId.makeUnsafe("environment-local"), | |
| 10 | environmentId: EnvironmentId.make("environment-local"), | |
| 11 | 11 | label: "Local environment", |
| 12 | 12 | platform: { |
| 13 | 13 | os: "darwin", |
bun.lock+14-14| ... | ... | @@ -189,16 +189,16 @@ |
| 189 | 189 | "vite": "^8.0.0", |
| 190 | 190 | }, |
| 191 | 191 | "catalog": { |
| 192 | "@effect/atom-react": "4.0.0-beta.43", | |
| 192 | "@effect/atom-react": "4.0.0-beta.45", | |
| 193 | 193 | "@effect/language-service": "0.84.2", |
| 194 | "@effect/platform-bun": "4.0.0-beta.43", | |
| 195 | "@effect/platform-node": "4.0.0-beta.43", | |
| 196 | "@effect/platform-node-shared": "4.0.0-beta.43", | |
| 197 | "@effect/sql-sqlite-bun": "4.0.0-beta.43", | |
| 198 | "@effect/vitest": "4.0.0-beta.43", | |
| 194 | "@effect/platform-bun": "4.0.0-beta.45", | |
| 195 | "@effect/platform-node": "4.0.0-beta.45", | |
| 196 | "@effect/platform-node-shared": "4.0.0-beta.45", | |
| 197 | "@effect/sql-sqlite-bun": "4.0.0-beta.45", | |
| 198 | "@effect/vitest": "4.0.0-beta.45", | |
| 199 | 199 | "@types/bun": "^1.3.9", |
| 200 | 200 | "@types/node": "^24.10.13", |
| 201 | "effect": "4.0.0-beta.43", | |
| 201 | "effect": "4.0.0-beta.45", | |
| 202 | 202 | "tsdown": "^0.20.3", |
| 203 | 203 | "typescript": "^5.7.3", |
| 204 | 204 | "vitest": "^4.0.0", |
| ... | ... | @@ -284,19 +284,19 @@ |
| 284 | 284 | |
| 285 | 285 | "@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="], |
| 286 | 286 | |
| 287 | "@effect/atom-react": ["@effect/atom-react@4.0.0-beta.43", "", { "peerDependencies": { "effect": "^4.0.0-beta.43", "react": "^19.2.4", "scheduler": "*" } }, "sha512-xSrRbGXuo4d0g4ph66TQST1GNSjtQZrZj8V7OiAQFuzMYcZ0kwRIPUUFwOBtbWHK43/zNENdNWOnlXh/iYM1dw=="], | |
| 287 | "@effect/atom-react": ["@effect/atom-react@4.0.0-beta.45", "", { "peerDependencies": { "effect": "^4.0.0-beta.45", "react": "^19.2.4", "scheduler": "*" } }, "sha512-jCoiae9UNeis9Yoal1p5V/P4eJK9nX89wORom7X5LpR2Ok920SZJc8dIeYkRXRAp9BCYJ/yWcO8gGLf7do71vg=="], | |
| 288 | 288 | |
| 289 | 289 | "@effect/language-service": ["@effect/language-service@0.84.2", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-l04qNxpiA8rY5yXWckRPJ7Mk5MNerXuNymSFf+IdflfI5i8jgL1bpBNLuP6ijg7wgjdHc/KmTnCj2kT0SCntuA=="], |
| 290 | 290 | |
| 291 | "@effect/platform-bun": ["@effect/platform-bun@4.0.0-beta.43", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.43" }, "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-nMZ9JsD6CzJNQ+5pDUFbPw7PSZdQdTQ092MbYrocVtvlf6qEFU/hji3ITvRIOX7eabyQ8AUyp55qFPQUeq+GIA=="], | |
| 291 | "@effect/platform-bun": ["@effect/platform-bun@4.0.0-beta.45", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.45" }, "peerDependencies": { "effect": "^4.0.0-beta.45" } }, "sha512-dZsbkJ+o4JfKE1OIAlMq8YWhmEfXxtTYennYADK/M/XlOtkFLsc2jkZppDvMznVni6JpFxWc7wd5rUf8jBVP5g=="], | |
| 292 | 292 | |
| 293 | "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.43", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.43", "mime": "^4.1.0", "undici": "^7.24.0" }, "peerDependencies": { "effect": "^4.0.0-beta.43", "ioredis": "^5.7.0" } }, "sha512-Uq6E1rjaIpjHauzjwoB2HzAg3battYt2Boy8XO50GoHiWCXKE6WapYZ0/AnaBx5v5qg2sOfqpuiLsUf9ZgxOkA=="], | |
| 293 | "@effect/platform-node": ["@effect/platform-node@4.0.0-beta.45", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-beta.45", "mime": "^4.1.0", "undici": "^7.24.0" }, "peerDependencies": { "effect": "^4.0.0-beta.45", "ioredis": "^5.7.0" } }, "sha512-P07NMG4eoy62iLX9szak0hkr7hrwgq5+XMkm7URVug/3zqfZVxEG2kxn9JzVK1lF5WbaVrEKwjt3IkEJxzSPtg=="], | |
| 294 | 294 | |
| 295 | "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.43", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-A9q0GEb61pYcQ06Dr6gXj1nKlDI3KHsar1sk3qb1ZY+kVSR64tBAylI8zGon23KY+NPtTUj/sEIToB7jc3Qt5w=="], | |
| 295 | "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-beta.45", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.19.0" }, "peerDependencies": { "effect": "^4.0.0-beta.45" } }, "sha512-0T4RG18o+aCVUSlmPxA7uAjHJkyE3MS/uRrR5kCNSZQNG3X71wdIbu82wE/MnV6+6YSSPDx/6TVdZWYkJF0JWw=="], | |
| 296 | 296 | |
| 297 | "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.43", "", { "peerDependencies": { "effect": "^4.0.0-beta.43" } }, "sha512-Ryb7x0rBjW5NHegbzvz9y2Yv4KpwZ1UiPk7/Rv+Mkux74Qkjdmotmrvy9P+M5A9TZyL2Av+GpaLTPJKsL0PG+Q=="], | |
| 297 | "@effect/sql-sqlite-bun": ["@effect/sql-sqlite-bun@4.0.0-beta.45", "", { "peerDependencies": { "effect": "^4.0.0-beta.45" } }, "sha512-sJBBztwI4YxjdjhdyjWelh3KKoZucmmZS2ONeNDIzYgqFlsrwEEUrhVkWf5ch9Io+kUUzeb6q7/SedFoLUWO7g=="], | |
| 298 | 298 | |
| 299 | "@effect/vitest": ["@effect/vitest@4.0.0-beta.43", "", { "peerDependencies": { "effect": "^4.0.0-beta.43", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-XN2LAwiUWPqbV2jrsYYRjrVydQ8MIgwr83MVImtUaOQco4vk43+8OHlXQMRN/u2HnGK29KT+O2yTMMBdk2Q6Sw=="], | |
| 299 | "@effect/vitest": ["@effect/vitest@4.0.0-beta.45", "", { "peerDependencies": { "effect": "^4.0.0-beta.45", "vitest": "^3.0.0 || ^4.0.0" } }, "sha512-38JA5Z6c2FoEhpVKbl7rjTrMU8Al5T30Kwtb6N3B9kOkyr2SsmvNsP9T65bh03IBh3ak9U//acrkmjS3hLQwKA=="], | |
| 300 | 300 | |
| 301 | 301 | "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="], |
| 302 | 302 | |
| ... | ... | @@ -1018,7 +1018,7 @@ |
| 1018 | 1018 | |
| 1019 | 1019 | "dts-resolver": ["dts-resolver@2.1.3", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw=="], |
| 1020 | 1020 | |
| 1021 | "effect": ["effect@4.0.0-beta.43", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ=="], | |
| 1021 | "effect": ["effect@4.0.0-beta.45", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-vvNrUWqnzBIW1hRMa+zw0CLRW6HLgdu7hQ6K7PT/rS+UY/73Ma11O+Oi9oc9zwL8KcN37M47UDseAdlF0bGNWw=="], | |
| 1022 | 1022 | |
| 1023 | 1023 | "electron": ["electron@40.6.0", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-ett8W+yOFGDuM0vhJMamYSkrbV3LoaffzJd9GfjI96zRAxyrNqUSKqBpf/WGbQCweDxX2pkUCUfrv4wwKpsFZA=="], |
| 1024 | 1024 |
package.json+7-7| ... | ... | @@ -8,13 +8,13 @@ |
| 8 | 8 | "scripts" |
| 9 | 9 | ], |
| 10 | 10 | "catalog": { |
| 11 | "effect": "4.0.0-beta.43", | |
| 12 | "@effect/atom-react": "4.0.0-beta.43", | |
| 13 | "@effect/platform-bun": "4.0.0-beta.43", | |
| 14 | "@effect/platform-node": "4.0.0-beta.43", | |
| 15 | "@effect/platform-node-shared": "4.0.0-beta.43", | |
| 16 | "@effect/sql-sqlite-bun": "4.0.0-beta.43", | |
| 17 | "@effect/vitest": "4.0.0-beta.43", | |
| 11 | "effect": "4.0.0-beta.45", | |
| 12 | "@effect/atom-react": "4.0.0-beta.45", | |
| 13 | "@effect/platform-bun": "4.0.0-beta.45", | |
| 14 | "@effect/platform-node": "4.0.0-beta.45", | |
| 15 | "@effect/platform-node-shared": "4.0.0-beta.45", | |
| 16 | "@effect/sql-sqlite-bun": "4.0.0-beta.45", | |
| 17 | "@effect/vitest": "4.0.0-beta.45", | |
| 18 | 18 | "@effect/language-service": "0.84.2", |
| 19 | 19 | "@types/bun": "^1.3.9", |
| 20 | 20 | "@types/node": "^24.10.13", |
packages/client-runtime/src/knownEnvironment.test.ts+5-5| ... | ... | @@ -61,9 +61,9 @@ describe("known environment bootstrap helpers", () => { |
| 61 | 61 | }); |
| 62 | 62 | |
| 63 | 63 | describe("scoped refs", () => { |
| 64 | const environmentId = EnvironmentId.makeUnsafe("environment-test"); | |
| 65 | const projectRef = scopeProjectRef(environmentId, ProjectId.makeUnsafe("project-1")); | |
| 66 | const threadRef = scopeThreadRef(environmentId, ThreadId.makeUnsafe("thread-1")); | |
| 64 | const environmentId = EnvironmentId.make("environment-test"); | |
| 65 | const projectRef = scopeProjectRef(environmentId, ProjectId.make("project-1")); | |
| 66 | const threadRef = scopeThreadRef(environmentId, ThreadId.make("thread-1")); | |
| 67 | 67 | |
| 68 | 68 | it("builds stable scoped project and thread keys", () => { |
| 69 | 69 | expect(scopedRefKey(projectRef)).toBe("environment-test:project-1"); |
| ... | ... | @@ -75,11 +75,11 @@ describe("scoped refs", () => { |
| 75 | 75 | it("returns typed scoped refs", () => { |
| 76 | 76 | expect(projectRef).toEqual({ |
| 77 | 77 | environmentId, |
| 78 | projectId: ProjectId.makeUnsafe("project-1"), | |
| 78 | projectId: ProjectId.make("project-1"), | |
| 79 | 79 | }); |
| 80 | 80 | expect(threadRef).toEqual({ |
| 81 | 81 | environmentId, |
| 82 | threadId: ThreadId.makeUnsafe("thread-1"), | |
| 82 | threadId: ThreadId.make("thread-1"), | |
| 83 | 83 | }); |
| 84 | 84 | }); |
| 85 | 85 |
packages/contracts/src/baseSchemas.ts+3-2| ... | ... | @@ -12,8 +12,9 @@ export type IsoDateTime = typeof IsoDateTime.Type; |
| 12 | 12 | /** |
| 13 | 13 | * Construct a branded identifier. Enforces non-empty trimmed strings |
| 14 | 14 | */ |
| 15 | const makeEntityId = <Brand extends string>(brand: Brand) => | |
| 16 | TrimmedNonEmptyString.pipe(Schema.brand(brand)); | |
| 15 | const makeEntityId = <Brand extends string>(brand: Brand) => { | |
| 16 | return TrimmedNonEmptyString.pipe(Schema.brand(brand)); | |
| 17 | }; | |
| 17 | 18 | |
| 18 | 19 | export const ThreadId = makeEntityId("ThreadId"); |
| 19 | 20 | export type ThreadId = typeof ThreadId.Type; |
packages/contracts/src/environment.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { Schema } from "effect"; | |
| 1 | import { Effect, Schema } from "effect"; | |
| 2 | 2 | |
| 3 | 3 | import { EnvironmentId, ProjectId, ThreadId, TrimmedNonEmptyString } from "./baseSchemas"; |
| 4 | 4 | |
| ... | ... | @@ -20,7 +20,7 @@ export const ExecutionEnvironmentPlatform = Schema.Struct({ |
| 20 | 20 | export type ExecutionEnvironmentPlatform = typeof ExecutionEnvironmentPlatform.Type; |
| 21 | 21 | |
| 22 | 22 | export const ExecutionEnvironmentCapabilities = Schema.Struct({ |
| 23 | repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)), | |
| 23 | repositoryIdentity: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), | |
| 24 | 24 | }); |
| 25 | 25 | export type ExecutionEnvironmentCapabilities = typeof ExecutionEnvironmentCapabilities.Type; |
| 26 | 26 |
packages/contracts/src/orchestration.ts+19-15| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { Option, Schema, SchemaIssue, Struct } from "effect"; | |
| 1 | import { Effect, Option, Schema, SchemaIssue, Struct } from "effect"; | |
| 2 | 2 | import { ClaudeModelOptions, CodexModelOptions } from "./model"; |
| 3 | 3 | import { RepositoryIdentity } from "./environment"; |
| 4 | 4 | import { |
| ... | ... | @@ -177,8 +177,10 @@ export const OrchestrationProposedPlan = Schema.Struct({ |
| 177 | 177 | id: OrchestrationProposedPlanId, |
| 178 | 178 | turnId: Schema.NullOr(TurnId), |
| 179 | 179 | planMarkdown: TrimmedNonEmptyString, |
| 180 | implementedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(() => null)), | |
| 181 | implementationThreadId: Schema.NullOr(ThreadId).pipe(Schema.withDecodingDefault(() => null)), | |
| 180 | implementedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))), | |
| 181 | implementationThreadId: Schema.NullOr(ThreadId).pipe( | |
| 182 | Schema.withDecodingDefault(Effect.succeed(null)), | |
| 183 | ), | |
| 182 | 184 | createdAt: IsoDateTime, |
| 183 | 185 | updatedAt: IsoDateTime, |
| 184 | 186 | }); |
| ... | ... | @@ -204,7 +206,7 @@ export const OrchestrationSession = Schema.Struct({ |
| 204 | 206 | threadId: ThreadId, |
| 205 | 207 | status: OrchestrationSessionStatus, |
| 206 | 208 | providerName: Schema.NullOr(TrimmedNonEmptyString), |
| 207 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)), | |
| 209 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), | |
| 208 | 210 | activeTurnId: Schema.NullOr(TurnId), |
| 209 | 211 | lastError: Schema.NullOr(TrimmedNonEmptyString), |
| 210 | 212 | updatedAt: IsoDateTime, |
| ... | ... | @@ -279,17 +281,19 @@ export const OrchestrationThread = Schema.Struct({ |
| 279 | 281 | modelSelection: ModelSelection, |
| 280 | 282 | runtimeMode: RuntimeMode, |
| 281 | 283 | interactionMode: ProviderInteractionMode.pipe( |
| 282 | Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE), | |
| 284 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)), | |
| 283 | 285 | ), |
| 284 | 286 | branch: Schema.NullOr(TrimmedNonEmptyString), |
| 285 | 287 | worktreePath: Schema.NullOr(TrimmedNonEmptyString), |
| 286 | 288 | latestTurn: Schema.NullOr(OrchestrationLatestTurn), |
| 287 | 289 | createdAt: IsoDateTime, |
| 288 | 290 | updatedAt: IsoDateTime, |
| 289 | archivedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(() => null)), | |
| 291 | archivedAt: Schema.NullOr(IsoDateTime).pipe(Schema.withDecodingDefault(Effect.succeed(null))), | |
| 290 | 292 | deletedAt: Schema.NullOr(IsoDateTime), |
| 291 | 293 | messages: Schema.Array(OrchestrationMessage), |
| 292 | proposedPlans: Schema.Array(OrchestrationProposedPlan).pipe(Schema.withDecodingDefault(() => [])), | |
| 294 | proposedPlans: Schema.Array(OrchestrationProposedPlan).pipe( | |
| 295 | Schema.withDecodingDefault(Effect.succeed([])), | |
| 296 | ), | |
| 293 | 297 | activities: Schema.Array(OrchestrationThreadActivity), |
| 294 | 298 | checkpoints: Schema.Array(OrchestrationCheckpointSummary), |
| 295 | 299 | session: Schema.NullOr(OrchestrationSession), |
| ... | ... | @@ -339,7 +343,7 @@ const ThreadCreateCommand = Schema.Struct({ |
| 339 | 343 | modelSelection: ModelSelection, |
| 340 | 344 | runtimeMode: RuntimeMode, |
| 341 | 345 | interactionMode: ProviderInteractionMode.pipe( |
| 342 | Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE), | |
| 346 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)), | |
| 343 | 347 | ), |
| 344 | 348 | branch: Schema.NullOr(TrimmedNonEmptyString), |
| 345 | 349 | worktreePath: Schema.NullOr(TrimmedNonEmptyString), |
| ... | ... | @@ -427,9 +431,9 @@ export const ThreadTurnStartCommand = Schema.Struct({ |
| 427 | 431 | }), |
| 428 | 432 | modelSelection: Schema.optional(ModelSelection), |
| 429 | 433 | titleSeed: Schema.optional(TrimmedNonEmptyString), |
| 430 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)), | |
| 434 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), | |
| 431 | 435 | interactionMode: ProviderInteractionMode.pipe( |
| 432 | Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE), | |
| 436 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)), | |
| 433 | 437 | ), |
| 434 | 438 | bootstrap: Schema.optional(ThreadTurnStartBootstrap), |
| 435 | 439 | sourceProposedPlan: Schema.optional(SourceProposedPlanReference), |
| ... | ... | @@ -680,9 +684,9 @@ export const ThreadCreatedPayload = Schema.Struct({ |
| 680 | 684 | projectId: ProjectId, |
| 681 | 685 | title: TrimmedNonEmptyString, |
| 682 | 686 | modelSelection: ModelSelection, |
| 683 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)), | |
| 687 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), | |
| 684 | 688 | interactionMode: ProviderInteractionMode.pipe( |
| 685 | Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE), | |
| 689 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)), | |
| 686 | 690 | ), |
| 687 | 691 | branch: Schema.NullOr(TrimmedNonEmptyString), |
| 688 | 692 | worktreePath: Schema.NullOr(TrimmedNonEmptyString), |
| ... | ... | @@ -724,7 +728,7 @@ export const ThreadRuntimeModeSetPayload = Schema.Struct({ |
| 724 | 728 | export const ThreadInteractionModeSetPayload = Schema.Struct({ |
| 725 | 729 | threadId: ThreadId, |
| 726 | 730 | interactionMode: ProviderInteractionMode.pipe( |
| 727 | Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE), | |
| 731 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)), | |
| 728 | 732 | ), |
| 729 | 733 | updatedAt: IsoDateTime, |
| 730 | 734 | }); |
| ... | ... | @@ -746,9 +750,9 @@ export const ThreadTurnStartRequestedPayload = Schema.Struct({ |
| 746 | 750 | messageId: MessageId, |
| 747 | 751 | modelSelection: Schema.optional(ModelSelection), |
| 748 | 752 | titleSeed: Schema.optional(TrimmedNonEmptyString), |
| 749 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(() => DEFAULT_RUNTIME_MODE)), | |
| 753 | runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), | |
| 750 | 754 | interactionMode: ProviderInteractionMode.pipe( |
| 751 | Schema.withDecodingDefault(() => DEFAULT_PROVIDER_INTERACTION_MODE), | |
| 755 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_PROVIDER_INTERACTION_MODE)), | |
| 752 | 756 | ), |
| 753 | 757 | sourceProposedPlan: Schema.optional(SourceProposedPlanReference), |
| 754 | 758 | createdAt: IsoDateTime, |
packages/contracts/src/providerRuntime.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { Option, Schema } from "effect"; | |
| 1 | import { Effect, Schema } from "effect"; | |
| 2 | 2 | import { |
| 3 | 3 | EventId, |
| 4 | 4 | IsoDateTime, |
| ... | ... | @@ -435,7 +435,7 @@ export const UserInputQuestion = Schema.Struct({ |
| 435 | 435 | question: TrimmedNonEmptyStringSchema, |
| 436 | 436 | options: Schema.Array(UserInputQuestionOption), |
| 437 | 437 | multiSelect: Schema.optional(Schema.Boolean).pipe( |
| 438 | Schema.withConstructorDefault(() => Option.some(false)), | |
| 438 | Schema.withConstructorDefault(Effect.succeed(false)), | |
| 439 | 439 | ), |
| 440 | 440 | }); |
| 441 | 441 | export type UserInputQuestion = typeof UserInputQuestion.Type; |
packages/contracts/src/settings.ts+28-24| ... | ... | @@ -24,16 +24,18 @@ export type SidebarThreadSortOrder = typeof SidebarThreadSortOrder.Type; |
| 24 | 24 | export const DEFAULT_SIDEBAR_THREAD_SORT_ORDER: SidebarThreadSortOrder = "updated_at"; |
| 25 | 25 | |
| 26 | 26 | export const ClientSettingsSchema = Schema.Struct({ |
| 27 | confirmThreadArchive: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)), | |
| 28 | confirmThreadDelete: Schema.Boolean.pipe(Schema.withDecodingDefault(() => true)), | |
| 29 | diffWordWrap: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)), | |
| 27 | confirmThreadArchive: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), | |
| 28 | confirmThreadDelete: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), | |
| 29 | diffWordWrap: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), | |
| 30 | 30 | sidebarProjectSortOrder: SidebarProjectSortOrder.pipe( |
| 31 | Schema.withDecodingDefault(() => DEFAULT_SIDEBAR_PROJECT_SORT_ORDER), | |
| 31 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_PROJECT_SORT_ORDER)), | |
| 32 | 32 | ), |
| 33 | 33 | sidebarThreadSortOrder: SidebarThreadSortOrder.pipe( |
| 34 | Schema.withDecodingDefault(() => DEFAULT_SIDEBAR_THREAD_SORT_ORDER), | |
| 34 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_THREAD_SORT_ORDER)), | |
| 35 | ), | |
| 36 | timestampFormat: TimestampFormat.pipe( | |
| 37 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_TIMESTAMP_FORMAT)), | |
| 35 | 38 | ), |
| 36 | timestampFormat: TimestampFormat.pipe(Schema.withDecodingDefault(() => DEFAULT_TIMESTAMP_FORMAT)), | |
| 37 | 39 | }); |
| 38 | 40 | export type ClientSettings = typeof ClientSettingsSchema.Type; |
| 39 | 41 | |
| ... | ... | @@ -53,48 +55,50 @@ const makeBinaryPathSetting = (fallback: string) => |
| 53 | 55 | encode: (value) => Effect.succeed(value), |
| 54 | 56 | }), |
| 55 | 57 | ), |
| 56 | Schema.withDecodingDefault(() => fallback), | |
| 58 | Schema.withDecodingDefault(Effect.succeed(fallback)), | |
| 57 | 59 | ); |
| 58 | 60 | |
| 59 | 61 | export const CodexSettings = Schema.Struct({ |
| 60 | enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(() => true)), | |
| 62 | enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), | |
| 61 | 63 | binaryPath: makeBinaryPathSetting("codex"), |
| 62 | homePath: TrimmedString.pipe(Schema.withDecodingDefault(() => "")), | |
| 63 | customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(() => [])), | |
| 64 | homePath: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), | |
| 65 | customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(Effect.succeed([]))), | |
| 64 | 66 | }); |
| 65 | 67 | export type CodexSettings = typeof CodexSettings.Type; |
| 66 | 68 | |
| 67 | 69 | export const ClaudeSettings = Schema.Struct({ |
| 68 | enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(() => true)), | |
| 70 | enabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), | |
| 69 | 71 | binaryPath: makeBinaryPathSetting("claude"), |
| 70 | customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(() => [])), | |
| 72 | customModels: Schema.Array(Schema.String).pipe(Schema.withDecodingDefault(Effect.succeed([]))), | |
| 71 | 73 | }); |
| 72 | 74 | export type ClaudeSettings = typeof ClaudeSettings.Type; |
| 73 | 75 | |
| 74 | 76 | export const ObservabilitySettings = Schema.Struct({ |
| 75 | otlpTracesUrl: TrimmedString.pipe(Schema.withDecodingDefault(() => "")), | |
| 76 | otlpMetricsUrl: TrimmedString.pipe(Schema.withDecodingDefault(() => "")), | |
| 77 | otlpTracesUrl: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), | |
| 78 | otlpMetricsUrl: TrimmedString.pipe(Schema.withDecodingDefault(Effect.succeed(""))), | |
| 77 | 79 | }); |
| 78 | 80 | export type ObservabilitySettings = typeof ObservabilitySettings.Type; |
| 79 | 81 | |
| 80 | 82 | export const ServerSettings = Schema.Struct({ |
| 81 | enableAssistantStreaming: Schema.Boolean.pipe(Schema.withDecodingDefault(() => false)), | |
| 83 | enableAssistantStreaming: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), | |
| 82 | 84 | defaultThreadEnvMode: ThreadEnvMode.pipe( |
| 83 | Schema.withDecodingDefault(() => "local" as const satisfies ThreadEnvMode), | |
| 85 | Schema.withDecodingDefault(Effect.succeed("local" as const satisfies ThreadEnvMode)), | |
| 84 | 86 | ), |
| 85 | 87 | textGenerationModelSelection: ModelSelection.pipe( |
| 86 | Schema.withDecodingDefault(() => ({ | |
| 87 | provider: "codex" as const, | |
| 88 | model: DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER.codex, | |
| 89 | })), | |
| 88 | Schema.withDecodingDefault( | |
| 89 | Effect.succeed({ | |
| 90 | provider: "codex" as const, | |
| 91 | model: DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER.codex, | |
| 92 | }), | |
| 93 | ), | |
| 90 | 94 | ), |
| 91 | 95 | |
| 92 | 96 | // Provider specific settings |
| 93 | 97 | providers: Schema.Struct({ |
| 94 | codex: CodexSettings.pipe(Schema.withDecodingDefault(() => ({}))), | |
| 95 | claudeAgent: ClaudeSettings.pipe(Schema.withDecodingDefault(() => ({}))), | |
| 96 | }).pipe(Schema.withDecodingDefault(() => ({}))), | |
| 97 | observability: ObservabilitySettings.pipe(Schema.withDecodingDefault(() => ({}))), | |
| 98 | codex: CodexSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), | |
| 99 | claudeAgent: ClaudeSettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), | |
| 100 | }).pipe(Schema.withDecodingDefault(Effect.succeed({}))), | |
| 101 | observability: ObservabilitySettings.pipe(Schema.withDecodingDefault(Effect.succeed({}))), | |
| 98 | 102 | }); |
| 99 | 103 | export type ServerSettings = typeof ServerSettings.Type; |
| 100 | 104 |
packages/contracts/src/terminal.ts+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | import { Schema } from "effect"; | |
| 1 | import { Effect, Schema } from "effect"; | |
| 2 | 2 | import { TrimmedNonEmptyString } from "./baseSchemas"; |
| 3 | 3 | |
| 4 | 4 | export const DEFAULT_TERMINAL_ID = "default"; |
| ... | ... | @@ -20,7 +20,7 @@ const TerminalEnvSchema = Schema.Record(TerminalEnvKeySchema, TerminalEnvValueSc |
| 20 | 20 | ); |
| 21 | 21 | |
| 22 | 22 | const TerminalIdWithDefaultSchema = TerminalIdSchema.pipe( |
| 23 | Schema.withDecodingDefault(() => DEFAULT_TERMINAL_ID), | |
| 23 | Schema.withDecodingDefault(Effect.succeed(DEFAULT_TERMINAL_ID)), | |
| 24 | 24 | ); |
| 25 | 25 | |
| 26 | 26 | export const TerminalThreadInput = Schema.Struct({ |
packages/shared/src/Net.ts+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | import * as Net from "node:net"; |
| 2 | 2 | |
| 3 | import { Data, Effect, Layer, ServiceMap } from "effect"; | |
| 3 | import { Data, Effect, Layer, Context } from "effect"; | |
| 4 | 4 | |
| 5 | 5 | export class NetError extends Data.TaggedError("NetError")<{ |
| 6 | 6 | readonly message: string; |
| ... | ... | @@ -85,7 +85,7 @@ export interface NetServiceShape { |
| 85 | 85 | /** |
| 86 | 86 | * NetService - Service tag for startup networking helpers. |
| 87 | 87 | */ |
| 88 | export class NetService extends ServiceMap.Service<NetService, NetServiceShape>()( | |
| 88 | export class NetService extends Context.Service<NetService, NetServiceShape>()( | |
| 89 | 89 | "@t3tools/shared/Net/NetService", |
| 90 | 90 | ) { |
| 91 | 91 | static readonly layer = Layer.sync(NetService, () => { |
scripts/build-desktop-artifact.test.ts created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | import * as NodeServices from "@effect/platform-node/NodeServices"; | |
| 2 | import { assert, it } from "@effect/vitest"; | |
| 3 | import { ConfigProvider, Effect, Option } from "effect"; | |
| 4 | ||
| 5 | import { resolveBuildOptions } from "./build-desktop-artifact.ts"; | |
| 6 | ||
| 7 | it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { | |
| 8 | it.effect("preserves explicit false boolean flags over true env defaults", () => | |
| 9 | Effect.gen(function* () { | |
| 10 | const resolved = yield* resolveBuildOptions({ | |
| 11 | platform: Option.some("mac"), | |
| 12 | target: Option.none(), | |
| 13 | arch: Option.some("arm64"), | |
| 14 | buildVersion: Option.none(), | |
| 15 | outputDir: Option.some("release-test"), | |
| 16 | skipBuild: Option.some(false), | |
| 17 | keepStage: Option.some(false), | |
| 18 | signed: Option.some(false), | |
| 19 | verbose: Option.some(false), | |
| 20 | mockUpdates: Option.some(false), | |
| 21 | mockUpdateServerPort: Option.none(), | |
| 22 | }).pipe( | |
| 23 | Effect.provide( | |
| 24 | ConfigProvider.layer( | |
| 25 | ConfigProvider.fromEnv({ | |
| 26 | env: { | |
| 27 | T3CODE_DESKTOP_SKIP_BUILD: "true", | |
| 28 | T3CODE_DESKTOP_KEEP_STAGE: "true", | |
| 29 | T3CODE_DESKTOP_SIGNED: "true", | |
| 30 | T3CODE_DESKTOP_VERBOSE: "true", | |
| 31 | T3CODE_DESKTOP_MOCK_UPDATES: "true", | |
| 32 | }, | |
| 33 | }), | |
| 34 | ), | |
| 35 | ), | |
| 36 | ); | |
| 37 | ||
| 38 | assert.equal(resolved.skipBuild, false); | |
| 39 | assert.equal(resolved.keepStage, false); | |
| 40 | assert.equal(resolved.signed, false); | |
| 41 | assert.equal(resolved.verbose, false); | |
| 42 | assert.equal(resolved.mockUpdates, false); | |
| 43 | }), | |
| 44 | ); | |
| 45 | }); |
scripts/build-desktop-artifact.ts+11-7| ... | ... | @@ -214,11 +214,13 @@ const BuildEnvConfig = Config.all({ |
| 214 | 214 | }); |
| 215 | 215 | |
| 216 | 216 | const resolveBooleanFlag = (flag: Option.Option<boolean>, envValue: boolean) => |
| 217 | Option.getOrElse(Option.filter(flag, Boolean), () => envValue); | |
| 217 | Option.getOrElse(flag, () => envValue); | |
| 218 | 218 | const mergeOptions = <A>(a: Option.Option<A>, b: Option.Option<A>, defaultValue: A) => |
| 219 | 219 | Option.getOrElse(a, () => Option.getOrElse(b, () => defaultValue)); |
| 220 | 220 | |
| 221 | const resolveBuildOptions = Effect.fn("resolveBuildOptions")(function* (input: BuildCliInput) { | |
| 221 | export const resolveBuildOptions = Effect.fn("resolveBuildOptions")(function* ( | |
| 222 | input: BuildCliInput, | |
| 223 | ) { | |
| 222 | 224 | const path = yield* Path.Path; |
| 223 | 225 | const repoRoot = yield* RepoRoot; |
| 224 | 226 | const env = yield* BuildEnvConfig.asEffect(); |
| ... | ... | @@ -838,8 +840,10 @@ const buildDesktopArtifactCli = Command.make("build-desktop-artifact", { |
| 838 | 840 | |
| 839 | 841 | const cliRuntimeLayer = Layer.mergeAll(Logger.layer([Logger.consolePretty()]), NodeServices.layer); |
| 840 | 842 | |
| 841 | Command.run(buildDesktopArtifactCli, { version: "0.0.0" }).pipe( | |
| 842 | Effect.scoped, | |
| 843 | Effect.provide(cliRuntimeLayer), | |
| 844 | NodeRuntime.runMain, | |
| 845 | ); | |
| 843 | if (import.meta.main) { | |
| 844 | Command.run(buildDesktopArtifactCli, { version: "0.0.0" }).pipe( | |
| 845 | Effect.scoped, | |
| 846 | Effect.provide(cliRuntimeLayer), | |
| 847 | NodeRuntime.runMain, | |
| 848 | ); | |
| 849 | } |
scripts/dev-runner.test.ts+3-1| ... | ... | @@ -121,7 +121,9 @@ it.layer(NodeServices.layer)("dev-runner", (it) => { |
| 121 | 121 | Effect.gen(function* () { |
| 122 | 122 | const env = yield* createDevRunnerEnv({ |
| 123 | 123 | mode: "dev", |
| 124 | baseEnv: {}, | |
| 124 | baseEnv: { | |
| 125 | T3CODE_LOG_WS_EVENTS: "1", | |
| 126 | }, | |
| 125 | 127 | serverOffset: 0, |
| 126 | 128 | webOffset: 0, |
| 127 | 129 | t3Home: undefined, |
scripts/dev-runner.ts+3-44| ... | ... | @@ -356,35 +356,6 @@ interface DevRunnerCliInput { |
| 356 | 356 | readonly turboArgs: ReadonlyArray<string>; |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | const readOptionalBooleanEnv = (name: string): boolean | undefined => { | |
| 360 | const value = process.env[name]; | |
| 361 | if (value === undefined) { | |
| 362 | return undefined; | |
| 363 | } | |
| 364 | if (value === "1" || value.toLowerCase() === "true") { | |
| 365 | return true; | |
| 366 | } | |
| 367 | if (value === "0" || value.toLowerCase() === "false") { | |
| 368 | return false; | |
| 369 | } | |
| 370 | return undefined; | |
| 371 | }; | |
| 372 | ||
| 373 | const resolveOptionalBooleanOverride = ( | |
| 374 | explicitValue: boolean | undefined, | |
| 375 | envValue: boolean | undefined, | |
| 376 | ): boolean | undefined => { | |
| 377 | if (explicitValue === true) { | |
| 378 | return true; | |
| 379 | } | |
| 380 | ||
| 381 | if (explicitValue === false) { | |
| 382 | return envValue; | |
| 383 | } | |
| 384 | ||
| 385 | return envValue; | |
| 386 | }; | |
| 387 | ||
| 388 | 359 | export function runDevRunnerWithInput(input: DevRunnerCliInput) { |
| 389 | 360 | return Effect.gen(function* () { |
| 390 | 361 | const { portOffset, devInstance } = yield* OffsetConfig.asEffect().pipe( |
| ... | ... | @@ -406,12 +377,6 @@ export function runDevRunnerWithInput(input: DevRunnerCliInput) { |
| 406 | 377 | }), |
| 407 | 378 | }); |
| 408 | 379 | |
| 409 | const envOverrides = { | |
| 410 | noBrowser: readOptionalBooleanEnv("T3CODE_NO_BROWSER"), | |
| 411 | autoBootstrapProjectFromCwd: readOptionalBooleanEnv("T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD"), | |
| 412 | logWebSocketEvents: readOptionalBooleanEnv("T3CODE_LOG_WS_EVENTS"), | |
| 413 | }; | |
| 414 | ||
| 415 | 380 | const { serverOffset, webOffset } = yield* resolveModePortOffsets({ |
| 416 | 381 | mode: input.mode, |
| 417 | 382 | startOffset: offset, |
| ... | ... | @@ -425,15 +390,9 @@ export function runDevRunnerWithInput(input: DevRunnerCliInput) { |
| 425 | 390 | serverOffset, |
| 426 | 391 | webOffset, |
| 427 | 392 | t3Home: input.t3Home, |
| 428 | noBrowser: resolveOptionalBooleanOverride(input.noBrowser, envOverrides.noBrowser), | |
| 429 | autoBootstrapProjectFromCwd: resolveOptionalBooleanOverride( | |
| 430 | input.autoBootstrapProjectFromCwd, | |
| 431 | envOverrides.autoBootstrapProjectFromCwd, | |
| 432 | ), | |
| 433 | logWebSocketEvents: resolveOptionalBooleanOverride( | |
| 434 | input.logWebSocketEvents, | |
| 435 | envOverrides.logWebSocketEvents, | |
| 436 | ), | |
| 393 | noBrowser: input.noBrowser, | |
| 394 | autoBootstrapProjectFromCwd: input.autoBootstrapProjectFromCwd, | |
| 395 | logWebSocketEvents: input.logWebSocketEvents, | |
| 437 | 396 | host: input.host, |
| 438 | 397 | port: input.port, |
| 439 | 398 | devUrl: input.devUrl, |