openshell: 0.0.22 -> 0.0.23

This commit is contained in:
m3tm3re
2026-04-06 18:23:44 +02:00
parent b65bbcacbe
commit 19332ebb74
7 changed files with 515 additions and 25 deletions

8
flake.lock generated
View File

@@ -60,16 +60,16 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1775004246, "lastModified": 1774996501,
"narHash": "sha256-P6Md0WzHK2/oAZ6VbpYnabVJyVcqwuYizoOqbxaf+lU=", "narHash": "sha256-1sEkQDdV/qU4/N9oHR4mptllcRWt503k6HZ8Yp4EooE=",
"owner": "anomalyco", "owner": "anomalyco",
"repo": "opencode", "repo": "opencode",
"rev": "6314f09c14fdd6a3ab8bedc4f7b7182647551d12", "rev": "892bdebaacbed3fc76976431c7aa7b81ab639fb6",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "anomalyco", "owner": "anomalyco",
"ref": "v1.3.13", "ref": "v1.3.12",
"repo": "opencode", "repo": "opencode",
"type": "github" "type": "github"
} }

View File

@@ -12,7 +12,7 @@
# opencode needs newer bun from master # opencode needs newer bun from master
opencode = { opencode = {
url = "github:anomalyco/opencode/v1.3.13"; url = "github:anomalyco/opencode/v1.3.12";
inputs.nixpkgs.follows = "nixpkgs-master"; inputs.nixpkgs.follows = "nixpkgs-master";
}; };

374
modules/nixos/honcho.nix Normal file
View File

