anythink 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 (106) hide show
  1. anythink-0.1.0/.github/workflows/ci.yml +107 -0
  2. anythink-0.1.0/.github/workflows/publish.yml +59 -0
  3. anythink-0.1.0/.gitignore +36 -0
  4. anythink-0.1.0/CHANGELOG.md +88 -0
  5. anythink-0.1.0/CLAUDE.md +110 -0
  6. anythink-0.1.0/CONTRIBUTING.md +35 -0
  7. anythink-0.1.0/LICENSE +21 -0
  8. anythink-0.1.0/PKG-INFO +290 -0
  9. anythink-0.1.0/README.md +206 -0
  10. anythink-0.1.0/anythink_app_description.md +733 -0
  11. anythink-0.1.0/pyproject.toml +134 -0
  12. anythink-0.1.0/src/anythink/__init__.py +10 -0
  13. anythink-0.1.0/src/anythink/app/__init__.py +1 -0
  14. anythink-0.1.0/src/anythink/app/chat.py +231 -0
  15. anythink-0.1.0/src/anythink/app/context.py +75 -0
  16. anythink-0.1.0/src/anythink/cli.py +333 -0
  17. anythink-0.1.0/src/anythink/commands/__init__.py +1 -0
  18. anythink-0.1.0/src/anythink/commands/base.py +36 -0
  19. anythink-0.1.0/src/anythink/commands/handlers.py +376 -0
  20. anythink-0.1.0/src/anythink/commands/registry.py +71 -0
  21. anythink-0.1.0/src/anythink/config/__init__.py +1 -0
  22. anythink-0.1.0/src/anythink/config/manager.py +155 -0
  23. anythink-0.1.0/src/anythink/config/models.py +102 -0
  24. anythink-0.1.0/src/anythink/config/personas.py +93 -0
  25. anythink-0.1.0/src/anythink/config/schema.py +26 -0
  26. anythink-0.1.0/src/anythink/exceptions.py +57 -0
  27. anythink-0.1.0/src/anythink/files/__init__.py +1 -0
  28. anythink-0.1.0/src/anythink/files/reader.py +161 -0
  29. anythink-0.1.0/src/anythink/keys/__init__.py +1 -0
  30. anythink-0.1.0/src/anythink/keys/manager.py +97 -0
  31. anythink-0.1.0/src/anythink/plugins/__init__.py +1 -0
  32. anythink-0.1.0/src/anythink/plugins/manager.py +71 -0
  33. anythink-0.1.0/src/anythink/plugins/models.py +17 -0
  34. anythink-0.1.0/src/anythink/providers/__init__.py +25 -0
  35. anythink-0.1.0/src/anythink/providers/anthropic.py +138 -0
  36. anythink-0.1.0/src/anythink/providers/base.py +128 -0
  37. anythink-0.1.0/src/anythink/providers/cohere.py +123 -0
  38. anythink-0.1.0/src/anythink/providers/gemini.py +152 -0
  39. anythink-0.1.0/src/anythink/providers/groq.py +121 -0
  40. anythink-0.1.0/src/anythink/providers/lm_studio.py +28 -0
  41. anythink-0.1.0/src/anythink/providers/mistral.py +124 -0
  42. anythink-0.1.0/src/anythink/providers/ollama.py +130 -0
  43. anythink-0.1.0/src/anythink/providers/openai.py +150 -0
  44. anythink-0.1.0/src/anythink/providers/registry.py +67 -0
  45. anythink-0.1.0/src/anythink/py.typed +0 -0
  46. anythink-0.1.0/src/anythink/search/__init__.py +1 -0
  47. anythink-0.1.0/src/anythink/search/base.py +35 -0
  48. anythink-0.1.0/src/anythink/search/duckduckgo.py +58 -0
  49. anythink-0.1.0/src/anythink/search/registry.py +48 -0
  50. anythink-0.1.0/src/anythink/search/serpapi.py +67 -0
  51. anythink-0.1.0/src/anythink/session/__init__.py +1 -0
  52. anythink-0.1.0/src/anythink/session/manager.py +82 -0
  53. anythink-0.1.0/src/anythink/session/models.py +115 -0
  54. anythink-0.1.0/src/anythink/ui/__init__.py +1 -0
  55. anythink-0.1.0/src/anythink/ui/banner.py +28 -0
  56. anythink-0.1.0/src/anythink/ui/console.py +31 -0
  57. anythink-0.1.0/src/anythink/ui/input.py +30 -0
  58. anythink-0.1.0/src/anythink/ui/renderer.py +59 -0
  59. anythink-0.1.0/src/anythink/ui/status.py +46 -0
  60. anythink-0.1.0/src/anythink/ui/theme.py +80 -0
  61. anythink-0.1.0/tests/__init__.py +0 -0
  62. anythink-0.1.0/tests/conftest.py +39 -0
  63. anythink-0.1.0/tests/test_app/__init__.py +0 -0
  64. anythink-0.1.0/tests/test_app/test_chat.py +565 -0
  65. anythink-0.1.0/tests/test_app/test_context.py +84 -0
  66. anythink-0.1.0/tests/test_cli.py +390 -0
  67. anythink-0.1.0/tests/test_commands/__init__.py +0 -0
  68. anythink-0.1.0/tests/test_commands/test_base.py +40 -0
  69. anythink-0.1.0/tests/test_commands/test_handlers.py +706 -0
  70. anythink-0.1.0/tests/test_commands/test_registry.py +144 -0
  71. anythink-0.1.0/tests/test_config/__init__.py +0 -0
  72. anythink-0.1.0/tests/test_config/test_manager.py +149 -0
  73. anythink-0.1.0/tests/test_config/test_models.py +96 -0
  74. anythink-0.1.0/tests/test_config/test_personas.py +75 -0
  75. anythink-0.1.0/tests/test_files/__init__.py +0 -0
  76. anythink-0.1.0/tests/test_files/test_reader.py +202 -0
  77. anythink-0.1.0/tests/test_init.py +16 -0
  78. anythink-0.1.0/tests/test_keys/__init__.py +0 -0
  79. anythink-0.1.0/tests/test_keys/test_manager.py +125 -0
  80. anythink-0.1.0/tests/test_plugins/__init__.py +0 -0
  81. anythink-0.1.0/tests/test_plugins/test_manager.py +171 -0
  82. anythink-0.1.0/tests/test_plugins/test_models.py +40 -0
  83. anythink-0.1.0/tests/test_providers/__init__.py +0 -0
  84. anythink-0.1.0/tests/test_providers/conftest.py +60 -0
  85. anythink-0.1.0/tests/test_providers/test_anthropic.py +83 -0
  86. anythink-0.1.0/tests/test_providers/test_base.py +123 -0
  87. anythink-0.1.0/tests/test_providers/test_groq.py +80 -0
  88. anythink-0.1.0/tests/test_providers/test_ollama.py +170 -0
  89. anythink-0.1.0/tests/test_providers/test_openai.py +64 -0
  90. anythink-0.1.0/tests/test_providers/test_providers_no_sdk.py +254 -0
  91. anythink-0.1.0/tests/test_providers/test_registry.py +79 -0
  92. anythink-0.1.0/tests/test_search/__init__.py +0 -0
  93. anythink-0.1.0/tests/test_search/test_base.py +23 -0
  94. anythink-0.1.0/tests/test_search/test_duckduckgo.py +115 -0
  95. anythink-0.1.0/tests/test_search/test_registry.py +101 -0
  96. anythink-0.1.0/tests/test_search/test_serpapi.py +116 -0
  97. anythink-0.1.0/tests/test_session/__init__.py +0 -0
  98. anythink-0.1.0/tests/test_session/test_manager.py +157 -0
  99. anythink-0.1.0/tests/test_session/test_models.py +126 -0
  100. anythink-0.1.0/tests/test_ui/__init__.py +0 -0
  101. anythink-0.1.0/tests/test_ui/test_banner.py +41 -0
  102. anythink-0.1.0/tests/test_ui/test_console.py +57 -0
  103. anythink-0.1.0/tests/test_ui/test_renderer.py +89 -0
  104. anythink-0.1.0/tests/test_ui/test_status.py +76 -0
  105. anythink-0.1.0/tests/test_ui/test_theme.py +75 -0
  106. anythink-0.1.0/ultraplan_anythink_ai.md +230 -0
