otaku 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- otaku-0.1.0/.gitignore +16 -0
- otaku-0.1.0/.pre-commit-config.yaml +46 -0
- otaku-0.1.0/CHANGELOG.md +45 -0
- otaku-0.1.0/CONTRIBUTING.md +88 -0
- otaku-0.1.0/LICENSE +21 -0
- otaku-0.1.0/Makefile +55 -0
- otaku-0.1.0/PKG-INFO +556 -0
- otaku-0.1.0/README.md +518 -0
- otaku-0.1.0/SECURITY.md +34 -0
- otaku-0.1.0/otaku/__init__.py +3 -0
- otaku-0.1.0/otaku/chat/__init__.py +1 -0
- otaku-0.1.0/otaku/chat/clipboard.py +64 -0
- otaku-0.1.0/otaku/chat/commands.py +630 -0
- otaku-0.1.0/otaku/chat/completer.py +60 -0
- otaku-0.1.0/otaku/chat/inference.py +293 -0
- otaku-0.1.0/otaku/chat/mdstream.py +335 -0
- otaku-0.1.0/otaku/chat/repl.py +190 -0
- otaku-0.1.0/otaku/chat/stats.py +44 -0
- otaku-0.1.0/otaku/chat/summary.py +190 -0
- otaku-0.1.0/otaku/cli.py +539 -0
- otaku-0.1.0/otaku/client/__init__.py +114 -0
- otaku-0.1.0/otaku/client/base.py +243 -0
- otaku-0.1.0/otaku/client/lmstudio.py +107 -0
- otaku-0.1.0/otaku/client/ollama.py +87 -0
- otaku-0.1.0/otaku/client/omlx.py +209 -0
- otaku-0.1.0/otaku/config.py +257 -0
- otaku-0.1.0/otaku/pickers/__init__.py +1 -0
- otaku-0.1.0/otaku/pickers/_widgets.py +143 -0
- otaku-0.1.0/otaku/pickers/history.py +618 -0
- otaku-0.1.0/otaku/pickers/model.py +602 -0
- otaku-0.1.0/otaku/spinner.py +44 -0
- otaku-0.1.0/otaku/storage/__init__.py +1 -0
- otaku-0.1.0/otaku/storage/crypto.py +301 -0
- otaku-0.1.0/otaku/storage/store.py +324 -0
- otaku-0.1.0/otaku/text.py +38 -0
- otaku-0.1.0/pyproject.toml +76 -0
- otaku-0.1.0/tests/__init__.py +0 -0
- otaku-0.1.0/tests/conftest.py +92 -0
- otaku-0.1.0/tests/support.py +113 -0
- otaku-0.1.0/tests/test_cli.py +422 -0
- otaku-0.1.0/tests/test_client_base.py +217 -0
- otaku-0.1.0/tests/test_client_lmstudio.py +138 -0
- otaku-0.1.0/tests/test_client_ollama.py +113 -0
- otaku-0.1.0/tests/test_client_omlx.py +193 -0
- otaku-0.1.0/tests/test_client_registry.py +125 -0
- otaku-0.1.0/tests/test_clipboard.py +84 -0
- otaku-0.1.0/tests/test_commands.py +660 -0
- otaku-0.1.0/tests/test_completer.py +64 -0
- otaku-0.1.0/tests/test_config.py +263 -0
- otaku-0.1.0/tests/test_crypto.py +254 -0
- otaku-0.1.0/tests/test_mdstream.py +191 -0
- otaku-0.1.0/tests/test_picker_history.py +265 -0
- otaku-0.1.0/tests/test_picker_model.py +210 -0
- otaku-0.1.0/tests/test_repl.py +154 -0
- otaku-0.1.0/tests/test_spinner.py +38 -0
- otaku-0.1.0/tests/test_stats.py +78 -0
- otaku-0.1.0/tests/test_store.py +321 -0
- otaku-0.1.0/tests/test_summary.py +235 -0
- otaku-0.1.0/tests/test_text.py +73 -0
- otaku-0.1.0/uv.lock +818 -0
otaku-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
# Lint + format — keep rev in sync with the `ruff` dev dependency
|
|
3
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
+
rev: v0.15.17
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff-check
|
|
7
|
+
args: [--fix]
|
|
8
|
+
- id: ruff-format
|
|
9
|
+
|
|
10
|
+
# General hygiene
|
|
11
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
12
|
+
rev: v6.0.0
|
|
13
|
+
hooks:
|
|
14
|
+
- id: trailing-whitespace
|
|
15
|
+
- id: end-of-file-fixer
|
|
16
|
+
- id: check-yaml
|
|
17
|
+
- id: check-toml
|
|
18
|
+
- id: check-merge-conflict
|
|
19
|
+
- id: debug-statements
|
|
20
|
+
- id: detect-private-key
|
|
21
|
+
- id: check-added-large-files
|
|
22
|
+
args: [--maxkb=512]
|
|
23
|
+
|
|
24
|
+
# Local: type-check against installed deps, plus project guards
|
|
25
|
+
- repo: local
|
|
26
|
+
hooks:
|
|
27
|
+
- id: mypy
|
|
28
|
+
name: mypy
|
|
29
|
+
entry: mypy otaku
|
|
30
|
+
language: system
|
|
31
|
+
types: [python]
|
|
32
|
+
pass_filenames: false
|
|
33
|
+
|
|
34
|
+
- id: pytest
|
|
35
|
+
name: pytest
|
|
36
|
+
entry: pytest
|
|
37
|
+
language: system
|
|
38
|
+
types: [python]
|
|
39
|
+
pass_filenames: false
|
|
40
|
+
|
|
41
|
+
- id: no-personal-paths
|
|
42
|
+
name: no /Users/ or /home/ paths in source
|
|
43
|
+
description: catch absolute home-dir paths leaking into committed files
|
|
44
|
+
entry: bash -c '! git diff --cached --name-only --diff-filter=ACM | xargs -I{} grep -Hn "/Users/\|/home/" "{}" 2>/dev/null'
|
|
45
|
+
language: system
|
|
46
|
+
pass_filenames: false
|
otaku-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to otaku are documented in this file. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and otaku follows
|
|
5
|
+
[Semantic Versioning](https://semver.org/) — while pre-1.0, minor releases may
|
|
6
|
+
include breaking changes.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
Initial release in preparation (`0.1.0`).
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Multi-backend client for Ollama, LM Studio, MLX (omlx), and any
|
|
14
|
+
OpenAI-compatible server — from one terminal command.
|
|
15
|
+
- Cross-provider model management: `otaku list` (with `--running` to show only
|
|
16
|
+
loaded models), load and unload from the picker, `otaku stop --all`, with a
|
|
17
|
+
live RAM gauge. Provider queries run concurrently with a short (0.5s) probe
|
|
18
|
+
timeout, so one configured-but-down provider no longer slows every command;
|
|
19
|
+
when nothing is reachable, otaku names each provider, whether it answered,
|
|
20
|
+
and points at `~/.otaku/config.toml` to fix.
|
|
21
|
+
- Chat REPL: streaming responses, thinking-effort control, tok/s stats
|
|
22
|
+
(`/set verbose`, off by default), triple-quoted multiline input, in-chat
|
|
23
|
+
model switching (`/model`), `/new` (fresh conversation) vs `/clear` (reset
|
|
24
|
+
context in place), and slash commands.
|
|
25
|
+
- Streaming markdown rendering: headers, lists, blockquotes, rules, and fenced
|
|
26
|
+
code blocks (syntax-highlighted via Pygments) on top of inline emphasis/code.
|
|
27
|
+
- omlx output smoothing (`[providers.omlx].smooth`, default on): de-jitters
|
|
28
|
+
omlx's bursty token delivery into steady typing, without affecting tok/s.
|
|
29
|
+
- Persistent session defaults: a `[defaults]` config section (system, think,
|
|
30
|
+
parameters, no_record) plus per-model overrides keyed by bare model name;
|
|
31
|
+
`/remember` saves the current settings as the model's defaults.
|
|
32
|
+
- One-shot / pipe mode: `otaku <model> "prompt"` and `… | otaku <model>`
|
|
33
|
+
print a plain reply and exit (prompt + stdin combined instruction-first),
|
|
34
|
+
so otaku works as a Unix filter.
|
|
35
|
+
- Encrypted conversation history (AES-256-GCM), searchable across all
|
|
36
|
+
conversations by full message content, with background LLM-generated
|
|
37
|
+
summaries (idle-debounced so they never block exit or reload a cold model;
|
|
38
|
+
`[defaults].create_summaries` / `summary_idle_seconds`), user-set titles
|
|
39
|
+
(`/title`, shown in the `/history` picker), and resume-from-any-turn.
|
|
40
|
+
- Get answers out: `/copy` (last reply or whole chat → clipboard, via the native
|
|
41
|
+
tool or an OSC 52 fallback) and `/save <file>` (conversation → Markdown).
|
|
42
|
+
- Install via `uv tool install` or Homebrew (`brew install enclavum/tap/otaku`).
|
|
43
|
+
- Runs on macOS, Linux, and Windows. On Windows the streaming-time Ctrl+R
|
|
44
|
+
(cancel + regenerate) shortcut is disabled — it needs a POSIX terminal — but
|
|
45
|
+
everything else works; WSL gives full parity.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Contributing to otaku
|
|
2
|
+
|
|
3
|
+
otaku is a small, focused project — a terminal chat client for local LLMs.
|
|
4
|
+
Contributions that keep it sharp are very welcome.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
otaku uses [uv](https://docs.astral.sh/uv/). With the repo cloned:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
uv sync --extra dev # create a venv and install runtime + dev deps
|
|
12
|
+
# or, with pip:
|
|
13
|
+
pip install -e ".[dev]"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Python 3.11+ is required.
|
|
17
|
+
|
|
18
|
+
## Before opening a PR
|
|
19
|
+
|
|
20
|
+
The automated safety net is **type-checking + linting**, run on every commit via
|
|
21
|
+
pre-commit:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pre-commit install # one-time: wires ruff + mypy into git hooks
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can run the same checks by hand — or all of them at once with `make check`:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
make check # lint + format-check + mypy + tests (see `make help`)
|
|
31
|
+
|
|
32
|
+
# …or individually:
|
|
33
|
+
ruff check otaku tests
|
|
34
|
+
ruff format --check otaku tests
|
|
35
|
+
mypy otaku
|
|
36
|
+
pytest
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `Makefile` targets run inside the conda env by default; override with
|
|
40
|
+
`make <target> RUN=` (bare PATH) or `RUN="uv run"`.
|
|
41
|
+
|
|
42
|
+
### On tests
|
|
43
|
+
|
|
44
|
+
otaku ships a **full pytest suite** (`tests/`) covering every module — unit
|
|
45
|
+
tests plus CLI tests that drive the typer app end-to-end via
|
|
46
|
+
`typer.testing.CliRunner`. Alongside strict `mypy` + `ruff`, it's the automated
|
|
47
|
+
net; behavioural changes should still be smoke-tested against a real backend
|
|
48
|
+
(Ollama, LM Studio, or an MLX server).
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pytest # whole suite (fast — no network, no real disk)
|
|
52
|
+
pytest tests/test_crypto.py # one module
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Conventions for new tests:
|
|
56
|
+
|
|
57
|
+
- An autouse `_isolate` fixture (in `tests/conftest.py`) redirects every
|
|
58
|
+
`~/.otaku` path into a tmp dir, points the DB at a throwaway sqlite file,
|
|
59
|
+
swaps the OS keychain for an in-memory store, and clears the client cache.
|
|
60
|
+
**No test may touch the real home directory, keychain, or network.**
|
|
61
|
+
- HTTP is mocked with [`respx`](https://lundberg.github.io/respx/) (the provider
|
|
62
|
+
layer speaks `httpx`); never hit a live server in a test.
|
|
63
|
+
- Shared, non-fixture helpers live in `tests/support.py` (`make_provider`, the
|
|
64
|
+
SSE builders, `FakeClient`); import them with `from tests.support import ...`.
|
|
65
|
+
- The TUI pickers are tested by calling their behaviour methods directly — the
|
|
66
|
+
prompt_toolkit `Application` is never run.
|
|
67
|
+
- When you add a provider, slash command, or KEK provider, add tests for it in
|
|
68
|
+
the same change (see the "Common tasks" checklists in `CLAUDE.md`).
|
|
69
|
+
|
|
70
|
+
## Style
|
|
71
|
+
|
|
72
|
+
- Ruff owns formatting and lint (line length 100) — let it do the work.
|
|
73
|
+
- Keep dependencies minimal: otaku aims to install fast and run anywhere a
|
|
74
|
+
terminal does. Prefer the standard library; a new runtime dependency needs a
|
|
75
|
+
real justification.
|
|
76
|
+
- Match the surrounding code: full type hints, `from __future__ import
|
|
77
|
+
annotations`, small focused modules.
|
|
78
|
+
|
|
79
|
+
## Reporting bugs and requesting features
|
|
80
|
+
|
|
81
|
+
Open an issue describing what you ran, what you expected, and what happened —
|
|
82
|
+
including your provider (Ollama / LM Studio / MLX) and the model. For security
|
|
83
|
+
issues, see [SECURITY.md](SECURITY.md) instead of the public tracker.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
By contributing, you agree that your contributions are licensed under the
|
|
88
|
+
project's [MIT License](LICENSE).
|
otaku-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 enclavum
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
otaku-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# otaku — developer task runner.
|
|
2
|
+
#
|
|
3
|
+
# Commands run inside the project's conda env by default (see CLAUDE.md).
|
|
4
|
+
# Override the runner for other setups, e.g.:
|
|
5
|
+
# make test RUN= # use whatever python is on PATH
|
|
6
|
+
# make test RUN="uv run" # use uv
|
|
7
|
+
#
|
|
8
|
+
# Pass extra arguments with ARGS=..., e.g.:
|
|
9
|
+
# make test ARGS="tests/test_crypto.py -x"
|
|
10
|
+
# make run ARGS="ollama/llama3"
|
|
11
|
+
|
|
12
|
+
RUN ?= conda run -n otaku
|
|
13
|
+
SRC := otaku tests
|
|
14
|
+
ARGS ?=
|
|
15
|
+
|
|
16
|
+
.DEFAULT_GOAL := help
|
|
17
|
+
.PHONY: help install lint format format-check fix typecheck test check run hooks clean
|
|
18
|
+
|
|
19
|
+
help: ## Show this help
|
|
20
|
+
@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | \
|
|
21
|
+
awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-13s\033[0m %s\n", $$1, $$2}'
|
|
22
|
+
|
|
23
|
+
install: ## Install the package + dev dependencies (editable)
|
|
24
|
+
$(RUN) pip install -e ".[dev]"
|
|
25
|
+
|
|
26
|
+
lint: ## Lint with ruff
|
|
27
|
+
$(RUN) ruff check $(SRC)
|
|
28
|
+
|
|
29
|
+
format: ## Auto-format with ruff
|
|
30
|
+
$(RUN) ruff format $(SRC)
|
|
31
|
+
|
|
32
|
+
format-check: ## Check formatting without writing changes
|
|
33
|
+
$(RUN) ruff format --check $(SRC)
|
|
34
|
+
|
|
35
|
+
fix: ## Auto-fix lint issues, then format
|
|
36
|
+
$(RUN) ruff check --fix $(SRC)
|
|
37
|
+
$(RUN) ruff format $(SRC)
|
|
38
|
+
|
|
39
|
+
typecheck: ## Type-check with mypy (strict; otaku/ only)
|
|
40
|
+
$(RUN) mypy otaku
|
|
41
|
+
|
|
42
|
+
test: ## Run the test suite (extra args via ARGS=...)
|
|
43
|
+
$(RUN) python -m pytest $(ARGS)
|
|
44
|
+
|
|
45
|
+
check: lint format-check typecheck test ## Full pre-flight: lint + format + types + tests
|
|
46
|
+
|
|
47
|
+
run: ## Run the app (args via ARGS=..., e.g. ARGS="ollama/llama3")
|
|
48
|
+
$(RUN) otaku $(ARGS)
|
|
49
|
+
|
|
50
|
+
hooks: ## Run all pre-commit hooks against every file
|
|
51
|
+
$(RUN) pre-commit run --all-files
|
|
52
|
+
|
|
53
|
+
clean: ## Remove caches and compiled artifacts
|
|
54
|
+
rm -rf .pytest_cache .mypy_cache .ruff_cache
|
|
55
|
+
find $(SRC) -type d -name __pycache__ -prune -exec rm -rf {} +
|