diff --git a/pkgs/by-name/t3/t3code/package.nix b/pkgs/by-name/t3/t3code/package.nix index 835c397f59ca..6352c9047ff7 100644 --- a/pkgs/by-name/t3/t3code/package.nix +++ b/pkgs/by-name/t3/t3code/package.nix @@ -1,25 +1,8 @@ { - cctools, - copyDesktopItems, - electron_41, - fetchFromGitHub, - installShellFiles, lib, - libicns, + callPackage, + symlinkJoin, makeBinaryWrapper, - makeDesktopItem, - nix-update-script, - node-gyp, - nodejs, - python3, - stdenv, - writeDarwinBundle, - xcbuild, - fetchPnpmDeps, - pnpm_10, - pnpmConfigHook, - pnpmBuildHook, - cacert, enableAzureDevOps ? false, azure-cli, azure-cli-extensions, @@ -43,214 +26,59 @@ jujutsu, enableOpencode ? false, opencode, + t3code-unwrapped ? callPackage ./unwrapped.nix { }, }: -stdenv.mkDerivation ( - finalAttrs: - let - appName = "T3 Code (Alpha)"; - electron = electron_41; - pnpm = pnpm_10; - desktopIcon = - if stdenv.hostPlatform.isDarwin then - "assets/prod/black-macos-1024.png" - else - "assets/prod/black-universal-1024.png"; - - runtimePackages = - lib.optionals enableAzureDevOps [ - azure-cli.withExtensions - [ azure-cli-extensions.azure-devops ] - ] - ++ lib.optionals enableBitbucket [ bitbucket-cli ] - ++ lib.optionals enableClaude [ claude-code ] - ++ lib.optionals enableCodex [ codex ] - ++ lib.optionals enableCursor [ code-cursor ] - ++ lib.optionals enableCursorCli [ cursor-cli ] - ++ lib.optionals enableGitHub [ gh ] - ++ lib.optionals enableGit [ git ] - ++ lib.optionals enableGitLab [ glab ] - ++ lib.optionals enableJujutsu [ jujutsu ] - ++ lib.optionals enableOpencode [ opencode ]; - - runtimePathWrapperArgs = lib.optionalString (runtimePackages != [ ]) '' - \ - --prefix PATH : ${lib.makeBinPath runtimePackages} - ''; - in - { - pname = "t3code"; - version = "0.0.28"; - strictDeps = true; - __structuredAttrs = true; - - src = fetchFromGitHub { - owner = "pingdotgg"; - repo = "t3code"; - tag = "v${finalAttrs.version}"; - hash = "sha256-InVrw9L281QSSPrHSiZuivmb+FkYEd6FkHwHIAAxmGk="; - }; - - postPatch = '' - substituteInPlace apps/web/vite.config.ts \ - --replace-fail 'const host = process.env.HOST?.trim() || "localhost";' \ - 'const host = process.env.HOST?.trim() || "127.0.0.1";' - ''; - - nativeBuildInputs = [ - installShellFiles - makeBinaryWrapper - node-gyp - nodejs - python3 - pnpmConfigHook - pnpmBuildHook - pnpm - cacert +let + runtimePackages = + lib.optionals enableAzureDevOps [ + (azure-cli.withExtensions [ azure-cli-extensions.azure-devops ]) ] - ++ lib.optionals stdenv.hostPlatform.isLinux [ copyDesktopItems ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ - cctools.libtool - libicns - writeDarwinBundle - xcbuild - ]; + ++ lib.optionals enableBitbucket [ bitbucket-cli ] + ++ lib.optionals enableClaude [ claude-code ] + ++ lib.optionals enableCodex [ codex ] + ++ lib.optionals enableCursor [ code-cursor ] + ++ lib.optionals enableCursorCli [ cursor-cli ] + ++ lib.optionals enableGitHub [ gh ] + ++ lib.optionals enableGit [ git ] + ++ lib.optionals enableGitLab [ glab ] + ++ lib.optionals enableJujutsu [ jujutsu ] + ++ lib.optionals enableOpencode [ opencode ]; - pnpmWorkspaces = [ - # `...` suffix is used to also include other workspace packages that are - # directly or indirectly depended on by the listed packages, such as - # `@t3tools/contracts` and `@t3tools/shared`. - "@t3tools/monorepo" - "t3..." - "@t3tools/desktop..." - "@t3tools/scripts..." - ]; +in +symlinkJoin { + pname = "t3code"; + inherit (t3code-unwrapped) version; + __structuredAttrs = true; + strictDeps = true; - pnpmDeps = fetchPnpmDeps { - inherit pnpm; - inherit (finalAttrs) - pname - version - src - pnpmWorkspaces - ; + paths = [ t3code-unwrapped ]; - fetcherVersion = 4; - hash = "sha256-+JqW/iI0wdRPxyL7y6ggD/+AvwwZXs9+fSUtG/SgW9s="; - }; + nativeBuildInputs = [ makeBinaryWrapper ]; - preBuild = '' - node scripts/update-release-package-versions.ts ${finalAttrs.version} + postBuild = lib.optionalString (runtimePackages != [ ]) '' + for program in "$out/bin"/*; do + wrapProgram "$program" \ + --prefix PATH : "${lib.makeBinPath runtimePackages}" + done + ''; - export npm_config_nodedir=${nodejs} - export ELECTRON_SKIP_BINARY_DOWNLOAD=1 - # Exclude the `@t3tools/monorepo` workspace from the pending rebuild since - # `vp config` needs git - pnpm rebuild --pending "''${pnpmInstallFlags[@]}" --filter '!@t3tools/monorepo' - ''; - - pnpmBuildScript = "build:desktop"; - - postBuild = '' - pnpm vp cache clean - ''; - - # Many dependencies vendors many prebuilt native artifacts for non-host - # platforms, and some of those binaries are statically linked. Let fixup - # handle wrappers, shebangs, and stripping, but skip patchelf on the - # vendored tree. - dontPatchELF = true; - # The tmpdir audit hook also shells out to patchelf while scanning every - # vendored ELF for leaked build paths. That produces spurious warnings on - # some dependencies' static foreign-platform binaries. - noAuditTmpdir = true; - - installPhase = '' - runHook preInstall - - mkdir --parents "$out"/libexec/t3code/apps/desktop "$out"/libexec/t3code/apps/server - cp --recursive --no-preserve=mode node_modules "$out"/libexec/t3code - cp --recursive --no-preserve=mode apps/server/{node_modules,dist} "$out"/libexec/t3code/apps/server - cp --recursive --no-preserve=mode \ - apps/desktop/{package.json,node_modules,dist-electron} \ - "$out"/libexec/t3code/apps/desktop - - mkdir --parents "$out"/libexec/t3code/apps/desktop/prod-resources - install --mode=444 ${desktopIcon} \ - "$out"/libexec/t3code/apps/desktop/prod-resources/icon.png - - find "$out"/libexec/t3code -xtype l -delete - - makeWrapper ${lib.getExe nodejs} "$out"/bin/t3 \ - --add-flags "$out"/libexec/t3code/apps/server/dist/bin.mjs ${runtimePathWrapperArgs} - - makeWrapper ${lib.getExe electron} "$out"/bin/t3code-desktop \ - --add-flags "$out"/libexec/t3code/apps/desktop \ - --inherit-argv0 ${runtimePathWrapperArgs} - '' - + lib.optionalString stdenv.hostPlatform.isDarwin '' - # node-pty tries to chmod this helper at runtime, but the Nix store is - # immutable by then. - find "$out"/libexec/t3code \ - -path '*/node-pty/prebuilds/darwin-*/spawn-helper' \ - -exec chmod 755 {} + - - mkdir --parents "$out/Applications/${appName}.app/Contents/"{MacOS,Resources} - png2icns \ - "$out/Applications/${appName}.app/Contents/Resources/t3code.icns" \ - ${desktopIcon} - - # writeDarwinBundle is a shebangless bash script; run it explicitly via - # stdenv.shell to avoid Darwin's intermittent ENOEXEC fallback issues. - ${stdenv.shell} ${lib.getExe writeDarwinBundle} \ - "$out" "${appName}" t3code-desktop t3code - '' - + '' - mkdir --parents \ - "$out"/share/icons/hicolor/scalable/apps - install --mode=444 ${desktopIcon} \ - "$out"/share/icons/t3code.png - install --mode=444 assets/prod/logo.svg \ - "$out"/share/icons/hicolor/scalable/apps/t3code.svg - - runHook postInstall - ''; - - postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' - for shell in bash fish zsh; do - installShellCompletion --cmd t3 --"$shell" <("$out/bin/t3" --completions "$shell") - done - ''; - - desktopItems = [ - (makeDesktopItem { - name = "t3code"; - desktopName = appName; - comment = "Minimal web GUI for coding agents"; - exec = "t3code-desktop %U"; - terminal = false; - icon = "t3code"; - startupWMClass = "t3code"; - categories = [ "Development" ]; - }) - ]; - - passthru = { - updateScript = nix-update-script { }; - }; - - meta = { - description = "Minimal web GUI for coding agents"; - homepage = "https://t3.codes"; - downloadPage = "https://t3.codes/download"; - changelog = "https://github.com/pingdotgg/t3code/releases/tag/${finalAttrs.src.tag}"; - license = lib.licenses.mit; - maintainers = with lib.maintainers; [ - iamanaws - qweered - ]; - mainProgram = "t3code-desktop"; - inherit (nodejs.meta) platforms; - }; + passthru = { + unwrapped = t3code-unwrapped; } -) + // t3code-unwrapped.passthru; + + meta = { + # Manually inherit so that pos works + inherit (t3code-unwrapped.meta) + description + homepage + downloadPage + changelog + license + maintainers + mainProgram + platforms + ; + }; +} diff --git a/pkgs/by-name/t3/t3code/unwrapped.nix b/pkgs/by-name/t3/t3code/unwrapped.nix new file mode 100644 index 000000000000..eddfbebb6874 --- /dev/null +++ b/pkgs/by-name/t3/t3code/unwrapped.nix @@ -0,0 +1,216 @@ +{ + cctools, + copyDesktopItems, + electron_41, + fetchFromGitHub, + installShellFiles, + lib, + libicns, + makeBinaryWrapper, + makeDesktopItem, + nix-update-script, + node-gyp, + nodejs, + python3, + stdenv, + writeDarwinBundle, + xcbuild, + fetchPnpmDeps, + pnpm_10, + pnpmConfigHook, + pnpmBuildHook, + cacert, +}: + +stdenv.mkDerivation ( + finalAttrs: + let + appName = "T3 Code (Alpha)"; + electron = electron_41; + pnpm = pnpm_10; + desktopIcon = + if stdenv.hostPlatform.isDarwin then + "assets/prod/black-macos-1024.png" + else + "assets/prod/black-universal-1024.png"; + + in + { + pname = "t3code-unwrapped"; + version = "0.0.28"; + strictDeps = true; + __structuredAttrs = true; + + src = fetchFromGitHub { + owner = "pingdotgg"; + repo = "t3code"; + tag = "v${finalAttrs.version}"; + hash = "sha256-InVrw9L281QSSPrHSiZuivmb+FkYEd6FkHwHIAAxmGk="; + }; + + postPatch = '' + substituteInPlace apps/web/vite.config.ts \ + --replace-fail 'const host = process.env.HOST?.trim() || "localhost";' \ + 'const host = process.env.HOST?.trim() || "127.0.0.1";' + ''; + + nativeBuildInputs = [ + installShellFiles + makeBinaryWrapper + node-gyp + nodejs + python3 + pnpmConfigHook + pnpmBuildHook + pnpm + cacert + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ copyDesktopItems ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + cctools.libtool + libicns + writeDarwinBundle + xcbuild + ]; + + pnpmWorkspaces = [ + # `...` suffix is used to also include other workspace packages that are + # directly or indirectly depended on by the listed packages, such as + # `@t3tools/contracts` and `@t3tools/shared`. + "@t3tools/monorepo" + "t3..." + "@t3tools/desktop..." + "@t3tools/scripts..." + ]; + + pnpmDeps = fetchPnpmDeps { + inherit pnpm; + inherit (finalAttrs) + pname + version + src + pnpmWorkspaces + ; + + fetcherVersion = 4; + hash = "sha256-+JqW/iI0wdRPxyL7y6ggD/+AvwwZXs9+fSUtG/SgW9s="; + }; + + preBuild = '' + node scripts/update-release-package-versions.ts ${finalAttrs.version} + + export npm_config_nodedir=${nodejs} + export ELECTRON_SKIP_BINARY_DOWNLOAD=1 + # Exclude the `@t3tools/monorepo` workspace from the pending rebuild since + # `vp config` needs git + pnpm rebuild --pending "''${pnpmInstallFlags[@]}" --filter '!@t3tools/monorepo' + ''; + + pnpmBuildScript = "build:desktop"; + + postBuild = '' + pnpm vp cache clean + ''; + + # Many dependencies vendors many prebuilt native artifacts for non-host + # platforms, and some of those binaries are statically linked. Let fixup + # handle wrappers, shebangs, and stripping, but skip patchelf on the + # vendored tree. + dontPatchELF = true; + # The tmpdir audit hook also shells out to patchelf while scanning every + # vendored ELF for leaked build paths. That produces spurious warnings on + # some dependencies' static foreign-platform binaries. + noAuditTmpdir = true; + + installPhase = '' + runHook preInstall + + mkdir --parents "$out"/libexec/t3code/apps/desktop "$out"/libexec/t3code/apps/server + cp --recursive --no-preserve=mode node_modules "$out"/libexec/t3code + cp --recursive --no-preserve=mode apps/server/{node_modules,dist} "$out"/libexec/t3code/apps/server + cp --recursive --no-preserve=mode \ + apps/desktop/{package.json,node_modules,dist-electron} \ + "$out"/libexec/t3code/apps/desktop + + mkdir --parents "$out"/libexec/t3code/apps/desktop/prod-resources + install --mode=444 ${desktopIcon} \ + "$out"/libexec/t3code/apps/desktop/prod-resources/icon.png + + find "$out"/libexec/t3code -xtype l -delete + + makeWrapper ${lib.getExe nodejs} "$out"/bin/t3 \ + --add-flags "$out"/libexec/t3code/apps/server/dist/bin.mjs + + makeWrapper ${lib.getExe electron} "$out"/bin/t3code-desktop \ + --add-flags "$out"/libexec/t3code/apps/desktop \ + --inherit-argv0 + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + # node-pty tries to chmod this helper at runtime, but the Nix store is + # immutable by then. + find "$out"/libexec/t3code \ + -path '*/node-pty/prebuilds/darwin-*/spawn-helper' \ + -exec chmod 755 {} + + + mkdir --parents "$out/Applications/${appName}.app/Contents/"{MacOS,Resources} + png2icns \ + "$out/Applications/${appName}.app/Contents/Resources/t3code.icns" \ + ${desktopIcon} + + # writeDarwinBundle is a shebangless bash script; run it explicitly via + # stdenv.shell to avoid Darwin's intermittent ENOEXEC fallback issues. + ${stdenv.shell} ${lib.getExe writeDarwinBundle} \ + "$out" "${appName}" t3code-desktop t3code + '' + + '' + mkdir --parents \ + "$out"/share/icons/hicolor/scalable/apps + install --mode=444 ${desktopIcon} \ + "$out"/share/icons/t3code.png + install --mode=444 assets/prod/logo.svg \ + "$out"/share/icons/hicolor/scalable/apps/t3code.svg + + runHook postInstall + ''; + + postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' + for shell in bash fish zsh; do + installShellCompletion --cmd t3 --"$shell" <("$out/bin/t3" --completions "$shell") + done + ''; + + desktopItems = [ + (makeDesktopItem { + name = "t3code"; + desktopName = appName; + comment = "Minimal web GUI for coding agents"; + exec = "t3code-desktop %U"; + terminal = false; + icon = "t3code"; + startupWMClass = "t3code"; + categories = [ "Development" ]; + }) + ]; + + passthru = { + updateScript = nix-update-script { + attrPath = "t3code.unwrapped"; + extraArgs = [ "--use-github-releases" ]; + }; + }; + + meta = { + description = "Minimal web GUI for coding agents"; + homepage = "https://t3.codes"; + downloadPage = "https://t3.codes/download"; + changelog = "https://github.com/pingdotgg/t3code/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ + iamanaws + qweered + ]; + mainProgram = "t3code-desktop"; + inherit (nodejs.meta) platforms; + }; + } +)