diff --git a/.gitignore b/.gitignore index b416337..2c25b15 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,9 @@ flake.lock.bak .sidecar/ .sidecar-* .sisyphus/ +.sidecar-agent +.sidecar-task +.sidecar-pr +.sidecar-start.sh +.sidecar-base +.td-root diff --git a/pkgs/default.nix b/pkgs/default.nix index 318e0e2..336c9d5 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -22,7 +22,8 @@ in { kestractl = pkgs.callPackage ./kestractl {}; openshell = pkgs.callPackage ./openshell {}; zellij-ps = pkgs.callPackage ./zellij-ps {}; - openwork = pkgs.callPackage ./openwork {}; + openwork = pkgs.callPackage ./openwork {inherit inputs;}; + vibetyper = pkgs.callPackage ./vibetyper {}; # Imported from flake inputs (pass-through, no modifications) basecamp = inputs.basecamp.packages.${system}.default; diff --git a/pkgs/openwork/default.nix b/pkgs/openwork/default.nix new file mode 100644 index 0000000..e8c7f66 --- /dev/null +++ b/pkgs/openwork/default.nix @@ -0,0 +1,206 @@ +{ + lib, + stdenv, + fetchFromGitHub, + rustPlatform, + pkg-config, + cargo-tauri, + bun, + nodejs, + pnpm_10, + fetchPnpmDeps, + pnpmConfigHook, + cargo, + rustc, + wrapGAppsHook3, + makeWrapper, + dbus, + glib, + gtk3, + libsoup_3, + librsvg, + libayatana-appindicator, + glib-networking, + openssl, + webkitgtk_4_1, + gst_all_1, + inputs ? null, +}: let + # Reuse the anomalyco/opencode binary already pinned in the flake + opencode = inputs.opencode.packages.${stdenv.hostPlatform.system}.default; + # NOTE: bun build --compile is run WITHOUT --target inside the Nix sandbox. + # Specifying a cross-target would cause Bun to download a remote runtime, + # which is forbidden in sandbox mode. We build for the host and rename the + # output binary to the Rust target triple that Tauri expects. +in + rustPlatform.buildRustPackage (finalAttrs: { + pname = "openwork"; + version = "0.11.199"; + + src = fetchFromGitHub { + owner = "different-ai"; + repo = "openwork"; + rev = "v${finalAttrs.version}"; + hash = "sha256-ErON7clClL0iFFbko4cAKgZROt/bJ8k9FTX8eivrDnA="; + }; + + # Rust crate lives inside the monorepo under apps/desktop/src-tauri + cargoRoot = "apps/desktop/src-tauri"; + cargoLock.lockFile = finalAttrs.src + "/apps/desktop/src-tauri/Cargo.lock"; + buildAndTestSubdir = finalAttrs.cargoRoot; + + # Prefetch the entire pnpm workspace store as a fixed-output derivation. + # After the first successful build, replace lib.fakeHash with the real hash + # from the error output. + pnpmDeps = fetchPnpmDeps { + inherit (finalAttrs) pname version src; + pnpm = pnpm_10; + fetcherVersion = 2; + hash = "sha256-+fN9h9htN5nGsh4wG4DqCilykmnJn0DDoFtrlF/ajRU="; + }; + + nativeBuildInputs = + [ + pkg-config + cargo-tauri.hook + bun + nodejs # needed for patchShebangs + pnpm_10 + pnpmConfigHook # installs workspace node_modules offline from pnpmDeps + cargo + rustc + makeWrapper + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [wrapGAppsHook3]; + + buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ + dbus + glib + gtk3 + libsoup_3 + librsvg + libayatana-appindicator + glib-networking + openssl + webkitgtk_4_1 + gst_all_1.gstreamer + gst_all_1.gst-plugins-base + gst_all_1.gst-plugins-good + gst_all_1.gst-plugins-bad + ]; + + strictDeps = true; + + # These two tests require docker or rely on OS-level process/timeout + # behaviour that differs inside the Nix sandbox: + # - docker_command_falls_back_after_timeout: expects docker (exit 127 = not found) + # - local_command_timeout_returns_when_descendant_keeps_pipe_open: sandbox kills + # descendant processes differently, so the expected error never arrives + checkFlags = [ + "--skip=commands::orchestrator::tests::docker_command_falls_back_after_timeout" + "--skip=commands::orchestrator::tests::local_command_timeout_returns_when_descendant_keeps_pipe_open" + ]; + + # cargo-tauri.hook: run `cargo tauri build` from this subdirectory + tauriRoot = "apps/desktop"; + + # Override tauri config at build time: + # - clear beforeBuildCommand (we run frontend + sidecars manually in preBuild) + # - disable updater artifact generation (no auto-update in Nix packages) + tauriBuildFlags = [ + "--config" + (builtins.toJSON { + build.beforeBuildCommand = ""; + bundle.createUpdaterArtifacts = false; + }) + "--no-sign" + ]; + + preBuild = let + target = stdenv.hostPlatform.rust.rustcTarget; + in '' + sidecarDir="$(pwd)/apps/desktop/src-tauri/sidecars" + mkdir -p "$sidecarDir" + + # ── 1. openwork-server ──────────────────────────────────────────────── + # Bun compiles TypeScript → self-contained native binary (no Bun runtime needed at runtime) + ( + cd apps/server + bun ./script/build.ts --outdir "$sidecarDir" --filename openwork-server + ) + # script/build.ts names the output after the bun target when --target is given; + # without --target it outputs just the filename. Rename to Tauri's expected triple format. + mv "$sidecarDir/openwork-server" "$sidecarDir/openwork-server-${target}" + + # ── 2. opencode-router ──────────────────────────────────────────────── + ( + cd apps/opencode-router + bun ./script/build.ts --outdir "$sidecarDir" --filename opencode-router + ) + mv "$sidecarDir/opencode-router" "$sidecarDir/opencode-router-${target}" + + # ── 3. openwork-orchestrator ────────────────────────────────────────── + ( + cd apps/orchestrator + bun ./script/build.ts --outdir "$sidecarDir" --filename openwork-orchestrator + ) + mv "$sidecarDir/openwork-orchestrator" "$sidecarDir/openwork-orchestrator-${target}" + + # ── 4. chrome-devtools-mcp shim ─────────────────────────────────────── + # This is a tiny TypeScript shim that proxies to `npm exec chrome-devtools-mcp`. + # We compile it the same way as the other sidecars. + bun build --compile apps/desktop/scripts/chrome-devtools-mcp-shim.ts \ + --outfile "$sidecarDir/chrome-devtools-mcp-${target}" + + # ── 5. opencode binary (from Nix store) ─────────────────────────────── + cp ${opencode}/bin/opencode "$sidecarDir/opencode-${target}" + chmod +x "$sidecarDir/opencode-${target}" + + # ── 6. versions.json (required by Tauri; sha256 computed at build time) ─ + oc_sha=$(sha256sum "$sidecarDir/opencode-${target}" | awk '{print $1}') + sv_sha=$(sha256sum "$sidecarDir/openwork-server-${target}" | awk '{print $1}') + rt_sha=$(sha256sum "$sidecarDir/opencode-router-${target}" | awk '{print $1}') + or_sha=$(sha256sum "$sidecarDir/openwork-orchestrator-${target}" | awk '{print $1}') + cd_sha=$(sha256sum "$sidecarDir/chrome-devtools-mcp-${target}" | awk '{print $1}') + + cat > "$sidecarDir/versions.json" <