From 85fd377ab1a5b93e574039a2f4aa868b73cb642d Mon Sep 17 00:00:00 2001 From: m3tm3re
Date: Fri, 3 Apr 2026 10:58:03 +0200
Subject: [PATCH] feat: openwork + vibetyper
---
.gitignore | 6 ++
pkgs/default.nix | 3 +-
pkgs/openwork/default.nix | 206 +++++++++++++++++++++++++++++++++++++
pkgs/vibetyper/default.nix | 34 ++++++
4 files changed, 248 insertions(+), 1 deletion(-)
create mode 100644 pkgs/openwork/default.nix
create mode 100644 pkgs/vibetyper/default.nix
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" <