| ... | @@ -38,7 +38,7 @@ import type { | ... | @@ -38,7 +38,7 @@ import type { |
| 38 | TerminalWriteInput, | 38 | TerminalWriteInput, |
| 39 | } from "@t3tools/contracts"; | 39 | } from "@t3tools/contracts"; |
| 40 | import { TerminalManager, type TerminalManagerShape } from "./terminal/Services/Manager"; | 40 | import { TerminalManager, type TerminalManagerShape } from "./terminal/Services/Manager"; |
| 41 | import { SqlitePersistenceMemory } from "./persistence/Layers/Sqlite"; | 41 | import { makeSqlitePersistenceLive, SqlitePersistenceMemory } from "./persistence/Layers/Sqlite"; |
| 42 | import { SqlClient } from "effect/unstable/sql"; | 42 | import { SqlClient } from "effect/unstable/sql"; |
| 43 | import { ProviderService, type ProviderServiceShape } from "./provider/Services/ProviderService"; | 43 | import { ProviderService, type ProviderServiceShape } from "./provider/Services/ProviderService"; |
| 44 | import { Open, type OpenShape } from "./open"; | 44 | import { Open, type OpenShape } from "./open"; |
| ... | @@ -506,6 +506,61 @@ describe("WebSocket Server", () => { | ... | @@ -506,6 +506,61 @@ describe("WebSocket Server", () => { |
| 506 | ); | 506 | ); |
| 507 | }); | 507 | }); |
| 508 | | 508 | |
| | 509 | it("includes bootstrap ids in welcome when cwd project and thread already exist", async () => { |
| | 510 | const stateDir = makeTempDir("t3code-state-bootstrap-existing-"); |
| | 511 | const persistenceLayer = makeSqlitePersistenceLive( |
| | 512 | path.join(stateDir, "state.sqlite"), |
| | 513 | ) as unknown as Layer.Layer<SqlClient.SqlClient, never>; |
| | 514 | const cwd = "/test/bootstrap-existing"; |
| | 515 | |
| | 516 | server = await createTestServer({ |
| | 517 | cwd, |
| | 518 | stateDir, |
| | 519 | persistenceLayer, |
| | 520 | autoBootstrapProjectFromCwd: true, |
| | 521 | }); |
| | 522 | let addr = server.address(); |
| | 523 | let port = typeof addr === "object" && addr !== null ? addr.port : 0; |
| | 524 | expect(port).toBeGreaterThan(0); |
| | 525 | |
| | 526 | const firstWs = await connectWs(port); |
| | 527 | connections.push(firstWs); |
| | 528 | const firstWelcome = (await waitForMessage(firstWs)) as WsPush; |
| | 529 | const firstBootstrapProjectId = (firstWelcome.data as { bootstrapProjectId?: string }) |
| | 530 | .bootstrapProjectId; |
| | 531 | const firstBootstrapThreadId = (firstWelcome.data as { bootstrapThreadId?: string }) |
| | 532 | .bootstrapThreadId; |
| | 533 | expect(firstBootstrapProjectId).toBeDefined(); |
| | 534 | expect(firstBootstrapThreadId).toBeDefined(); |
| | 535 | |
| | 536 | firstWs.close(); |
| | 537 | await closeTestServer(); |
| | 538 | server = null; |
| | 539 | |
| | 540 | server = await createTestServer({ |
| | 541 | cwd, |
| | 542 | stateDir, |
| | 543 | persistenceLayer, |
| | 544 | autoBootstrapProjectFromCwd: true, |
| | 545 | }); |
| | 546 | addr = server.address(); |
| | 547 | port = typeof addr === "object" && addr !== null ? addr.port : 0; |
| | 548 | expect(port).toBeGreaterThan(0); |
| | 549 | |
| | 550 | const secondWs = await connectWs(port); |
| | 551 | connections.push(secondWs); |
| | 552 | const secondWelcome = (await waitForMessage(secondWs)) as WsPush; |
| | 553 | expect(secondWelcome.channel).toBe(WS_CHANNELS.serverWelcome); |
| | 554 | expect(secondWelcome.data).toEqual( |
| | 555 | expect.objectContaining({ |
| | 556 | cwd, |
| | 557 | projectName: "bootstrap-existing", |
| | 558 | bootstrapProjectId: firstBootstrapProjectId, |
| | 559 | bootstrapThreadId: firstBootstrapThreadId, |
| | 560 | }), |
| | 561 | ); |
| | 562 | }); |
| | 563 | |
| 509 | it("logs outbound websocket push events in dev mode", async () => { | 564 | it("logs outbound websocket push events in dev mode", async () => { |
| 510 | const logSpy = vi.spyOn(console, "log").mockImplementation(() => { | 565 | const logSpy = vi.spyOn(console, "log").mockImplementation(() => { |
| 511 | // Keep test output clean while verifying websocket logs. | 566 | // Keep test output clean while verifying websocket logs. |