diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 36d3f071aa4..a64c23b2bec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -138,7 +138,7 @@ jobs: echo "release_channel=stable" >> "$GITHUB_OUTPUT" echo "version=$version" >> "$GITHUB_OUTPUT" echo "tag=v$version" >> "$GITHUB_OUTPUT" - echo "name=TritonAI Code v$version" >> "$GITHUB_OUTPUT" + echo "name=TritonAI Harness v$version" >> "$GITHUB_OUTPUT" echo "cli_dist_tag=latest" >> "$GITHUB_OUTPUT" if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "is_prerelease=false" >> "$GITHUB_OUTPUT" diff --git a/README.md b/README.md index 6aebfc7e8b8..88e60c01275 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# T3 Code +# TritonAI Harness -T3 Code is a minimal web GUI for coding agents (currently Codex, Claude, Cursor, and OpenCode, more coming soon). +TritonAI Harness is a minimal web GUI for coding agents (currently Codex, Claude, Cursor, and OpenCode, more coming soon). ## Installation > [!WARNING] -> T3 Code currently supports Codex, Claude, Cursor, and OpenCode. +> TritonAI Harness currently supports Codex, Claude, Cursor, and OpenCode. > Install and authenticate at least one provider before use: > > - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login` @@ -63,7 +63,7 @@ There's no public docs site yet, checkout the miscellaneous markdown files in [d ### Install `vp` -T3 Code uses Vite+ so you'll need to install the global `vp` command-line tool. +TritonAI Harness uses Vite+ so you'll need to install the global `vp` command-line tool. #### macOS / Linux diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 52c5114f1e3..0153ae2449b 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -32,5 +32,5 @@ "tailwindcss": "^4.0.0", "vite-plus": "catalog:" }, - "productName": "TritonAI Code" + "productName": "TritonAI Harness" } diff --git a/apps/desktop/scripts/electron-launcher.mjs b/apps/desktop/scripts/electron-launcher.mjs index 9fe3fa23135..1bda7c846fe 100644 --- a/apps/desktop/scripts/electron-launcher.mjs +++ b/apps/desktop/scripts/electron-launcher.mjs @@ -1,4 +1,4 @@ -// This file mostly exists because we want dev mode to say "TritonAI Code (Dev)" instead of "electron" +// This file mostly exists because we want dev mode to say "TritonAI Harness (Dev)" instead of "electron" import { spawnSync } from "node:child_process"; import { @@ -26,7 +26,7 @@ const repoRoot = resolve(desktopDir, "..", ".."); const devBundleIdSuffix = basename(repoRoot) .toLowerCase() .replaceAll(/[^a-z0-9]+/g, ""); -export const APP_DISPLAY_NAME = isDevelopment ? "TritonAI Code (Dev)" : "TritonAI Code"; +export const APP_DISPLAY_NAME = isDevelopment ? "TritonAI Harness (Dev)" : "TritonAI Harness"; export const APP_BUNDLE_ID = isDevelopment ? `edu.ucsd.ai.tritonai-code.dev.${devBundleIdSuffix || "local"}` : "edu.ucsd.ai.tritonai-code"; diff --git a/apps/desktop/src/app/DesktopApp.ts b/apps/desktop/src/app/DesktopApp.ts index 69167e75bb5..41cca978623 100644 --- a/apps/desktop/src/app/DesktopApp.ts +++ b/apps/desktop/src/app/DesktopApp.ts @@ -120,7 +120,7 @@ const handleFatalStartupError = Effect.fn("desktop.startup.handleFatalStartupErr const wasQuitting = yield* Ref.getAndSet(state.quitting, true); if (!wasQuitting) { yield* electronDialog.showErrorBox( - "TritonAI Code failed to start", + "TritonAI Harness failed to start", `Stage: ${stage}\n${message}${detail}`, ); } diff --git a/apps/desktop/src/app/DesktopAppIdentity.test.ts b/apps/desktop/src/app/DesktopAppIdentity.test.ts index 661ccb4000e..d142a5d88ad 100644 --- a/apps/desktop/src/app/DesktopAppIdentity.test.ts +++ b/apps/desktop/src/app/DesktopAppIdentity.test.ts @@ -19,9 +19,9 @@ const defaultEnvironmentInput = { platform: "darwin", processArch: "arm64", appVersion: "1.2.3", - appPath: "/Applications/TritonAI Code.app/Contents/Resources/app.asar", + appPath: "/Applications/TritonAI Harness.app/Contents/Resources/app.asar", isPackaged: true, - resourcesPath: "/Applications/TritonAI Code.app/Contents/Resources", + resourcesPath: "/Applications/TritonAI Harness.app/Contents/Resources", runningUnderArm64Translation: false, } satisfies DesktopEnvironment.MakeDesktopEnvironmentInput; @@ -38,7 +38,7 @@ interface ElectronAppCalls { const makeElectronAppLayer = (calls: ElectronAppCalls) => Layer.succeed(ElectronApp.ElectronApp, { metadata: Effect.die("unexpected metadata read"), - name: Effect.succeed("TritonAI Code"), + name: Effect.succeed("TritonAI Harness"), whenReady: Effect.void, quit: Effect.void, exit: () => Effect.void, @@ -105,6 +105,7 @@ const withIdentity = ( readonly calls?: ElectronAppCalls; readonly environment?: TestEnvironmentInput; readonly legacyPathExists?: boolean; + readonly legacyPathNeedle?: string; readonly packageJson?: string; readonly pngIconPath?: Option.Option; } = {}, @@ -121,7 +122,10 @@ const withIdentity = ( Layer.provideMerge( FileSystem.layerNoop({ exists: (path) => - Effect.succeed(input.legacyPathExists === true && path.includes("T3 Code")), + Effect.succeed( + input.legacyPathExists === true && + path.includes(input.legacyPathNeedle ?? "T3 Code"), + ), readFileString: () => Effect.succeed(input.packageJson ?? '{"t3codeCommitHash":"abcdef1234567890"}'), }), @@ -136,6 +140,17 @@ const withIdentity = ( describe("DesktopAppIdentity", () => { it.effect("uses the downstream userData path for packaged builds", () => + withIdentity( + Effect.gen(function* () { + const identity = yield* DesktopAppIdentity.DesktopAppIdentity; + const userDataPath = yield* identity.resolveUserDataPath; + + assert.equal(userDataPath, "/Users/alice/Library/Application Support/TritonAI Harness"); + }), + ), + ); + + it.effect("keeps using the legacy TritonAI Code userData path when it already exists", () => withIdentity( Effect.gen(function* () { const identity = yield* DesktopAppIdentity.DesktopAppIdentity; @@ -143,7 +158,7 @@ describe("DesktopAppIdentity", () => { assert.equal(userDataPath, "/Users/alice/Library/Application Support/TritonAI Code"); }), - { legacyPathExists: true }, + { legacyPathExists: true, legacyPathNeedle: "TritonAI Code" }, ), ); @@ -179,8 +194,8 @@ describe("DesktopAppIdentity", () => { const identity = yield* DesktopAppIdentity.DesktopAppIdentity; yield* identity.configure; - assert.deepEqual(calls.setName, ["TritonAI Code"]); - assert.equal(calls.setAboutPanelOptions[0]?.applicationName, "TritonAI Code"); + assert.deepEqual(calls.setName, ["TritonAI Harness"]); + assert.equal(calls.setAboutPanelOptions[0]?.applicationName, "TritonAI Harness"); assert.equal(calls.setAboutPanelOptions[0]?.applicationVersion, "1.2.3"); assert.equal(calls.setAboutPanelOptions[0]?.version, "0123456789ab"); assert.deepEqual(calls.setDockIcon, ["/icon.png"]); diff --git a/apps/desktop/src/app/DesktopEnvironment.test.ts b/apps/desktop/src/app/DesktopEnvironment.test.ts index 7fa1432da75..d6f90ac729b 100644 --- a/apps/desktop/src/app/DesktopEnvironment.test.ts +++ b/apps/desktop/src/app/DesktopEnvironment.test.ts @@ -13,9 +13,9 @@ const defaultInput = { platform: "darwin", processArch: "arm64", appVersion: "0.0.22", - appPath: "/Applications/TritonAI Code.app/Contents/Resources/app.asar", + appPath: "/Applications/TritonAI Harness.app/Contents/Resources/app.asar", isPackaged: false, - resourcesPath: "/Applications/TritonAI Code.app/Contents/Resources", + resourcesPath: "/Applications/TritonAI Harness.app/Contents/Resources", runningUnderArm64Translation: false, } satisfies DesktopEnvironment.MakeDesktopEnvironmentInput; diff --git a/apps/desktop/src/app/DesktopEnvironment.ts b/apps/desktop/src/app/DesktopEnvironment.ts index 969707c8e15..30319cadfae 100644 --- a/apps/desktop/src/app/DesktopEnvironment.ts +++ b/apps/desktop/src/app/DesktopEnvironment.ts @@ -81,7 +81,7 @@ export class DesktopEnvironment extends Context.Service< DesktopEnvironmentShape >()("@t3tools/desktop/app/DesktopEnvironment") {} -const APP_BASE_NAME = "TritonAI Code"; +const APP_BASE_NAME = "TritonAI Harness"; function resolveDesktopAppStageLabel(input: { readonly isDevelopment: boolean; @@ -162,8 +162,8 @@ const makeDesktopEnvironment = Effect.fn("desktop.environment.make")(function* ( }); const displayName = branding.displayName; const stateDir = path.join(baseDir, isDevelopment ? "dev" : "userdata"); - const userDataDirName = isDevelopment ? "tritonai-code-dev" : "TritonAI Code"; - const legacyUserDataDirName = isDevelopment ? "T3 Code (Dev)" : null; + const userDataDirName = isDevelopment ? "tritonai-code-dev" : "TritonAI Harness"; + const legacyUserDataDirName = isDevelopment ? "T3 Code (Dev)" : "TritonAI Code"; const resourcesPath = input.resourcesPath; return DesktopEnvironment.of({ diff --git a/apps/desktop/src/electron/ElectronApp.test.ts b/apps/desktop/src/electron/ElectronApp.test.ts index 446b966333d..b026c650f4b 100644 --- a/apps/desktop/src/electron/ElectronApp.test.ts +++ b/apps/desktop/src/electron/ElectronApp.test.ts @@ -54,7 +54,7 @@ vi.mock("electron", () => ({ getVersion: getVersionMock, isDefaultProtocolClient: isDefaultProtocolClientMock, isPackaged: true, - name: "TritonAI Code", + name: "TritonAI Harness", on: onMock, quit: quitMock, relaunch: relaunchMock, diff --git a/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts b/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts index e55896b0a86..c5cbe7fd394 100644 --- a/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts +++ b/apps/desktop/src/ssh/DesktopSshPasswordPrompts.ts @@ -16,7 +16,8 @@ import * as IpcChannels from "../ipc/channels.ts"; import * as ElectronWindow from "../electron/ElectronWindow.ts"; const DEFAULT_SSH_PASSWORD_PROMPT_TIMEOUT_MS = 3 * 60 * 1000; -const WINDOW_UNAVAILABLE_MESSAGE = "TritonAI Code window is not available for SSH authentication."; +const WINDOW_UNAVAILABLE_MESSAGE = + "TritonAI Harness window is not available for SSH authentication."; type DesktopSshPasswordPromptResolutionInput = typeof DesktopSshPasswordPromptResolutionInputSchema.Type; diff --git a/apps/desktop/src/window/DesktopApplicationMenu.test.ts b/apps/desktop/src/window/DesktopApplicationMenu.test.ts index 68b3269e8b7..ece325f33db 100644 --- a/apps/desktop/src/window/DesktopApplicationMenu.test.ts +++ b/apps/desktop/src/window/DesktopApplicationMenu.test.ts @@ -30,7 +30,7 @@ const environmentInput = { const electronAppLayer = Layer.succeed(ElectronApp.ElectronApp, { metadata: Effect.die("unexpected metadata read"), - name: Effect.succeed("TritonAI Code"), + name: Effect.succeed("TritonAI Harness"), whenReady: Effect.void, quit: Effect.void, exit: () => Effect.void, diff --git a/apps/desktop/src/window/DesktopApplicationMenu.ts b/apps/desktop/src/window/DesktopApplicationMenu.ts index 2a070146b71..733888de804 100644 --- a/apps/desktop/src/window/DesktopApplicationMenu.ts +++ b/apps/desktop/src/window/DesktopApplicationMenu.ts @@ -53,7 +53,7 @@ const checkForUpdatesFromMenu: Effect.Effect< yield* electronDialog.showMessageBox({ type: "info", title: "You're up to date!", - message: `TritonAI Code ${updateState.currentVersion} is currently the newest version available.`, + message: `TritonAI Harness ${updateState.currentVersion} is currently the newest version available.`, buttons: ["OK"], }); } else if (updateState.status === "error") { diff --git a/apps/marketing/src/layouts/Layout.astro b/apps/marketing/src/layouts/Layout.astro index 2f13a07d2f1..de3d8e10a9c 100644 --- a/apps/marketing/src/layouts/Layout.astro +++ b/apps/marketing/src/layouts/Layout.astro @@ -7,8 +7,8 @@ interface Props { } const { - title = "TritonAI Code", - description = "TritonAI Code — The open-source control plane for coding agents.", + title = "TritonAI Harness", + description = "TritonAI Harness — The open-source control plane for coding agents.", } = Astro.props; --- @@ -33,8 +33,8 @@ const {