@@ -0,0 +1,107 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint-typecheck:
11
+ name: Lint & Type Check
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.11"
19
+ cache: pip
20
+
21
+ - name: Install dev dependencies
22
+ run: pip install -e ".[dev]"
23
+
24
+ - name: Lint (ruff)
25
+ run: ruff check src/
26
+
27
+ - name: Format check (black)
28
+ run: black --check src/ tests/
29
+
30
+ - name: Type check (mypy)
31
+ run: mypy src/anythink
32
+
33
+ security:
34
+ name: Security Scan
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: "3.11"
42
+ cache: pip
43
+
44
+ - name: Install dev dependencies
45
+ run: pip install -e ".[dev]"
46
+
47
+ - name: Security scan (bandit)
48
+ run: bandit -r src/anythink -c pyproject.toml
49
+
50
+ test:
51
+ name: Test (Python ${{ matrix.python-version }})
52
+ runs-on: ubuntu-latest
53
+ strategy:
54
+ fail-fast: false
55
+ matrix:
56
+ python-version: ["3.11", "3.12", "3.13"]
57
+ env:
58
+ PYTHON_KEYRING_BACKEND: keyrings.alt.file.PlaintextKeyring
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+
62
+ - uses: actions/setup-python@v5
63
+ with:
64
+ python-version: ${{ matrix.python-version }}
65
+ cache: pip
66
+
67
+ - name: Install with dev dependencies
68
+ run: pip install -e ".[dev]"
69
+
70
+ - name: Run tests with coverage
71
+ run: pytest tests/ -v --cov-report=xml
72
+
73
+ - name: Upload coverage report
74
+ if: matrix.python-version == '3.11'
75
+ uses: actions/upload-artifact@v4
76
+ with:
77
+ name: coverage-report
78
+ path: coverage.xml
79
+ retention-days: 7
80
+
81
+ build:
82
+ name: Build & Verify Package
83
+ runs-on: ubuntu-latest
84
+ needs: [lint-typecheck, security, test]
85
+ steps:
86
+ - uses: actions/checkout@v4
87
+
88
+ - uses: actions/setup-python@v5
89
+ with:
90
+ python-version: "3.11"
91
+ cache: pip
92
+
93
+ - name: Install build tools
94
+ run: pip install build twine
95
+
96
+ - name: Build distribution
97
+ run: python -m build
98
+
99
+ - name: Verify distribution metadata
100
+ run: twine check dist/*
101
+
102
+ - name: Upload dist artifacts
103
+ uses: actions/upload-artifact@v4
104
+ with:
105
+ name: dist
106
+ path: dist/
107
+ retention-days: 7
@@ -0,0 +1,59 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+
8
+ jobs:
9
+ build:
10
+ name: Build & Verify
11
+ runs-on: ubuntu-latest
12
+ env:
13
+ PYTHON_KEYRING_BACKEND: keyrings.alt.file.PlaintextKeyring
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11"
20
+ cache: pip
21
+
22
+ - name: Install with dev dependencies
23
+ run: pip install -e ".[dev]"
24
+
25
+ - name: Run full test suite
26
+ run: pytest tests/ -v --cov-fail-under=80
27
+
28
+ - name: Install build tools
29
+ run: pip install build twine
30
+
31
+ - name: Build distribution
32
+ run: python -m build
33
+
34
+ - name: Verify distribution metadata
35
+ run: twine check dist/*
36
+
37
+ - name: Upload dist artifacts
38
+ uses: actions/upload-artifact@v4
39
+ with:
40
+ name: dist
41
+ path: dist/
42
+
43
+ publish:
44
+ name: Publish to PyPI
45
+ runs-on: ubuntu-latest
46
+ needs: build
47
+ environment: pypi
48
+ permissions:
49
+ id-token: write # required for OIDC trusted publishing
50
+ contents: read
51
+ steps:
52
+ - name: Download dist artifacts
53
+ uses: actions/download-artifact@v4
54
+ with:
55
+ name: dist
56
+ path: dist/
57
+
58
+ - name: Publish to PyPI
59
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,36 @@
1
+ # Byte-compiled / optimized / cache
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging / build
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+ wheels/
12
+ *.egg
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+ .env
19
+
20
+ # Test / coverage / type-check caches
21
+ .pytest_cache/
22
+ .mypy_cache/
23
+ .ruff_cache/
24
+ .coverage
25
+ .coverage.*
26
+ htmlcov/
27
+ coverage.xml
28
+
29
+ # IDE / editor
30
+ .idea/
31
+ .vscode/
32
+ *.swp
33
+
34
+ # OS
35
+ .DS_Store
36
+ Thumbs.db
@@ -0,0 +1,88 @@
1
+ # Changelog
2
+
3
+ All notable changes to Anythink are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+ Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ---
8
+
9
+ ## [0.1.0] — 2026-06-19
10
+
11
+ Initial release of Anythink — a universal, AI-powered CLI chatbot.
12
+
13
+ ### Added
14
+
15
+ #### Core & Configuration
16
+ - `AnythinkError` exception hierarchy: `ConfigError`, `ProviderError` (+ `AuthenticationError`, `RateLimitError`, `ProviderUnavailableError`, `ModelNotFoundError`), `SessionError`, `KeychainError`, `PluginError`, `SearchError`, `FileError`
17
+ - `AppConfig` frozen dataclass with XDG Base Directory compliant storage
18
+ - `ConfigManager` for loading/saving `config.yaml`; `Paths` helper resolving all XDG dirs
19
+ - 4 built-in color themes: **Midnight** (default), **Aurora**, **Ember**, **Arctic**
20
+
21
+ #### LLM Providers
22
+ - `BaseProvider` ABC with `stream_chat`, `list_models`, `test_connection`, `supports_vision`, `requires_api_key`
23
+ - Built-in providers: Groq, Google Gemini, OpenAI, Anthropic, Mistral, Cohere, Ollama, LM Studio
24
+ - Optional extras: `pip install anythink[groq|gemini|openai|anthropic|mistral|cohere|all]`
25
+ - Provider registry via Python `anythink.providers` entry points
26
+
27
+ #### Terminal UI
28
+ - ASCII logo startup banner (version, model alias, provider)
29
+ - `StreamRenderer`: real-time token streaming with Rich markup
30
+ - `ContextStatusBar`: live token usage bar with color thresholds (green → yellow → orange → red)
31
+ - `make_console` / `make_prompt_session`: theme-aware terminal I/O
32
+
33
+ #### Chat Loop
34
+ - Interactive async chat loop with slash command dispatch and legacy `exit`/`quit` shortcuts
35
+ - Persona / system prompt management: `/persona <name>|clear`
36
+ - Approaching-context-limit warnings at 60 % / 85 % / 95 % thresholds
37
+
38
+ #### API Key Management
39
+ - OS keychain storage via `keyring` (macOS Keychain, Linux Secret Service, Windows Credential Manager)
40
+ - YAML index file tracks configured providers (keyring has no list-by-service API)
41
+ - CLI: `anythink keys add|show|update|delete|test <provider>`
42
+
43
+ #### Model Aliases
44
+ - `ModelAlias` + `ModelRegistry` backed by `models.yaml`
45
+ - Friendly user-defined names for provider/model pairs with context-window sizes and vision flags
46
+ - CLI: `anythink model add|list|remove`
47
+
48
+ #### Session Management
49
+ - `Session` + `SessionManager` with JSON-backed storage in `$XDG_DATA_HOME/anythink/sessions/`
50
+ - Automatic session saving after each conversation (configurable via `session_autosave`)
51
+ - Session search by name or ID prefix
52
+ - `/session save|load|list|delete|rename` slash commands
53
+
54
+ #### Slash Command System
55
+ - `CommandRegistry` with entry-point discovery (`anythink.slash_commands`)
56
+ - `CommandResult` pattern (`should_exit`, `message`, `error`) drives the chat loop
57
+ - Built-in commands: `/help`, `/clear`, `/history`, `/tokens`, `/model`, `/persona`, `/session`, `/file`, `/image`, `/files`, `/search`, `/plugins`, `/exit`, `/quit`
58
+
59
+ #### File Input & Multimodal Support
60
+ - `TextAttachment` (≤ 1 MB, UTF-8): `.py`, `.js`, `.ts`, `.go`, `.rs`, `.json`, `.yaml`, `.md`, `.txt`, and 20+ more extensions
61
+ - `ImageAttachment` (≤ 10 MB): PNG, JPEG, WEBP, GIF with automatic MIME-type mapping
62
+ - `read_file()` auto-detects type by extension; `read_text_file()` / `read_image_file()` for explicit type
63
+ - Multimodal messages: `TextPart` (file header + content) + `ImagePart` + `TextPart` (user text) via `ChatMessage.content: list[ContentPart]`
64
+ - `ChatState.pending_attachments` cleared after each send
65
+
66
+ #### Agentic Web Search
67
+ - `BaseSearchBackend` ABC; `SearchResult` dataclass
68
+ - `DuckDuckGoSearch`: free, lazy-imports `duckduckgo-search` (`pip install anythink[search]`)
69
+ - `SerpAPISearch`: async `httpx` client, Google results via SerpAPI (requires key)
70
+ - `SearchRegistry` with entry-point discovery and `get_available(preferred)` fallback
71
+ - Auto-search mode: `/search on|off` injects results as `TextPart` before each user message
72
+ - One-off search: `/search <query>` shows title / URL / snippet in terminal
73
+ - `AppContext.search_registry` wired at startup (SerpAPI key looked up from keychain)
74
+
75
+ #### Plugin Architecture
76
+ - `PluginInfo` dataclass: name, version, description, author, entry_point_groups, homepage
77
+ - `PluginManager.list_plugins()` discovers packages contributing to any `anythink.*` entry point group via distribution metadata
78
+ - `PluginManager.install(pkg)` / `remove(pkg)` wrap `pip` via `subprocess`
79
+ - `/plugins list|info|install|remove` slash commands
80
+ - CLI: `anythink plugins list|info|install|remove`
81
+
82
+ #### CI/CD
83
+ - GitHub Actions `ci.yml`: lint (ruff), format check (black), type check (mypy), security scan (bandit), test matrix (Python 3.11 / 3.12 / 3.13), coverage XML upload, build + `twine check`
84
+ - GitHub Actions `publish.yml`: tests → build → `twine check` → PyPI via OIDC trusted publishing (no stored secrets)
85
+ - 80 % minimum test coverage enforced (`--cov-fail-under=80`)
86
+ - 526 tests across 40+ test files
87
+
88
+ [0.1.0]: https://github.com/dhineshtheprogrammer/anythink_ai/releases/tag/v0.1.0
@@ -0,0 +1,110 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Anythink is a universal, AI-powered CLI chatbot (`pip install anythink`) built in Python 3.11+. It is currently at **early implementation stage** — only the CLI skeleton, config schema/manager, and exception hierarchy exist. The detailed feature spec lives in `anythink_app_description.md`.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Install for development (editable, with all dev tools)
13
+ pip install -e ".[dev]"
14
+
15
+ # Run the CLI
16
+ anythink
17
+ anythink --version
18
+ anythink keys list
19
+ anythink model list
20
+
21
+ # Lint
22
+ ruff check src/
23
+
24
+ # Format check (never auto-format in CI; use --check locally too)
25
+ black --check src/ tests/
26
+
27
+ # Type check (strict mypy, src/anythink only)
28
+ mypy src/anythink
29
+
30
+ # Security scan
31
+ bandit -r src/anythink -c pyproject.toml
32
+
33
+ # Tests (must set keyring backend to avoid OS keychain prompts)
34
+ PYTHON_KEYRING_BACKEND=keyrings.alt.file.PlaintextKeyring pytest tests/ -v
35
+
36
+ # Run a single test file
37
+ PYTHON_KEYRING_BACKEND=keyrings.alt.file.PlaintextKeyring pytest tests/test_cli.py -v
38
+
39
+ # Build PyPI distribution
40
+ python -m build
41
+ ```
42
+
43
+ Coverage minimum is 80% (enforced via `--cov-fail-under=80` in `pyproject.toml`). `src/anythink/ui/input.py` is excluded from coverage.
44
+
45
+ ## Architecture
46
+
47
+ ### Source layout
48
+
49
+ ```
50
+ src/anythink/
51
+ __init__.py # exposes __version__
52
+ cli.py # Typer app — entry point (anythink command)
53
+ exceptions.py # full exception hierarchy
54
+ config/
55
+ schema.py # AppConfig frozen dataclass + VALID_THEMES
56
+ manager.py # ConfigManager (load/save/validate) + Paths (XDG)
57
+ ```
58
+
59
+ ### Plugin system (entry points)
60
+
61
+ New providers, search backends, and slash commands are registered via Python entry points in `pyproject.toml` — the core never changes to add capabilities:
62
+
63
+ - `anythink.providers` → each provider class (e.g. `GroqProvider`)
64
+ - `anythink.search_backends` → search backend classes
65
+ - `anythink.slash_commands` → registration functions
66
+
67
+ Provider SDKs are optional extras: `pip install anythink[groq]`, `[gemini]`, `[openai]`, `[anthropic]`, `[mistral]`, `[cohere]`, `[all]`.
68
+
69
+ ### Configuration & storage (XDG)
70
+
71
+ All data follows XDG Base Directory Specification. Key paths are resolved in `config/manager.py:_resolve_paths()`:
72
+
73
+ | File/Dir | Location |
74
+ |---|---|
75
+ | Main config | `$XDG_CONFIG_HOME/anythink/config.yaml` |
76
+ | Model aliases | `$XDG_CONFIG_HOME/anythink/models.yaml` |
77
+ | Personas | `$XDG_CONFIG_HOME/anythink/personas.yaml` |
78
+ | Plugins | `$XDG_CONFIG_HOME/anythink/plugins.yaml` |
79
+ | Sessions | `$XDG_DATA_HOME/anythink/sessions/` |
80
+ | Logs | `$XDG_STATE_HOME/anythink/logs/` |
81
+
82
+ Defaults without env vars: `~/.config/anythink/`, `~/.local/share/anythink/`, etc.
83
+
84
+ `ConfigManager.is_configured()` checks for the existence of `config.yaml`. `ConfigManager.load()` returns an `AppConfig` frozen dataclass.
85
+
86
+ ### Exception hierarchy
87
+
88
+ ```
89
+ AnythinkError
90
+ ConfigError
91
+ ProviderError
92
+ AuthenticationError
93
+ RateLimitError
94
+ ProviderUnavailableError
95
+ ModelNotFoundError
96
+ SessionError
97
+ KeychainError
98
+ PluginError
99
+ SearchError
100
+ ```
101
+
102
+ `AnythinkError` carries both an internal `message` and a `user_message` (displayed in the terminal). `ProviderError` also carries the `provider` name.
103
+
104
+ ### CLI structure
105
+
106
+ The Typer app in `cli.py` has two sub-apps: `keys_app` and `model_app`. The root callback (`main`) invokes `ConfigManager.is_configured()` before starting a chat session. All sub-commands beyond the initial skeleton are stubs referencing the implementation phase.
107
+
108
+ ### Testing conventions
109
+
110
+ The `xdg_dirs` fixture in `tests/conftest.py` redirects all four XDG env vars to `tmp_path` subdirectories. Every test that touches the filesystem should use this fixture (or `config_manager` which builds on it) to avoid touching `~/.config`. The `PYTHON_KEYRING_BACKEND=keyrings.alt.file.PlaintextKeyring` env var must be set for any test that indirectly imports keyring code.
@@ -0,0 +1,35 @@
1
+ # Contributing to Anythink
2
+
3
+ Thank you for your interest in contributing!
4
+
5
+ ## Development Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/dhineshtheprogrammer/anythink_ai
9
+ cd anythink_ai
10
+ pip install -e ".[dev]"
11
+ ```
12
+
13
+ ## Running Tests
14
+
15
+ ```bash
16
+ pytest tests/ -v
17
+ ```
18
+
19
+ ## Code Style
20
+
21
+ - **Ruff** for linting: `ruff check src/`
22
+ - **Black** for formatting: `black src/ tests/`
23
+ - **Mypy** for type checking: `mypy src/anythink`
24
+
25
+ ## Submitting Changes
26
+
27
+ 1. Fork the repository
28
+ 2. Create a feature branch from `main`
29
+ 3. Make your changes with tests
30
+ 4. Ensure all CI checks pass
31
+ 5. Open a pull request
32
+
33
+ ## Plugin Development
34
+
35
+ See the documentation on creating Anythink plugins (provider, search backend, slash command, file handler, or tool plugins) via Python entry points.
anythink-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dhineshtheprogrammer
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.