Skip to content
Draft
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
6 changes: 3 additions & 3 deletions apps/desktop/src/app/DesktopAppIdentity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const withIdentity = <A, E, R>(
input.legacyPathProbeError
? Effect.fail(input.legacyPathProbeError)
: Effect.succeed(
input.legacyPathExists === true && path.includes("T3 Code (Alpha v2)"),
input.legacyPathExists === true && path.includes("T3 Code (Alpha)"),
),
readFileString: () =>
Effect.succeed(input.packageJson ?? '{"t3codeCommitHash":"abcdef1234567890"}'),
Expand All @@ -147,14 +147,14 @@ describe("DesktopAppIdentity", () => {
const identity = yield* DesktopAppIdentity.DesktopAppIdentity;
const userDataPath = yield* identity.resolveUserDataPath;

assert.equal(userDataPath, "/Users/alice/Library/Application Support/T3 Code (Alpha v2)");
assert.equal(userDataPath, "/Users/alice/Library/Application Support/T3 Code (Alpha)");
}),
{ legacyPathExists: true },
),
);

it.effect("preserves failures while inspecting the legacy userData path", () => {
const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Alpha v2)";
const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Alpha)";
const cause = PlatformError.systemError({
_tag: "PermissionDenied",
module: "FileSystem",
Expand Down
16 changes: 8 additions & 8 deletions apps/desktop/src/app/DesktopConnectionCatalogStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ describe("DesktopConnectionCatalogStore", () => {
_tag: "PermissionDenied",
module: "FileSystem",
method: "readFileString",
pathOrDescriptor: `${baseDir}/userdata-v2/connection-catalog.json`,
pathOrDescriptor: `${baseDir}/userdata/connection-catalog.json`,
});
const fileSystemLayer = Layer.succeed(
FileSystem.FileSystem,
Expand All @@ -271,11 +271,11 @@ describe("DesktopConnectionCatalogStore", () => {
error,
DesktopConnectionCatalogStore.DesktopConnectionCatalogStoreReadError,
);
assert.equal(error.catalogPath, `${baseDir}/userdata-v2/connection-catalog.json`);
assert.equal(error.catalogPath, `${baseDir}/userdata/connection-catalog.json`);
assert.strictEqual(error.cause, permissionError);
assert.equal(
error.message,
`Failed to read the desktop connection catalog at ${baseDir}/userdata-v2/connection-catalog.json.`,
`Failed to read the desktop connection catalog at ${baseDir}/userdata/connection-catalog.json.`,
);
assert.notEqual(error.message, permissionError.message);
}).pipe(Effect.provide(NodeServices.layer), Effect.scoped),
Expand All @@ -291,7 +291,7 @@ describe("DesktopConnectionCatalogStore", () => {
_tag: "PermissionDenied",
module: "FileSystem",
method: "makeDirectory",
pathOrDescriptor: `${baseDir}/userdata-v2`,
pathOrDescriptor: `${baseDir}/userdata`,
});
const fileSystemLayer = Layer.succeed(
FileSystem.FileSystem,
Expand All @@ -309,11 +309,11 @@ describe("DesktopConnectionCatalogStore", () => {
DesktopConnectionCatalogStore.DesktopConnectionCatalogStoreWriteError,
);
assert.equal(error.operation, "create-directory");
assert.equal(error.path, `${baseDir}/userdata-v2`);
assert.equal(error.path, `${baseDir}/userdata`);
assert.strictEqual(error.cause, permissionError);
assert.equal(
error.message,
`Desktop connection catalog write failed during create-directory at ${baseDir}/userdata-v2.`,
`Desktop connection catalog write failed during create-directory at ${baseDir}/userdata.`,
);
assert.notEqual(error.message, permissionError.message);
}).pipe(Effect.provide(NodeServices.layer), Effect.scoped),
Expand Down Expand Up @@ -398,14 +398,14 @@ describe("DesktopConnectionCatalogStore", () => {
DesktopConnectionCatalogStore.DesktopConnectionCatalogStoreProtectionError,
);
assert.equal(error.operation, "decrypt-catalog");
assert.equal(error.catalogPath, `${baseDir}/userdata-v2/connection-catalog.json`);
assert.equal(error.catalogPath, `${baseDir}/userdata/connection-catalog.json`);
assert.instanceOf(error.cause, ElectronSafeStorage.ElectronSafeStorageDecryptError);
const decryptError = error.cause as ElectronSafeStorage.ElectronSafeStorageDecryptError;
assert.instanceOf(decryptError.cause, Error);
assert.equal(decryptError.cause.message, "invalid encrypted catalog");
assert.equal(
error.message,
`Desktop connection catalog protection failed during decrypt-catalog at ${baseDir}/userdata-v2/connection-catalog.json.`,
`Desktop connection catalog protection failed during decrypt-catalog at ${baseDir}/userdata/connection-catalog.json.`,
);
assert.notEqual(error.message, decryptError.message);
yield* Ref.set(failDecrypt, false);
Expand Down
30 changes: 15 additions & 15 deletions apps/desktop/src/app/DesktopEnvironment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ describe("DesktopEnvironment", () => {
assert.equal(environment.isDevelopment, true);
assert.equal(environment.appDataDirectory, "/Users/alice/Library/Application Support");
assert.equal(environment.baseDir, "/tmp/t3");
assert.equal(environment.stateDir, "/tmp/t3/userdata-v2");
assert.equal(environment.desktopSettingsPath, "/tmp/t3/userdata-v2/desktop-settings.json");
assert.equal(environment.clientSettingsPath, "/tmp/t3/userdata-v2/client-settings.json");
assert.equal(environment.stateDir, "/tmp/t3/userdata");
assert.equal(environment.desktopSettingsPath, "/tmp/t3/userdata/desktop-settings.json");
assert.equal(environment.clientSettingsPath, "/tmp/t3/userdata/client-settings.json");
assert.equal(
environment.savedEnvironmentRegistryPath,
"/tmp/t3/userdata-v2/saved-environments.json",
"/tmp/t3/userdata/saved-environments.json",
);
assert.equal(environment.serverSettingsPath, "/tmp/t3/userdata-v2/settings.json");
assert.equal(environment.logDir, "/tmp/t3/userdata-v2/logs");
assert.equal(environment.browserArtifactsDir, "/tmp/t3/userdata-v2/browser-artifacts");
assert.equal(environment.serverSettingsPath, "/tmp/t3/userdata/settings.json");
assert.equal(environment.logDir, "/tmp/t3/userdata/logs");
assert.equal(environment.browserArtifactsDir, "/tmp/t3/userdata/browser-artifacts");
assert.equal(environment.rootDir, "/repo");
assert.equal(environment.appRoot, "/repo");
assert.equal(environment.backendEntryPath, "/repo/apps/server/dist/bin.mjs");
Expand All @@ -81,7 +81,7 @@ describe("DesktopEnvironment", () => {
}),
);

it.effect("stores production state under userdata-v2 in an explicit home", () =>
it.effect("stores production state under userdata in an explicit home", () =>
Effect.gen(function* () {
const environment = yield* makeEnvironment(
{},
Expand All @@ -91,12 +91,12 @@ describe("DesktopEnvironment", () => {
);

assert.equal(environment.isDevelopment, false);
assert.equal(environment.stateDir, "/tmp/t3/userdata-v2");
assert.equal(environment.logDir, "/tmp/t3/userdata-v2/logs");
assert.equal(environment.browserArtifactsDir, "/tmp/t3/userdata-v2/browser-artifacts");
assert.equal(environment.serverSettingsPath, "/tmp/t3/userdata-v2/settings.json");
assert.equal(environment.userDataDirName, "t3code-v2");
assert.equal(environment.legacyUserDataDirName, "T3 Code (Alpha v2)");
assert.equal(environment.stateDir, "/tmp/t3/userdata");
assert.equal(environment.logDir, "/tmp/t3/userdata/logs");
assert.equal(environment.browserArtifactsDir, "/tmp/t3/userdata/browser-artifacts");
assert.equal(environment.serverSettingsPath, "/tmp/t3/userdata/settings.json");
assert.equal(environment.userDataDirName, "t3code");
assert.equal(environment.legacyUserDataDirName, "T3 Code (Alpha)");
}),
);

Expand All @@ -109,7 +109,7 @@ describe("DesktopEnvironment", () => {
const production = yield* makeEnvironment();

assert.equal(development.stateDir, "/Users/alice/.t3/dev");
assert.equal(production.stateDir, "/Users/alice/.t3/userdata-v2");
assert.equal(production.stateDir, "/Users/alice/.t3/userdata");
}),
);

Expand Down
6 changes: 3 additions & 3 deletions apps/desktop/src/app/DesktopEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@ const make = Effect.fn("desktop.environment.make")(function* (
const displayName = branding.displayName;
const stateDir = path.join(
baseDir,
isDevelopment && Option.isNone(configuredBaseDir) ? "dev" : "userdata-v2",
isDevelopment && Option.isNone(configuredBaseDir) ? "dev" : "userdata",
);
const userDataDirName = isDevelopment ? "t3code-dev" : "t3code-v2";
const legacyUserDataDirName = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha v2)";
const userDataDirName = isDevelopment ? "t3code-dev" : "t3code";
const legacyUserDataDirName = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const resourcesPath = input.resourcesPath;

return DesktopEnvironment.of({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ describe("DesktopBackendConfiguration", () => {
const baseDir = yield* fileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-backend-config-test-",
});
const settingsPath = path.join(baseDir, "userdata-v2", "settings.json");
const settingsPath = path.join(baseDir, "userdata", "settings.json");
const cause = PlatformError.systemError({
_tag: "PermissionDenied",
module: "FileSystem",
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/backend/DesktopBackendConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ const resolveWslStartConfig = Effect.fn("desktop.backendConfiguration.resolveWsl
};

// Forward the dev-server URL as an explicit CLI flag so the WSL backend's
// config resolution lands in dev/ instead of userdata-v2/. Inheriting through
// config resolution lands in dev/ instead of userdata/. Inheriting through
// WSLENV is unreliable in practice (URL-shaped values with colons /
// slashes get translated unpredictably depending on flags), and the
// packaged build leaves devServerUrl as None anyway.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe("DesktopClientSettings diagnostics", () => {
_tag: "PermissionDenied",
module: "FileSystem",
method: "readFileString",
pathOrDescriptor: `${baseDir}/userdata-v2/client-settings.json`,
pathOrDescriptor: `${baseDir}/userdata/client-settings.json`,
});

return Effect.gen(function* () {
Expand Down
8 changes: 4 additions & 4 deletions apps/desktop/src/settings/DesktopSavedEnvironments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ describe("DesktopSavedEnvironments", () => {
const baseDir = yield* baseFileSystem.makeTempDirectoryScoped({
prefix: "t3-desktop-saved-environments-test-",
});
const registryPath = `${baseDir}/userdata-v2/saved-environments.json`;
const registryPath = `${baseDir}/userdata/saved-environments.json`;
const permissionError = PlatformError.systemError({
_tag: "PermissionDenied",
module: "FileSystem",
Expand Down Expand Up @@ -439,7 +439,7 @@ describe("DesktopSavedEnvironments", () => {
_tag: "PermissionDenied",
module: "FileSystem",
method: "makeDirectory",
pathOrDescriptor: `${baseDir}/userdata-v2`,
pathOrDescriptor: `${baseDir}/userdata`,
});
const fileSystemLayer = Layer.succeed(
FileSystem.FileSystem,
Expand All @@ -455,11 +455,11 @@ describe("DesktopSavedEnvironments", () => {
const error = yield* savedEnvironments.setRegistry([savedRegistryRecord]).pipe(Effect.flip);
assert.instanceOf(error, DesktopSavedEnvironments.DesktopSavedEnvironmentsWriteError);
assert.equal(error.operation, "create-directory");
assert.equal(error.path, `${baseDir}/userdata-v2`);
assert.equal(error.path, `${baseDir}/userdata`);
assert.strictEqual(error.cause, permissionError);
assert.equal(
error.message,
`Desktop saved-environment write failed during create-directory at ${baseDir}/userdata-v2.`,
`Desktop saved-environment write failed during create-directory at ${baseDir}/userdata.`,
);
assert.notEqual(error.message, permissionError.message);
}).pipe(Effect.provide(NodeServices.layer), Effect.scoped),
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/cli/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => {
tailscaleServeEnabled: false,
tailscaleServePort: 443,
});
assert.equal(join(baseDir, "userdata-v2"), resolved.stateDir);
assert.equal(join(baseDir, "userdata"), resolved.stateDir);
}),
);

Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const deriveServerPaths = Effect.fn(function* (
const { join } = yield* Path.Path;
const stateDir = join(
baseDir,
devUrl !== undefined && !options.baseDirIsExplicit ? "dev" : "userdata-v2",
devUrl !== undefined && !options.baseDirIsExplicit ? "dev" : "userdata",
);
const dbPath = join(stateDir, "state.sqlite");
const attachmentsDir = join(stateDir, "attachments");
Expand Down
107 changes: 107 additions & 0 deletions apps/server/src/orchestration-v2/ContextHandoffService.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { assert, it } from "@effect/vitest";
import {
MessageId,
ProviderInstanceId,
ProviderThreadId,
RunId,
ThreadId,
TurnItemId,
type OrchestrationV2TurnItem,
} from "@t3tools/contracts";
import * as DateTime from "effect/DateTime";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";

import {
ContextHandoffServiceV2,
layer as contextHandoffServiceLayer,
providerMessageWithContextHandoff,
} from "./ContextHandoffService.ts";
import { layer as idAllocatorLayer } from "./IdAllocator.ts";

const TestLayer = contextHandoffServiceLayer.pipe(Layer.provide(idAllocatorLayer));

function importedItem(
input:
| {
readonly role: "user";
readonly id: string;
readonly text: string;
readonly ordinal: number;
}
| {
readonly role: "assistant";
readonly id: string;
readonly text: string;
readonly ordinal: number;
},
): OrchestrationV2TurnItem {
const now = DateTime.makeUnsafe("2026-01-01T00:00:00.000Z");
const base = {
id: TurnItemId.make(`turn-item:${input.id}`),
threadId: ThreadId.make("thread:legacy-context"),
runId: null,
nodeId: null,
providerThreadId: null,
providerTurnId: null,
nativeItemRef: null,
parentItemId: null,
ordinal: input.ordinal,
status: "completed" as const,
title: null,
startedAt: now,
completedAt: now,
updatedAt: now,
messageId: MessageId.make(`message:${input.id}`),
text: input.text,
};
return input.role === "user"
? {
...base,
createdBy: "user",
creationSource: "server",
type: "user_message",
inputIntent: "turn_start",
attachments: [],
}
: {
...base,
type: "assistant_message",
streaming: false,
};
}

it.layer(TestLayer)("ContextHandoffService legacy import", (it) => {
it.effect("prepares imported history for the first native v2 turn", () =>
Effect.gen(function* () {
const service = yield* ContextHandoffServiceV2;
const handoff = yield* service.prepareLegacyImport({
threadId: ThreadId.make("thread:legacy-context"),
targetRunId: RunId.make("run:first-v2"),
toProviderThreadId: ProviderThreadId.make("provider-thread:first-v2"),
toProviderInstanceId: ProviderInstanceId.make("codex"),
items: [
importedItem({ role: "user", id: "one", text: "What did we decide?", ordinal: 1 }),
importedItem({
role: "assistant",
id: "two",
text: "We decided to keep the migration lightweight.",
ordinal: 2,
}),
],
createdAt: DateTime.makeUnsafe("2026-01-02T00:00:00.000Z"),
});

assert.equal(handoff.strategy, "manual_context");
assert.deepStrictEqual(handoff.fromProviderThreadIds, []);
assert.include(handoff.summaryText, "What did we decide?");
assert.include(handoff.summaryText, "keep the migration lightweight");
const providerMessage = providerMessageWithContextHandoff({
handoff,
userText: "Continue from there.",
});
assert.include(providerMessage, handoff.summaryText);
assert.include(providerMessage, "User message:\nContinue from there.");
}),
);
});
Loading
Loading