Files
t3code-flake/packages/t3code-server/default.nix
T
unexplrd cd931c951e Wrap T3 Code apps with optional agent CLI paths
- Split base desktop/server derivations from wrapper layers
- Add optional PATH injection for codex, claudeCode, and opencode
- Update flake inputs and lock entries for nixpkgs/llm-agents
2026-04-28 12:47:38 +03:00

154 lines
4.4 KiB
Nix

{
lib,
src,
stdenv,
symlinkJoin,
bun,
codex ? null,
claudeCode ? null,
makeBinaryWrapper,
node-gyp,
nodejs,
opencode ? null,
python3,
writableTmpDirAsHomeHook,
withClaudeCode ? false,
withCodex ? false,
withOpencode ? false,
}: let
common = import ../common.nix {
inherit
lib
stdenv
bun
nodejs
writableTmpDirAsHomeHook
;
};
serverPackageJson = lib.importJSON "${src}/apps/server/package.json";
pname = "t3code-server";
version = serverPackageJson.version;
basePackage = stdenv.mkDerivation (finalAttrs: {
inherit pname version;
inherit src;
strictDeps = true;
nodeModules = common.mkNodeModules {
inherit (finalAttrs) pname version src;
outputHash = "sha256-eXNOHRuNv9XFhXmsFtkunZswtRPd8gzJB1Jdw2DxYZY=";
filters = [
"."
"./apps/server"
"./apps/web"
"./packages/client-runtime"
"./packages/contracts"
"./packages/effect-acp"
"./packages/effect-codex-app-server"
"./packages/shared"
];
};
runtimeNodeModules = common.mkNodeModules {
inherit (finalAttrs) pname version src;
outputHash = "sha256-EcUsCt8liYnmzsDXzdwfLbMEk4/OYHB6DkcjjvmTWEM=";
installFlags = [
"--production"
];
filters = [
"."
"./apps/server"
"./apps/web"
"./packages/client-runtime"
"./packages/contracts"
"./packages/effect-acp"
"./packages/effect-codex-app-server"
"./packages/shared"
];
};
nativeBuildInputs = [
bun
makeBinaryWrapper
node-gyp
nodejs
python3
writableTmpDirAsHomeHook
];
configurePhase = common.mkNodePtyConfigurePhase {
nodeModules = finalAttrs.nodeModules;
};
buildPhase = ''
runHook preBuild
export HOME="$TMPDIR"
export BUN_INSTALL_CACHE_DIR="$(mktemp -d)"
bun run --cwd apps/web build
bun run --cwd apps/server build
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p "$out/libexec/t3code/apps/server"
mkdir -p "$out/libexec/t3code/apps"
mkdir -p "$out/libexec/t3code/packages"
cp -R --no-preserve=mode ${finalAttrs.runtimeNodeModules} "$out/libexec/t3code/node_modules"
chmod -R u+rwX "$out/libexec/t3code/node_modules"
rm -rf "$out/libexec/t3code/node_modules/node-pty"
cp -R --no-preserve=mode node_modules/node-pty "$out/libexec/t3code/node_modules/"
cp -R --no-preserve=mode apps/server/dist "$out/libexec/t3code/apps/server/"
cp -R --no-preserve=mode apps/web "$out/libexec/t3code/apps/"
cp -R --no-preserve=mode packages/client-runtime "$out/libexec/t3code/packages/"
cp -R --no-preserve=mode packages/contracts "$out/libexec/t3code/packages/"
cp -R --no-preserve=mode packages/effect-acp "$out/libexec/t3code/packages/"
cp -R --no-preserve=mode packages/effect-codex-app-server "$out/libexec/t3code/packages/"
cp -R --no-preserve=mode packages/shared "$out/libexec/t3code/packages/"
makeWrapper ${lib.getExe nodejs} "$out/bin/t3" \
--add-flags "$out/libexec/t3code/apps/server/dist/bin.mjs"
runHook postInstall
'';
meta = {
description = "T3 Code web/server app";
homepage = "https://github.com/pingdotgg/t3code";
license = lib.licenses.mit;
mainProgram = "t3";
platforms = lib.platforms.unix;
sourceProvenance = with lib.sourceTypes; [fromSource];
};
});
withAgentPath = withCodex || withClaudeCode || withOpencode;
agentPath = lib.makeBinPath (
lib.optionals withCodex [codex]
++ lib.optionals withClaudeCode [claudeCode]
++ lib.optionals withOpencode [opencode]
);
in
assert lib.assertMsg (!withCodex || codex != null) "withCodex requires a codex package";
assert lib.assertMsg (!withClaudeCode || claudeCode != null) "withClaudeCode requires a claudeCode package";
assert lib.assertMsg (!withOpencode || opencode != null) "withOpencode requires an opencode package";
if withAgentPath
then
symlinkJoin {
inherit pname version;
name = "${pname}-${version}";
paths = [basePackage];
nativeBuildInputs = [makeBinaryWrapper];
postBuild = ''
wrapProgram "$out/bin/t3" \
--prefix PATH : "${agentPath}"
'';
meta = basePackage.meta;
}
else basePackage