Files
sundynix-agentix/architecture.html
T
Blizzard c7a02c3905 feat: 初始化 sundynix-agentix 分层式 AI Agent 平台脚手架
5 层 + 1 条 NATS 零拷贝消息总线的 monorepo(Monolith First → Microservices Morph B)。
纵向主干(任务流 + Token 流回流)已真实跑通,横向各层能力为带注释的桩。

已贯通(real code):
- sundynix-shared: 共享契约 + JetStream/core NATS 真实收发(bus) + 内嵌 NATS(devnats) + e2e 测试
- sundynix-gateway: Gin 接入 + DSL 解析组装 + NATS Publish + SSE 流式输出
- sundynix-dispatcher: NATS 消费 + Eino Orchestrator 流式回流 + 熔断器 + LLM Pool 占位流式
- 链路: HTTP POST → DSL → sundynix.tasks.* → Dispatcher → Token 经 sundynix.streams.<id> 回流 → SSE
- 基础设施: docker-compose(nats/postgres/redis/neo4j/milvus) + Makefile(make demo/e2e)

待填(桩):
- Eino 图编排 compose.NewGraph、LLM Pool 接 vLLM/Ollama
- Gateway store 换真实 pgx/redis
- sundynix-mcp-go: Bleve+Milvus+Neo4j 混合检索 / UniOffice / 外部 API
- sundynix-mcp-py: gVisor 沙箱 / MinerU(PaddleOCR) / Docker 解释器
- sundynix-desktop: React Flow 画布 → DSL 导出 → SSE 展示
2026-06-10 11:00:29 +08:00

