Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions .github/workflows/integration-cross-repo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
name: Cross-Repo Integration Tests

on:
Comment on lines +1 to +3
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add least-privilege workflow/job permissions.

There is no permissions: block, so this runs with default token permissions. Please explicitly set minimal permissions (contents: read) at workflow level and only elevate per-job if needed.

Also applies to: 18-19, 122-123

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 1-165: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/integration-cross-repo.yml around lines 1 - 3, Add a
top-level GitHub Actions permissions block to enforce least-privilege by setting
permissions: contents: read for the "Cross-Repo Integration Tests" workflow, and
then lift permissions only for specific jobs that require extra scopes by adding
per-job permissions entries; update the existing jobs that need broader access
(the ones noted in the review) to explicitly set their required permissions
instead of relying on the default token.

push:
branches: [ main ]
paths:
- 'src/praisonai/praisonai/integration/**'
- 'src/praisonai/tests/integration/test_aiui_*'
- 'src/praisonai/pyproject.toml'
pull_request:
branches: [ main ]
paths:
- 'src/praisonai/praisonai/integration/**'
- 'src/praisonai/tests/integration/test_aiui_*'
- 'src/praisonai/pyproject.toml'
workflow_dispatch:
Comment on lines +6 to +16
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Path filters currently skip CI when this workflow/docs change.

As written, updates to .github/workflows/integration-cross-repo.yml or RELEASE_INTEGRATION.md won’t trigger this workflow on push/PR. That can hide breakage in the exact assets this PR introduces.

Suggested trigger additions
   push:
     branches: [ main ]
     paths:
+      - '.github/workflows/integration-cross-repo.yml'
+      - 'RELEASE_INTEGRATION.md'
       - 'src/praisonai/praisonai/integration/**'
       - 'src/praisonai/tests/integration/test_aiui_*'
       - 'src/praisonai/pyproject.toml'
   pull_request:
     branches: [ main ]
     paths:
+      - '.github/workflows/integration-cross-repo.yml'
+      - 'RELEASE_INTEGRATION.md'
       - 'src/praisonai/praisonai/integration/**'
       - 'src/praisonai/tests/integration/test_aiui_*'
       - 'src/praisonai/pyproject.toml'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
paths:
- 'src/praisonai/praisonai/integration/**'
- 'src/praisonai/tests/integration/test_aiui_*'
- 'src/praisonai/pyproject.toml'
pull_request:
branches: [ main ]
paths:
- 'src/praisonai/praisonai/integration/**'
- 'src/praisonai/tests/integration/test_aiui_*'
- 'src/praisonai/pyproject.toml'
workflow_dispatch:
paths:
- '.github/workflows/integration-cross-repo.yml'
- 'RELEASE_INTEGRATION.md'
- 'src/praisonai/praisonai/integration/**'
- 'src/praisonai/tests/integration/test_aiui_*'
- 'src/praisonai/pyproject.toml'
pull_request:
branches: [ main ]
paths:
- '.github/workflows/integration-cross-repo.yml'
- 'RELEASE_INTEGRATION.md'
- 'src/praisonai/praisonai/integration/**'
- 'src/praisonai/tests/integration/test_aiui_*'
- 'src/praisonai/pyproject.toml'
workflow_dispatch:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/integration-cross-repo.yml around lines 6 - 16, The
workflow's path filters in integration-cross-repo.yml exclude changes to the
workflow file itself and to RELEASE_INTEGRATION.md, so update the push and
pull_request path lists (the entries under the paths: blocks in
integration-cross-repo.yml) to include
'.github/workflows/integration-cross-repo.yml' and 'RELEASE_INTEGRATION.md' (or
a pattern matching that doc) so edits to the workflow or release docs will
trigger the workflow; modify both the push and pull_request sections to keep
behavior consistent.


