CmdForge/architecture.html

208 lines
6.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CmdForge Architecture</title>
<style>
:root {
--bg: #1a1a2e;
--surface: #16213e;
--primary: #0f3460;
--accent: #e94560;
--text: #eaeaea;
--text-muted: #a0a0a0;
--code-bg: #0d1117;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.7;
padding: 2rem;
}
.container { max-width: 900px; margin: 0 auto; }
a { color: var(--accent); }
h1, h2, h3, h4 { margin: 1.5rem 0 1rem; color: var(--text); }
h1 { font-size: 2rem; border-bottom: 2px solid var(--accent); padding-bottom: 0.5rem; }
h2 { font-size: 1.5rem; border-bottom: 1px solid var(--primary); padding-bottom: 0.3rem; }
h3 { font-size: 1.25rem; }
p { margin: 1rem 0; }
pre {
background: var(--code-bg);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
margin: 1rem 0;
}
code {
font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
font-size: 0.9rem;
}
:not(pre) > code {
background: var(--code-bg);
padding: 0.2rem 0.4rem;
border-radius: 4px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
}
th, td {
border: 1px solid var(--primary);
padding: 0.75rem;
text-align: left;
}
th { background: var(--surface); }
.back-link {
display: inline-block;
margin-bottom: 1rem;
color: var(--text-muted);
text-decoration: none;
}
.back-link:hover { color: var(--accent); }
ul, ol { margin: 1rem 0; padding-left: 2rem; }
li { margin: 0.5rem 0; }
strong { color: var(--text); }
blockquote {
border-left: 4px solid var(--accent);
margin: 1rem 0;
padding-left: 1rem;
color: var(--text-muted);
}
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back-link">← Back to Index</a>
<article>
<h1>CmdForge Architecture</h1>
<h2>Module Structure</h2>
<pre><code>src/cmdforge/
├── cli/ # CLI commands
│ ├── __init__.py
│ ├── tool_commands.py # list, create, edit, delete
│ ├── provider_commands.py # providers management
│ └── registry_commands.py # publish, install
├── registry/ # Registry API
│ ├── app.py # Flask API endpoints
│ ├── db.py # SQLite schema and queries
│ ├── sync.py # Git repo sync
│ └── rate_limit.py
├── web/ # Web UI
│ ├── app.py # Flask app factory
│ ├── routes.py # Page routes
│ ├── auth.py # User authentication
│ ├── forum/ # Forum feature
│ ├── templates/ # Jinja2 templates
│ └── static/ # CSS, JS
├── ui_urwid/ # Terminal UI
│ ├── __init__.py # Main TUI
│ ├── widgets.py # Custom widgets
│ └── palette.py # Color scheme
├── tool.py # Tool dataclass and loading
├── runner.py # Tool execution engine
└── providers.py # AI provider abstraction
</code></pre>
<h2>Data Flow</h2>
<h3>CLI Tool Execution</h3>
<pre><code>User Input (stdin)
┌─────────────┐
│ runner.py │ ──── Loads tool from ~/.cmdforge/&lt;name&gt;/config.yaml
└─────────────┘
┌─────────────┐
│ Steps │
│ (prompt/ │ ──── For prompt steps, calls providers.py
│ code) │ ──── For code steps, exec() Python
└─────────────┘
Output (stdout)
</code></pre>
<h3>Web UI Request Flow</h3>
<pre><code>Browser Request
┌─────────────────┐
│ Cloudflare │ ──── HTTPS termination
└─────────────────┘
┌─────────────────┐
│ Flask :5050 │ ──── web/app.py
└─────────────────┘
├──── /api/* → registry/app.py (API)
└──── /* → web/routes.py (Pages)
┌─────────────┐
│ SQLite DB │
└─────────────┘
</code></pre>
<h2>Key Classes</h2>
<h3>Tool (tool.py)</h3>
<pre><code class="language-python">@dataclass
class Tool:
name: str
description: str
category: str
arguments: List[ToolArgument]
steps: List[Step] # PromptStep | CodeStep | ToolStep
output: str
dependencies: List[str]
source: Optional[ToolSource] # Attribution for imports
version: str
</code></pre>
<h3>ToolSource (tool.py)</h3>
<pre><code class="language-python">@dataclass
class ToolSource:
type: str # &quot;original&quot;, &quot;imported&quot;, &quot;forked&quot;
license: str
url: str
author: str
original_tool: str # e.g., &quot;fabric/patterns/extract_wisdom&quot;
</code></pre>
<h3>Provider (providers.py)</h3>
<pre><code class="language-python">@dataclass
class Provider:
name: str # e.g., &quot;opencode-pickle&quot;
command: str # e.g., &quot;$HOME/.opencode/bin/opencode run --model ...&quot;
description: str
</code></pre>
<h2>Configuration Files</h2>
<table>
<thead>
<tr>
<th>File</th>
<th>Location</th>
<th>Purpose</th>
</tr>
</thead>
<tbody><tr>
<td>Tool config</td>
<td><code>~/.cmdforge/&lt;name&gt;/config.yaml</code></td>
<td>Tool definition</td>
</tr>
<tr>
<td>Providers</td>
<td><code>~/.cmdforge/providers.yaml</code></td>
<td>AI provider commands</td>
</tr>
<tr>
<td>Main config</td>
<td><code>~/.cmdforge/config.yaml</code></td>
<td>Registry URL, client ID</td>
</tr>
</tbody></table>
</article>
</div>
</body>
</html>