speiidev 1.0.1 → 1.2.0

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.
package/PLAN.md ADDED
@@ -0,0 +1,292 @@
1
+ # Implementation Plan: Say Hi Feature for SpeiiDev
2
+
3
+ Phased implementation plan for adding the `say hi` feature to `autodev-orchestrator` (SpeiiDev).
4
+
5
+ ## Goal Description
6
+ Implement an interactive and CLI greeting feature (`say hi` / `hi`) for SpeiiDev (`autodev`).
7
+ This feature enables users to say hi both in non-interactive batch/scripting mode and interactively in the REPL:
8
+ 1. A dedicated greeting utility module (`/Users/mac/Documents/AI/autodev/src/autodev/hi.py`) with Catppuccin Bok Choy styling and ASCII / 3D block typography.
9
+ 2. A CLI flag `--hi [NAME]` allowing users to print a greeting banner and exit cleanly.
10
+ 3. An interactive REPL slash command `/hi [NAME]` providing friendly greeting banners and mascot artwork within the TUI.
11
+ 4. Comprehensive unit and integration test coverage and updated documentation.
12
+
13
+ ```mermaid
14
+ flowchart TD
15
+ User([User / Shell]) --> ModeCheck{Invocation Mode}
16
+ ModeCheck -->|CLI flag: --hi [NAME]| CLIRunner["/Users/mac/Documents/AI/autodev/src/autodev/cli.py:main()"]
17
+ ModeCheck -->|REPL command: /hi [NAME]| REPLRunner["/Users/mac/Documents/AI/autodev/src/autodev/cli.py:interactive_repl()"]
18
+
19
+ CLIRunner --> HiHandler["/Users/mac/Documents/AI/autodev/src/autodev/cli.py:handle_hi()"]
20
+ REPLRunner --> HiHandler
21
+
22
+ HiHandler --> CorePrint["/Users/mac/Documents/AI/autodev/src/autodev/hi.py:print_hi()"]
23
+ CorePrint --> CoreFormat["/Users/mac/Documents/AI/autodev/src/autodev/hi.py:get_hi_greeting()"]
24
+ CoreFormat --> BlockFont["/Users/mac/Documents/AI/autodev/src/autodev/font.py:render_block_text()"]
25
+ CorePrint --> ConsoleOutput([Rich Console Rendered Banner])
26
+ ```
27
+
28
+ ---
29
+
30
+ ## User Review Required
31
+ > [!NOTE]
32
+ > No breaking changes are introduced. All existing CLI flags, slash commands, configurations, and test suites will remain fully backwards-compatible.
33
+
34
+ ---
35
+
36
+ ## Open Questions
37
+ *None* — Requirements are well-defined and integrate cleanly into the existing modular CLI architecture.
38
+
39
+ ---
40
+
41
+ ## Proposed Changes
42
+
43
+ ### Core Greeting Component
44
+
45
+ #### [NEW] `/Users/mac/Documents/AI/autodev/src/autodev/hi.py`
46
+ Exact Path: `/Users/mac/Documents/AI/autodev/src/autodev/hi.py`
47
+ Provides formatting and rendering routines for stylized "say hi" greetings.
48
+ - **Interface Signatures**:
49
+ ```python
50
+ from __future__ import annotations
51
+ from typing import Optional
52
+ from rich.console import Console
53
+
54
+ def get_hi_greeting(name: str = "World", style: str = "claude") -> str:
55
+ """Generate a stylized 'HI' greeting string with block font art.
56
+
57
+ Args:
58
+ name: The recipient name to greet (default: 'World').
59
+ style: The typography style ('claude' for 3D shadow or 'mini' for 2-line).
60
+
61
+ Returns:
62
+ Formatted greeting text containing block art typography.
63
+ """
64
+ ...
65
+
66
+ def print_hi(
67
+ name: str = "World",
68
+ style: str = "claude",
69
+ console: Optional[Console] = None,
70
+ ) -> None:
71
+ """Render the 'HI' greeting inside a Rich Panel with Bok Choy Green accent.
72
+
73
+ Args:
74
+ name: The recipient name to greet (default: 'World').
75
+ style: The typography style ('claude' or 'mini').
76
+ console: Optional Rich Console instance (defaults to global Console()).
77
+ """
78
+ ...
79
+
80
+ def say_hi(name: str = "World", style: str = "claude") -> None:
81
+ """Top-level convenience entry point to say hi.
82
+
83
+ Args:
84
+ name: The recipient name to greet (default: 'World').
85
+ style: The typography style ('claude' or 'mini').
86
+ """
87
+ ...
88
+ ```
89
+
90
+ #### [MODIFY] `/Users/mac/Documents/AI/autodev/src/autodev/__init__.py`
91
+ Exact Path: `/Users/mac/Documents/AI/autodev/src/autodev/__init__.py`
92
+ Export public symbols `get_hi_greeting`, `print_hi`, and `say_hi`.
93
+ - **Interface Signatures**:
94
+ ```python
95
+ from autodev.hi import get_hi_greeting, print_hi, say_hi
96
+
97
+ __all__ = [
98
+ ...,
99
+ "get_hi_greeting",
100
+ "print_hi",
101
+ "say_hi",
102
+ ]
103
+ ```
104
+
105
+ ---
106
+
107
+ ### CLI & TUI Integration
108
+
109
+ #### [MODIFY] `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`
110
+ Exact Path: `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`
111
+ - **Interface Signatures & Additions**:
112
+ ```python
113
+ # 1. Update SLASH_COMMANDS list:
114
+ SLASH_COMMANDS: list[str] = [
115
+ ...,
116
+ "/hi",
117
+ "/font",
118
+ "/clear",
119
+ "/help",
120
+ "/exit",
121
+ ]
122
+
123
+ # 2. Add handler function:
124
+ def handle_hi(state: AgentState, arg: str = "") -> None:
125
+ """Handle the /hi slash command in the interactive REPL.
126
+
127
+ Args:
128
+ state: Current AgentState instance.
129
+ arg: Optional argument containing recipient name (defaults to 'World').
130
+ """
131
+ ...
132
+
133
+ # 3. Add argument in main() -> int:
134
+ parser.add_argument(
135
+ "--hi",
136
+ nargs="?",
137
+ const="World",
138
+ default=None,
139
+ metavar="NAME",
140
+ help="Say hi with a stylized greeting banner and exit",
141
+ )
142
+
143
+ # 4. Add slash command dispatch in interactive_repl(state: AgentState) -> int:
144
+ elif user_input.startswith("/hi"):
145
+ parts = user_input.split(maxsplit=1)
146
+ name_arg = parts[1].strip() if len(parts) > 1 else "World"
147
+ handle_hi(state, name_arg)
148
+
149
+ # 5. Add /hi row in show_help() -> None:
150
+ table.add_row("/hi [name]", "Say hi with a stylized greeting banner")
151
+ ```
152
+
153
+ ---
154
+
155
+ ### Test Suite
156
+
157
+ #### [NEW] `/Users/mac/Documents/AI/autodev/tests/test_hi.py`
158
+ Exact Path: `/Users/mac/Documents/AI/autodev/tests/test_hi.py`
159
+ Unit tests for `autodev.hi`.
160
+ - **Interface Signatures**:
161
+ ```python
162
+ import unittest
163
+
164
+ class TestHi(unittest.TestCase):
165
+ def test_default_greeting(self) -> None:
166
+ """Test get_hi_greeting() returns default greeting for 'World'."""
167
+ ...
168
+
169
+ def test_custom_name_greeting(self) -> None:
170
+ """Test get_hi_greeting('SpeiiDev') includes the target name."""
171
+ ...
172
+
173
+ def test_mini_font_style(self) -> None:
174
+ """Test get_hi_greeting with style='mini'."""
175
+ ...
176
+
177
+ def test_print_hi_panel(self) -> None:
178
+ """Test print_hi renders without exception to a captured Console."""
179
+ ...
180
+
181
+ def test_say_hi_convenience(self) -> None:
182
+ """Test say_hi convenience wrapper executes cleanly."""
183
+ ...
184
+ ```
185
+
186
+ #### [MODIFY] `/Users/mac/Documents/AI/autodev/tests/test_cli.py`
187
+ Exact Path: `/Users/mac/Documents/AI/autodev/tests/test_cli.py`
188
+ Integration test cases added to `TestCLIHelpers`:
189
+ - **Interface Signatures**:
190
+ ```python
191
+ class TestCLIHelpers(unittest.TestCase):
192
+ ...
193
+ def test_cli_hi_flag(self) -> None:
194
+ """Invoking --hi must exit 0 and print greeting."""
195
+ ...
196
+
197
+ def test_cli_hi_custom_name(self) -> None:
198
+ """Invoking --hi 'Developer' must include 'Developer' in stdout."""
199
+ ...
200
+
201
+ def test_slash_command_hi_registered(self) -> None:
202
+ """Ensure '/hi' is present in SLASH_COMMANDS."""
203
+ ...
204
+ ```
205
+
206
+ ---
207
+
208
+ ### Documentation
209
+
210
+ #### [MODIFY] `/Users/mac/Documents/AI/autodev/README.md`
211
+ Exact Path: `/Users/mac/Documents/AI/autodev/README.md`
212
+ - Document `/hi [name]` in the Interactive Slash Commands table.
213
+ - Document `--hi [NAME]` in the CLI Options section.
214
+
215
+ ---
216
+
217
+ ## Phased Implementation Plan
218
+
219
+ ### Phase 1: Core Greeting Module
220
+ - [ ] 1.1 Create `/Users/mac/Documents/AI/autodev/src/autodev/hi.py` implementing `get_hi_greeting(name: str = "World", style: str = "claude") -> str`, `print_hi(name: str = "World", style: str = "claude", console: Optional[Console] = None) -> None`, and `say_hi(name: str = "World", style: str = "claude") -> None`.
221
+ - [ ] 1.2 Export `get_hi_greeting`, `print_hi`, and `say_hi` in `/Users/mac/Documents/AI/autodev/src/autodev/__init__.py` and include them in `__all__`.
222
+
223
+ **Verification Command**:
224
+ ```bash
225
+ PYTHONPATH=src ./venv/bin/python3 -c "from autodev import get_hi_greeting, print_hi, say_hi; print(get_hi_greeting('World'))"
226
+ ```
227
+
228
+ ---
229
+
230
+ ### Phase 2: CLI & Slash Command Dispatch
231
+ - [ ] 2.1 Add `"/hi"` to `SLASH_COMMANDS` list in `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`.
232
+ - [ ] 2.2 Add `handle_hi(state: AgentState, arg: str = "") -> None` handler function in `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`.
233
+ - [ ] 2.3 Add `--hi` flag (`nargs="?", const="World", default=None, metavar="NAME"`) in `parser.add_argument` within `main()` in `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`.
234
+ - [ ] 2.4 Add execution handler in `main()` for `args.hi is not None` to call `print_hi(args.hi, style=args.font_style)` and return 0.
235
+ - [ ] 2.5 Add `/hi` handling in the REPL command loop in `interactive_repl()` in `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`.
236
+ - [ ] 2.6 Add `/hi [name]` entry to `show_help()` table in `/Users/mac/Documents/AI/autodev/src/autodev/cli.py`.
237
+
238
+ **Verification Commands**:
239
+ ```bash
240
+ PYTHONPATH=src ./venv/bin/python3 -m autodev.cli --help | grep -E "(--hi|hi)"
241
+ PYTHONPATH=src ./venv/bin/python3 -m autodev.cli --hi "SpeiiDev"
242
+ ```
243
+
244
+ ---
245
+
246
+ ### Phase 3: Unit and Integration Tests
247
+ - [ ] 3.1 Implement unit tests in `/Users/mac/Documents/AI/autodev/tests/test_hi.py` testing `get_hi_greeting` (default name, custom name, styles), `print_hi`, and `say_hi`.
248
+ - [ ] 3.2 Add test cases `test_cli_hi_flag`, `test_cli_hi_custom_name`, and `test_slash_command_hi_registered` to `TestCLIHelpers` in `/Users/mac/Documents/AI/autodev/tests/test_cli.py`.
249
+ - [ ] 3.3 Execute unit and integration tests to confirm zero regressions.
250
+
251
+ **Verification Commands**:
252
+ ```bash
253
+ PYTHONPATH=src ./venv/bin/pytest tests/test_hi.py -v
254
+ PYTHONPATH=src ./venv/bin/pytest tests/test_cli.py -k "hi" -v
255
+ PYTHONPATH=src ./venv/bin/pytest
256
+ ```
257
+
258
+ ---
259
+
260
+ ### Phase 4: Documentation & Final Verification
261
+ - [ ] 4.1 Update `/Users/mac/Documents/AI/autodev/README.md` with `/hi` slash command description and `--hi` CLI flag documentation.
262
+ - [ ] 4.2 Run end-to-end regression testing and git status verification.
263
+
264
+ **Verification Commands**:
265
+ ```bash
266
+ PYTHONPATH=src ./venv/bin/pytest
267
+ git diff --stat
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Verification Plan
273
+
274
+ ### Automated Tests
275
+ Run full test suite via pytest:
276
+ ```bash
277
+ PYTHONPATH=src ./venv/bin/pytest -v
278
+ ```
279
+
280
+ ### Manual Verification
281
+ 1. Test CLI execution:
282
+ ```bash
283
+ PYTHONPATH=src ./venv/bin/python3 -m autodev.cli --hi "Pair Programmer"
284
+ ```
285
+ 2. Verify output displays:
286
+ - TrueColor Bok Choy banner
287
+ - Styled block font greeting "HI"
288
+ - Friendly greeting message: "Hi, Pair Programmer! Welcome to SpeiiDev."
289
+ 3. Test interactive REPL slash command:
290
+ ```bash
291
+ echo -e "/hi Alice\n/exit" | PYTHONPATH=src ./venv/bin/python3 -m autodev.cli --no-splash
292
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speiidev",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "Multi-agent terminal orchestrator wrapper",
5
5
  "author": "Toek Sopanha",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "autodev-orchestrator"
