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.
Files changed (60) hide show
  1. otaku-0.1.0/.gitignore +16 -0
  2. otaku-0.1.0/.pre-commit-config.yaml +46 -0
  3. otaku-0.1.0/CHANGELOG.md +45 -0
  4. otaku-0.1.0/CONTRIBUTING.md +88 -0
  5. otaku-0.1.0/LICENSE +21 -0
  6. otaku-0.1.0/Makefile +55 -0
  7. otaku-0.1.0/PKG-INFO +556 -0
  8. otaku-0.1.0/README.md +518 -0
  9. otaku-0.1.0/SECURITY.md +34 -0
  10. otaku-0.1.0/otaku/__init__.py +3 -0
  11. otaku-0.1.0/otaku/chat/__init__.py +1 -0
  12. otaku-0.1.0/otaku/chat/clipboard.py +64 -0
  13. otaku-0.1.0/otaku/chat/commands.py +630 -0
  14. otaku-0.1.0/otaku/chat/completer.py +60 -0
  15. otaku-0.1.0/otaku/chat/inference.py +293 -0
  16. otaku-0.1.0/otaku/chat/mdstream.py +335 -0
  17. otaku-0.1.0/otaku/chat/repl.py +190 -0
  18. otaku-0.1.0/otaku/chat/stats.py +44 -0
  19. otaku-0.1.0/otaku/chat/summary.py +190 -0
  20. otaku-0.1.0/otaku/cli.py +539 -0
  21. otaku-0.1.0/otaku/client/__init__.py +114 -0
  22. otaku-0.1.0/otaku/client/base.py +243 -0
  23. otaku-0.1.0/otaku/client/lmstudio.py +107 -0
  24. otaku-0.1.0/otaku/client/ollama.py +87 -0
  25. otaku-0.1.0/otaku/client/omlx.py +209 -0
  26. otaku-0.1.0/otaku/config.py +257 -0
  27. otaku-0.1.0/otaku/pickers/__init__.py +1 -0
  28. otaku-0.1.0/otaku/pickers/_widgets.py +143 -0
  29. otaku-0.1.0/otaku/pickers/history.py +618 -0
  30. otaku-0.1.0/otaku/pickers/model.py +602 -0
  31. otaku-0.1.0/otaku/spinner.py +44 -0
  32. otaku-0.1.0/otaku/storage/__init__.py +1 -0
  33. otaku-0.1.0/otaku/storage/crypto.py +301 -0
  34. otaku-0.1.0/otaku/storage/store.py +324 -0
  35. otaku-0.1.0/otaku/text.py +38 -0
  36. otaku-0.1.0/pyproject.toml +76 -0
  37. otaku-0.1.0/tests/__init__.py +0 -0
  38. otaku-0.1.0/tests/conftest.py +92 -0
  39. otaku-0.1.0/tests/support.py +113 -0
  40. otaku-0.1.0/tests/test_cli.py +422 -0
  41. otaku-0.1.0/tests/test_client_base.py +217 -0
  42. otaku-0.1.0/tests/test_client_lmstudio.py +138 -0
  43. otaku-0.1.0/tests/test_client_ollama.py +113 -0
  44. otaku-0.1.0/tests/test_client_omlx.py +193 -0
  45. otaku-0.1.0/tests/test_client_registry.py +125 -0
  46. otaku-0.1.0/tests/test_clipboard.py +84 -0
  47. otaku-0.1.0/tests/test_commands.py +660 -0
  48. otaku-0.1.0/tests/test_completer.py +64 -0
  49. otaku-0.1.0/tests/test_config.py +263 -0
  50. otaku-0.1.0/tests/test_crypto.py +254 -0
  51. otaku-0.1.0/tests/test_mdstream.py +191 -0
  52. otaku-0.1.0/tests/test_picker_history.py +265 -0
  53. otaku-0.1.0/tests/test_picker_model.py +210 -0
  54. otaku-0.1.0/tests/test_repl.py +154 -0
  55. otaku-0.1.0/tests/test_spinner.py +38 -0
  56. otaku-0.1.0/tests/test_stats.py +78 -0
  57. otaku-0.1.0/tests/test_store.py +321 -0
  58. otaku-0.1.0/tests/test_summary.py +235 -0
  59. otaku-0.1.0/tests/test_text.py +73 -0
  60. otaku-0.1.0/uv.lock +818 -0
otaku-0.1.0/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ .mypy_cache/
9
+ .ruff_cache/
10
+ .pytest_cache/
11
+ .idea/
12
+ .claude/
13
+ # private project notes — kept local, never committed
14
+ CLAUDE.md
15
+ .DS_Store
16
+ notes/
@@ -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
@@ -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 {} +