@@ -0,0 +1,374 @@
# NixOS Module for Honcho AI Memory Server
#
# This module provides systemd services for the Honcho API server and
# background deriver process, with configurable PostgreSQL and Redis backends.
#
# Usage in your NixOS configuration:
#
# imports = [ inputs.m3ta-nixpkgs.nixosModules.default ];
#
# m3ta.honcho = {
# enable = true;
# port = 8000;
# host = "127.0.0.1";
#
# # Database (PostgreSQL with pgvector)
# database = {
# connectionUri = "postgresql+psycopg://honcho:password@localhost:5432/honcho";
# };
#
# # Redis cache
# cache = {
# url = "redis://localhost:6379/0";
# };
#
# # LLM API keys (use agenix or sops-nix for secrets)
# environmentFile = "/run/secrets/honcho-env";
# };
#
# Using with m3ta.ports (recommended):
#
# m3ta.ports = {
# enable = true;
# definitions = { honcho = 8000; };
# currentHost = config.networking.hostName;
# };
#
# m3ta.honcho = {
# enable = true;
# port = config.m3ta.ports.get "honcho";
# };
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.m3ta.honcho;
# Python environment with honcho and FastAPI CLI
pythonEnv = pkgs.python3.withPackages (ps:
with ps; [
cfg.package
]);
# Start script for the API server
startScript = pkgs.writeShellScript "honcho-start" ''
set -e
# Load environment file if specified
${optionalString (cfg.environmentFile != null) ''
if [ -f "${cfg.environmentFile}" ]; then
set -a
source "${cfg.environmentFile}"
set +a
fi
''}
# Create state directory
mkdir -p ${cfg.stateDir}
# Run database migrations
${pythonEnv}/bin/python -c "
import sys; sys.path.insert(0, '${cfg.package}/${pythonEnv.sitePackages}')
from scripts.provision_db import *
" 2>/dev/null || echo "Skipping database provisioning (script may not be available)"
# Run the API server
exec ${pythonEnv}/bin/fastapi run \
--host ${cfg.host} \
--port ${toString cfg.port} \
${cfg.package}/${pythonEnv.sitePackages}/src/main.py
'';
# Start script for the deriver background worker
deriverScript = pkgs.writeShellScript "honcho-deriver" ''
set -e
# Load environment file if specified
${optionalString (cfg.environmentFile != null) ''
if [ -f "${cfg.environmentFile}" ]; then
set -a
source "${cfg.environmentFile}"
set +a
fi
''}
# Create state directory
mkdir -p ${cfg.stateDir}
# Run the deriver
exec ${pythonEnv}/bin/python -m src.deriver
'';
in {
options.m3ta.honcho = {
enable = mkEnableOption "Honcho AI memory server";
package = mkOption {
type = types.package;
default = pkgs.honcho;
defaultText = literalExpression "pkgs.honcho";
description = "The honcho package to use.";
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Host address to bind the API server to.";
};
port = mkOption {
type = types.port;
default = 8000;
description = "Port to run the API server on.";
};
stateDir = mkOption {
type = types.path;
default = "/var/lib/honcho";
description = "Directory to store honcho data and state.";
};
user = mkOption {
type = types.str;
default = "honcho";
description = "User account under which honcho runs.";
};
group = mkOption {
type = types.str;
default = "honcho";
description = "Group under which honcho runs.";
};
environmentFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Environment file containing configuration and secrets.
This file should contain KEY=value pairs, one per line.
Use this for API keys, database credentials, and other secrets.
See the honcho .env.template for available variables.
'';
example = "/run/secrets/honcho-env";
};
# Database Configuration
database = {
connectionUri = mkOption {
type = types.str;
default = "postgresql+psycopg://honcho:honcho@localhost:5432/honcho";
description = ''
PostgreSQL connection URI with pgvector support.
Must use postgresql+psycopg prefix for SQLAlchemy compatibility.
'';
example = "postgresql+psycopg://honcho:password@localhost:5432/honcho";
};
schema = mkOption {
type = types.str;
default = "public";
description = "Database schema to use.";
};
poolSize = mkOption {
type = types.int;
default = 10;
description = "Connection pool size.";
};
maxOverflow = mkOption {
type = types.int;
default = 20;
description = "Maximum connection pool overflow.";
};
};
# Cache Configuration
cache = {
url = mkOption {
type = types.str;
default = "redis://localhost:6379/0";
description = ''
Redis cache URL.
Set suppress=true to suppress connection errors: redis://localhost:6379/0?suppress=true
'';
example = "redis://localhost:6379/0?suppress=true";
};
};
# Deriver (background worker) Configuration
deriver = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
Enable the honcho deriver background worker.
Processes asynchronous tasks like representation updates and session summarization.
'';
};
workers = mkOption {
type = types.int;
default = 1;
description = "Number of deriver worker processes.";
};
provider = mkOption {
type = types.str;
default = "google";
description = "LLM provider for the deriver.";
};
model = mkOption {
type = types.str;
default = "gemini-2.5-flash-lite";
description = "LLM model for the deriver.";
};
};
# Logging
logLevel = mkOption {
type = types.enum ["CRITICAL" "ERROR" "WARNING" "INFO" "DEBUG"];
default = "INFO";
description = "Logging level for the server.";
};
# Authentication
auth = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable JWT authentication.";
};
jwtSecretFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to file containing the JWT secret key.
Required when auth is enabled.
'';
example = "/run/secrets/honcho-jwt-secret";
};
};
};
config = mkIf cfg.enable {
# Create user and group
users.users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
description = "Honcho service user";
home = cfg.stateDir;
createHome = true;
};
users.groups.${cfg.group} = {};
# API Server systemd service
systemd.services.honcho = {
description = "Honcho AI Memory API Server";
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
ExecStart = startScript;
Restart = "on-failure";
RestartSec = "5s";
# Security hardening
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [cfg.stateDir];
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictRealtime = true;
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = false; # Python needs this
RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
};
environment =
{
PYTHONUNBUFFERED = "1";
DB_CONNECTION_URI = cfg.database.connectionUri;
DB_SCHEMA = cfg.database.schema;
DB_POOL_SIZE = toString cfg.database.poolSize;
DB_MAX_OVERFLOW = toString cfg.database.maxOverflow;
CACHE_URL = cfg.cache.url;
LOG_LEVEL = cfg.logLevel;
AUTH_USE_AUTH =
if cfg.auth.enable
then "true"
else "false";
DERIVER_ENABLED =
if cfg.deriver.enable
then "true"
else "false";
}
// optionalAttrs (cfg.auth.jwtSecretFile != null) {
AUTH_JWT_SECRET_FILE = cfg.auth.jwtSecretFile;
};
};
# Deriver background worker systemd service
systemd.services.honcho-deriver = mkIf cfg.deriver.enable {
description = "Honcho Deriver Background Worker";
after = ["network.target"];
wantedBy = ["multi-user.target"];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
ExecStart = deriverScript;
Restart = "on-failure";
RestartSec = "5s";
# Security hardening
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [cfg.stateDir];
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictRealtime = true;
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = false; # Python needs this
RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
};
environment =
{
PYTHONUNBUFFERED = "1";
DB_CONNECTION_URI = cfg.database.connectionUri;
DB_SCHEMA = cfg.database.schema;
CACHE_URL = cfg.cache.url;
LOG_LEVEL = cfg.logLevel;
DERIVER_ENABLED = "true";
DERIVER_WORKERS = toString cfg.deriver.workers;
DERIVER_PROVIDER = cfg.deriver.provider;
DERIVER_MODEL = cfg.deriver.model;
METRICS_ENABLED = "true";
}
// optionalAttrs (cfg.auth.jwtSecretFile != null) {
AUTH_JWT_SECRET_FILE = cfg.auth.jwtSecretFile;
};
};
# Open firewall port if binding to non-localhost
networking.firewall.allowedTCPPorts = mkIf (cfg.host != "127.0.0.1" && cfg.host != "localhost") [cfg.port];
};
}