287 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sundynix-agentix · 系统架构图</title>
<style>
:root{
--client:#f6d9b0; --client-bg:#fdf2e3; --client-br:#e0a85a;
--gateway:#f8c9c9; --gateway-stroke:#d96b6b;
--nats:#cfe8c6; --nats-bg:#e7f4e1; --nats-br:#86c06a;
--dispatcher:#dcc7ef; --dispatcher-bg:#efe5f8; --dispatcher-br:#a984cf;
--gotools:#bcdcef; --gotools-bg:#dcecf7; --gotools-br:#5fa9d4;
--pytools:#f6e6a8; --pytools-bg:#fbf3cf; --pytools-br:#d8bf52;
--ginserver:#bfe3c4;
--box:#eef1f4; --box-br:#c4ccd4;
--ink:#1c2b3a; --muted:#5a6b7b;
}
*{box-sizing:border-box;}
body{
margin:0; padding:32px;
font-family:"PingFang SC","Microsoft YaHei","Segoe UI",system-ui,sans-serif;
background:#f3f5f7; color:var(--ink);
}
h1{font-size:22px; margin:0 0 4px;}
.sub{color:var(--muted); margin:0 0 24px; font-size:13px;}
.grid{
display:grid;
grid-template-columns: 1.05fr 1.05fr 1.15fr;
gap:22px;
align-items:start;
max-width:1980px;
}
/* ---- generic layer card ---- */
.layer{
border-radius:14px; padding:14px;
border:2px solid transparent;
}
.layer > .ltitle{
font-weight:800; font-size:15px; margin:0 0 12px; letter-spacing:.2px;
}
.layer > .ltitle small{display:block; font-weight:600; font-size:11px; color:var(--muted); margin-top:2px;}
.panel{
background:rgba(255,255,255,.65);
border-radius:11px; padding:12px; margin-bottom:12px;
}
.panel:last-child{margin-bottom:0;}
.panel-title{font-weight:700; font-size:13px; margin:0 0 10px;}
.panel-title small{font-weight:500; color:var(--muted);}
.box{
background:var(--box); border:1px solid var(--box-br);
border-radius:8px; padding:9px 11px; margin-bottom:8px;
font-size:12.5px; line-height:1.35; text-align:center;
}
.box:last-child{margin-bottom:0;}
.box b{display:block; font-weight:700;}
.box span{display:block; color:var(--muted); font-size:11px; margin-top:2px;}
.box.hl{background:#fff;}
.row2{display:grid; grid-template-columns:1fr 1fr; gap:8px;}
.row2 .box{margin-bottom:0;}
/* ---- layer colors ---- */
.client { background:var(--client-bg); border-color:var(--client-br); }
.gateway { background:#e6eef6; border-color:var(--gotools-br); }
.gateway .panel{background:#cfe0ef;}
.nats { background:var(--nats-bg); border-color:var(--nats-br); }
.dispatcher{ background:var(--dispatcher-bg); border-color:var(--dispatcher-br); }
.toolswrap { background:var(--nats-bg); border-color:var(--nats-br); padding:14px; border-radius:14px; border:2px solid var(--nats-br);}
.mcp-go { background:#d6e7f3; border:2px solid var(--gotools-br); border-radius:12px; padding:12px; margin-bottom:14px;}
.mcp-py { background:var(--pytools-bg); border:2px solid var(--pytools-br); border-radius:12px; padding:12px;}
.colA{display:flex; flex-direction:column; gap:0;}
.colB{display:flex; flex-direction:column; gap:18px;}
/* connector labels */
.conn{
text-align:center; font-size:11px; color:#2a3a49; font-weight:700;
margin:6px 0; line-height:1.4;
}
.conn .arr{font-size:15px; color:#33485c;}
.conn small{display:block; font-weight:500; color:var(--muted);}
.midbar{
display:flex; align-items:center; justify-content:center; gap:8px;
font-weight:800; font-size:12px; color:#2a3a49; text-align:center;
background:#fff; border:1px dashed #9fb0bf; border-radius:8px;
padding:8px 10px; margin:14px 0;
}
.llmpool{
background:#e9edf0; border:1px solid #c4ccd4; border-radius:50px/40px;
padding:14px 16px; text-align:center; font-size:12.5px;
}
.llmpool b{display:block;}
.einolink{text-align:center; font-size:11px; font-weight:700; color:#6a4fa0; margin:8px 0;}
/* legend */
.legend{
margin-top:26px; display:flex; flex-wrap:wrap; gap:10px 26px;
align-items:center; background:#fff; border:1px solid var(--box-br);
border-radius:12px; padding:14px 18px; max-width:1980px;
}
.legend b{width:100%; font-size:13px; margin-bottom:2px;}
.lg{display:flex; align-items:center; gap:8px; font-size:12.5px;}
.sw{width:20px; height:14px; border-radius:4px; border:1px solid rgba(0,0,0,.15);}
.sw.client{background:var(--client);} .sw.gateway{background:var(--gateway);}
.sw.nats{background:var(--nats);} .sw.dispatcher{background:var(--dispatcher);}
.sw.gotools{background:var(--gotools);} .sw.pytools{background:var(--pytools);}
.sw.ginserver{background:var(--ginserver);}
.flow-note{
max-width:1980px; margin-top:22px; background:#fff; border:1px solid var(--box-br);
border-radius:12px; padding:16px 20px; font-size:13px; line-height:1.7;
}
.flow-note b{color:#2a3a49;}
.tag{display:inline-block; background:#eef1f4; border:1px solid var(--box-br);
border-radius:5px; padding:1px 7px; font-size:11.5px; font-family:ui-monospace,monospace;}
</style>
</head>
<body>
<h1>sundynix-agentix · 系统架构图</h1>
<p class="sub">分层式 AI Agent 平台 — Client / Gateway / NATS 总线 / Dispatcher / MCP ToolsMonolith First → Microservices Morph B</p>
<div class="grid">
<!-- ===================== 列 1:左纵列 (Client → Gateway → NATS → Dispatcher) ===================== -->
<div class="colA">
<!-- 1. CLIENT -->
<div class="layer client">
<div class="ltitle">1. CLIENT LAYER <small>Edge Interaction</small></div>
<div class="panel">
<div class="panel-title">sundynix-desktop <small>(User Device App)</small></div>
<div class="box hl"><b>UI Representation Layer</b><span>React 19 + TypeScript</span></div>
<div class="box"><b>shadcn/ui + Tailwind CSS</b><span>Styles / Components</span></div>
<div class="row2" style="margin-bottom:8px;">
<div class="box"><b>React Flow Canvas</b><span>Agent Orchestration</span></div>
<div class="box"><b>JSON DSL export</b><span>&nbsp;</span></div>
</div>
<div class="box"><b>LLM Wiki Management Panel</b></div>
<div class="box hl" style="background:var(--ginserver);"><b>Wails Local Go Runtime</b></div>
<div class="row2">
<div class="box hl" style="background:var(--gotools);"><b>Strong Binding</b><span>TS / Go</span></div>
<div class="box hl" style="background:var(--gotools);"><b>Local File System I/O</b></div>
</div>
</div>
</div>
<!-- connector client <-> gateway -->
<div class="conn">
<span class="arr"></span> 4. PHYSICAL COMMUNICATION<br>
<small>HTTPS / WebSocket / SSE &nbsp;·&nbsp; <span class="tag">sundynix.streams.task_id</span> Token Stream</small>
</div>
<!-- 2. GATEWAY -->
<div class="layer gateway">
<div class="ltitle">2. BUSINESS GATEWAY LAYER</div>
<div class="panel">
<div class="panel-title">sundynix-gateway <small>(Gin 微服务 · 集成 Monolith First)</small></div>
<div class="box hl"><b>Gin 微服务 / 统一接入层</b></div>
<div class="row2" style="margin-bottom:8px;">
<div class="box">🗄️ <b>MainDB</b><span>PgSQL: Users, Billing, DSL</span></div>
<div class="box">🧱 <b>CacheDB</b><span>Session / Rate Limit</span></div>
</div>
<div class="row2" style="margin-bottom:8px;">
<div class="box">🧱 <b>CacheDB</b><span>Redis: Session, Rate Limit</span></div>
<div class="box"><b>商业化与计费模块</b></div>
</div>
<div class="row2">
<div class="box"><b>Harness</b><span>Input / Output Guardrail</span></div>
<div class="box"><b>Task DSL Parser & Assembly</b></div>
</div>
</div>
</div>
<!-- connector gateway <-> nats -->
<div class="conn">
<span class="arr"></span> 1. Publish Task DSL &nbsp;&nbsp;|&nbsp;&nbsp; 4. Subscribe Stream <span class="arr"></span>
</div>
<!-- 3. NATS -->
<div class="layer nats">
<div class="ltitle">3. MESSAGE BUS — NATS 零拷贝骨干网</div>
<div class="panel">
<div class="panel-title" style="text-align:center;">NATS Server (Go) 🗄️</div>
<div class="row2">
<div class="box"><b>NATS Queue</b><span>分布式任务队列<br><span class="tag">sundynix.tasks.*</span></span></div>
<div class="box"><b>NATS Stream</b><span>零拷贝字节管道<br><span class="tag">sundynix.streams.*</span></span></div>
</div>
</div>
</div>
<!-- connector nats <-> dispatcher -->
<div class="conn"><span class="arr"></span> 4. Subscribe Stream</div>
<!-- 4. DISPATCHER -->
<div class="layer dispatcher">
<div class="ltitle">4. AI AGENT DISPATCHER LAYER</div>
<div class="llmpool" style="margin-bottom:10px;">
<b>LLM Pool</b><span style="color:var(--muted); font-size:11px;">vLLM / Ollama 集群</span>
</div>
<div class="einolink">↑ EinoCore &nbsp;·&nbsp; Eino 回调机制 ↓</div>
<div class="panel">
<div class="panel-title">sundynix-dispatcher <small>(Go / Eino 集群)</small></div>
<div class="row2" style="margin-bottom:8px;">
<div class="box hl"><b>Eino 图编排引擎</b></div>
<div class="box hl"><b>nats.go client</b></div>
</div>
<div class="box"><b>Harness: LLM 自动化评测</b></div>
<div class="box"><b>Harness: 熔断降级中心</b></div>
</div>
</div>
</div>
<!-- ===================== 列 2:留白做视觉间隔 / 物理通信说明 ===================== -->
<div class="colA" style="justify-content:flex-start;">
<div class="midbar">&nbsp; 4. PHYSICAL COMMUNICATION &nbsp;</div>
<div class="flow-note" style="margin-top:0;">
<b>核心数据流(编号对应连线)</b><br>
<b>1.</b> Gateway 解析 DSL 后 <b>Publish Task DSL</b> → NATS Queue<span class="tag">sundynix.tasks.*</span><br>
<b>2.</b> Dispatcher 通过 <span class="tag">nats.go</span> 订阅任务,Eino 图编排引擎驱动 LLM Pool 推理<br>
<b>3.</b> Dispatcher / Gateway 经 NATS 调用第 5 层 MCP 工具(Go I/O 型 + Python 算法型)<br>
<b>4.</b> 推理结果以 <b>零拷贝 Token Stream</b><span class="tag">sundynix.streams.task_id</span> 回流 Gateway → 经 SSE/WS 推送给 Client
</div>
<div class="midbar" style="margin-top:18px;">&nbsp; 4. Subscribe Stream &nbsp;&nbsp; MCP Tools</div>
</div>
<!-- ===================== 列 3MCP Tools 层 ===================== -->
<div class="colB">
<div class="toolswrap">
<div style="font-weight:800; font-size:15px; margin-bottom:4px;">5. MICROSERVICE MCP TOOLS LAYER</div>
<div style="font-size:11px; color:var(--muted); margin-bottom:12px;">Standalone microservices · Morph B</div>
<!-- mcp_go -->
<div class="mcp-go">
<div class="panel-title">sundynix-mcp-go <small>(Go 微服务 · I/O 型)</small></div>
<div class="box hl"><b>MCP Protocol Gateway</b></div>
<div class="box hl"><b>LLM Wiki 搜索引擎</b><span>Hybrid Search: Bleve · Milvus Go SDK · Neo4j Go Driver</span></div>
<div class="row2" style="margin-bottom:8px;">
<div class="box">🧊 <b>Milvus</b><span>Vector DB</span></div>
<div class="box">🔎 <b>Bleve</b><span>Go Search Index</span></div>
</div>
<div class="row2" style="margin-bottom:8px;">
<div class="box">🕸️ <b>Neo4j</b><span>Knowledge Graph</span></div>
<div class="box">🕸️ <b>Neo4j</b><span>Graph</span></div>
</div>
<div class="row2">
<div class="box">📄 <b>UniOffice</b><span>Word/Doc Rendering</span></div>
<div class="box"><b>External APIs</b></div>
</div>
</div>
<!-- mcp_py -->
<div class="mcp-py">
<div class="panel-title">sundynix-mcp-py <small>(Python 微服务 · 算法型)</small></div>
<div class="box hl"><b>MCP Protocol Gateway</b></div>
<div class="box"><b>Harness: Secure Code Sandbox</b><span>gVisor / KataVM · Static Code Guard</span></div>
<div class="box"><b>MinerU</b><span>Multimodal Parser: PaddleOCR</span></div>
<div class="box"><b>Docker 隔离沙箱</b><span>Code Interpreter</span></div>
</div>
</div>
</div>
</div>
<!-- ===================== 图例 ===================== -->
<div class="legend">
<b>Legend</b>
<div class="lg"><span class="sw client"></span>Client</div>
<div class="lg"><span class="sw gateway"></span>Gateway</div>
<div class="lg"><span class="sw nats"></span>NATS</div>
<div class="lg"><span class="sw dispatcher"></span>Dispatcher</div>
<div class="lg"><span class="sw gotools"></span>Go Tools</div>
<div class="lg"><span class="sw pytools"></span>Python Tools</div>
<div class="lg"><span class="sw ginserver"></span>GinServer</div>
</div>
</body>
</html>