jobs:
cross-repo-integration:
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout PraisonAI
uses: actions/checkout@v4
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/integration-cross-repo.yml"
echo "== file =="; wc -l "$FILE"
echo "== relevant uses: lines =="; rg -n "uses:\s*actions/(checkout|setup-python)@" "$FILE" || true
echo "== setup-python uses =="; rg -n "uses:\s*actions/setup-python@" "$FILE" || true
echo "== checkout uses =="; rg -n "uses:\s*actions/checkout@" "$FILE" || true
echo "== full workflow (for context, limited) =="; sed -n '1,220p' "$FILE"

Repository: MervinPraison/PraisonAI

Length of output: 5996


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/integration-cross-repo.yml"

echo "== permissions blocks =="; rg -n '^\s*permissions:' "$FILE" || true
echo "== persist-credentials settings =="; rg -n 'persist-credentials' "$FILE" || true
echo "== uses actions/checkout/setup-python with context (near matches) =="; rg -n -C 2 'uses:\s*actions/(checkout|setup-python)@' "$FILE"

Repository: MervinPraison/PraisonAI

Length of output: 1202


🌐 Web query:

actions/setup-python latest major version v5 guidance

💡 Result:

As of May 2026, actions/setup-python has progressed to version v6 (specifically v6.2.0 as of January 2026) [1][2]. While you asked about guidance for v5, it is important to note that v5 is no longer the latest major version [1][2]. General guidance for using actions/setup-python includes: 1. Use the Latest Stable Major Version: It is recommended to use the latest major version (currently v6) to benefit from the latest features, dependency updates (e.g., node24 compatibility), and security improvements [1][2]. 2. Pinning and Security: For production environments and to protect against supply chain attacks, best practices suggest pinning actions to a specific full commit SHA rather than relying solely on tags like @v5 or @v6 [3][4]. Tags are mutable and can be redirected by repository maintainers or compromised accounts [3][4][5]. 3. Explicit Versioning: Always specify the Python version explicitly using the python-version or python-version-file inputs [6][7]. Relying on the runner's pre-installed version is discouraged because it can change unexpectedly [6][7]. 4. Caching: Use the built-in cache input to speed up dependency installation for pip, pipenv, or poetry [6][7]. The action automatically handles dependency file hashing (e.g., requirements.txt or pyproject.toml) [6][7]. 5. Check for Updates: You can monitor the official actions/setup-python repository releases page to stay informed about breaking changes, new features, and deprecated versions [8][2]. If you are currently on v5 and planning to upgrade, review the release notes for v6 in the official repository to identify any breaking changes, such as the required runner version updates (e.g., v2.327.1 or later) necessitated by the transition to Node 24 [1][2].

Citations:


🌐 Web query:

actions/checkout persist-credentials default value true documentation

💡 Result:

The input persist-credentials for the GitHub Action actions/checkout has a default value of true. [1] Evidence (official docs): the action.yml input definition for persist-credentials shows default: true. [1]. The README also describes the behavior and notes you can opt out with persist-credentials: false. [2]

Citations:


Pin GitHub Actions to commit SHAs and upgrade actions/setup-python

In .github/workflows/integration-cross-repo.yml, actions/checkout@v4 is used at lines 25, 30, 39, 130, and 135, and actions/setup-python@v4 is used at lines 46 and 142; all are tag-based (not commit-SHA pinned), which weakens supply-chain/reproducibility guarantees. Upgrade actions/setup-python from v4 to the latest major (currently v6) and pin both checkout and setup-python to specific commit SHAs.

🧰 Tools
🪛 zizmor (1.25.2)

[error] 25-25: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/integration-cross-repo.yml at line 25, The workflow uses
tag-based actions which weakens reproducibility: replace every usage of
actions/checkout@v4 and actions/setup-python@v4 with pinned commit SHAs and
upgrade setup-python to the current major (v6); locate the occurrences of
"actions/checkout@v4" and "actions/setup-python@v4" in the workflow, change the
setup-python references to use the v6 major (e.g., actions/setup-python@v6) and
replace both actions' tag references with their corresponding commit SHA pins
(use the official action repos to copy the exact commit SHA), and verify the
workflow still runs with the pinned SHAs.

