CmdForge/assets/js/5281b7a2.06e90270.js

1 line
8.1 KiB
JavaScript

"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[443],{936(e,n,r){r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>i,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"architecture","title":"CmdForge Architecture","description":"Module Structure","source":"@site/docs/architecture.md","sourceDirName":".","slug":"/architecture","permalink":"/rob/CmdForge/architecture","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2},"sidebar":"docs","previous":{"title":"CmdForge Overview","permalink":"/rob/CmdForge/"},"next":{"title":"CmdForge TODOs","permalink":"/rob/CmdForge/todos"}}');var t=r(4848),s=r(8453);const i={sidebar_position:2},l="CmdForge Architecture",d={},c=[{value:"Module Structure",id:"module-structure",level:2},{value:"Data Flow",id:"data-flow",level:2},{value:"CLI Tool Execution",id:"cli-tool-execution",level:3},{value:"Web UI Request Flow",id:"web-ui-request-flow",level:3},{value:"Key Classes",id:"key-classes",level:2},{value:"Tool (tool.py)",id:"tool-toolpy",level:3},{value:"ToolSource (tool.py)",id:"toolsource-toolpy",level:3},{value:"Provider (providers.py)",id:"provider-providerspy",level:3},{value:"Configuration Files",id:"configuration-files",level:2}];function a(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"cmdforge-architecture",children:"CmdForge Architecture"})}),"\n",(0,t.jsx)(n.h2,{id:"module-structure",children:"Module Structure"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"src/cmdforge/\n\u251c\u2500\u2500 cli/ # CLI commands\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u251c\u2500\u2500 tool_commands.py # list, create, edit, delete\n\u2502 \u251c\u2500\u2500 provider_commands.py # providers management\n\u2502 \u2514\u2500\u2500 registry_commands.py # publish, install\n\u251c\u2500\u2500 registry/ # Registry API\n\u2502 \u251c\u2500\u2500 app.py # Flask API endpoints\n\u2502 \u251c\u2500\u2500 db.py # SQLite schema and queries\n\u2502 \u251c\u2500\u2500 sync.py # Git repo sync\n\u2502 \u2514\u2500\u2500 rate_limit.py\n\u251c\u2500\u2500 web/ # Web UI\n\u2502 \u251c\u2500\u2500 app.py # Flask app factory\n\u2502 \u251c\u2500\u2500 routes.py # Page routes\n\u2502 \u251c\u2500\u2500 auth.py # User authentication\n\u2502 \u251c\u2500\u2500 forum/ # Forum feature\n\u2502 \u251c\u2500\u2500 templates/ # Jinja2 templates\n\u2502 \u2514\u2500\u2500 static/ # CSS, JS\n\u251c\u2500\u2500 ui_urwid/ # Terminal UI\n\u2502 \u251c\u2500\u2500 __init__.py # Main TUI\n\u2502 \u251c\u2500\u2500 widgets.py # Custom widgets\n\u2502 \u2514\u2500\u2500 palette.py # Color scheme\n\u251c\u2500\u2500 tool.py # Tool dataclass and loading\n\u251c\u2500\u2500 runner.py # Tool execution engine\n\u2514\u2500\u2500 providers.py # AI provider abstraction\n"})}),"\n",(0,t.jsx)(n.h2,{id:"data-flow",children:"Data Flow"}),"\n",(0,t.jsx)(n.h3,{id:"cli-tool-execution",children:"CLI Tool Execution"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"User Input (stdin)\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 runner.py \u2502 \u2500\u2500\u2500\u2500 Loads tool from ~/.cmdforge/<name>/config.yaml\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Steps \u2502\n\u2502 (prompt/ \u2502 \u2500\u2500\u2500\u2500 For prompt steps, calls providers.py\n\u2502 code) \u2502 \u2500\u2500\u2500\u2500 For code steps, exec() Python\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n Output (stdout)\n"})}),"\n",(0,t.jsx)(n.h3,{id:"web-ui-request-flow",children:"Web UI Request Flow"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"Browser Request\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Cloudflare \u2502 \u2500\u2500\u2500\u2500 HTTPS termination\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Flask :5050 \u2502 \u2500\u2500\u2500\u2500 web/app.py\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u251c\u2500\u2500\u2500\u2500 /api/* \u2192 registry/app.py (API)\n \u2514\u2500\u2500\u2500\u2500 /* \u2192 web/routes.py (Pages)\n \u2502\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 SQLite DB \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n"})}),"\n",(0,t.jsx)(n.h2,{id:"key-classes",children:"Key Classes"}),"\n",(0,t.jsx)(n.h3,{id:"tool-toolpy",children:"Tool (tool.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:"@dataclass\nclass Tool:\n name: str\n description: str\n category: str\n arguments: List[ToolArgument]\n steps: List[Step] # PromptStep | CodeStep | ToolStep\n output: str\n dependencies: List[str]\n source: Optional[ToolSource] # Attribution for imports\n version: str\n"})}),"\n",(0,t.jsx)(n.h3,{id:"toolsource-toolpy",children:"ToolSource (tool.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'@dataclass\nclass ToolSource:\n type: str # "original", "imported", "forked"\n license: str\n url: str\n author: str\n original_tool: str # e.g., "fabric/patterns/extract_wisdom"\n'})}),"\n",(0,t.jsx)(n.h3,{id:"provider-providerspy",children:"Provider (providers.py)"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'@dataclass\nclass Provider:\n name: str # e.g., "opencode-pickle"\n command: str # e.g., "$HOME/.opencode/bin/opencode run --model ..."\n description: str\n'})}),"\n",(0,t.jsx)(n.h2,{id:"configuration-files",children:"Configuration Files"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"File"}),(0,t.jsx)(n.th,{children:"Location"}),(0,t.jsx)(n.th,{children:"Purpose"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Tool config"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/<name>/config.yaml"})}),(0,t.jsx)(n.td,{children:"Tool definition"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Providers"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/providers.yaml"})}),(0,t.jsx)(n.td,{children:"AI provider commands"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Main config"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"~/.cmdforge/config.yaml"})}),(0,t.jsx)(n.td,{children:"Registry URL, client ID"})]})]})]})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},8453(e,n,r){r.d(n,{R:()=>i,x:()=>l});var o=r(6540);const t={},s=o.createContext(t);function i(e){const n=o.useContext(s);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]);