aboutsummaryrefslogtreecommitdiff
path: root/nixos/profiles/workstation/pkgs/pi.nix
blob: 243bff24388e35059d581510bcfcf1424002e27a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
{
  bubblewrap,
  coreutils,
  lib,
  pi-coding-agent,
  python3,
  runCommand,
  symlinkJoin,
  writeShellScriptBin,
}:

let
  # Patch away the new distracting block-art logo. We're patching dist/
  # rather than src to avoid downloading >600MB of npm-deps.
  pi-coding-agent-patched = runCommand "${pi-coding-agent.name}-no-logo" { } ''
    cp -a ${pi-coding-agent} "$out"
    chmod -R u+w "$out"

    substituteInPlace "$out/lib/node_modules/pi-monorepo/dist/modes/interactive/components/pi-logo.js" \
      --replace-fail 'return !isAppleTerminalSession();' 'return false;' \
      --replace-fail 'return `''${foregroundAnsi(CORAL, mode)}P''${RESET}''${foregroundAnsi(YELLOW, mode)}i''${RESET}`;' \
                     'return theme.bold(theme.fg("accent", "pi"));'
    substituteInPlace "$out/lib/node_modules/pi-monorepo/dist/bundle/chunks/chunk-66G7ITPS.js" \
      --replace-fail 'function supportsPiLogo(){return!isAppleTerminalSession()}' \
                     'function supportsPiLogo(){return false}' \
      --replace-fail 'function piWordmark(){let mode=theme.getColorMode();return`''${foregroundAnsi(CORAL,mode)}P''${RESET}''${foregroundAnsi(YELLOW,mode)}i''${RESET}`}' \
                     'function piWordmark(){return theme.bold(theme.fg("accent","pi"))}'

    substituteInPlace "$out/bin/pi" "$out/bin/.pi-wrapped" \
      --replace-fail '${pi-coding-agent}' "$out"
  '';

  sbox = writeShellScriptBin "sbox" ''
    set -euo pipefail

    ${coreutils}/bin/mkdir -p /tmp/pi "$HOME/.local/share/cargo-pi"

    bwrap_args=(
      --die-with-parent
      --unshare-pid
      --unshare-uts
      --unshare-cgroup
      --tmpfs /
      --dev /dev
      --proc /proc
      --bind /tmp/pi /tmp
      --ro-bind /etc /etc
      --bind /nix/store /nix/store
      --ro-bind /usr/bin/env /usr/bin/env
      --setenv NIX_REMOTE daemon
      --bind-try /nix/var/nix/daemon-socket /nix/var/nix/daemon-socket
      --dir /run
      --ro-bind-try /run/current-system /run/current-system
      --ro-bind /doc /doc
      --ro-bind "$HOME/.config/git" "$HOME/.config/git"
      --ro-bind "$HOME/.config/jj" "$HOME/.config/jj"
      --ro-bind "$HOME/repos/config" "$HOME/repos/config"
      # jj must be able to write to ~/.config/jj/repos: https://github.com/jj-vcs/jj/issues/8841
      --overlay-src "$HOME/.config/jj" --tmp-overlay "$HOME/.config/jj"
      --setenv CARGO_HOME "$HOME/.local/share/cargo"
      --bind "$HOME/.local/share/cargo-pi" "$HOME/.local/share/cargo"
    )

    exec ${bubblewrap}/bin/bwrap "''${bwrap_args[@]}" "$@"
  '';

  pi = writeShellScriptBin "pi" ''
    set -euo pipefail

    physical_pwd="$(${coreutils}/bin/pwd -P)"

    exec ${sbox}/bin/sbox \
      --setenv PATH "${lib.makeBinPath [ python3 ]}:$PATH" \
      --setenv PI_CODING_AGENT_DIR "$HOME/.config/pi" \
      --bind "$HOME/.config/pi" "$HOME/.config/pi" \
      --bind "$physical_pwd" "$physical_pwd" \
      --chdir "$physical_pwd" \
      ${pi-coding-agent-patched}/bin/pi \
        --append-system-prompt "You're running in a sandbox with an ephemeral root filesystem and a separate PID namespace. The current working directory and a few configuration and cache paths are mounted from the host." \
        --append-system-prompt "$HOME/.config/pi/APPEND_SYSTEM.md" \
        "$@"
  '';

  pit = writeShellScriptBin "pit" ''
    set -euo pipefail

    tmp_cwd="$(${coreutils}/bin/mktemp -d /tmp/pit.XXXXXX)"
    cleanup() {
      ${coreutils}/bin/rmdir "$tmp_cwd" 2>/dev/null || true
    }
    trap cleanup EXIT

    cd "$tmp_cwd"
    exec ${pi}/bin/pi "$@"
  '';
in
symlinkJoin {
  name = "pi-sandboxed";
  paths = [
    sbox
    pi
    pit
  ];
}