{ description = "slopbot - Zulip bot with stock price lookups and LLM replies"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; agentd = { url = "git+file:///home/ben/src/bsima/agentd"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, agentd }: let system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; pythonEnv = pkgs.python3.withPackages (ps: [ ps.zulip ps.yfinance ps.openai ps.requests ]); agent = pkgs.rustPlatform.buildRustPackage { pname = "agent"; version = "0.1.0"; src = agentd; cargoLock.lockFile = "${agentd}/Cargo.lock"; cargoBuildFlags = [ "-p" "agent" ]; doCheck = false; }; researchPython = pkgs.python3.withPackages (ps: [ ps.trafilatura ]); slopSearch = pkgs.writeShellApplication { name = "slop-search"; runtimeInputs = [ pkgs.curl pkgs.jq pkgs.python3 ]; text = '' if [ "$#" -eq 0 ]; then echo "usage: slop-search QUERY" >&2 exit 2 fi if [ -z "''${KAGI_API_KEY:-}" ]; then echo "error: KAGI_API_KEY is not set" >&2 exit 1 fi query="$*" encoded="$(${pkgs.python3}/bin/python -c 'import sys, urllib.parse; print(urllib.parse.urlencode({"q": " ".join(sys.argv[1:])}))' "$@")" curl -fsS \ -H "Authorization: Bot ''${KAGI_API_KEY}" \ -H "Accept: application/json" \ "https://kagi.com/api/v0/search?''${encoded}" \ | jq -r --arg query "$query" ' "QUERY: \($query)", "", (.data // []) | map(select((.t // .type // "") == "search_result" or has("url"))) | .[:8] | to_entries[] | "[\(.key + 1)] \(.value.title // "untitled")\nURL: \(.value.url)\nSNIPPET: \(.value.snippet // .value.description // "")\n" ' ''; }; slopFetch = pkgs.writeShellApplication { name = "slop-fetch"; runtimeInputs = [ pkgs.curl researchPython ]; text = '' if [ "$#" -ne 1 ]; then echo "usage: slop-fetch URL" >&2 exit 2 fi url="$1" tmp="$(mktemp)" trap 'rm -f "$tmp"' EXIT curl -fsSL --max-time 20 -A 'slopbot/1.0' "$url" -o "$tmp" ${researchPython}/bin/python - "$url" "$tmp" <<'PY' import sys import trafilatura url, path = sys.argv[1], sys.argv[2] html = open(path, "rb").read() text = trafilatura.extract(html, url=url, include_comments=False, include_tables=False) if not text: print(f"error: could not extract readable text from {url}", file=sys.stderr) sys.exit(1) print(text[:12000]) PY ''; }; slopTools = pkgs.symlinkJoin { name = "slopbot-agent-tools"; paths = [ slopSearch slopFetch ]; }; in { devShells.${system}.default = pkgs.mkShell { buildInputs = [ pythonEnv agent slopTools ]; shellHook = '' echo "slopbot dev shell ready" echo "Run: python main.py" ''; }; packages.${system} = rec { default = slopbot; slopbot = pkgs.writeShellScriptBin "slopbot" '' cd /home/ben/src/bsima/slopbot export PATH=${slopTools}/bin export SLOPBOT_AGENT=${agent}/bin/agent export SLOPBOT_AGENT_PATH=${slopTools}/bin exec ${pythonEnv}/bin/python ${./main.py} ''; inherit agent slopTools slopSearch slopFetch; }; }; }