This repository has no description
3.6 kB
88 lines
1{ inputs, ... }:
2{
3 perSystem =
4 {
5 pkgs,
6 self',
7 system,
8 ...
9 }:
10 let
11 server = "https://omni.lassul.us";
12 omp = inputs.llm-agents.packages.${system}.omp;
13
14 # The agent this machine runs. omp speaks the Agent Client Protocol
15 # (`omp acp`), so omnigent's generic `acp` harness drives it with no
16 # adapter code. The command is the absolute store path because the spec
17 # is consumed by the runner started here, and that path is in this
18 # wrapper's closure — unlike the server-side catalog entry in
19 # 2configs/omnigent.nix, which has to stay unqualified.
20 #
21 # os_env is what unlocks the dashboard's file panel: without it the
22 # runner reports no OS environment and the changed-files/diff endpoints
23 # 404. sandbox none because omp needs its own ~/.omp credential store and
24 # unrestricted egress to the model APIs; confinement, if we want it, has
25 # to happen a layer down (a separate uid, or nspawn), not here.
26 #
27 # omnigent_mcp: false is load-bearing. With it on, omnigent hands omp an
28 # `mcpServers` entry in `session/new` whose command is
29 # `sys.executable -I -m omnigent.claude_native_bridge serve-mcp`; `-I`
30 # (isolated) makes that child ignore PYTHONPATH, so under a nixpkgs
31 # console-script wrapping it cannot import omnigent. omp starts every
32 # declared MCP server eagerly and fails the whole session when one dies —
33 # `ACP session/new failed: Internal error`. The relay only bridges
34 # *omnigent's* builtin tools into the agent, and omp brings its own, so
35 # turning it off costs nothing here.
36 spec = pkgs.writeText "omp-agent.yaml" ''
37 name: omp
38 prompt: You are omp (Oh My Pi), a concise coding assistant.
39
40 executor:
41 harness: acp
42 acp_agent:
43 name: Oh My Pi
44 command: ${omp}/bin/omp acp
45 omnigent_mcp: false
46
47 os_env:
48 type: caller_process
49 cwd: "."
50 sandbox:
51 type: none
52 '';
53 in
54 {
55 # Launch omp as a session on the omni.lassul.us dashboard: the agent and
56 # its runner stay on this machine (local runner + remote server
57 # topology), while the server holds the transcript, the diff view and the
58 # per-session ACLs, so a session can be shared read-only or read-write
59 # with another pocket-id account. The terminal REPL and the browser drive
60 # the same session.
61 #
62 # First use per machine opens a browser for the pocket-id login; the
63 # session JWT is cached in ~/.omnigent/auth_tokens.json afterwards.
64 # Arguments go to `omnigent run`, so `covibe -p "fix the tests"` runs one
65 # non-interactive turn and `covibe --fork <session-id>` continues someone
66 # else's session here.
67 packages.covibe =
68 (pkgs.writeShellApplication {
69 name = "covibe";
70 runtimeInputs = [
71 self'.packages.omnigent
72 omp
73 pkgs.jq
74 pkgs.git
75 ];
76 text = ''
77 server=${server}
78 tokens="$HOME/.omnigent/auth_tokens.json"
79 if ! jq -e --arg s "$server" '.[$s].token // empty' "$tokens" >/dev/null 2>&1; then
80 echo "covibe: no session for $server yet, logging in" >&2
81 omnigent login "$server"
82 fi
83 exec omnigent run ${spec} --server "$server" "$@"
84 '';
85 }).overrideAttrs
86 { passthru.usage = builtins.readFile ./usage.kdl; };
87 };
88}