praisonai-code 0.0.1__py3-none-any.whl
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.
- praisonai_code/__init__.py +17 -0
- praisonai_code/cli/__init__.py +12 -0
- praisonai_code/cli/_forward_shim.py +10 -0
- praisonai_code/cli/_paths.py +88 -0
- praisonai_code/cli/_warnings.py +58 -0
- praisonai_code/cli/app.py +757 -0
- praisonai_code/cli/approval_backend.py +272 -0
- praisonai_code/cli/branding.py +94 -0
- praisonai_code/cli/commands/__init__.py +114 -0
- praisonai_code/cli/commands/acp.py +80 -0
- praisonai_code/cli/commands/agent.py +116 -0
- praisonai_code/cli/commands/agents.py +80 -0
- praisonai_code/cli/commands/app.py +139 -0
- praisonai_code/cli/commands/attach.py +95 -0
- praisonai_code/cli/commands/audit.py +102 -0
- praisonai_code/cli/commands/auth.py +508 -0
- praisonai_code/cli/commands/batch.py +848 -0
- praisonai_code/cli/commands/benchmark.py +286 -0
- praisonai_code/cli/commands/browser.py +299 -0
- praisonai_code/cli/commands/call.py +45 -0
- praisonai_code/cli/commands/chat.py +332 -0
- praisonai_code/cli/commands/checkpoint.py +170 -0
- praisonai_code/cli/commands/code.py +276 -0
- praisonai_code/cli/commands/command.py +114 -0
- praisonai_code/cli/commands/commit.py +47 -0
- praisonai_code/cli/commands/completion.py +333 -0
- praisonai_code/cli/commands/config.py +681 -0
- praisonai_code/cli/commands/context.py +414 -0
- praisonai_code/cli/commands/daemon.py +203 -0
- praisonai_code/cli/commands/debug.py +142 -0
- praisonai_code/cli/commands/deploy.py +71 -0
- praisonai_code/cli/commands/diag.py +55 -0
- praisonai_code/cli/commands/docs.py +1575 -0
- praisonai_code/cli/commands/doctor.py +332 -0
- praisonai_code/cli/commands/endpoints.py +51 -0
- praisonai_code/cli/commands/environment.py +179 -0
- praisonai_code/cli/commands/eval.py +131 -0
- praisonai_code/cli/commands/examples.py +953 -0
- praisonai_code/cli/commands/flow.py +436 -0
- praisonai_code/cli/commands/github.py +752 -0
- praisonai_code/cli/commands/hooks.py +74 -0
- praisonai_code/cli/commands/init.py +174 -0
- praisonai_code/cli/commands/knowledge.py +440 -0
- praisonai_code/cli/commands/langextract.py +120 -0
- praisonai_code/cli/commands/langfuse.py +984 -0
- praisonai_code/cli/commands/loop.py +211 -0
- praisonai_code/cli/commands/lsp.py +112 -0
- praisonai_code/cli/commands/managed.py +659 -0
- praisonai_code/cli/commands/mcp.py +763 -0
- praisonai_code/cli/commands/memory.py +298 -0
- praisonai_code/cli/commands/models.py +264 -0
- praisonai_code/cli/commands/n8n.py +326 -0
- praisonai_code/cli/commands/obs.py +19 -0
- praisonai_code/cli/commands/package.py +76 -0
- praisonai_code/cli/commands/paths.py +106 -0
- praisonai_code/cli/commands/permissions.py +272 -0
- praisonai_code/cli/commands/plugins.py +609 -0
- praisonai_code/cli/commands/port.py +530 -0
- praisonai_code/cli/commands/profile.py +466 -0
- praisonai_code/cli/commands/publish.py +193 -0
- praisonai_code/cli/commands/rag.py +913 -0
- praisonai_code/cli/commands/realtime.py +52 -0
- praisonai_code/cli/commands/recipe.py +684 -0
- praisonai_code/cli/commands/registry.py +59 -0
- praisonai_code/cli/commands/replay.py +830 -0
- praisonai_code/cli/commands/research.py +49 -0
- praisonai_code/cli/commands/retrieval.py +377 -0
- praisonai_code/cli/commands/rules.py +71 -0
- praisonai_code/cli/commands/run.py +1573 -0
- praisonai_code/cli/commands/sandbox.py +371 -0
- praisonai_code/cli/commands/schedule.py +529 -0
- praisonai_code/cli/commands/serve.py +690 -0
- praisonai_code/cli/commands/session.py +450 -0
- praisonai_code/cli/commands/setup.py +174 -0
- praisonai_code/cli/commands/skills.py +545 -0
- praisonai_code/cli/commands/standardise.py +711 -0
- praisonai_code/cli/commands/templates.py +54 -0
- praisonai_code/cli/commands/test.py +558 -0
- praisonai_code/cli/commands/todo.py +74 -0
- praisonai_code/cli/commands/tools.py +205 -0
- praisonai_code/cli/commands/traces.py +145 -0
- praisonai_code/cli/commands/tracker.py +852 -0
- praisonai_code/cli/commands/train.py +613 -0
- praisonai_code/cli/commands/ui.py +172 -0
- praisonai_code/cli/commands/up.py +354 -0
- praisonai_code/cli/commands/validate.py +291 -0
- praisonai_code/cli/commands/version.py +101 -0
- praisonai_code/cli/commands/workflow.py +97 -0
- praisonai_code/cli/config_loader.py +437 -0
- praisonai_code/cli/configuration/__init__.py +27 -0
- praisonai_code/cli/configuration/config.schema.json +57 -0
- praisonai_code/cli/configuration/credentials.py +446 -0
- praisonai_code/cli/configuration/loader.py +364 -0
- praisonai_code/cli/configuration/model_resolver.py +161 -0
- praisonai_code/cli/configuration/oauth.py +389 -0
- praisonai_code/cli/configuration/paths.py +224 -0
- praisonai_code/cli/configuration/resolver.py +687 -0
- praisonai_code/cli/configuration/schema.py +317 -0
- praisonai_code/cli/execution/__init__.py +99 -0
- praisonai_code/cli/execution/core.py +208 -0
- praisonai_code/cli/execution/profiler.py +898 -0
- praisonai_code/cli/execution/request.py +85 -0
- praisonai_code/cli/execution/result.py +74 -0
- praisonai_code/cli/fallback_schema.py +416 -0
- praisonai_code/cli/features/__init__.py +278 -0
- praisonai_code/cli/features/_endpoint_registry.py +64 -0
- praisonai_code/cli/features/_search_registry.py +43 -0
- praisonai_code/cli/features/acp.py +236 -0
- praisonai_code/cli/features/action_orchestrator.py +576 -0
- praisonai_code/cli/features/agent_scheduler.py +773 -0
- praisonai_code/cli/features/agent_tools.py +603 -0
- praisonai_code/cli/features/agents.py +397 -0
- praisonai_code/cli/features/at_mentions.py +471 -0
- praisonai_code/cli/features/audit_cli.py +270 -0
- praisonai_code/cli/features/auto_memory.py +182 -0
- praisonai_code/cli/features/auto_mode.py +552 -0
- praisonai_code/cli/features/autonomy_mode.py +546 -0
- praisonai_code/cli/features/background.py +356 -0
- praisonai_code/cli/features/base.py +168 -0
- praisonai_code/cli/features/benchmark.py +1462 -0
- praisonai_code/cli/features/capabilities.py +1326 -0
- praisonai_code/cli/features/checkpoints.py +345 -0
- praisonai_code/cli/features/cli_profiler.py +335 -0
- praisonai_code/cli/features/code_intelligence.py +666 -0
- praisonai_code/cli/features/compaction.py +294 -0
- praisonai_code/cli/features/compare.py +534 -0
- praisonai_code/cli/features/config_hierarchy.py +366 -0
- praisonai_code/cli/features/context_manager.py +597 -0
- praisonai_code/cli/features/cost_tracker.py +514 -0
- praisonai_code/cli/features/csv_test_runner.py +736 -0
- praisonai_code/cli/features/custom_definitions.py +790 -0
- praisonai_code/cli/features/debug.py +810 -0
- praisonai_code/cli/features/deploy.py +605 -0
- praisonai_code/cli/features/diag.py +289 -0
- praisonai_code/cli/features/display_jsonl.py +173 -0
- praisonai_code/cli/features/doctor/__init__.py +63 -0
- praisonai_code/cli/features/doctor/checks/__init__.py +29 -0
- praisonai_code/cli/features/doctor/checks/acp_checks.py +220 -0
- praisonai_code/cli/features/doctor/checks/bot_checks.py +340 -0
- praisonai_code/cli/features/doctor/checks/config_checks.py +373 -0
- praisonai_code/cli/features/doctor/checks/db_checks.py +366 -0
- praisonai_code/cli/features/doctor/checks/env_checks.py +637 -0
- praisonai_code/cli/features/doctor/checks/gateway_checks.py +387 -0
- praisonai_code/cli/features/doctor/checks/lsp_checks.py +231 -0
- praisonai_code/cli/features/doctor/checks/mcp_checks.py +367 -0
- praisonai_code/cli/features/doctor/checks/memory_checks.py +268 -0
- praisonai_code/cli/features/doctor/checks/network_checks.py +251 -0
- praisonai_code/cli/features/doctor/checks/obs_checks.py +328 -0
- praisonai_code/cli/features/doctor/checks/packaging_checks.py +422 -0
- praisonai_code/cli/features/doctor/checks/performance_checks.py +235 -0
- praisonai_code/cli/features/doctor/checks/permissions_checks.py +259 -0
- praisonai_code/cli/features/doctor/checks/runtime_checks.py +650 -0
- praisonai_code/cli/features/doctor/checks/runtime_migration_checks.py +220 -0
- praisonai_code/cli/features/doctor/checks/selftest_checks.py +322 -0
- praisonai_code/cli/features/doctor/checks/serve_checks.py +426 -0
- praisonai_code/cli/features/doctor/checks/skills_checks.py +327 -0
- praisonai_code/cli/features/doctor/checks/tools_checks.py +371 -0
- praisonai_code/cli/features/doctor/engine.py +266 -0
- praisonai_code/cli/features/doctor/formatters.py +377 -0
- praisonai_code/cli/features/doctor/handler.py +564 -0
- praisonai_code/cli/features/doctor/models.py +276 -0
- praisonai_code/cli/features/doctor/registry.py +239 -0
- praisonai_code/cli/features/endpoints.py +1016 -0
- praisonai_code/cli/features/eval.py +559 -0
- praisonai_code/cli/features/examples.py +707 -0
- praisonai_code/cli/features/external_agents.py +231 -0
- praisonai_code/cli/features/fast_context.py +410 -0
- praisonai_code/cli/features/file_history.py +320 -0
- praisonai_code/cli/features/flow_display.py +566 -0
- praisonai_code/cli/features/git_attribution.py +159 -0
- praisonai_code/cli/features/git_integration.py +651 -0
- praisonai_code/cli/features/guardrail.py +171 -0
- praisonai_code/cli/features/handoff.py +252 -0
- praisonai_code/cli/features/hooks.py +583 -0
- praisonai_code/cli/features/hybrid_workflow.py +391 -0
- praisonai_code/cli/features/image.py +384 -0
- praisonai_code/cli/features/interactive_core_headless.py +450 -0
- praisonai_code/cli/features/interactive_runtime.py +600 -0
- praisonai_code/cli/features/interactive_test_harness.py +537 -0
- praisonai_code/cli/features/interactive_tools.py +428 -0
- praisonai_code/cli/features/interactive_tui.py +603 -0
- praisonai_code/cli/features/job_workflow.py +906 -0
- praisonai_code/cli/features/jobs.py +632 -0
- praisonai_code/cli/features/knowledge.py +531 -0
- praisonai_code/cli/features/knowledge_cli.py +438 -0
- praisonai_code/cli/features/lite.py +244 -0
- praisonai_code/cli/features/logs.py +200 -0
- praisonai_code/cli/features/lsp_cli.py +225 -0
- praisonai_code/cli/features/lsp_diagnostics.py +185 -0
- praisonai_code/cli/features/mcp.py +344 -0
- praisonai_code/cli/features/message_queue.py +587 -0
- praisonai_code/cli/features/metrics.py +210 -0
- praisonai_code/cli/features/migrate.py +1329 -0
- praisonai_code/cli/features/migration_flow.py +463 -0
- praisonai_code/cli/features/migration_spec.py +276 -0
- praisonai_code/cli/features/n8n.py +703 -0
- praisonai_code/cli/features/observability.py +293 -0
- praisonai_code/cli/features/ollama.py +361 -0
- praisonai_code/cli/features/output_modes.py +155 -0
- praisonai_code/cli/features/output_style.py +273 -0
- praisonai_code/cli/features/package.py +631 -0
- praisonai_code/cli/features/performance.py +308 -0
- praisonai_code/cli/features/persistence.py +636 -0
- praisonai_code/cli/features/profiler/__init__.py +81 -0
- praisonai_code/cli/features/profiler/core.py +558 -0
- praisonai_code/cli/features/profiler/optimizations.py +652 -0
- praisonai_code/cli/features/profiler/suite.py +386 -0
- praisonai_code/cli/features/queue/__init__.py +73 -0
- praisonai_code/cli/features/queue/manager.py +435 -0
- praisonai_code/cli/features/queue/models.py +289 -0
- praisonai_code/cli/features/queue/persistence.py +564 -0
- praisonai_code/cli/features/queue/scheduler.py +529 -0
- praisonai_code/cli/features/queue/worker.py +400 -0
- praisonai_code/cli/features/recipe.py +2187 -0
- praisonai_code/cli/features/recipe_creator.py +996 -0
- praisonai_code/cli/features/recipe_optimizer.py +1364 -0
- praisonai_code/cli/features/recipe_prompts.py +226 -0
- praisonai_code/cli/features/registry.py +229 -0
- praisonai_code/cli/features/repo_map.py +860 -0
- praisonai_code/cli/features/router.py +466 -0
- praisonai_code/cli/features/safe_shell.py +427 -0
- praisonai_code/cli/features/sandbox_cli.py +283 -0
- praisonai_code/cli/features/sandbox_executor.py +536 -0
- praisonai_code/cli/features/sdk_knowledge.py +500 -0
- praisonai_code/cli/features/session.py +222 -0
- praisonai_code/cli/features/session_checkpoints.py +208 -0
- praisonai_code/cli/features/setup/__init__.py +9 -0
- praisonai_code/cli/features/setup/handler.py +355 -0
- praisonai_code/cli/features/setup/templates.py +62 -0
- praisonai_code/cli/features/skills.py +940 -0
- praisonai_code/cli/features/slash_commands.py +692 -0
- praisonai_code/cli/features/telemetry.py +179 -0
- praisonai_code/cli/features/templates.py +1390 -0
- praisonai_code/cli/features/thinking.py +343 -0
- praisonai_code/cli/features/todo.py +334 -0
- praisonai_code/cli/features/tools.py +680 -0
- praisonai_code/cli/features/tui/__init__.py +83 -0
- praisonai_code/cli/features/tui/app.py +871 -0
- praisonai_code/cli/features/tui/cli.py +580 -0
- praisonai_code/cli/features/tui/config.py +150 -0
- praisonai_code/cli/features/tui/debug.py +526 -0
- praisonai_code/cli/features/tui/events.py +99 -0
- praisonai_code/cli/features/tui/mock_provider.py +328 -0
- praisonai_code/cli/features/tui/orchestrator.py +652 -0
- praisonai_code/cli/features/tui/screens/__init__.py +50 -0
- praisonai_code/cli/features/tui/screens/help.py +157 -0
- praisonai_code/cli/features/tui/screens/main.py +568 -0
- praisonai_code/cli/features/tui/screens/queue.py +174 -0
- praisonai_code/cli/features/tui/screens/session.py +124 -0
- praisonai_code/cli/features/tui/screens/settings.py +148 -0
- praisonai_code/cli/features/tui/session_store.py +198 -0
- praisonai_code/cli/features/tui/widgets/__init__.py +56 -0
- praisonai_code/cli/features/tui/widgets/chat.py +263 -0
- praisonai_code/cli/features/tui/widgets/command_popup.py +258 -0
- praisonai_code/cli/features/tui/widgets/composer.py +292 -0
- praisonai_code/cli/features/tui/widgets/file_popup.py +207 -0
- praisonai_code/cli/features/tui/widgets/queue_panel.py +223 -0
- praisonai_code/cli/features/tui/widgets/status.py +181 -0
- praisonai_code/cli/features/tui/widgets/tool_panel.py +307 -0
- praisonai_code/cli/features/wizard.py +289 -0
- praisonai_code/cli/features/workflow.py +802 -0
- praisonai_code/cli/features/yaml_utils.py +321 -0
- praisonai_code/cli/interactive/__init__.py +48 -0
- praisonai_code/cli/interactive/async_tui.py +1218 -0
- praisonai_code/cli/interactive/config.py +139 -0
- praisonai_code/cli/interactive/core.py +618 -0
- praisonai_code/cli/interactive/events.py +131 -0
- praisonai_code/cli/interactive/frontends/__init__.py +31 -0
- praisonai_code/cli/interactive/frontends/rich_frontend.py +462 -0
- praisonai_code/cli/interactive/frontends/textual_frontend.py +157 -0
- praisonai_code/cli/interactive/praison_io.py +502 -0
- praisonai_code/cli/interactive/repl.py +297 -0
- praisonai_code/cli/interactive/split_tui.py +456 -0
- praisonai_code/cli/interactive/tui_app.py +457 -0
- praisonai_code/cli/langfuse_client.py +360 -0
- praisonai_code/cli/main.py +7421 -0
- praisonai_code/cli/output/__init__.py +25 -0
- praisonai_code/cli/output/console.py +456 -0
- praisonai_code/cli/output/event_bridge.py +191 -0
- praisonai_code/cli/schedule_cli.py +54 -0
- praisonai_code/cli/schema_provider.py +23 -0
- praisonai_code/cli/session/__init__.py +16 -0
- praisonai_code/cli/session/resume.py +148 -0
- praisonai_code/cli/session/unified.py +548 -0
- praisonai_code/cli/state/__init__.py +31 -0
- praisonai_code/cli/state/identifiers.py +161 -0
- praisonai_code/cli/state/project_sessions.py +383 -0
- praisonai_code/cli/state/sessions.py +390 -0
- praisonai_code/cli/ui/__init__.py +160 -0
- praisonai_code/cli/ui/config.py +46 -0
- praisonai_code/cli/ui/events.py +61 -0
- praisonai_code/cli/ui/mg_backend.py +342 -0
- praisonai_code/cli/ui/plain.py +133 -0
- praisonai_code/cli/ui/rich_backend.py +162 -0
- praisonai_code/cli/unified_schema.py +655 -0
- praisonai_code/cli/utils/env_utils.py +126 -0
- praisonai_code/cli/utils/project.py +131 -0
- praisonai_code/cli_backends/__init__.py +73 -0
- praisonai_code/cli_backends/claude.py +373 -0
- praisonai_code/cli_backends/registry.py +113 -0
- praisonai_code/runtime/__init__.py +36 -0
- praisonai_code/runtime/__main__.py +81 -0
- praisonai_code/runtime/client.py +131 -0
- praisonai_code/runtime/descriptor.py +209 -0
- praisonai_code/runtime/server.py +356 -0
- praisonai_code-0.0.1.dist-info/METADATA +80 -0
- praisonai_code-0.0.1.dist-info/RECORD +309 -0
- praisonai_code-0.0.1.dist-info/WHEEL +5 -0
- praisonai_code-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UI command — launch the PraisonAI Clean Chat UI.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
praisonai ui # Chat on :8081
|
|
6
|
+
praisonai ui --port 9000 # Custom port
|
|
7
|
+
praisonai ui --app my-chat.py # Custom app file
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
import typer
|
|
15
|
+
|
|
16
|
+
app = typer.Typer(
|
|
17
|
+
help=(
|
|
18
|
+
"🤖 PraisonAI Clean Chat UI (Pattern B host via bundled default_app). "
|
|
19
|
+
"Pattern C: AIUIGateway. Legacy: PRAISONAI_HOST_LEGACY=1."
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _launch_aiui_app(
|
|
25
|
+
app_dir: str,
|
|
26
|
+
default_app_name: str,
|
|
27
|
+
port: int,
|
|
28
|
+
host: str,
|
|
29
|
+
app_file: Optional[str],
|
|
30
|
+
reload: bool,
|
|
31
|
+
ui_name: str
|
|
32
|
+
) -> None:
|
|
33
|
+
"""Common function to launch aiui apps."""
|
|
34
|
+
# 1. Check praisonaiui is installed
|
|
35
|
+
try:
|
|
36
|
+
import importlib.util
|
|
37
|
+
if importlib.util.find_spec("praisonaiui") is None:
|
|
38
|
+
raise ImportError
|
|
39
|
+
except ImportError:
|
|
40
|
+
print(f"\n\033[91mERROR: PraisonAI UI (aiui) is not installed.\033[0m")
|
|
41
|
+
print('\nInstall with:\n pip install "praisonai[ui]"\n')
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
|
|
44
|
+
# 2. Resolve app file
|
|
45
|
+
if app_file:
|
|
46
|
+
resolved = Path(app_file)
|
|
47
|
+
if not resolved.exists():
|
|
48
|
+
print(f"\033[91mERROR: App file not found: {app_file}\033[0m")
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
else:
|
|
51
|
+
ui_dir = Path.home() / ".praisonai" / app_dir
|
|
52
|
+
default_app = ui_dir / "app.py"
|
|
53
|
+
|
|
54
|
+
# Ensure default app exists
|
|
55
|
+
if not default_app.exists():
|
|
56
|
+
ui_dir.mkdir(parents=True, exist_ok=True)
|
|
57
|
+
bundled = Path(__file__).parent.parent.parent / default_app_name / "default_app.py"
|
|
58
|
+
if not bundled.exists():
|
|
59
|
+
print(f"\033[91mERROR: Bundled default_app.py not found at {bundled}\033[0m")
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
default_app.write_text(bundled.read_text())
|
|
62
|
+
print(f" ✓ Created default {ui_name} config: {default_app}")
|
|
63
|
+
|
|
64
|
+
resolved = default_app
|
|
65
|
+
|
|
66
|
+
# 3. Launch via aiui run
|
|
67
|
+
import subprocess
|
|
68
|
+
|
|
69
|
+
cmd = ["aiui", "run", str(resolved), "--port", str(port), "--host", host]
|
|
70
|
+
if reload:
|
|
71
|
+
cmd.append("--reload")
|
|
72
|
+
|
|
73
|
+
print(f"\n🤖 PraisonAI {ui_name} starting at http://{host}:{port}")
|
|
74
|
+
print(f" App: {resolved}\n")
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
subprocess.run(cmd, check=True)
|
|
78
|
+
except FileNotFoundError:
|
|
79
|
+
# Fallback: python -m praisonaiui.cli
|
|
80
|
+
cmd = [sys.executable, "-m", "praisonaiui.cli", "run", str(resolved),
|
|
81
|
+
"--port", str(port), "--host", host]
|
|
82
|
+
if reload:
|
|
83
|
+
cmd.append("--reload")
|
|
84
|
+
subprocess.run(cmd, check=True)
|
|
85
|
+
except KeyboardInterrupt:
|
|
86
|
+
print(f"\n🤖 {ui_name} stopped.")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@app.callback(invoke_without_command=True)
|
|
90
|
+
def ui(
|
|
91
|
+
ctx: typer.Context,
|
|
92
|
+
port: int = typer.Option(8081, "--port", "-p", help="Port to run chat UI on"),
|
|
93
|
+
host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
|
|
94
|
+
app_file: Optional[str] = typer.Option(
|
|
95
|
+
None, "--app", "-a", help="Custom app.py file (default: ~/.praisonai/ui/app.py)"
|
|
96
|
+
),
|
|
97
|
+
reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
|
|
98
|
+
):
|
|
99
|
+
"""
|
|
100
|
+
Launch the PraisonAI Clean Chat UI.
|
|
101
|
+
|
|
102
|
+
Starts a clean chat interface powered by PraisonAIUI — no sidebar,
|
|
103
|
+
single-page chat experience.
|
|
104
|
+
|
|
105
|
+
For the full dashboard with agents, memory, knowledge, etc.,
|
|
106
|
+
use: praisonai claw
|
|
107
|
+
|
|
108
|
+
Examples:
|
|
109
|
+
praisonai ui
|
|
110
|
+
praisonai ui --port 9000
|
|
111
|
+
praisonai ui --app my-chat.py
|
|
112
|
+
praisonai ui agents # YAML agents dashboard
|
|
113
|
+
praisonai ui bot # Bot interface
|
|
114
|
+
praisonai ui realtime # Voice realtime
|
|
115
|
+
"""
|
|
116
|
+
if ctx.invoked_subcommand is not None:
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
_launch_aiui_app("ui", "ui_chat", port, host, app_file, reload, "Chat")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@app.command()
|
|
123
|
+
def agents(
|
|
124
|
+
port: int = typer.Option(8083, "--port", "-p", help="Port to run agents UI on"),
|
|
125
|
+
host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
|
|
126
|
+
app_file: Optional[str] = typer.Option(
|
|
127
|
+
None, "--app", "-a", help="Custom app.py file"
|
|
128
|
+
),
|
|
129
|
+
reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
|
|
130
|
+
):
|
|
131
|
+
"""
|
|
132
|
+
Launch YAML Agents Dashboard.
|
|
133
|
+
|
|
134
|
+
Replaces the old Chainlit agents interface with aiui.
|
|
135
|
+
Loads agents from agents.yaml in the current directory.
|
|
136
|
+
"""
|
|
137
|
+
_launch_aiui_app("ui_agents", "ui_agents", port, host, app_file, reload, "Agents Dashboard")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@app.command()
|
|
141
|
+
def bot(
|
|
142
|
+
port: int = typer.Option(8084, "--port", "-p", help="Port to run bot UI on"),
|
|
143
|
+
host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
|
|
144
|
+
app_file: Optional[str] = typer.Option(
|
|
145
|
+
None, "--app", "-a", help="Custom app.py file"
|
|
146
|
+
),
|
|
147
|
+
reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
|
|
148
|
+
):
|
|
149
|
+
"""
|
|
150
|
+
Launch Bot Interface.
|
|
151
|
+
|
|
152
|
+
Replaces the old Chainlit bot interface with aiui.
|
|
153
|
+
Provides step-by-step interaction visualization.
|
|
154
|
+
"""
|
|
155
|
+
_launch_aiui_app("ui_bot", "ui_bot", port, host, app_file, reload, "Bot Interface")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@app.command()
|
|
159
|
+
def realtime(
|
|
160
|
+
port: int = typer.Option(8085, "--port", "-p", help="Port to run realtime UI on"),
|
|
161
|
+
host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
|
|
162
|
+
app_file: Optional[str] = typer.Option(
|
|
163
|
+
None, "--app", "-a", help="Custom app.py file"
|
|
164
|
+
),
|
|
165
|
+
reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload"),
|
|
166
|
+
):
|
|
167
|
+
"""
|
|
168
|
+
Launch Realtime Voice Interface.
|
|
169
|
+
|
|
170
|
+
Uses aiui's OpenAIRealtimeManager for WebRTC voice conversations.
|
|
171
|
+
"""
|
|
172
|
+
_launch_aiui_app("ui_realtime", "ui_realtime", port, host, app_file, reload, "Realtime Voice")
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"""PraisonAI Up — Unified startup command.
|
|
2
|
+
|
|
3
|
+
Starts Langfuse + Langflow + observability in one command for
|
|
4
|
+
the complete PraisonAI × Langfuse × Langflow experience.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import signal
|
|
9
|
+
import subprocess
|
|
10
|
+
import time
|
|
11
|
+
from typing import List, Optional
|
|
12
|
+
|
|
13
|
+
import typer
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
from rich.table import Table
|
|
17
|
+
|
|
18
|
+
app = typer.Typer(name="up", help="Start unified PraisonAI stack (Langfuse + Langflow + tracing)")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ServiceManager:
|
|
22
|
+
"""Manages multiple services with graceful shutdown."""
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
self.services: List[subprocess.Popen] = []
|
|
26
|
+
self.console = Console()
|
|
27
|
+
|
|
28
|
+
def add_service(self, cmd: List[str], name: str, env: Optional[dict] = None) -> subprocess.Popen:
|
|
29
|
+
"""Start a service and add to managed list."""
|
|
30
|
+
self.console.print(f"[cyan]Starting {name}...[/cyan]")
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
proc = subprocess.Popen(
|
|
34
|
+
cmd,
|
|
35
|
+
env=env or os.environ.copy(),
|
|
36
|
+
stdout=subprocess.DEVNULL,
|
|
37
|
+
stderr=subprocess.DEVNULL,
|
|
38
|
+
)
|
|
39
|
+
self.services.append(proc)
|
|
40
|
+
self.console.print(f"[green]✅ {name} started (PID: {proc.pid})[/green]")
|
|
41
|
+
return proc
|
|
42
|
+
|
|
43
|
+
except Exception as e:
|
|
44
|
+
self.console.print(f"[red]❌ Failed to start {name}: {e}[/red]")
|
|
45
|
+
raise typer.Abort()
|
|
46
|
+
|
|
47
|
+
def wait_for_service(self, url: str, service_name: str, timeout: int = 60) -> bool:
|
|
48
|
+
"""Wait for service to become healthy."""
|
|
49
|
+
try:
|
|
50
|
+
import requests
|
|
51
|
+
except ImportError:
|
|
52
|
+
self.console.print(f"[yellow]⚠️ Cannot health-check {service_name} (requests not installed)[/yellow]")
|
|
53
|
+
return True
|
|
54
|
+
|
|
55
|
+
self.console.print(f"[cyan]Waiting for {service_name} at {url}...[/cyan]")
|
|
56
|
+
|
|
57
|
+
start_time = time.time()
|
|
58
|
+
while time.time() - start_time < timeout:
|
|
59
|
+
try:
|
|
60
|
+
response = requests.get(f"{url}/api/v1/health", timeout=5)
|
|
61
|
+
if response.status_code == 200:
|
|
62
|
+
self.console.print(f"[green]✅ {service_name} is ready![/green]")
|
|
63
|
+
return True
|
|
64
|
+
except requests.RequestException:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
time.sleep(2)
|
|
68
|
+
|
|
69
|
+
self.console.print(f"[yellow]⚠️ {service_name} health check timed out[/yellow]")
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
def shutdown_all(self):
|
|
73
|
+
"""Gracefully shutdown all services."""
|
|
74
|
+
if not self.services:
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
self.console.print("\n[yellow]Shutting down services...[/yellow]")
|
|
78
|
+
|
|
79
|
+
# Send SIGTERM to all processes
|
|
80
|
+
for proc in self.services:
|
|
81
|
+
if proc.poll() is None: # Process still running
|
|
82
|
+
try:
|
|
83
|
+
proc.terminate()
|
|
84
|
+
except ProcessLookupError:
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
# Wait for graceful shutdown
|
|
88
|
+
time.sleep(3)
|
|
89
|
+
|
|
90
|
+
# Force kill any remaining processes
|
|
91
|
+
for proc in self.services:
|
|
92
|
+
if proc.poll() is None:
|
|
93
|
+
try:
|
|
94
|
+
proc.kill()
|
|
95
|
+
proc.wait(timeout=5)
|
|
96
|
+
except (ProcessLookupError, subprocess.TimeoutExpired):
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
self.console.print("[green]✅ All services stopped[/green]")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@app.callback(invoke_without_command=True)
|
|
103
|
+
def up_start(
|
|
104
|
+
ctx: typer.Context,
|
|
105
|
+
# Langfuse options
|
|
106
|
+
langfuse_port: int = typer.Option(3000, "--langfuse-port", help="Langfuse port"),
|
|
107
|
+
no_langfuse: bool = typer.Option(False, "--no-langfuse", help="Skip starting Langfuse"),
|
|
108
|
+
|
|
109
|
+
# Langflow options
|
|
110
|
+
langflow_port: int = typer.Option(7860, "--langflow-port", help="Langflow port"),
|
|
111
|
+
no_langflow: bool = typer.Option(False, "--no-langflow", help="Skip starting Langflow"),
|
|
112
|
+
|
|
113
|
+
# Observability options
|
|
114
|
+
observe: str = typer.Option("langfuse", "--observe", help="Enable observability (langfuse)"),
|
|
115
|
+
|
|
116
|
+
# General options
|
|
117
|
+
host: str = typer.Option("127.0.0.1", "--host", help="Host to bind to"),
|
|
118
|
+
no_open: bool = typer.Option(False, "--no-open", help="Don't open browser"),
|
|
119
|
+
wait_timeout: int = typer.Option(60, "--wait", help="Seconds to wait for services"),
|
|
120
|
+
):
|
|
121
|
+
"""Start unified PraisonAI stack.
|
|
122
|
+
|
|
123
|
+
Launches Langfuse (observability) + Langflow (visual builder) with
|
|
124
|
+
automatic observability wiring. The complete PraisonAI experience.
|
|
125
|
+
|
|
126
|
+
Examples:
|
|
127
|
+
praisonai up
|
|
128
|
+
praisonai up --no-langfuse # Langflow only
|
|
129
|
+
praisonai up --no-langflow # Langfuse only
|
|
130
|
+
praisonai up --host 0.0.0.0 --langfuse-port 3001
|
|
131
|
+
"""
|
|
132
|
+
if ctx.invoked_subcommand is not None:
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
console = Console()
|
|
136
|
+
manager = ServiceManager()
|
|
137
|
+
|
|
138
|
+
# Validate options
|
|
139
|
+
if no_langfuse and no_langflow:
|
|
140
|
+
console.print("[red]Error: Cannot skip both Langfuse and Langflow[/red]")
|
|
141
|
+
raise typer.Abort()
|
|
142
|
+
|
|
143
|
+
# Show startup banner
|
|
144
|
+
console.print()
|
|
145
|
+
console.print(Panel.fit(
|
|
146
|
+
"[bold green]🚀 PraisonAI Stack Starting[/bold green]\n\n"
|
|
147
|
+
f"[cyan]Langfuse:[/cyan] {'✅ Enabled' if not no_langfuse else '❌ Disabled'} "
|
|
148
|
+
f"(port {langfuse_port})\n"
|
|
149
|
+
f"[cyan]Langflow:[/cyan] {'✅ Enabled' if not no_langflow else '❌ Disabled'} "
|
|
150
|
+
f"(port {langflow_port})\n"
|
|
151
|
+
f"[cyan]Observability:[/cyan] {observe}",
|
|
152
|
+
title="PraisonAI Up",
|
|
153
|
+
border_style="green"
|
|
154
|
+
))
|
|
155
|
+
console.print()
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
import sys
|
|
159
|
+
|
|
160
|
+
# Setup environment for observability
|
|
161
|
+
env = os.environ.copy()
|
|
162
|
+
if observe == "langfuse" and not no_langfuse:
|
|
163
|
+
# Configure Langfuse environment
|
|
164
|
+
env["LANGFUSE_HOST"] = f"http://{host}:{langfuse_port}"
|
|
165
|
+
env["PRAISONAI_OBSERVE"] = "langfuse"
|
|
166
|
+
|
|
167
|
+
# Suppress macOS warnings
|
|
168
|
+
if sys.platform == "darwin":
|
|
169
|
+
env.setdefault("OBJC_DISABLE_INITIALIZE_FORK_SAFETY", "YES")
|
|
170
|
+
|
|
171
|
+
services_started = []
|
|
172
|
+
|
|
173
|
+
# Start Langfuse
|
|
174
|
+
if not no_langfuse:
|
|
175
|
+
try:
|
|
176
|
+
# Check if praisonai langfuse command exists
|
|
177
|
+
langfuse_cmd = [
|
|
178
|
+
sys.executable, "-m", "praisonai.cli.main", "langfuse",
|
|
179
|
+
"--port", str(langfuse_port),
|
|
180
|
+
"--host", host,
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
langfuse_proc = manager.add_service(langfuse_cmd, "Langfuse", env)
|
|
184
|
+
services_started.append(("Langfuse", f"http://{host}:{langfuse_port}"))
|
|
185
|
+
|
|
186
|
+
# Wait for Langfuse to be ready
|
|
187
|
+
if wait_timeout > 0:
|
|
188
|
+
manager.wait_for_service(
|
|
189
|
+
f"http://{host}:{langfuse_port}",
|
|
190
|
+
"Langfuse",
|
|
191
|
+
timeout=wait_timeout
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
except Exception as e:
|
|
195
|
+
console.print(f"[red]Failed to start Langfuse: {e}[/red]")
|
|
196
|
+
console.print("[yellow]Try: pip install 'praisonai[langfuse]'[/yellow]")
|
|
197
|
+
if not no_langflow:
|
|
198
|
+
console.print("[cyan]Continuing with Langflow only...[/cyan]")
|
|
199
|
+
|
|
200
|
+
# Start Langflow
|
|
201
|
+
if not no_langflow:
|
|
202
|
+
try:
|
|
203
|
+
# Get path to praisonai flow command
|
|
204
|
+
langflow_cmd = [
|
|
205
|
+
sys.executable, "-m", "praisonai.cli.main", "flow",
|
|
206
|
+
"--port", str(langflow_port),
|
|
207
|
+
"--host", host,
|
|
208
|
+
"--no-open", # We'll handle browser opening
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
langflow_proc = manager.add_service(langflow_cmd, "Langflow", env)
|
|
212
|
+
services_started.append(("Langflow", f"http://{host}:{langflow_port}"))
|
|
213
|
+
|
|
214
|
+
# Wait for Langflow to be ready
|
|
215
|
+
if wait_timeout > 0:
|
|
216
|
+
manager.wait_for_service(
|
|
217
|
+
f"http://{host}:{langflow_port}",
|
|
218
|
+
"Langflow",
|
|
219
|
+
timeout=wait_timeout
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
except Exception as e:
|
|
223
|
+
console.print(f"[red]Failed to start Langflow: {e}[/red]")
|
|
224
|
+
console.print("[yellow]Try: pip install 'praisonai[flow]'[/yellow]")
|
|
225
|
+
|
|
226
|
+
if not services_started:
|
|
227
|
+
console.print("[red]No services started successfully[/red]")
|
|
228
|
+
raise typer.Abort()
|
|
229
|
+
|
|
230
|
+
# Show service summary
|
|
231
|
+
console.print()
|
|
232
|
+
table = Table(title="🎉 Services Ready")
|
|
233
|
+
table.add_column("Service", style="cyan")
|
|
234
|
+
table.add_column("URL", style="green")
|
|
235
|
+
table.add_column("Status", style="bold")
|
|
236
|
+
|
|
237
|
+
for service_name, service_url in services_started:
|
|
238
|
+
table.add_row(service_name, service_url, "✅ Running")
|
|
239
|
+
|
|
240
|
+
console.print(table)
|
|
241
|
+
|
|
242
|
+
# Show usage instructions
|
|
243
|
+
console.print()
|
|
244
|
+
console.print(Panel(
|
|
245
|
+
"[bold]Quick Start:[/bold]\n\n"
|
|
246
|
+
"1. Open Langflow in your browser to build visual workflows\n"
|
|
247
|
+
"2. Use PraisonAI Agent/AgentTeam components from the sidebar\n"
|
|
248
|
+
"3. Run workflows with: [cyan]praisonai run workflow.yaml --observe langfuse[/cyan]\n"
|
|
249
|
+
"4. View traces in Langfuse dashboard\n\n"
|
|
250
|
+
"[dim]Press Ctrl+C to stop all services[/dim]",
|
|
251
|
+
title="Next Steps",
|
|
252
|
+
border_style="blue"
|
|
253
|
+
))
|
|
254
|
+
|
|
255
|
+
# Open browser if requested
|
|
256
|
+
if not no_open and not no_langflow:
|
|
257
|
+
try:
|
|
258
|
+
import webbrowser
|
|
259
|
+
webbrowser.open(f"http://{host}:{langflow_port}")
|
|
260
|
+
console.print("[dim]Opening Langflow in browser...[/dim]")
|
|
261
|
+
except Exception:
|
|
262
|
+
pass
|
|
263
|
+
|
|
264
|
+
# Setup signal handler for graceful shutdown
|
|
265
|
+
def signal_handler(signum, frame):
|
|
266
|
+
raise KeyboardInterrupt() # Let the try/except/finally handle cleanup
|
|
267
|
+
|
|
268
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
269
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
270
|
+
|
|
271
|
+
# Keep running until interrupted
|
|
272
|
+
try:
|
|
273
|
+
while True:
|
|
274
|
+
time.sleep(1)
|
|
275
|
+
# Check if any service died
|
|
276
|
+
for proc in manager.services[:]:
|
|
277
|
+
if proc.poll() is not None:
|
|
278
|
+
console.print(f"[red]Service died (exit code: {proc.returncode})[/red]")
|
|
279
|
+
manager.services.remove(proc)
|
|
280
|
+
|
|
281
|
+
# If all services died, exit
|
|
282
|
+
if not manager.services:
|
|
283
|
+
console.print("[yellow]All services stopped[/yellow]")
|
|
284
|
+
break
|
|
285
|
+
|
|
286
|
+
except KeyboardInterrupt:
|
|
287
|
+
pass
|
|
288
|
+
finally:
|
|
289
|
+
manager.shutdown_all()
|
|
290
|
+
|
|
291
|
+
except Exception as e:
|
|
292
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
293
|
+
manager.shutdown_all()
|
|
294
|
+
raise typer.Abort()
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@app.command("status")
|
|
298
|
+
def up_status(
|
|
299
|
+
langfuse_url: str = typer.Option("http://localhost:3000", "--langfuse-url", help="Langfuse URL"),
|
|
300
|
+
langflow_url: str = typer.Option("http://localhost:7860", "--langflow-url", help="Langflow URL"),
|
|
301
|
+
):
|
|
302
|
+
"""Check status of PraisonAI services."""
|
|
303
|
+
console = Console()
|
|
304
|
+
|
|
305
|
+
try:
|
|
306
|
+
import requests
|
|
307
|
+
except ImportError:
|
|
308
|
+
console.print("[red]requests package required for status checks[/red]")
|
|
309
|
+
raise typer.Abort()
|
|
310
|
+
|
|
311
|
+
table = Table(title="Service Status")
|
|
312
|
+
table.add_column("Service", style="cyan")
|
|
313
|
+
table.add_column("URL", style="blue")
|
|
314
|
+
table.add_column("Status", style="bold")
|
|
315
|
+
table.add_column("Response Time", style="dim")
|
|
316
|
+
|
|
317
|
+
services = [
|
|
318
|
+
("Langfuse", langfuse_url),
|
|
319
|
+
("Langflow", langflow_url),
|
|
320
|
+
]
|
|
321
|
+
|
|
322
|
+
for service_name, service_url in services:
|
|
323
|
+
try:
|
|
324
|
+
start_time = time.time()
|
|
325
|
+
response = requests.get(f"{service_url}/health", timeout=5)
|
|
326
|
+
response_time = f"{(time.time() - start_time)*1000:.0f}ms"
|
|
327
|
+
|
|
328
|
+
if response.status_code == 200:
|
|
329
|
+
status = "✅ Healthy"
|
|
330
|
+
status_style = "green"
|
|
331
|
+
else:
|
|
332
|
+
status = f"⚠️ Error {response.status_code}"
|
|
333
|
+
status_style = "yellow"
|
|
334
|
+
|
|
335
|
+
except requests.RequestException as e:
|
|
336
|
+
status = "❌ Down"
|
|
337
|
+
status_style = "red"
|
|
338
|
+
response_time = "N/A"
|
|
339
|
+
|
|
340
|
+
table.add_row(service_name, service_url, status, response_time)
|
|
341
|
+
|
|
342
|
+
console.print(table)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
@app.command("logs")
|
|
346
|
+
def up_logs(
|
|
347
|
+
service: str = typer.Option("all", "--service", help="Service to show logs for (all, langfuse, langflow)"),
|
|
348
|
+
follow: bool = typer.Option(False, "--follow", "-f", help="Follow log output"),
|
|
349
|
+
lines: int = typer.Option(50, "--lines", "-n", help="Number of lines to show"),
|
|
350
|
+
):
|
|
351
|
+
"""Show logs from PraisonAI services."""
|
|
352
|
+
console = Console()
|
|
353
|
+
console.print("[yellow]Log viewing not implemented yet[/yellow]")
|
|
354
|
+
console.print("[dim]Use docker logs or check process output directly[/dim]")
|