speiidev 1.4.2 → 1.4.4
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/bin/speiidev.js +1 -0
- package/package.json +1 -1
- package/src/autodev/_version.py +1 -1
- package/src/autodev/cli.py +91 -0
- package/tests/test_cli.py +16 -0
package/bin/speiidev.js
CHANGED
|
@@ -31,6 +31,7 @@ const srcDir = path.resolve(__dirname, '..', 'src');
|
|
|
31
31
|
const args = process.argv.slice(2);
|
|
32
32
|
const env = {
|
|
33
33
|
...process.env,
|
|
34
|
+
SPEIIDEV_INSTALLER: 'npm',
|
|
34
35
|
PYTHONPATH: srcDir + (process.env.PYTHONPATH ? path.delimiter + process.env.PYTHONPATH : ''),
|
|
35
36
|
};
|
|
36
37
|
|
package/package.json
CHANGED
package/src/autodev/_version.py
CHANGED
package/src/autodev/cli.py
CHANGED
|
@@ -118,6 +118,7 @@ SLASH_COMMANDS = [
|
|
|
118
118
|
"/model",
|
|
119
119
|
"/effort",
|
|
120
120
|
"/perms",
|
|
121
|
+
"/update",
|
|
121
122
|
"/log",
|
|
122
123
|
"/conv",
|
|
123
124
|
"/rember",
|
|
@@ -2361,6 +2362,7 @@ def open_action_menu(state: AgentState) -> None:
|
|
|
2361
2362
|
("model", "🧠 Switch model"),
|
|
2362
2363
|
("effort", "⚡ Change effort"),
|
|
2363
2364
|
("perms", "🔐 Permission gate"),
|
|
2365
|
+
("update", "🔄 Update SpeiiDev"),
|
|
2364
2366
|
("help", "❓ Help"),
|
|
2365
2367
|
("exit", "🚪 Exit"),
|
|
2366
2368
|
],
|
|
@@ -2380,6 +2382,8 @@ def open_action_menu(state: AgentState) -> None:
|
|
|
2380
2382
|
handle_effort_switcher(state)
|
|
2381
2383
|
elif action == "perms":
|
|
2382
2384
|
handle_permissions(state)
|
|
2385
|
+
elif action == "update":
|
|
2386
|
+
handle_self_update()
|
|
2383
2387
|
elif action == "help":
|
|
2384
2388
|
show_help()
|
|
2385
2389
|
|
|
@@ -2418,10 +2422,86 @@ def show_help() -> None:
|
|
|
2418
2422
|
table.add_row("/font <text>", "Render text in 3D wireframe shadow or mini block font")
|
|
2419
2423
|
table.add_row("/clear", "Clear the screen and redraw the banner")
|
|
2420
2424
|
table.add_row("Ctrl+L", "Clear the screen and redraw responsive banner")
|
|
2425
|
+
table.add_row("/update", "Update SpeiiDev to the latest version from npm or PyPI")
|
|
2421
2426
|
table.add_row("/exit", "Quit SpeiiDev")
|
|
2422
2427
|
console.print(table)
|
|
2423
2428
|
|
|
2424
2429
|
|
|
2430
|
+
def check_latest_version(timeout: float = 2.0) -> str | None:
|
|
2431
|
+
"""Query PyPI or npm registry to check the latest released version."""
|
|
2432
|
+
import urllib.request
|
|
2433
|
+
try:
|
|
2434
|
+
url = "https://pypi.org/pypi/speiidev/json"
|
|
2435
|
+
req = urllib.request.Request(url, headers={"User-Agent": "speiidev-updater"})
|
|
2436
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
2437
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
2438
|
+
v = data.get("info", {}).get("version")
|
|
2439
|
+
if v:
|
|
2440
|
+
return str(v)
|
|
2441
|
+
except Exception:
|
|
2442
|
+
pass
|
|
2443
|
+
try:
|
|
2444
|
+
url = "https://registry.npmjs.org/speiidev/latest"
|
|
2445
|
+
req = urllib.request.Request(url, headers={"User-Agent": "speiidev-updater"})
|
|
2446
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
2447
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
2448
|
+
v = data.get("version")
|
|
2449
|
+
if v:
|
|
2450
|
+
return str(v)
|
|
2451
|
+
except Exception:
|
|
2452
|
+
pass
|
|
2453
|
+
return None
|
|
2454
|
+
|
|
2455
|
+
|
|
2456
|
+
def handle_self_update() -> int:
|
|
2457
|
+
"""Automatically detect installation method and update SpeiiDev."""
|
|
2458
|
+
console.print(f"\n[bold {THEME['primary']}]🔄 Checking for SpeiiDev updates…[/bold {THEME['primary']}]")
|
|
2459
|
+
latest = check_latest_version(timeout=2.5)
|
|
2460
|
+
if latest:
|
|
2461
|
+
console.print(
|
|
2462
|
+
f"[{THEME['dim']}]Current version:[/] [bold]{APP_VERSION}[/] "
|
|
2463
|
+
f"[{THEME['dim']}]Latest version:[/] [bold green]{latest}[/]"
|
|
2464
|
+
)
|
|
2465
|
+
if latest == APP_VERSION:
|
|
2466
|
+
console.print(f"[bold {THEME['ok']}]✅ SpeiiDev is already up to date ({APP_VERSION})![/]\n")
|
|
2467
|
+
return 0
|
|
2468
|
+
console.print(f"[{THEME['accent']}]🚀 Upgrading SpeiiDev {APP_VERSION} → {latest}…[/]")
|
|
2469
|
+
else:
|
|
2470
|
+
console.print(f"[{THEME['dim']}]Checking latest release packages…[/]")
|
|
2471
|
+
|
|
2472
|
+
is_npm = os.environ.get("SPEIIDEV_INSTALLER") == "npm" or "node_modules" in sys.argv[0]
|
|
2473
|
+
npm_bin = shutil.which("npm")
|
|
2474
|
+
pipx_bin = shutil.which("pipx")
|
|
2475
|
+
|
|
2476
|
+
updated = False
|
|
2477
|
+
if is_npm and npm_bin:
|
|
2478
|
+
console.print(f"[{THEME['dim']}]Updating via npm: npm install -g --force speiidev@latest[/]")
|
|
2479
|
+
res = subprocess.run([npm_bin, "install", "-g", "--force", "speiidev@latest"])
|
|
2480
|
+
updated = (res.returncode == 0)
|
|
2481
|
+
elif pipx_bin and "pipx" in sys.prefix:
|
|
2482
|
+
console.print(f"[{THEME['dim']}]Updating via pipx: pipx upgrade speiidev[/]")
|
|
2483
|
+
res = subprocess.run([pipx_bin, "upgrade", "speiidev"])
|
|
2484
|
+
updated = (res.returncode == 0)
|
|
2485
|
+
else:
|
|
2486
|
+
console.print(f"[{THEME['dim']}]Updating via pip: python -m pip install -U speiidev[/]")
|
|
2487
|
+
res = subprocess.run([sys.executable, "-m", "pip", "install", "-U", "speiidev"])
|
|
2488
|
+
if res.returncode != 0:
|
|
2489
|
+
console.print(f"[{THEME['dim']}]Retrying with --break-system-packages…[/]")
|
|
2490
|
+
res = subprocess.run([sys.executable, "-m", "pip", "install", "-U", "--break-system-packages", "speiidev"])
|
|
2491
|
+
updated = (res.returncode == 0)
|
|
2492
|
+
|
|
2493
|
+
if updated:
|
|
2494
|
+
console.print(f"\n[bold {THEME['ok']}]🎉 SpeiiDev successfully updated to {latest or 'latest'}![/bold {THEME['ok']}]")
|
|
2495
|
+
console.print(f"[{THEME['text']}]Please restart speiidev to run the new version.[/]\n")
|
|
2496
|
+
return 0
|
|
2497
|
+
else:
|
|
2498
|
+
console.print(f"\n[{THEME['err']}]❌ Automatic update encountered an issue. Run one of these manually:[/]")
|
|
2499
|
+
console.print(f" [{THEME['primary']}]npm install -g --force speiidev@latest[/]")
|
|
2500
|
+
console.print(f" [{THEME['primary']}]pipx install speiidev --force[/]")
|
|
2501
|
+
console.print(f" [{THEME['primary']}]pip install -U speiidev[/]\n")
|
|
2502
|
+
return 1
|
|
2503
|
+
|
|
2504
|
+
|
|
2425
2505
|
def handle_rember(state: AgentState, arg: str = "") -> None:
|
|
2426
2506
|
"""List remembered chats or resume one by index/id."""
|
|
2427
2507
|
entries = load_rember()
|
|
@@ -2625,6 +2705,8 @@ def interactive_repl(state: AgentState) -> int:
|
|
|
2625
2705
|
return 0
|
|
2626
2706
|
elif user_input == "/help":
|
|
2627
2707
|
show_help()
|
|
2708
|
+
elif user_input == "/update":
|
|
2709
|
+
handle_self_update()
|
|
2628
2710
|
elif user_input == "/clear":
|
|
2629
2711
|
console.clear()
|
|
2630
2712
|
print_banner(state)
|
|
@@ -2720,8 +2802,17 @@ def main() -> int:
|
|
|
2720
2802
|
default="claude",
|
|
2721
2803
|
help="Font style: claude (3D wireframe shadow) or mini (compact 2-line)",
|
|
2722
2804
|
)
|
|
2805
|
+
parser.add_argument("-v", "--version", action="store_true", help="Print version and exit")
|
|
2806
|
+
parser.add_argument("--update", action="store_true", help="Update SpeiiDev to latest version and exit")
|
|
2723
2807
|
args = parser.parse_args()
|
|
2724
2808
|
|
|
2809
|
+
if args.version:
|
|
2810
|
+
console.print(f"SpeiiDev v{APP_VERSION}")
|
|
2811
|
+
return 0
|
|
2812
|
+
|
|
2813
|
+
if args.update:
|
|
2814
|
+
return handle_self_update()
|
|
2815
|
+
|
|
2725
2816
|
if args.font is not None:
|
|
2726
2817
|
console.print(f"[bold {THEME['primary']}]{render_block_text(args.font, style=args.font_style, color='none')}[/]")
|
|
2727
2818
|
return 0
|
package/tests/test_cli.py
CHANGED
|
@@ -204,6 +204,22 @@ class TestCLIHelpers(unittest.TestCase):
|
|
|
204
204
|
f"Stream view panel line width {len(line)} exceeded terminal width {w} at {w}x{h}",
|
|
205
205
|
)
|
|
206
206
|
|
|
207
|
+
def test_version_flag(self):
|
|
208
|
+
from autodev.cli import main
|
|
209
|
+
import sys
|
|
210
|
+
old_argv = sys.argv
|
|
211
|
+
try:
|
|
212
|
+
sys.argv = ["speiidev", "--version"]
|
|
213
|
+
rc = main()
|
|
214
|
+
self.assertEqual(rc, 0)
|
|
215
|
+
finally:
|
|
216
|
+
sys.argv = old_argv
|
|
217
|
+
|
|
218
|
+
def test_slash_commands_include_update(self):
|
|
219
|
+
from autodev.cli import SLASH_COMMANDS
|
|
220
|
+
self.assertIn("/update", SLASH_COMMANDS)
|
|
221
|
+
|
|
207
222
|
|
|
208
223
|
if __name__ == "__main__":
|
|
209
224
|
unittest.main()
|
|
225
|
+
|