nandi/oripublic Fork 0
55d4c9e2f7a9027b52846558166f42e50851523a
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

ori-architecture.drawio.svg · 80 lines · 22.9 KBXML Blame HistoryRaw
 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
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1220" height="640" viewBox="0 0 1220 640" content="&lt;mxfile host=&quot;Electron&quot; agent=&quot;make-diagram.mjs&quot; type=&quot;device&quot;&gt;&lt;diagram name=&quot;Ori Architecture&quot; id=&quot;diagram-1&quot;&gt;&lt;mxGraphModel dx=&quot;1000&quot; dy=&quot;600&quot; grid=&quot;1&quot; gridSize=&quot;10&quot; guides=&quot;1&quot; tooltips=&quot;1&quot; connect=&quot;1&quot; arrows=&quot;1&quot; fold=&quot;1&quot; page=&quot;1&quot; pageScale=&quot;1&quot; pageWidth=&quot;1169&quot; pageHeight=&quot;826&quot; math=&quot;0&quot; shadow=&quot;0&quot;&gt;&lt;root&gt;&lt;mxCell id=&quot;0&quot;/&gt;&lt;mxCell id=&quot;1&quot; parent=&quot;0&quot;/&gt;&lt;mxCell id=&quot;3&quot; value=&quot;Browser&amp;amp;#10;React SPA&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#fdfdfb;strokeColor=#15202b;fontColor=#15202b;fontSize=17;fontStyle=0;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;20&quot; y=&quot;20&quot; width=&quot;220&quot; height=&quot;110&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;4&quot; value=&quot;UI Components&amp;amp;#10;· Agent Panel&amp;amp;#10;· Workspace Panel&amp;amp;#10;· File Tree&amp;amp;#10;· Monaco Editor&amp;amp;#10;· Terminal (xterm.js)&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#e8ebda;strokeColor=#15202b;fontColor=#15202b;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;20&quot; y=&quot;150&quot; width=&quot;220&quot; height=&quot;150&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;5&quot; value=&quot;httpserver&amp;amp;#10;Serves SPA + /ws&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#15202b;strokeColor=#15202b;fontColor=#fdfdfb;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;370&quot; y=&quot;20&quot; width=&quot;280&quot; height=&quot;90&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;6&quot; value=&quot;bridge&amp;amp;#10;· WebSocket ⇄ ACP&amp;amp;#10;· Event broadcast&amp;amp;#10;· Permission routing&amp;amp;#10;· History replay&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#15202b;strokeColor=#15202b;fontColor=#fdfdfb;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;370&quot; y=&quot;140&quot; width=&quot;280&quot; height=&quot;130&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;7&quot; value=&quot;agent&amp;amp;#10;ACP session&amp;amp;#10;lifecycle&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#15202b;strokeColor=#15202b;fontColor=#fdfdfb;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;370&quot; y=&quot;300&quot; width=&quot;135&quot; height=&quot;90&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;8&quot; value=&quot;files&amp;amp;#10;Workspace&amp;amp;#10;file API&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#15202b;strokeColor=#15202b;fontColor=#fdfdfb;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;515&quot; y=&quot;300&quot; width=&quot;135&quot; height=&quot;90&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;9&quot; value=&quot;terminal&amp;amp;#10;PTY per&amp;amp;#10;connection&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#15202b;strokeColor=#15202b;fontColor=#fdfdfb;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;370&quot; y=&quot;410&quot; width=&quot;135&quot; height=&quot;90&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;10&quot; value=&quot;mockagent&amp;amp;#10;Demo agent&amp;amp;#10;(testing)&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#e8ebda;strokeColor=#15202b;fontColor=#15202b;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;515&quot; y=&quot;410&quot; width=&quot;135&quot; height=&quot;90&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;11&quot; value=&quot;ACP Agent&amp;amp;#10;(claude-code-acp / Gemini CLI)&amp;amp;#10;&amp;amp;#10;JSON-RPC over stdio&amp;amp;#10;session_update · permission_request&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#fdfdfb;strokeColor=#0062FF;fontColor=#0062FF;fontSize=17;fontStyle=1;strokeWidth=2;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;800&quot; y=&quot;230&quot; width=&quot;400&quot; height=&quot;130&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;12&quot; value=&quot;Go backend bridges browser WebSockets to ACP stdio, broadcasting agent updates to all connected browsers while routing permissions back to the waiting call.&quot; style=&quot;rounded=1;arcSize=12;whiteSpace=wrap;html=1;fillColor=#fdfdfb;strokeColor=#15202b;fontColor=#15202b;fontSize=15;fontStyle=0;strokeWidth=2;dashed=1;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&lt;mxGeometry x=&quot;20&quot; y=&quot;560&quot; width=&quot;1180&quot; height=&quot;60&quot; as=&quot;geometry&quot;/&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;13&quot; value=&quot;1. load SPA&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#15202b;fontSize=14;fontColor=#15202b;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;3&quot; target=&quot;5&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;14&quot; value=&quot;2. WebSocket&amp;amp;#10;/ws&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#15202b;fontSize=14;fontColor=#15202b;exitX=1;exitY=0.7272727272727273;exitDx=0;exitDy=0;entryX=0;entryY=0.3076923076923077;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;3&quot; target=&quot;6&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;15&quot; value=&quot;3. prompt +&amp;amp;#10;permission&amp;amp;#10;responses&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#15202b;fontSize=14;fontColor=#15202b;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.6538461538461539;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;4&quot; target=&quot;6&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;16&quot; value=&quot;4. session_update&amp;amp;#10;events (replay)&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#0062FF;fontSize=14;fontColor=#0062FF;dashed=1;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;6&quot; target=&quot;4&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;310&quot; y=&quot;230&quot;/&gt;&lt;mxPoint x=&quot;280&quot; y=&quot;230&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;17&quot; value=&quot;5. ACP&amp;amp;#10;lifecycle&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#15202b;fontSize=14;fontColor=#15202b;exitX=0.2857142857142857;exitY=1;exitDx=0;exitDy=0;entryX=0.4962962962962963;entryY=0;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;6&quot; target=&quot;7&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;18&quot; value=&quot;6. stdio&amp;amp;#10;JSON-RPC&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#15202b;fontSize=14;fontColor=#15202b;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;7&quot; target=&quot;11&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;19&quot; value=&quot;7. updates +&amp;amp;#10;permissions&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#0062FF;fontSize=14;fontColor=#0062FF;dashed=1;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;11&quot; target=&quot;6&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;Array as=&quot;points&quot;&gt;&lt;mxPoint x=&quot;720&quot; y=&quot;200&quot;/&gt;&lt;mxPoint x=&quot;650&quot; y=&quot;200&quot;/&gt;&lt;/Array&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;20&quot; value=&quot;file ops&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#0062FF;fontSize=14;fontColor=#0062FF;dashed=1;exitX=1;exitY=0.8666666666666667;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;4&quot; target=&quot;8&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;mxCell id=&quot;21&quot; value=&quot;shell I/O&quot; style=&quot;edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeWidth=2;strokeColor=#0062FF;fontSize=14;fontColor=#0062FF;dashed=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot; source=&quot;4&quot; target=&quot;9&quot;&gt;&lt;mxGeometry relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&lt;/mxGeometry&gt;&lt;/mxCell&gt;&lt;/root&gt;&lt;/mxGraphModel&gt;&lt;/diagram&gt;&lt;/mxfile&gt;">
    <defs><marker id="arrow-dark" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="#15202b"/></marker><marker id="arrow-blue" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="#0062FF"/></marker></defs>
    <path d="M 242 75 L 364 75" fill="none" stroke="#15202b" stroke-width="2" marker-end="url(#arrow-dark)"/>
    <rect x="254.2" y="62.5" width="97.6" height="25" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="303" y="75" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">1. load SPA</text>
    <path d="M 242 100 L 364 180" fill="none" stroke="#15202b" stroke-width="2" marker-end="url(#arrow-dark)"/>
    <rect x="250.4" y="119" width="105.19999999999999" height="42" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="303" y="131.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">2. WebSocket</text>
    <text x="303" y="148.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">/ws</text>
    <path d="M 242 225 L 364 225" fill="none" stroke="#15202b" stroke-width="2" marker-end="url(#arrow-dark)"/>
    <rect x="254.2" y="195.5" width="97.6" height="59" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="303" y="208" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">3. prompt +</text>
    <text x="303" y="225" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">permission</text>
    <text x="303" y="242" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">responses</text>
    <path d="M 368 205 L 310 230 L 280 230 L 246 225" fill="none" stroke="#0062FF" stroke-width="2" stroke-dasharray="6 5" marker-end="url(#arrow-blue)"/>
    <rect x="267.4" y="196.5" width="143.2" height="42" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="339" y="209" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#0062FF">4. session_update</text>
    <text x="339" y="226" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#0062FF">events (replay)</text>
    <path d="M 450 272 L 437 294" fill="none" stroke="#15202b" stroke-width="2" marker-end="url(#arrow-dark)"/>
    <rect x="402.3" y="262" width="82.39999999999999" height="42" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="443.5" y="274.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">5. ACP</text>
    <text x="443.5" y="291.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">lifecycle</text>
    <path d="M 507 345 L 794 295" fill="none" stroke="#15202b" stroke-width="2" marker-end="url(#arrow-dark)"/>
    <rect x="613.1" y="299" width="74.8" height="42" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="650.5" y="311.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">6. stdio</text>
    <text x="650.5" y="328.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#15202b">JSON-RPC</text>
    <path d="M 798 295 L 720 200 L 650 200 L 656 205" fill="none" stroke="#0062FF" stroke-width="2" stroke-dasharray="6 5" marker-end="url(#arrow-blue)"/>
    <rect x="706.4" y="226.5" width="105.19999999999999" height="42" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="759" y="239" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#0062FF">7. updates +</text>
    <text x="759" y="256" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#0062FF">permissions</text>
    <path d="M 242 280 L 509 345" fill="none" stroke="#0062FF" stroke-width="2" stroke-dasharray="6 5" marker-end="url(#arrow-blue)"/>
    <rect x="338.1" y="300" width="74.8" height="25" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="375.5" y="312.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#0062FF">file ops</text>
    <path d="M 130 302 L 364 455" fill="none" stroke="#0062FF" stroke-width="2" stroke-dasharray="6 5" marker-end="url(#arrow-blue)"/>
    <rect x="205.8" y="366" width="82.39999999999999" height="25" rx="4" fill="#fdfdfb" opacity="0.92"/>
    <text x="247" y="378.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="14" fill="#0062FF">shell I/O</text>
    <rect x="20" y="20" width="220" height="110" rx="10" ry="10" fill="#fdfdfb" stroke="#15202b" stroke-width="2"/>
    <text x="130" y="64.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="normal" fill="#15202b">Browser</text>
    <text x="130" y="85.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="normal" fill="#15202b">React SPA</text>
    <rect x="20" y="150" width="220" height="150" rx="10" ry="10" fill="#e8ebda" stroke="#15202b" stroke-width="2"/>
    <text x="130" y="172.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">UI Components</text>
    <text x="130" y="193.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">· Agent Panel</text>
    <text x="130" y="214.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">· Workspace Panel</text>
    <text x="130" y="235.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">· File Tree</text>
    <text x="130" y="256.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">· Monaco Editor</text>
    <text x="130" y="277.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">· Terminal (xterm.js)</text>
    <rect x="370" y="20" width="280" height="90" rx="10" ry="10" fill="#15202b" stroke="#15202b" stroke-width="2"/>
    <text x="510" y="54.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">httpserver</text>
    <text x="510" y="75.5" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">Serves SPA + /ws</text>
    <rect x="370" y="140" width="280" height="130" rx="10" ry="10" fill="#15202b" stroke="#15202b" stroke-width="2"/>
    <text x="510" y="163" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">bridge</text>
    <text x="510" y="184" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">· WebSocket ⇄ ACP</text>
    <text x="510" y="205" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">· Event broadcast</text>
    <text x="510" y="226" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">· Permission routing</text>
    <text x="510" y="247" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">· History replay</text>
    <rect x="370" y="300" width="135" height="90" rx="10" ry="10" fill="#15202b" stroke="#15202b" stroke-width="2"/>
    <text x="437.5" y="324" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">agent</text>
    <text x="437.5" y="345" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">ACP session</text>
    <text x="437.5" y="366" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">lifecycle</text>
    <rect x="515" y="300" width="135" height="90" rx="10" ry="10" fill="#15202b" stroke="#15202b" stroke-width="2"/>
    <text x="582.5" y="324" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">files</text>
    <text x="582.5" y="345" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">Workspace</text>
    <text x="582.5" y="366" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">file API</text>
    <rect x="370" y="410" width="135" height="90" rx="10" ry="10" fill="#15202b" stroke="#15202b" stroke-width="2"/>
    <text x="437.5" y="434" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">terminal</text>
    <text x="437.5" y="455" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">PTY per</text>
    <text x="437.5" y="476" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#fdfdfb">connection</text>
    <rect x="515" y="410" width="135" height="90" rx="10" ry="10" fill="#e8ebda" stroke="#15202b" stroke-width="2"/>
    <text x="582.5" y="434" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">mockagent</text>
    <text x="582.5" y="455" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">Demo agent</text>
    <text x="582.5" y="476" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#15202b">(testing)</text>
    <rect x="800" y="230" width="400" height="130" rx="10" ry="10" fill="#fdfdfb" stroke="#0062FF" stroke-width="2"/>
    <text x="1000" y="253" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#0062FF">ACP Agent</text>
    <text x="1000" y="274" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#0062FF">(claude-code-acp / Gemini CLI)</text>
    <text x="1000" y="295" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#0062FF"></text>
    <text x="1000" y="316" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#0062FF">JSON-RPC over stdio</text>
    <text x="1000" y="337" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#0062FF">session_update · permission_request</text>
    <rect x="20" y="560" width="1180" height="60" rx="10" ry="10" fill="#fdfdfb" stroke="#15202b" stroke-width="2" stroke-dasharray="6 5"/>
    <text x="610" y="590" text-anchor="middle" dominant-baseline="central" font-family="Helvetica Neue, Helvetica, Arial, sans-serif" font-size="15" font-weight="normal" fill="#15202b">Go backend bridges browser WebSockets to ACP stdio, broadcasting agent updates to all connected browsers while routing permissions back to the waiting call.</text>
</svg>