315 lines
8.9 KiB
Nix
315 lines
8.9 KiB
Nix
{
|
|
description = "Reusable jailed LLM agents (opencode)";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
jail-nix.url = "sourcehut:~alexdavid/jail.nix";
|
|
llm-agents.url = "github:numtide/llm-agents.nix";
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
};
|
|
|
|
outputs =
|
|
{
|
|
self,
|
|
nixpkgs,
|
|
flake-utils,
|
|
jail-nix,
|
|
llm-agents,
|
|
...
|
|
}:
|
|
flake-utils.lib.eachDefaultSystem (
|
|
system:
|
|
let
|
|
pkgs = nixpkgs.legacyPackages.${system};
|
|
jail = jail-nix.lib.init pkgs;
|
|
|
|
defaultPackages = with pkgs; [
|
|
bashInteractive
|
|
curl
|
|
wget
|
|
jq
|
|
git
|
|
which
|
|
ripgrep
|
|
gnugrep
|
|
gawkInteractive
|
|
ps
|
|
findutils
|
|
gzip
|
|
unzip
|
|
gnutar
|
|
diffutils
|
|
];
|
|
|
|
makeJailedConfig = {
|
|
name,
|
|
jail,
|
|
pkgs,
|
|
extraPkgs ? [ ],
|
|
extraCombinators ? [ ],
|
|
mountCwd ? true,
|
|
}:
|
|
with jail.combinators;
|
|
(
|
|
[
|
|
network
|
|
time-zone
|
|
no-new-session
|
|
]
|
|
++ (if mountCwd then [ mount-cwd ] else [ ])
|
|
++ [
|
|
(readwrite (noescape "~/.config/${name}"))
|
|
(readwrite (noescape "~/.local/share/${name}"))
|
|
(readwrite (noescape "~/.local/state/${name}"))
|
|
(add-pkg-deps defaultPackages)
|
|
(add-pkg-deps extraPkgs)
|
|
]
|
|
++ extraCombinators
|
|
);
|
|
|
|
makeJailedAgent = {
|
|
name,
|
|
pkg,
|
|
extraPkgs ? [ ],
|
|
extraCombinators ? [ ],
|
|
mountCwd ? true,
|
|
}:
|
|
jail name pkg (makeJailedConfig {
|
|
inherit name jail pkgs extraPkgs extraCombinators mountCwd;
|
|
});
|
|
|
|
# CWD-mounted variants
|
|
opencode-jailed = makeJailedAgent {
|
|
name = "opencode";
|
|
pkg = llm-agents.packages.${system}.opencode;
|
|
};
|
|
|
|
claude-jailed = makeJailedAgent {
|
|
name = "claude-code";
|
|
pkg = llm-agents.packages.${system}.claude-code;
|
|
};
|
|
|
|
# No-CWD variants
|
|
opencode-jailed-nocwd = makeJailedAgent {
|
|
name = "opencode";
|
|
pkg = llm-agents.packages.${system}.opencode;
|
|
mountCwd = false;
|
|
};
|
|
|
|
claude-jailed-nocwd = makeJailedAgent {
|
|
name = "claude-code";
|
|
pkg = llm-agents.packages.${system}.claude-code;
|
|
mountCwd = false;
|
|
};
|
|
|
|
lib = {
|
|
# Call as: inputs.jailed-agents.lib.makeJailed system { agentTool = "opencode"; extraPkgs = [...]; mountCwd = false; }
|
|
makeJailed =
|
|
system':
|
|
{
|
|
agentTool,
|
|
extraPkgs ? [ ],
|
|
extraCombinators ? [ ],
|
|
mountCwd ? true,
|
|
}:
|
|
let
|
|
pkgs' = nixpkgs.legacyPackages.${system'};
|
|
jail' = jail-nix.lib.init pkgs';
|
|
pkg' = llm-agents.packages.${system'}.opencode;
|
|
defaultPackages' = with pkgs'; [
|
|
bashInteractive
|
|
curl
|
|
wget
|
|
jq
|
|
git
|
|
which
|
|
ripgrep
|
|
gnugrep
|
|
gawkInteractive
|
|
ps
|
|
findutils
|
|
gzip
|
|
unzip
|
|
gnutar
|
|
diffutils
|
|
];
|
|
makeJailedConfig' = {
|
|
name,
|
|
jail,
|
|
pkgs,
|
|
extraPkgs ? [ ],
|
|
extraCombinators ? [ ],
|
|
mountCwd ? true,
|
|
}:
|
|
with jail'.combinators;
|
|
(
|
|
[
|
|
network
|
|
time-zone
|
|
no-new-session
|
|
]
|
|
++ (if mountCwd then [ mount-cwd ] else [ ])
|
|
++ [
|
|
(readwrite (noescape "~/.config/${name}"))
|
|
(readwrite (noescape "~/.local/share/${name}"))
|
|
(readwrite (noescape "~/.local/state/${name}"))
|
|
(add-pkg-deps defaultPackages')
|
|
(add-pkg-deps extraPkgs)
|
|
]
|
|
++ extraCombinators
|
|
);
|
|
in
|
|
jail' agentTool pkg' (makeJailedConfig' {
|
|
name = agentTool;
|
|
jail = jail';
|
|
pkgs = pkgs';
|
|
inherit extraPkgs extraCombinators mountCwd;
|
|
});
|
|
};
|
|
|
|
test-agent-basic = lib.makeJailed system {
|
|
agentTool = "test-agent";
|
|
};
|
|
|
|
test-agent-extra = lib.makeJailed system {
|
|
agentTool = "test-agent-extra";
|
|
extraPkgs = [ pkgs.hello ];
|
|
};
|
|
in
|
|
{
|
|
packages = {
|
|
inherit
|
|
opencode-jailed
|
|
claude-jailed
|
|
opencode-jailed-nocwd
|
|
claude-jailed-nocwd
|
|
;
|
|
};
|
|
|
|
checks = {
|
|
opencode-jailed-build = pkgs.runCommand "test-opencode-jailed" {
|
|
buildInputs = [ opencode-jailed ];
|
|
} ''
|
|
test -f ${opencode-jailed}/bin/opencode
|
|
touch $out
|
|
'';
|
|
|
|
claude-jailed-build = pkgs.runCommand "test-claude-jailed" {
|
|
buildInputs = [ claude-jailed ];
|
|
} ''
|
|
test -f ${claude-jailed}/bin/claude-code
|
|
touch $out
|
|
'';
|
|
|
|
opencode-jailed-nocwd-build = pkgs.runCommand "test-opencode-jailed-nocwd" {
|
|
buildInputs = [ opencode-jailed-nocwd ];
|
|
} ''
|
|
test -f ${opencode-jailed-nocwd}/bin/opencode-nocwd
|
|
touch $out
|
|
'';
|
|
|
|
claude-jailed-nocwd-build = pkgs.runCommand "test-claude-jailed-nocwd" {
|
|
buildInputs = [ claude-jailed-nocwd ];
|
|
} ''
|
|
test -f ${claude-jailed-nocwd}/bin/claude-code-nocwd
|
|
touch $out
|
|
'';
|
|
|
|
lib-makeJailed-basic = pkgs.runCommand "test-lib-makeJailed-basic" {
|
|
buildInputs = [ test-agent-basic ];
|
|
} ''
|
|
test -f ${test-agent-basic}/bin/test-agent
|
|
touch $out
|
|
'';
|
|
|
|
lib-makeJailed-with-extraPkgs = pkgs.runCommand "test-lib-makeJailed-extraPkgs" {
|
|
buildInputs = [ test-agent-extra ];
|
|
} ''
|
|
test -f ${test-agent-extra}/bin/test-agent-extra
|
|
test -d ${pkgs.hello}
|
|
touch $out
|
|
'';
|
|
|
|
test-opencode-tools = pkgs.runCommand "test-opencode-tools" {
|
|
buildInputs = [ opencode-jailed ];
|
|
} ''
|
|
test -f ${opencode-jailed}/bin/opencode
|
|
touch $out
|
|
'';
|
|
|
|
test-claude-tools = pkgs.runCommand "test-claude-tools" {
|
|
buildInputs = [ claude-jailed ];
|
|
} ''
|
|
test -f ${claude-jailed}/bin/claude-code
|
|
touch $out
|
|
'';
|
|
};
|
|
|
|
lib = {
|
|
# Call as: inputs.jailed-agents.lib.makeJailed system { agentTool = "opencode"; extraPkgs = [...]; mountCwd = false; }
|
|
makeJailed =
|
|
system':
|
|
{
|
|
agentTool,
|
|
extraPkgs ? [ ],
|
|
extraCombinators ? [ ],
|
|
mountCwd ? true,
|
|
}:
|
|
let
|
|
pkgs' = nixpkgs.legacyPackages.${system'};
|
|
jail' = jail-nix.lib.init pkgs';
|
|
pkg' = llm-agents.packages.${system'}.opencode;
|
|
defaultPackages' = with pkgs'; [
|
|
bashInteractive
|
|
curl
|
|
wget
|
|
jq
|
|
git
|
|
which
|
|
ripgrep
|
|
gnugrep
|
|
gawkInteractive
|
|
ps
|
|
findutils
|
|
gzip
|
|
unzip
|
|
gnutar
|
|
diffutils
|
|
];
|
|
makeJailedConfig' = {
|
|
name,
|
|
jail,
|
|
pkgs,
|
|
extraPkgs ? [ ],
|
|
extraCombinators ? [ ],
|
|
mountCwd ? true,
|
|
}:
|
|
with jail'.combinators;
|
|
(
|
|
[
|
|
network
|
|
time-zone
|
|
no-new-session
|
|
]
|
|
++ (if mountCwd then [ mount-cwd ] else [ ])
|
|
++ [
|
|
(readwrite (noescape "~/.config/${name}"))
|
|
(readwrite (noescape "~/.local/share/${name}"))
|
|
(readwrite (noescape "~/.local/state/${name}"))
|
|
(add-pkg-deps defaultPackages')
|
|
(add-pkg-deps extraPkgs)
|
|
]
|
|
++ extraCombinators
|
|
);
|
|
in
|
|
jail' agentTool pkg' (makeJailedConfig' {
|
|
name = agentTool;
|
|
jail = jail';
|
|
pkgs = pkgs';
|
|
inherit extraPkgs extraCombinators mountCwd;
|
|
});
|
|
};
|
|
}
|
|
);
|
|
}
|