View File

@@ -10,6 +10,7 @@ in {
sidecar = pkgs.callPackage ./sidecar {}; sidecar = pkgs.callPackage ./sidecar {};
td = pkgs.callPackage ./td {}; td = pkgs.callPackage ./td {};
code2prompt = pkgs.callPackage ./code2prompt {}; code2prompt = pkgs.callPackage ./code2prompt {};
eigent = pkgs.callPackage ./eigent {};
hyprpaper-random = pkgs.callPackage ./hyprpaper-random {}; hyprpaper-random = pkgs.callPackage ./hyprpaper-random {};
launch-webapp = pkgs.callPackage ./launch-webapp {}; launch-webapp = pkgs.callPackage ./launch-webapp {};
mem0 = pkgs.callPackage ./mem0 {}; mem0 = pkgs.callPackage ./mem0 {};
@@ -23,6 +24,7 @@ in {
openshell = pkgs.callPackage ./openshell {}; openshell = pkgs.callPackage ./openshell {};
zellij-ps = pkgs.callPackage ./zellij-ps {}; zellij-ps = pkgs.callPackage ./zellij-ps {};
vibetyper = pkgs.callPackage ./vibetyper {}; vibetyper = pkgs.callPackage ./vibetyper {};
honcho = pkgs.callPackage ./honcho {};
# Imported from flake inputs (pass-through, no modifications) # Imported from flake inputs (pass-through, no modifications)
basecamp = inputs.basecamp.packages.${system}.default; basecamp = inputs.basecamp.packages.${system}.default;

View File

@@ -6,38 +6,66 @@
nodePackages, nodePackages,
uv, uv,
python3, python3,
makeWrapper, nix-update-script,
}: let }: let
pname = "eigent"; pname = "eigent";
version = "0.0.89"; version = "0.0.89";
src = fetchurl { src = fetchurl {
url = "https://github.com/eigent-ai/eigent/releases/download/v${version}/Eigent-${version}.AppImage"; url = "https://github.com/eigent-ai/eigent/releases/download/v${version}/Eigent-${version}.AppImage";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; hash = "sha256-9KuiFjegfXhCu1W/FCinWX4ae/DsNPudeBcXFfW18Hc=";
}; };
appimageContents = appimageTools.extractType2 {inherit pname version src;}; appimageContents = appimageTools.extractType2 {inherit pname version src;};
in in
appimageTools.wrapType2 { appimageTools.wrapType2 {
inherit pname version src; inherit pname version src;
nativeBuildInputs = [makeWrapper]; extraPkgs = _: [
extraPkgs = pkgs: [
nodejs nodejs
nodePackages.npm nodePackages.npm
uv uv
python3 python3
]; ];
extraInstallCommands = '' # Runs before bubblewrap launches — sets up writable state for the sandbox.
install -m 444 -D ${appimageContents}/Eigent.desktop -t $out/share/applications extraPreBwrapCmds = ''
substituteInPlace $out/share/applications/Eigent.desktop \ # eigent writes to multiple dirs under resources/ at runtime:
--replace 'Exec=AppRun' 'Exec=${pname}' # prebuilt/ pyvenv.cfg, .terminal_venv_fixed sentinel
install -m 444 -D ${appimageContents}/Eigent.png \ # backend/ creates runtime/ dir for temporary state
$out/share/icons/hicolor/256x256/apps/Eigent.png # Nix store is read-only EROFS. Copy to writable location on first
wrapProgram $out/bin/${pname} \ # launch (or when the package version changes).
--prefix PATH : ${lib.makeBinPath [nodejs nodePackages.npm uv python3]} DATA_DIR="$HOME/.local/share/${pname}"
mkdir -p "$DATA_DIR"
for subdir in prebuilt backend; do
SRC="${appimageContents}/resources/$subdir"
DST="$DATA_DIR/$subdir"
if [ ! -f "$DST/.nix-src" ] || [ "$(cat "$DST/.nix-src")" != "${appimageContents}" ]; then
rm -rf "$DST"
cp -r "$SRC" "$DST"
chmod -R u+w "$DST"
echo "${appimageContents}" > "$DST/.nix-src"
fi
done
''; '';
# Bind-mount writable copies over the read-only store paths so the app
# sees its files at the expected locations but can write to them.
extraBwrapArgs = [
"--bind $HOME/.local/share/${pname}/prebuilt ${appimageContents}/resources/prebuilt"
"--bind $HOME/.local/share/${pname}/backend ${appimageContents}/resources/backend"
];
extraInstallCommands = ''
install -m 444 -D ${appimageContents}/eigent.desktop -t $out/share/applications
substituteInPlace $out/share/applications/eigent.desktop \
--replace-fail 'Exec=AppRun --no-sandbox %U' 'Exec=${pname} %U'
install -m 444 -D ${appimageContents}/eigent.png \
$out/share/icons/hicolor/256x256/apps/eigent.png
'';
passthru = {
updateScript = nix-update-script {};
};
meta = { meta = {
description = "Open source AI cowork desktop app local alternative to Claude Cowork"; description = "Open source AI cowork desktop app local alternative to Claude Cowork";
homepage = "https://github.com/eigent-ai/eigent"; homepage = "https://github.com/eigent-ai/eigent";

86
pkgs/honcho/default.nix Normal file
View File

@@ -0,0 +1,86 @@
{
lib,
nix-update-script,
python3,
fetchFromGitHub,
}:
python3.pkgs.buildPythonPackage rec {
pname = "honcho";
version = "3.0.5";
pyproject = true;
src = fetchFromGitHub {
owner = "plastic-labs";
repo = "honcho";
rev = "refs/heads/main";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
# Relax Python dependency version constraints
pythonRelaxDeps = true;
build-system = with python3.pkgs; [
hatchling
];
dependencies = with python3.pkgs; [
fastapi
groq
python-dotenv
sqlalchemy
pgvector
greenlet
psycopg
httpx
rich
nanoid
alembic
pyjwt
tenacity
tiktoken
langfuse
openai
pydantic
pydantic-settings
google-genai
pdfplumber
typing-extensions
json-repair
turbopuffer
lancedb
pyarrow
redis
cashews
scikit-learn
prometheus_client
cloudevents
fastapi-pagination
sentry-sdk
];
# Skip tests - they require a running PostgreSQL with pgvector and Redis
doCheck = false;
# Disable imports check because honcho tries to connect to database at import time
pythonImportsCheck = [];
passthru.updateScript = nix-update-script {};
meta = with lib; {
description = "Memory library for building stateful AI agents";
longDescription = ''
Honcho provides a sophisticated memory and reasoning system for AI agents:
- Rich Reasoning System: Multiple implementation methods that extract
conclusions from interactions and build comprehensive peer representations
- Chat API: Reasoning-informed responses integrating conclusions with context
- Background Processing: Asynchronous pipeline for expensive operations
- Multi-Provider Support: Configurable LLM providers (OpenAI, Anthropic, Google, Groq)
- REST API server for easy integration with any application
- PostgreSQL with pgvector for storage
'';
homepage = "https://github.com/plastic-labs/honcho";
license = licenses.agpl3Only;
platforms = platforms.linux;
mainProgram = "honcho";
};
}

View File

@@ -1,17 +1,17 @@
{ {
"version": "v0.0.22", "version": "v0.0.23",
"sources": { "sources": {
"aarch64-linux": { "aarch64-linux": {
"url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.22/openshell-aarch64-unknown-linux-musl.tar.gz", "url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.23/openshell-aarch64-unknown-linux-musl.tar.gz",
"hash": "sha256-yeogvG6sxUWijYTUl5QbHyb9z0f84dKwKGsmSlxyPqk=" "hash": "sha256-x+TMlj8sc68rbkxwW80NrmyC0xaeC81TJMNEtUNhOLg="
}, },
"x86_64-linux": { "x86_64-linux": {
"url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.22/openshell-x86_64-unknown-linux-musl.tar.gz", "url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.23/openshell-x86_64-unknown-linux-musl.tar.gz",
"hash": "sha256-5qJCwQJgI8XgQ64WetNZc9jS++buT1Z0PqfBC+dYu94=" "hash": "sha256-WLmYWn7mCC6VzUFEFN/O49hui81U0zPI6f3E5Hc9SjI="
}, },
"aarch64-darwin": { "aarch64-darwin": {
"url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.22/openshell-aarch64-apple-darwin.tar.gz", "url": "https://github.com/NVIDIA/OpenShell/releases/download/v0.0.23/openshell-aarch64-apple-darwin.tar.gz",
"hash": "sha256-XZLhP/7jLnkt0qmxVtZumsAwQCss7alaeiWbUW4njwM=" "hash": "sha256-Bm8YP+7+CRKjfjNevirKRWHFBrdy3h5XV7gegvvcWXc="
} }
} }
} }