Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
"smoke-test": "node scripts/smoke-test.mjs"
},
"dependencies": {
"@t3tools/contracts": "workspace:*",
"@t3tools/shared": "workspace:*",
"effect": "catalog:",
"electron": "40.6.0",
"electron-updater": "^6.6.2"
},
"devDependencies": {
"@t3tools/contracts": "workspace:*",
"@t3tools/shared": "workspace:*",
"@types/node": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/lib/releases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface ReleaseAsset {
browser_download_url: string;
}

export interface Release {
interface Release {
tag_name: string;
html_url: string;
assets: ReleaseAsset[];
Expand Down
16 changes: 10 additions & 6 deletions apps/server/integration/OrchestrationEngineHarness.integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ import { GitCore, type GitCoreShape } from "../src/git/Services/GitCore.ts";
import { TextGeneration, type TextGenerationShape } from "../src/git/Services/TextGeneration.ts";
import { OrchestrationCommandReceiptRepositoryLive } from "../src/persistence/Layers/OrchestrationCommandReceipts.ts";
import { OrchestrationEventStoreLive } from "../src/persistence/Layers/OrchestrationEventStore.ts";
import { ProjectionCheckpointRepositoryLive } from "../src/persistence/Layers/ProjectionCheckpoints.ts";
import { ProjectionPendingApprovalRepositoryLive } from "../src/persistence/Layers/ProjectionPendingApprovals.ts";
import { ProviderSessionRuntimeRepositoryLive } from "../src/persistence/Layers/ProviderSessionRuntime.ts";
import { makeSqlitePersistenceLive } from "../src/persistence/Layers/Sqlite.ts";
import { ProjectionCheckpointRepository } from "../src/persistence/Services/ProjectionCheckpoints.ts";
import { makeSqlitePersistenceLive } from "../src/persistence/Layers/Sqlite.testing.ts";
import { ProjectionPendingApprovalRepository } from "../src/persistence/Services/ProjectionPendingApprovals.ts";
import { ProviderUnsupportedError } from "../src/provider/Errors.ts";
import { ProviderAdapterRegistry } from "../src/provider/Services/ProviderAdapterRegistry.ts";
Expand Down Expand Up @@ -70,6 +68,10 @@ import {
import { deriveServerPaths, ServerConfig } from "../src/config.ts";
import { WorkspaceEntriesLive } from "../src/workspace/Layers/WorkspaceEntries.ts";
import { WorkspacePathsLive } from "../src/workspace/Layers/WorkspacePaths.ts";
import {
ProjectionCheckpointRepository,
ProjectionCheckpointRepositoryLive,
} from "./support/ProjectionCheckpoints.ts";

function runGit(cwd: string, args: ReadonlyArray<string>) {
return execFileSync("git", args, {
Expand Down Expand Up @@ -126,7 +128,7 @@ function waitFor<A, E>(
read: Effect.Effect<A, E>,
predicate: (value: A) => boolean,
description: string,
timeoutMs = 40_000,
timeoutMs = 10_000,
): Effect.Effect<A, never> {
const RETRY_SIGNAL = "wait_for_retry";
const retryIntervalMs = 10;
Expand Down Expand Up @@ -499,7 +501,7 @@ export const makeOrchestrationIntegrationHarness = (
yield* shutdown;
});

return {
const harness: OrchestrationIntegrationHarness = {
rootDir,
workspaceDir,
dbPath,
Expand All @@ -515,5 +517,7 @@ export const makeOrchestrationIntegrationHarness = (
waitForPendingApproval,
waitForReceipt,
dispose,
} satisfies OrchestrationIntegrationHarness;
};

return harness;
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { checkpointRefForThreadTurn } from "../src/checkpointing/Utils.ts";
import type {
CheckpointDiffFinalizedReceipt,
TurnProcessingQuiescedReceipt,
} from "../src/orchestration/Services/RuntimeReceiptBus.ts";
} from "../src/orchestration/Services/RuntimeReceiptBus.shared.ts";
import * as NodeServices from "@effect/platform-node/NodeServices";

const asMessageId = (value: string): MessageId => MessageId.makeUnsafe(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from "../src/provider/Services/ProviderService.ts";
import { ServerSettingsService } from "../src/serverSettings.ts";
import { AnalyticsService } from "../src/telemetry/Services/AnalyticsService.ts";
import { SqlitePersistenceMemory } from "../src/persistence/Layers/Sqlite.ts";
import { SqlitePersistenceMemory } from "../src/persistence/Layers/Sqlite.testing.ts";
import { ProviderSessionRuntimeRepositoryLive } from "../src/persistence/Layers/ProviderSessionRuntime.ts";

import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
import { OrchestrationCheckpointFile } from "@t3tools/contracts";
import { Effect, Layer, Option, Schema, ServiceMap, Struct } from "effect";
import type { Effect as EffectType } from "effect";
import * as SqlClient from "effect/unstable/sql/SqlClient";
import * as SqlSchema from "effect/unstable/sql/SqlSchema";
import { Effect, Layer, Option, Schema, Struct } from "effect";

import { toPersistenceDecodeError, toPersistenceSqlError } from "../Errors.ts";
import {
DeleteByThreadIdInput,
GetByThreadAndTurnCountInput,
ListByThreadIdInput,
ProjectionCheckpoint,

import { NonNegativeInt, ThreadId } from "@t3tools/contracts";
import type { ProjectionRepositoryError } from "../../src/persistence/Errors.ts";
import { toPersistenceDecodeError, toPersistenceSqlError } from "../../src/persistence/Errors.ts";
import { ProjectionCheckpoint } from "../../src/persistence/Services/ProjectionCheckpoints.ts";

const ListByThreadIdInput = Schema.Struct({
threadId: ThreadId,
});
type ListByThreadIdInput = typeof ListByThreadIdInput.Type;

const GetByThreadAndTurnCountInput = Schema.Struct({
threadId: ThreadId,
checkpointTurnCount: NonNegativeInt,
});
type GetByThreadAndTurnCountInput = typeof GetByThreadAndTurnCountInput.Type;

const DeleteByThreadIdInput = Schema.Struct({
threadId: ThreadId,
});
type DeleteByThreadIdInput = typeof DeleteByThreadIdInput.Type;

interface ProjectionCheckpointRepositoryShape {
readonly upsert: (
row: typeof ProjectionCheckpoint.Type,
) => EffectType.Effect<void, ProjectionRepositoryError>;
readonly listByThreadId: (
input: ListByThreadIdInput,
) => EffectType.Effect<
ReadonlyArray<typeof ProjectionCheckpoint.Type>,
ProjectionRepositoryError
>;
readonly getByThreadAndTurnCount: (
input: GetByThreadAndTurnCountInput,
) => EffectType.Effect<
Option.Option<typeof ProjectionCheckpoint.Type>,
ProjectionRepositoryError
>;
readonly deleteByThreadId: (
input: DeleteByThreadIdInput,
) => EffectType.Effect<void, ProjectionRepositoryError>;
}

export class ProjectionCheckpointRepository extends ServiceMap.Service<
ProjectionCheckpointRepository,
type ProjectionCheckpointRepositoryShape,
} from "../Services/ProjectionCheckpoints.ts";
ProjectionCheckpointRepositoryShape
>()("t3/integration/support/ProjectionCheckpoints/ProjectionCheckpointRepository") {}

const ProjectionCheckpointDbRowSchema = ProjectionCheckpoint.mapFields(
Struct.assign({
Expand Down Expand Up @@ -170,7 +208,7 @@ const makeProjectionCheckpointRepository = Effect.gen(function* () {
"ProjectionCheckpointRepository.listByThreadId:decodeRows",
),
),
Effect.map((rows) => rows as ReadonlyArray<Schema.Schema.Type<typeof ProjectionCheckpoint>>),
Effect.map((rows) => rows as ReadonlyArray<typeof ProjectionCheckpoint.Type>),
);

const getByThreadAndTurnCount: ProjectionCheckpointRepositoryShape["getByThreadAndTurnCount"] = (
Expand All @@ -186,8 +224,7 @@ const makeProjectionCheckpointRepository = Effect.gen(function* () {
Effect.flatMap((rowOption) =>
Option.match(rowOption, {
onNone: () => Effect.succeed(Option.none()),
onSome: (row) =>
Effect.succeed(Option.some(row as Schema.Schema.Type<typeof ProjectionCheckpoint>)),
onSome: (row) => Effect.succeed(Option.some(row as typeof ProjectionCheckpoint.Type)),
}),
),
);
Expand Down
5 changes: 2 additions & 3 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,15 @@
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@pierre/diffs": "^1.1.0-beta.16",
"@t3tools/contracts": "workspace:*",
"@t3tools/shared": "workspace:*",
"effect": "catalog:",
"node-pty": "^1.1.0",
"open": "^10.1.0"
},
"devDependencies": {
"@effect/language-service": "catalog:",
"@effect/vitest": "catalog:",
"@t3tools/contracts": "workspace:*",
"@t3tools/shared": "workspace:*",
"@t3tools/web": "workspace:*",
"@types/bun": "catalog:",
"@types/node": "catalog:",
"tsdown": "catalog:",
Expand Down
12 changes: 12 additions & 0 deletions apps/server/src/bootstrap.shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function resolveFdPath(
fd: number,
platform: NodeJS.Platform = process.platform,
): string | undefined {
if (platform === "linux") {
return `/proc/self/fd/${fd}`;
}
if (platform === "win32") {
return undefined;
}
return `/dev/fd/${fd}`;
}
3 changes: 2 additions & 1 deletion apps/server/src/bootstrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import * as Fiber from "effect/Fiber";
import { TestClock } from "effect/testing";
import { vi } from "vitest";

import { readBootstrapEnvelope, resolveFdPath } from "./bootstrap";
import { readBootstrapEnvelope } from "./bootstrap";
import { resolveFdPath } from "./bootstrap.shared";
import { assertNone, assertSome } from "@effect/vitest/utils";

const openSyncInterceptor = vi.hoisted(() => ({ failPath: null as string | null }));
Expand Down
14 changes: 1 addition & 13 deletions apps/server/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Readable } from "node:stream";

import { Data, Effect, Option, Predicate, Result, Schema } from "effect";
import { decodeJsonResult } from "@t3tools/shared/schemaJson";
import { resolveFdPath } from "./bootstrap.shared";

class BootstrapError extends Data.TaggedError("BootstrapError")<{
readonly message: string;
Expand Down Expand Up @@ -158,16 +159,3 @@ const isBootstrapFdPathDuplicationError = Predicate.compose(
Predicate.hasProperty("code"),
(_) => _.code === "ENXIO" || _.code === "EINVAL" || _.code === "EPERM",
);

export function resolveFdPath(
fd: number,
platform: NodeJS.Platform = process.platform,
): string | undefined {
if (platform === "linux") {
return `/proc/self/fd/${fd}`;
}
if (platform === "win32") {
return undefined;
}
return `/dev/fd/${fd}`;
}
2 changes: 1 addition & 1 deletion apps/server/src/checkpointing/Diffs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { parsePatchFiles } from "@pierre/diffs";

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

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

export function checkpointRefForThreadTurn(threadId: ThreadId, turnCount: number): CheckpointRef {
return CheckpointRef.makeUnsafe(
Expand Down
64 changes: 63 additions & 1 deletion apps/server/src/cli-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ConfigProvider, Effect, FileSystem, Layer, Option, Path } from "effect"
import { NetService } from "@t3tools/shared/Net";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { deriveServerPaths } from "./config";
import { resolveServerConfig } from "./cli";
import { resolveServerConfig } from "./cli.logic";

it.layer(NodeServices.layer)("cli config resolution", (it) => {
const defaultObservabilityConfig = {
Expand Down Expand Up @@ -153,6 +153,68 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => {
}),
);

it.effect("uses explicit false CLI boolean flags over env and bootstrap values", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
const baseDir = join(os.tmpdir(), "t3-cli-config-false-flags-base");
const fd = yield* openBootstrapFd({
noBrowser: true,
autoBootstrapProjectFromCwd: true,
logWebSocketEvents: true,
});
const derivedPaths = yield* deriveServerPaths(baseDir, new URL("http://127.0.0.1:4173"));

const resolved = yield* resolveServerConfig(
{
mode: Option.some("web"),
port: Option.some(8788),
host: Option.some("127.0.0.1"),
baseDir: Option.some(baseDir),
devUrl: Option.some(new URL("http://127.0.0.1:4173")),
noBrowser: Option.some(false),
authToken: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.some(false),
logWebSocketEvents: Option.some(false),
},
Option.none(),
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(
ConfigProvider.fromEnv({
env: {
T3CODE_BOOTSTRAP_FD: String(fd),
T3CODE_NO_BROWSER: "true",
T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD: "true",
T3CODE_LOG_WS_EVENTS: "true",
},
}),
),
NetService.layer,
),
),
);

expect(resolved).toEqual({
logLevel: "Info",
...defaultObservabilityConfig,
mode: "web",
port: 8788,
cwd: process.cwd(),
baseDir,
...derivedPaths,
host: "127.0.0.1",
staticDir: undefined,
devUrl: new URL("http://127.0.0.1:4173"),
noBrowser: false,
authToken: undefined,
autoBootstrapProjectFromCwd: false,
logWebSocketEvents: false,
});
}),
);

it.effect("uses bootstrap envelope values as fallbacks when flags and env are absent", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
Expand Down
Loading
Loading