File size: 5,504 Bytes
28a08e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""
architecture.py — Free distributed no-PC architecture profile

The selected zero-cost architecture is deliberately split into control,
execution, tools and memory layers:

- iPhone/mobile browser: control surface only.
- GitHub Actions: event-triggered Agent Kernel and lightweight execution.
- Hugging Face Spaces: backend tools/API runtime, not a heavy persistent VM.
- LiteLLM/OpenAI-compatible provider routing: free remote model pool.
- GitHub repository: primary memory, code, task history and run reports.

This keeps the system usable without Replit, without a local PC and without
paid infrastructure while making the real limits explicit.
"""
from __future__ import annotations

import os
from dataclasses import dataclass, asdict
from typing import Any


@dataclass(frozen=True)
class Capability:
    name: str
    status: str
    reason: str


FREE_REMOTE_PLAN = {
    "name": "github_actions_hf_spaces_free_agent",
    "label": "GitHub Actions + HF Spaces Free Agent Kernel",
    "mode": "total_free_no_local_pc",
    "control_surface": "iPhone via GitHub Actions workflow_dispatch or web frontend",
    "primary_runtime": "GitHub Actions for agent runs; Hugging Face Spaces for backend tools/API",
    "tool_runtime": "Hugging Face Spaces Docker free tier",
    "memory_primary": "GitHub repository under .agent/ plus code/history",
    "memory_secondary": "SQLite/local backend memory when the Space is available",
    "principle": "Distributed backend-first agent kernel with safe-by-default GitHub memory, provider fallback and mobile review.",
    "model_priority": ["openrouter", "gemini", "groq", "huggingface", "openai_compatible"],
    "execution": "GitHub Actions for bounded jobs; backend allowlisted tools only; browser sandbox disabled by default",
}


def _env_enabled(name: str, default: bool = False) -> bool:
    raw = os.getenv(name)
    if raw is None:
        return default
    return raw.strip().lower() in {"1", "true", "yes", "on"}


def get_architecture_profile() -> dict[str, Any]:
    """Return runtime capabilities for the free no-PC deployment plan."""
    providers = {
        "openrouter": bool(os.getenv("OPENROUTER_API_KEY")),
        "gemini": bool(os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY")),
        "groq": bool(os.getenv("GROQ_API_KEY")),
        "huggingface": bool(os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_API_KEY") or os.getenv("HUGGINGFACE_TOKEN")),
        "openai_compatible": bool(os.getenv("OPENAI_API_KEY")),
    }

    github_actions_configured = bool(os.getenv("GITHUB_ACTIONS") or os.getenv("GITHUB_REPOSITORY"))
    github_token_configured = bool(os.getenv("GITHUB_TOKEN") or os.getenv("GH_TOKEN"))

    capabilities = [
        Capability("mobile_control", "enabled", "GitHub Actions workflow_dispatch and the frontend can be used from iPhone."),
        Capability("github_actions_agent_kernel", "enabled", "Bounded agent runs execute in GitHub Actions and persist reports under .agent/."),
        Capability("github_memory", "enabled", "State, task history and run reports are committed to the repository for durable zero-cost memory."),
        Capability("hf_spaces_tools", "enabled", "The FastAPI backend remains the lightweight tools/API runtime for the free Space."),
        Capability("litellm_routing", "enabled", "OpenAI-compatible provider order supports OpenRouter, Gemini, Groq, Hugging Face and optional OpenAI-compatible endpoints."),
        Capability("sqlite_memory", "secondary", "Backend SQLite/local memory remains useful but is not the primary no-PC source of truth."),
        Capability("qdrant", "optional", "Use only if an external free Qdrant endpoint is configured; not required for the baseline."),
        Capability("openhands", "external_optional", "Full OpenHands remains too heavy for the free baseline and should not run inside the free Space."),
        Capability("docker_sandbox", "disabled_on_free_space", "Nested Docker is intentionally disabled on the free plan."),
        Capability("browser_sandbox", "disabled_by_default", "Client-side code execution is not a real isolated workspace and is not part of the main path."),
    ]

    return {
        "plan": FREE_REMOTE_PLAN,
        "providers": providers,
        "capabilities": [asdict(c) for c in capabilities],
        "limits": {
            "requires_local_pc": False,
            "requires_paid_vm": False,
            "runs_heavy_local_models": False,
            "supports_nested_docker": False,
            "long_running_24_7_agent": False,
            "bounded_actions_runtime": True,
        },
        "github_actions": {
            "workflow": ".github/workflows/agent-kernel.yml",
            "workflow_template": "docs/workflows/agent-kernel.yml",
            "activation_note": "Copy the template to .github/workflows/agent-kernel.yml with GitHub UI or a token that has workflow permission.",
            "script": "scripts/agent_kernel.py",
            "memory_dir": ".agent/",
            "configured_in_current_runtime": github_actions_configured,
            "token_available_in_current_runtime": github_token_configured,
            "trigger_modes": ["workflow_dispatch", "issue_label_agent-run"],
        },
        "feature_flags": {
            "browser_sandbox_enabled": _env_enabled("VITE_ENABLE_BROWSER_SANDBOX", False),
            "browser_llm_enabled": _env_enabled("VITE_ENABLE_BROWSER_LLM", False),
            "qdrant_enabled": bool(os.getenv("QDRANT_URL")),
        },
    }