7
- version = "1.0.1"
7
+ dynamic = ["version"]
8
8
  description = "Interactive Multi-Agent TUI with pluggable agents, model switcher, diff gate, and conversation memory."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -60,3 +60,6 @@ render-pixel-art = "autodev.pixel_art:main"
60
60
 
61
61
  [tool.setuptools.packages.find]
62
62
  where = ["src"]
63
+
64
+ [tool.setuptools.dynamic]
65
+ version = { attr = "autodev._version.__version__" }
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env python3
2
+ """Bump the SpeiiDev version from ONE place.
3
+
4
+ Usage:
5
+ python scripts/bump_version.py 1.2.3
6
+
7
+ What it updates:
8
+ - src/autodev/_version.py (the single source of truth)
9
+ - package.json (npm wrapper; Node can't read the Python file)
10
+
11
+ Not needed (they read the version dynamically):
12
+ - pyproject.toml -> [tool.setuptools.dynamic] attr = autodev._version.__version__
13
+ - src/autodev/cli.py -> APP_VERSION = autodev._version.__version__
14
+
15
+ Pass --check to verify all files agree without changing anything (used by tests).
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import re
22
+ import sys
23
+ from pathlib import Path
24
+
25
+ ROOT = Path(__file__).resolve().parent.parent
26
+ VERSION_FILE = ROOT / "src" / "autodev" / "_version.py"
27
+ PACKAGE_JSON = ROOT / "package.json"
28
+
29
+ SEMVER_RE = re.compile(r"^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.\-]+)?$")
30
+
31
+
32
+ def read_source_version() -> str:
33
+ text = VERSION_FILE.read_text(encoding="utf-8")
34
+ m = re.search(r'^__version__\s*=\s*["\']([^"\']+)["\']', text, re.MULTILINE)
35
+ if not m:
36
+ raise SystemExit(f"❌ Could not find __version__ in {VERSION_FILE}")
37
+ return m.group(1)
38
+
39
+
40
+ def read_package_version() -> str:
41
+ data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
42
+ return str(data.get("version", ""))
43
+
44
+
45
+ def write_source_version(version: str) -> None:
46
+ text = VERSION_FILE.read_text(encoding="utf-8")
47
+ text = re.sub(
48
+ r'^(__version__\s*=\s*)["\'][^"\']+["\']',
49
+ rf'\1"{version}"',
50
+ text,
51
+ count=1,
52
+ flags=re.MULTILINE,
53
+ )
54
+ VERSION_FILE.write_text(text, encoding="utf-8")
55
+
56
+
57
+ def write_package_version(version: str) -> None:
58
+ text = PACKAGE_JSON.read_text(encoding="utf-8")
59
+ text = re.sub(
60
+ r'("version"\s*:\s*)["\'][^"\']+["\']',
61
+ rf'\1"{version}"',
62
+ text,
63
+ count=1,
64
+ )
65
+ PACKAGE_JSON.write_text(text, encoding="utf-8")
66
+
67
+
68
+ def check() -> int:
69
+ src = read_source_version()
70
+ pkg = read_package_version()
71
+ ok = src == pkg
72
+ print(f" src/autodev/_version.py : {src}")
73
+ print(f" package.json : {pkg}")
74
+ if ok:
75
+ print(f"✓ Versions agree ({src})")
76
+ return 0
77
+ print("❌ Versions differ — run: python scripts/bump_version.py <version>")
78
+ return 1
79
+
80
+
81
+ def main(argv: list[str]) -> int:
82
+ if len(argv) == 2 and argv[1] in ("--check", "-c"):
83
+ return check()
84
+ if len(argv) != 2:
85
+ print(__doc__)
86
+ return 2
87
+
88
+ version = argv[1].strip().lstrip("v")
89
+ if not SEMVER_RE.match(version):
90
+ print(f"❌ Invalid version '{version}'. Expected something like 1.2.3")
91
+ return 2
92
+
93
+ old = read_source_version()
94
+ write_source_version(version)
95
+ write_package_version(version)
96
+
97
+ print(f"✅ SpeiiDev version: {old} → {version}")
98
+ print(" updated: src/autodev/_version.py, package.json")
99
+ print(" pyproject.toml & cli.py read it dynamically.")
100
+ return 0
101
+
102
+
103
+ if __name__ == "__main__":
104
+ sys.exit(main(sys.argv))
@@ -3,13 +3,8 @@ autodev: Interactive Multi-Agent TUI with pluggable agents, model switcher,
3
3
  diff gate, and conversation memory.
4
4
  """