with:
path: PraisonAI
Comment on lines +24 to +27
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable checkout credential persistence.

Each checkout step should set persist-credentials: false to avoid leaving the token in local git config for later steps.

Also applies to: 29-35, 37-43, 129-132, 134-139

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 24-27: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 25-25: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/integration-cross-repo.yml around lines 24 - 27, The
checkout steps using "uses: actions/checkout@v4" (e.g., the step named "Checkout
PraisonAI" and the other checkout steps around the commented ranges) must set
persist-credentials: false to prevent the runner from storing the GITHUB_TOKEN
in local git config; update each checkout step (those with "uses:
actions/checkout@v4") to include a with block key persist-credentials: false
alongside any existing with entries.

ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}

- name: Checkout PraisonAIUI
uses: actions/checkout@v4
with:
repository: MervinPraison/PraisonAIUI
path: PraisonAIUI
ref: main

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Install PraisonAI packages in development mode
cd PraisonAI/src/praisonai-agents
pip install -e .
cd ../praisonai
pip install -e ".[ui,dev]"
# Install PraisonAIUI in development mode
cd ../../../PraisonAIUI
pip install -e .

- name: Verify versions
run: |
python -c "import praisonaiagents; print(f'praisonaiagents: {praisonaiagents.__version__}')"
python -c "import praisonai; print(f'praisonai: {praisonai.__version__}')"
python -c "import praisonaiui; print(f'praisonaiui: {praisonaiui.__version__}')"

- name: Run PraisonAI integration tests
run: |
cd PraisonAI/src/praisonai
python -m pytest tests/integration/test_aiui_* -v --timeout=300

- name: Run PraisonAIUI integration tests
run: |
cd PraisonAIUI
if [ -f tests/integration/test_agentic_roundtrip.py ]; then
python -m pytest tests/integration/test_agentic_roundtrip.py -v --timeout=300
fi
if [ -f tests/test_feature_sdk_backends.py ]; then
python -m pytest tests/test_feature_sdk_backends.py -v --timeout=300
fi

- name: Test Pattern C CLI
run: |
cd PraisonAI/src/praisonai
# Test that ui-gateway command exists
python -m praisonai serve --help | grep ui-gateway

- name: Test public API exports
run: |
cd PraisonAI/src/praisonai
python -c "from praisonai import run_integrated_gateway; print('✓ run_integrated_gateway imported')"
python -c "from praisonai import configure_host; print('✓ configure_host imported')"

- name: Integration smoke test
env:
PRAISONAI_TEST_MODE: "1"
PYTHONPATH: ${{ github.workspace }}/PraisonAI/src/praisonai:${{ github.workspace }}/PraisonAI/src/praisonai-agents:${{ github.workspace }}/PraisonAIUI
run: |
cd PraisonAI/src/praisonai
python -c "
import sys
sys.path.insert(0, '.')
from praisonai.integration.host_app import configure_host
from praisonai import run_integrated_gateway
print('✓ Integration imports successful')

# Test configure_host with new parameters
try:
configure_host(
style='dashboard',
context_paths=['AGENTS.md'],
title='Test App'
)
print('✓ configure_host with new parameters works')
except Exception as e:
print(f'× configure_host failed: {e}')
sys.exit(1)
"

# Optional job with API key for agentic tests (if secret is available)
agentic-integration:
runs-on: ubuntu-latest
timeout-minutes: 30
if: ${{ vars.RUN_AGENTIC_TESTS == 'true' }}
needs: cross-repo-integration

steps:
- name: Checkout PraisonAI
uses: actions/checkout@v4
with:
path: PraisonAI
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}

