Files
a433c483c1 fix: document bootstrap entrypoints in examples (fixes #71) (#96)
* feat: standardize bootstrap entrypoint to 'aiui run app.py' across examples

Standardizes platform bootstrap patterns across examples per issue #71:

- Update examples README table to use 'aiui run app.py' consistently
- Update docstrings in examples 10, 12, 19-21 to show 'aiui run' instead of 'python app.py'
- Remove fragmented bootstrap approaches (uvicorn.run, asyncio patterns)
- Enforce single bootstrap SSOT as designed in CLI

Co-authored-by: Mervin Praison <[email protected]>

* feat: consolidate bootstrap entrypoints - auto-detect gateway apps (fixes #71)

- Add bootstrap detection in CLI run command
- Auto-detect gateway pattern (async main + AIUIGateway imports)
- Auto-switch to praisonai backend for gateway apps
- Delegate to user-defined main() when present
- Remove sys.path hacks from example 14
- Update examples README to show unified aiui run entrypoint
- Add BOOTSTRAP.md documentation for migration patterns

Co-authored-by: Mervin Praison <[email protected]>

* fix: resolve critical bootstrap entrypoint issues

- Fix AST parsing bug in gateway auto-detection (cli.py:1419)
- Revert background bots (email-bot, agentmail-bot) to python app.py
- Revert custom UI apps (agent-dashboard) to python app.py
- Update README.md to reflect correct run commands
- Fix import formatting and remove unused imports

These changes ensure that:
1. Gateway auto-detection works correctly by properly checking ast.alias.name
2. Background bots execute their __main__ blocks and don't start unnecessary web servers
3. Custom UI apps register their custom routes in __main__ blocks
4. Documentation matches actual working run commands

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Mervin Praison <[email protected]>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mervin Praison <[email protected]>
Co-authored-by: Mervin Praison <[email protected]>
Co-authored-by: Cursor <[email protected]>
2026-06-15 16:36:35 +01:00

73 lines
2.3 KiB
Python

"""Unit tests for surface CLI commands (mocked API)."""
import json
from pathlib import Path
from unittest.mock import patch
from typer.testing import CliRunner
from praisonaiui.cli import app
runner = CliRunner()
SERVER = "http://127.0.0.1:8099"
@patch("praisonaiui.cli._api_get")
def test_surface_list_empty(mock_get):
mock_get.return_value = {"surfaces": []}
result = runner.invoke(app, ["surface", "list", "--server", SERVER])
assert result.exit_code == 0
assert "No surfaces yet" in result.output
@patch("praisonaiui.cli._api_get")
def test_surface_list_with_data(mock_get):
mock_get.return_value = {"surfaces": [{"id": "main", "message_count": 2}]}
result = runner.invoke(app, ["surface", "list", "--server", SERVER])
assert result.exit_code == 0
assert "main" in result.output
@patch("praisonaiui.cli._api_get")
def test_surface_get_empty(mock_get):
mock_get.return_value = {"id": "main", "messages": []}
result = runner.invoke(app, ["surface", "get", "main", "--server", SERVER])
assert result.exit_code == 0
assert "Messages: 0" in result.output
@patch("praisonaiui.cli._api_post")
def test_surface_push(mock_post, tmp_path: Path):
payload = {
"messages": [
{"updateComponents": {"components": [{"component": "Button", "text": {"literal": "Go"}}]}}
]
}
f = tmp_path / "ui.json"
f.write_text(json.dumps(payload), encoding="utf-8")
mock_post.return_value = {"id": "main", "message_count": 1}
result = runner.invoke(
app,
["surface", "push", "main", "--file", str(f), "--server", SERVER],
)
assert result.exit_code == 0
mock_post.assert_called_once()
assert "Pushed to main" in result.output
@patch("praisonaiui.cli._api_delete")
def test_surface_clear(mock_delete):
mock_delete.return_value = {"status": "deleted", "id": "main"}
result = runner.invoke(app, ["surface", "clear", "main", "--server", SERVER])
assert result.exit_code == 0
assert "Cleared surface" in result.output
@patch("praisonaiui.cli._api_get")
def test_surface_status(mock_get):
mock_get.return_value = {"surfaces": [{"id": "main", "message_count": 3}]}
result = runner.invoke(app, ["surface", "status", "--server", SERVER])
assert result.exit_code == 0
assert "Surfaces: 1" in result.output
assert "Total messages: 3" in result.output