5
5
 
6
- from autodev.cli import (
7
- AgentProfile,
8
- AgentState,
9
- FileChange,
10
- PROFILES,
11
- main,
12
- )
6
+ from typing import TYPE_CHECKING
7
+ from autodev._version import __version__
13
8
  from autodev.font import (
14
9
  BLOCK_FONT,
15
10
  CLAUDE_3D_FONT,
@@ -22,7 +17,22 @@ from autodev.pixel_art import (
22
17
  render_pixel_art,
23
18
  )
24
19
 
25
- __version__ = "1.0.1"
20
+ if TYPE_CHECKING:
21
+ from autodev.cli import (
22
+ AgentProfile,
23
+ AgentState,
24
+ FileChange,
25
+ PROFILES,
26
+ main,
27
+ )
28
+
29
+
30
+ def __getattr__(name: str):
31
+ if name in ("AgentProfile", "AgentState", "FileChange", "PROFILES", "main"):
32
+ import autodev.cli as cli
33
+ return getattr(cli, name)
34
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
35
+
26
36
  __all__ = [
27
37
  "AgentProfile",
28
38
  "AgentState",
@@ -0,0 +1,14 @@
1
+ """Single source of truth for the SpeiiDev version.
2
+
3
+ Everything else reads from here:
4
+ - ``autodev.__version__`` and ``autodev.cli.APP_VERSION`` import it.
5
+ - ``pyproject.toml`` reads it dynamically (``attr = "autodev._version.__version__"``).
6
+ - ``package.json`` (npm wrapper) is kept in sync by ``scripts/bump_version.py``.
7
+
8
+ To release a new version, change it in ONE place:
9
+
10
+ python scripts/bump_version.py 1.2.3
11
+
12
+ """
13
+
14
+ __version__ = "1.2.0"