- name: Checkout PraisonAIUI
uses: actions/checkout@v4
with:
repository: MervinPraison/PraisonAIUI
path: PraisonAIUI
ref: main

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
cd PraisonAI/src/praisonai-agents
pip install -e .
cd ../praisonai
pip install -e ".[ui,dev]"
cd ../../../PraisonAIUI
pip install -e .

- name: Run agentic integration test
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
cd PraisonAI/src/praisonai
if [ -n "$OPENAI_API_KEY" ]; then
python -m pytest tests/integration/test_aiui_host_agentic.py -v --timeout=600
else
echo "OPENAI_API_KEY not available, skipping agentic tests"
fi
5 changes: 5 additions & 0 deletions src/praisonai/praisonai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
'HostedAgentConfig',
'LocalAgent',
'LocalAgentConfig',
# Integration functions
'run_integrated_gateway',
]

# Telemetry initialization state - thread-safe (threading imported above)
Expand Down Expand Up @@ -144,6 +146,9 @@ def __getattr__(name):
elif name == 'configure_host':
from .integration.host_app import configure_host
return configure_host
elif name == 'run_integrated_gateway':
from .integration.gateway_host import run_integrated_gateway
return run_integrated_gateway
elif name == 'AgentApp':
# Silent alias for AgentOS (backward compatibility)
from .app import AgentOS
Expand Down
37 changes: 37 additions & 0 deletions src/praisonai/praisonai/cli/commands/serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def serve_callback(ctx: typer.Context):
[bold]Server Types:[/bold]
[green]agents[/green] HTTP REST API for agents (port 8000)
[green]gateway[/green] WebSocket multi-agent coordination (port 8765)
[green]ui-gateway[/green] Integrated UI-Gateway (Pattern C) (port 8765)
[green]mcp[/green] MCP server for Claude/Cursor (port 8080)
[green]acp[/green] Agent Client Protocol for IDEs (STDIO)
[green]lsp[/green] Language Server Protocol (STDIO)
Expand Down Expand Up @@ -369,6 +370,42 @@ def serve_ui(
raise typer.Exit(4)


@app.command("ui-gateway")
def serve_ui_gateway(
host: str = typer.Option("127.0.0.1", "--host", "-h", help="Host to bind to"),
port: int = typer.Option(8765, "--port", "-p", help="Port to bind to"),
title: str = typer.Option("PraisonAI", "--title", "-t", help="Application title"),
style: str = typer.Option("dashboard", "--style", "-s", help="UI style: dashboard, chat"),
agents_file: Optional[str] = typer.Option(None, "--agents", "-a", help="Agents YAML file"),
):
"""Start integrated UI-Gateway (Pattern C) - aiui with backend bridges.

Combines PraisonAI host integration with AIUIGateway for unified dashboard + chat.

Examples:
praisonai serve ui-gateway
praisonai serve ui-gateway --style chat --port 8765
praisonai serve ui-gateway --agents agents.yaml --title "My App"
"""
output = get_output_controller()

try:
from ...integration.gateway_host import run_integrated_gateway
run_integrated_gateway(
host=host,
port=port,
title=title,
style=style
)
Comment on lines +394 to +399
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The serve_ui_gateway command passes agents_file to run_integrated_gateway, which eventually passes it to configure_host. However, configure_host does not accept an agents_file parameter and does not define **kwargs. This will cause a TypeError at runtime, crashing the command even when no arguments are provided (since agents_file defaults to None but is still passed as a keyword argument).

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
greptile-apps[bot] marked this conversation as resolved.
except ImportError as e:
output.print_error(f"UI-Gateway module not available: {e}")
output.print("Install with: pip install praisonai[ui]")
raise typer.Exit(4)
except Exception as e:
output.print_error(f"Failed to start UI-Gateway: {e}")
raise typer.Exit(1)


@app.command("rag")
def serve_rag(
host: str = typer.Option("127.0.0.1", "--host", "-h", help="Host to bind to"),
Expand Down
29 changes: 27 additions & 2 deletions src/praisonai/praisonai/integration/gateway_host.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

from __future__ import annotations

import asyncio
from typing import Any, Optional


async def run_integrated_gateway(
async def _run_integrated_gateway_async(
*,
port: int = 8080,
port: int = 8765,
host: str = "127.0.0.1",
static_dir: Optional[str] = None,
ui_config: Optional[dict[str, Any]] = None,
Expand All @@ -25,3 +26,27 @@ async def run_integrated_gateway(
ui_config=ui_config or {},
)
await gateway.start()


def run_integrated_gateway(
*,
port: int = 8765,
host: str = "127.0.0.1",
Comment thread
greptile-apps[bot] marked this conversation as resolved.
static_dir: Optional[str] = None,
ui_config: Optional[dict[str, Any]] = None,
**configure_kwargs: Any,
) -> None:
"""Sync wrapper for integrated gateway (for CLI usage)."""
asyncio.run(_run_integrated_gateway_async(
port=port,
host=host,
static_dir=static_dir,
ui_config=ui_config,
**configure_kwargs
))


# Alias for backward compatibility
async def run_integrated_gateway_async(**kwargs) -> None:
"""Async version (for direct usage)."""
await _run_integrated_gateway_async(**kwargs)
39 changes: 31 additions & 8 deletions src/praisonai/praisonai/integration/host_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def configure_host(
agent_kwargs: Optional[Dict[str, Any]] = None,
gateway: Any = None,
modules: Optional[Sequence[str]] = None,
style: str = "dashboard",
context_paths: Optional[Sequence[str]] = None,
**kwargs: Any,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

configure_host(**kwargs) is currently a no-op because kwargs gets shadowed.

At Line 82, reassignment drops the function-level **kwargs, so provider options passed by callers are ignored unless duplicated in agent_kwargs.

Minimal fix to preserve both call paths
-    **kwargs: Any,
+    **kwargs: Any,
 ) -> None:
@@
-        kwargs = dict(agent_kwargs or {})
+        provider_kwargs = dict(kwargs)
+        if agent_kwargs:
+            provider_kwargs.update(agent_kwargs)
         if agents:
-            set_provider(PraisonAIProvider(agents=list(agents), **kwargs))
+            set_provider(PraisonAIProvider(agents=list(agents), **provider_kwargs))
         else:
             # Load context files if specified
-            instructions = kwargs.pop("instructions", "You are a helpful assistant.")
+            instructions = provider_kwargs.pop("instructions", "You are a helpful assistant.")
@@
                 PraisonAIProvider(
-                    name=kwargs.pop("name", "PraisonAI"),
+                    name=provider_kwargs.pop("name", "PraisonAI"),
                     instructions=instructions,
-                    llm=kwargs.pop(
+                    llm=provider_kwargs.pop(
                         "llm", os.getenv("PRAISONAI_MODEL", "gpt-4o-mini")
                     ),
-                    **kwargs,
+                    **provider_kwargs,
                 )
             )

Also applies to: 82-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai/praisonai/integration/host_app.py` at line 38,
configure_host(**kwargs) is a no-op because the function parameter kwargs is
being reassigned/shadowed by a local variable of the same name (coming from
agent_kwargs), so caller-provided options are dropped; fix by not reusing the
name — either rename the local to agent_kwargs or merged_kwargs and call
configure_host with a merged dict that preserves caller options (e.g., merged =
{**kwargs, **agent_kwargs} or pass both explicitly), and apply the same
rename/merge pattern for the other occurrences in the
configure_host/agent_kwargs block (lines referenced around 82–105) so both call
paths are preserved.

) -> None:
Comment on lines 33 to 39
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding **kwargs to configure_host would make the integration layer more resilient to extra arguments passed from the CLI or other wrappers. This prevents TypeError crashes when new options are added to the CLI (like agents_file in this PR) before the integration logic is fully updated to handle them.

Suggested change
agent_kwargs: Optional[Dict[str, Any]] = None,
gateway: Any = None,
modules: Optional[Sequence[str]] = None,
style: str = "dashboard",
context_paths: Optional[Sequence[str]] = None,
) -> None:
agent_kwargs: Optional[Dict[str, Any]] = None,
gateway: Any = None,
modules: Optional[Sequence[str]] = None,
style: str = "dashboard",
context_paths: Optional[Sequence[str]] = None,
**kwargs: Any,
) -> None:

"""Apply PraisonAIUI host settings and wire L1 backends (unless legacy mode)."""
global _CONFIGURED
Expand All @@ -41,7 +44,7 @@ def configure_host(
from praisonai.ui._aiui_datastore import PraisonAISessionDataStore

aiui.set_datastore(PraisonAISessionDataStore())
aiui.set_style("dashboard")
aiui.set_style(style)
aiui.set_branding(title=title, logo=logo)

if pages is not None:
Expand Down Expand Up @@ -80,13 +83,21 @@ def configure_host(
if agents:
set_provider(PraisonAIProvider(agents=list(agents), **kwargs))
else:
# Load context files if specified
instructions = kwargs.pop("instructions", "You are a helpful assistant.")
if context_paths:
try:
from praisonai.integration.context_files import load_context_files
context = load_context_files(list(context_paths))
if context:
instructions = f"{instructions}\n\nContext:\n{context}"
except ImportError:
pass # Context files helper is optional

set_provider(
PraisonAIProvider(
name=kwargs.pop("name", "PraisonAI"),
instructions=kwargs.pop(
"instructions",
"You are a helpful assistant.",
),
instructions=instructions,
llm=kwargs.pop(
"llm", os.getenv("PRAISONAI_MODEL", "gpt-4o-mini")
),
Expand All @@ -95,6 +106,12 @@ def configure_host(
)
setup_bridges()

# Register L3 dashboard pages
try:
from praisonai.integration.pages import workflow_runs, bot_health
except ImportError:
pass # L3 pages are optional

_CONFIGURED = True


Expand All @@ -109,15 +126,19 @@ def setup_bridges() -> None:
from praisonai.integration.bridges.usage_bridge import register_usage_sink

sink = register_usage_sink()
except Exception as exc:
except ImportError as exc:
log.debug("usage bridge unavailable: %s", exc)
except Exception as exc:
log.warning("usage bridge unavailable: %s", exc)

try:
from praisonai.integration.bridges.schedules_runner import ensure_schedule_runner

ensure_schedule_runner()
except Exception as exc:
except ImportError as exc:
log.debug("schedule runner unavailable: %s", exc)
except Exception as exc:
log.warning("schedule runner unavailable: %s", exc)

try:
import praisonaiui.backends as backends
Expand All @@ -144,8 +165,10 @@ def _workflow_backend(wf_id, *, workflow, input_data):

backends.set_backend("approvals_pending", list_pending_approvals)
backends.set_backend("approvals_policies", get_approval_policies)
except Exception as exc:
except ImportError as exc:
log.debug("aiui backend injection failed: %s", exc)
except Exception as exc:
log.warning("aiui backend injection failed: %s", exc)


def create_host_app():
Expand Down
8 changes: 8 additions & 0 deletions src/praisonai/praisonai/integration/pages/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Optional L3 dashboard pages for PraisonAI integration."""

# Import pages to register them with aiui
try:
from . import workflow_runs, bot_health
except ImportError:
# Pages are optional and may not be available if aiui is not installed
pass
Comment on lines +1 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 workflow_runs and bot_health modules don't exist — L3 page registration silently no-ops

pages/__init__.py tries to import workflow_runs and bot_health as submodules, and host_app.py does the same after configure_host runs. Neither workflow_runs.py nor bot_health.py were added in this PR, so both imports always raise ImportError and are silently swallowed. The "Register L3 dashboard pages" feature mentioned in the PR description effectively does nothing at runtime.

Loading
Loading