@vpxa/aikit 0.1.351 → 0.1.353
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/blocks-core/dist/index.mjs +949 -118
- package/packages/core/dist/index.d.ts +3 -0
- package/packages/core/dist/index.js +1 -1
- package/packages/present/dist/annotation-layer.js +48 -74
- package/packages/present/dist/index.html +977 -153
- package/packages/server/dist/bin.js +1 -1
- package/packages/server/dist/index.js +288 -109
- package/packages/server/dist/prelude-DetbWo8R.js +1 -0
- package/packages/server/dist/prelude-hfAEi93R.js +2 -0
- package/packages/server/dist/sampling-CWjnUevo.js +2 -0
- package/packages/server/dist/sampling-CnE3owSt.js +1 -0
- package/packages/server/dist/{server-Dc2XtS92.js → server-D5eu57oU.js} +150 -148
- package/packages/server/dist/{server-Ct4BK2hi.js → server-D7gZ4K_H.js} +150 -148
- package/packages/server/dist/{server-http-DBmzukZH.js → server-http-AarbD3gm.js} +1 -1
- package/packages/server/dist/{server-http-BNC9qZBj.js → server-http-wnYmWFkC.js} +1 -1
- package/packages/server/dist/{server-stdio-JHWimdo9.js → server-stdio-BWoMqXU8.js} +1 -1
- package/packages/server/dist/{server-stdio-DkDdZI98.js → server-stdio-CBGO6XiO.js} +1 -1
- package/packages/server/viewers/canvas.html +944 -127
- package/packages/server/viewers/code-review-viewer.html +352 -0
- package/packages/server/viewers/report-template.html +918 -101
- package/packages/server/viewers/task-plan-static.html +1 -1
- package/packages/server/viewers/tour-viewer.html +919 -102
- package/packages/tools/dist/index.js +82 -82
- package/scaffold/dist/definitions/skills/c4-architecture.mjs +1 -1
- package/scaffold/dist/definitions/skills/docs.mjs +19 -3
- package/scaffold/dist/definitions/skills/present.mjs +317 -13
- package/scaffold/dist/generated/block-docs.mjs +18 -64
- package/packages/server/dist/prelude-Clxlztkk.js +0 -1
- package/packages/server/dist/prelude-Dn7jTsqe.js +0 -2
- package/packages/server/dist/sampling-giGWyrcO.js +0 -1
- package/packages/server/dist/sampling-nivAea83.js +0 -2
|
@@ -4,164 +4,297 @@ import{a as e,i as t,n,r,t as i}from"./server-utils-De-aZNQa.js";import{n as a,r
|
|
|
4
4
|
`;if(!e.diagram_type)return`# Diagram
|
|
5
5
|
|
|
6
6
|
*Missing diagram type*
|
|
7
|
-
`;switch(e.diagram_type){case`architecture`:return
|
|
7
|
+
`;switch(e.diagram_type){case`architecture`:return v(e);case`workflow`:return ee(e);case`sequence`:return te(e);case`dataflow`:return y(e);case`lifecycle`:return ne(e);default:{let t=e;return`# ${typeof t.meta?.title==`string`&&t.meta.title.length>0?t.meta.title:`Diagram`}\n\nUnknown diagram type: ${typeof t.diagram_type==`string`?t.diagram_type:`unknown`}`}}}function v(e){let t=[`# ${e.meta.title}`,e.meta.subtitle?`> ${e.meta.subtitle}\n`:``,`## Components
|
|
8
8
|
`,`| # | Type | Component | Description |`,`|---|------|-----------|-------------|`];if(e.components.forEach((e,n)=>{t.push(`| ${n+1} | ${e.type} | **${e.label}** | ${e.sublabel??``} |`)}),t.push(`
|
|
9
9
|
## Connections
|
|
10
10
|
`),e.connections.length===0)t.push(`*No connections defined.*
|
|
11
11
|
`);else{let n=new Map(e.components.map(e=>[e.id,e.label]));for(let r of e.connections){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to;t.push(`- **${e}** → **${i}**${r.label?`: ${r.label}`:``}`)}}if(e.boundaries?.length){t.push(`
|
|
12
12
|
## Boundaries
|
|
13
|
-
`);for(let n of e.boundaries){let r=n.wraps.map(t=>e.components.find(e=>e.id===t)?.label??t).join(`, `);t.push(`- **${n.label}** (${n.kind}): ${r}`)}}return e.cards?.length&&
|
|
14
|
-
`)}function
|
|
13
|
+
`);for(let n of e.boundaries){let r=n.wraps.map(t=>e.components.find(e=>e.id===t)?.label??t).join(`, `);t.push(`- **${n.label}** (${n.kind}): ${r}`)}}return e.cards?.length&&b(t,e.cards),t.filter(Boolean).join(`
|
|
14
|
+
`)}function ee(e){let t=[`# ${e.meta.title}`,e.meta.subtitle?`> ${e.meta.subtitle}\n`:``,`## Lanes
|
|
15
15
|
`];for(let[n,r]of e.lanes.entries())t.push(`${n+1}. **${r.label}**`);t.push(`
|
|
16
16
|
## Steps
|
|
17
17
|
`);let n=new Map(e.lanes.map(e=>[e.id,e.label])),r=[...e.nodes].sort((e,t)=>e.lane.localeCompare(t.lane)||e.col-t.col);for(let e of r){let r=n.get(e.lane)??e.lane,i=e.tag?` (${e.tag})`:``;t.push(`- [${r}] **${e.label}**${i}${e.sublabel?` — ${e.sublabel}`:``}`)}if(e.edges.length>0){t.push(`
|
|
18
18
|
## Transitions
|
|
19
|
-
`);let n=new Map(e.nodes.map(e=>[e.id,e.label]));for(let r of e.edges){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to;t.push(`- **${e}** → **${i}**${r.label?`: ${r.label}`:``}`)}}return e.cards?.length&&
|
|
20
|
-
`)}function
|
|
19
|
+
`);let n=new Map(e.nodes.map(e=>[e.id,e.label]));for(let r of e.edges){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to;t.push(`- **${e}** → **${i}**${r.label?`: ${r.label}`:``}`)}}return e.cards?.length&&b(t,e.cards),t.filter(Boolean).join(`
|
|
20
|
+
`)}function te(e){let t=[`# ${e.meta.title}`,e.meta.subtitle?`> ${e.meta.subtitle}\n`:``,`## Participants
|
|
21
21
|
`];for(let n of e.participants)t.push(`- **${n.label}** (${n.type})${n.sublabel?` — ${n.sublabel}`:``}`);if(t.push(`
|
|
22
22
|
## Message Flow
|
|
23
|
-
`),e.segments)for(let n of e.segments)t.push(`\n### ${n.label}`);for(let n of e.messages){let r=e.participants.find(e=>e.id===n.from)?.label??n.from,i=e.participants.find(e=>e.id===n.to)?.label??n.to,a=n.variant&&n.variant!=="default"?` [${n.variant}]`:``;t.push(`- **${r}** → **${i}**${a}: ${n.label}${n.note?` (${n.note})`:``}`)}return e.cards?.length&&
|
|
24
|
-
`)}function
|
|
23
|
+
`),e.segments)for(let n of e.segments)t.push(`\n### ${n.label}`);for(let n of e.messages){let r=e.participants.find(e=>e.id===n.from)?.label??n.from,i=e.participants.find(e=>e.id===n.to)?.label??n.to,a=n.variant&&n.variant!=="default"?` [${n.variant}]`:``;t.push(`- **${r}** → **${i}**${a}: ${n.label}${n.note?` (${n.note})`:``}`)}return e.cards?.length&&b(t,e.cards),t.filter(Boolean).join(`
|
|
24
|
+
`)}function y(e){let t=[`# ${e.meta.title}`,e.meta.subtitle?`> ${e.meta.subtitle}\n`:``,`## Stages
|
|
25
25
|
`];for(let[n,r]of e.stages.entries())t.push(`${n+1}. **${r.label}**`);if(t.push(`
|
|
26
26
|
## Data Nodes
|
|
27
27
|
`),e.nodes.forEach(n=>{let r=e.stages[n.stage]?.label??n.stage;t.push(`- [${r}] **${n.label}** (${n.type})${n.sublabel?` — ${n.sublabel}`:``}`)}),e.flows.length>0){t.push(`
|
|
28
28
|
## Data Flows
|
|
29
|
-
`);let n=new Map(e.nodes.map(e=>[e.id,e.label]));for(let r of e.flows){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to,a=r.classification?` [${r.classification}]`:``,o=r.variant&&r.variant!=="default"?` (${r.variant})`:``;t.push(`- **${e}** → **${i}**: ${r.label}${a}${o}`)}}return e.cards?.length&&
|
|
30
|
-
`)}function
|
|
29
|
+
`);let n=new Map(e.nodes.map(e=>[e.id,e.label]));for(let r of e.flows){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to,a=r.classification?` [${r.classification}]`:``,o=r.variant&&r.variant!=="default"?` (${r.variant})`:``;t.push(`- **${e}** → **${i}**: ${r.label}${a}${o}`)}}return e.cards?.length&&b(t,e.cards),t.filter(Boolean).join(`
|
|
30
|
+
`)}function ne(e){let t=[`# ${e.meta.title}`,e.meta.subtitle?`> ${e.meta.subtitle}\n`:``,`## States
|
|
31
31
|
`],n=new Map(e.lanes.map(e=>[e.id,e.label]));if(e.states.forEach(e=>{let r=n.get(e.lane)??e.lane,i=e.step?` (Step ${e.step})`:``,a=e.tag?` [${e.tag}]`:``;t.push(`- [${r}] **${e.label}** (${e.type})${i}${a}${e.sublabel?` — ${e.sublabel}`:``}`)}),e.transitions.length>0){t.push(`
|
|
32
32
|
## Transitions
|
|
33
|
-
`);let n=new Map(e.states.map(e=>[e.id,e.label]));for(let r of e.transitions){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to,a=r.label?`: ${r.label}`:``,o=r.note?` (${r.note})`:``;t.push(`- **${e}** → **${i}**${a}${o}`)}}return e.cards?.length&&
|
|
34
|
-
`)}function
|
|
33
|
+
`);let n=new Map(e.states.map(e=>[e.id,e.label]));for(let r of e.transitions){let e=n.get(r.from)??r.from,i=n.get(r.to)??r.to,a=r.label?`: ${r.label}`:``,o=r.note?` (${r.note})`:``;t.push(`- **${e}** → **${i}**${a}${o}`)}}return e.cards?.length&&b(t,e.cards),t.filter(Boolean).join(`
|
|
34
|
+
`)}function b(e,t){e.push(`
|
|
35
35
|
## Summary
|
|
36
|
-
`);for(let n of t){e.push(`\n### ${n.title}`);for(let t of n.items)e.push(`- ${t}`)}}function
|
|
36
|
+
`);for(let n of t){e.push(`\n### ${n.title}`);for(let t of n.items)e.push(`- ${t}`)}}function x(e){let t={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`};return String(e??``).replace(/[&<>"']/g,e=>t[e]??e)}const re=/[ᄀ-ᅟ⺀-가-힣豈-︰-﹏-⦆¢-₩ -〿\u{1F000}-\u{1FAFF}\u{20000}-\u{3FFFD}]/u;function S(e){let t=0;for(let n of String(e??``))t+=re.test(n)?2:1;return t}function ie(e,t,n=0){return!(e.x+e.width+n<=t.x||t.x+t.width+n<=e.x||e.y+e.height+n<=t.y||t.y+t.height+n<=e.y)}function C(e,t){switch(t){case`left`:return{x:e.x,y:e.y+e.height/2};case`right`:return{x:e.x+e.width,y:e.y+e.height/2};case`top`:return{x:e.x+e.width/2,y:e.y};case`bottom`:return{x:e.x+e.width/2,y:e.y+e.height};default:return{x:e.x+e.width,y:e.y+e.height/2}}}function w(e,t){return t.x+t.width/2<e.x+e.width/2?`left`:t.x+t.width/2>e.x+e.width/2?`right`:t.y+t.height/2>e.y+e.height/2?`bottom`:`top`}function T(e,t){return t.x+t.width/2<e.x+e.width/2?`right`:t.x+t.width/2>e.x+e.width/2?`left`:t.y+t.height/2>e.y+e.height/2?`top`:`bottom`}function E(e,t){return e&&e!==`auto`?e:t}function D(e){return e.map((e,t)=>`${t===0?`M`:`L`} ${e.x} ${e.y}`).join(` `)}function O(e,t=10){if(e.length<3||t<=0)return D(e);let n=[`M ${e[0].x} ${e[0].y}`];for(let r=1;r<e.length-1;r++){let i=e[r-1],a=e[r],o=e[r+1],s=Math.hypot(a.x-i.x,a.y-i.y),c=Math.hypot(o.x-a.x,o.y-a.y),l=Math.min(t,s/2,c/2);if(l<1){n.push(`L ${a.x} ${a.y}`);continue}let u={x:a.x-(a.x-i.x)/s*l,y:a.y-(a.y-i.y)/s*l},d={x:a.x+(o.x-a.x)/c*l,y:a.y+(o.y-a.y)/c*l};n.push(`L ${u.x} ${u.y}`),n.push(`Q ${a.x} ${a.y} ${d.x} ${d.y}`)}let r=e[e.length-1];return n.push(`L ${r.x} ${r.y}`),n.join(` `)}const k={frontend:`c-frontend`,backend:`c-backend`,database:`c-database`,cloud:`c-cloud`,security:`c-security`,messagebus:`c-messagebus`,external:`c-external`},A={default:[`a-default`,`arrowhead`],emphasis:[`a-emphasis`,`arrowhead-emphasis`],security:[`a-security`,`arrowhead-security`],dashed:[`a-dashed`,`arrowhead-dashed`],animated:[`a-animated`,`arrowhead`]};function j(){return`<defs>
|
|
37
37
|
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" class="m-default"/></marker>
|
|
38
38
|
<marker id="arrowhead-emphasis" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" class="m-emphasis"/></marker>
|
|
39
39
|
<marker id="arrowhead-security" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" class="m-security"/></marker>
|
|
40
40
|
<marker id="arrowhead-dashed" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" class="m-dashed"/></marker>
|
|
41
41
|
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse"><path d="M 40 0 L 0 0 0 40" class="c-grid" stroke-width="0.5"/></pattern>
|
|
42
|
-
</defs>`}function
|
|
43
|
-
`),cardsHtml:
|
|
44
|
-
`):``}const
|
|
45
|
-
`)}`);let n=e.meta.viewBox??
|
|
46
|
-
`),cardsHtml:
|
|
47
|
-
`):``}const
|
|
48
|
-
`)}`);let n=e.meta.viewBox??
|
|
49
|
-
`),cardsHtml:
|
|
50
|
-
`):``}const
|
|
51
|
-
`)}`);let n=e.meta.viewBox??
|
|
52
|
-
`),cardsHtml:
|
|
53
|
-
`):``}const
|
|
54
|
-
`)}`);let n=new Map(e.lanes.map((e,t)=>[e.id,t]));function r(e){return
|
|
55
|
-
`),cardsHtml:
|
|
56
|
-
`):``}function
|
|
42
|
+
</defs>`}function ae(e){let t=oe(e);if(t.length>0)return{svg:`<svg viewBox="0 0 600 200"><text x="300" y="100" text-anchor="middle" fill="var(--text)">Architecture validation failed</text><text x="300" y="130" text-anchor="middle" font-size="12" fill="var(--text-muted)">${x(t.join(`; `))}</text></svg>`,cardsHtml:``};let n=new Map;for(let t of e.components){let e=t.size?.[0]??120,r=t.size?.[1]??60;n.set(t.id,{...t,x:t.pos.x,y:t.pos.y,width:e,height:r})}let r=100,i=100;for(let e of n.values())r=Math.max(r,e.x+e.width+40),i=Math.max(i,e.y+e.height+40);let a=e.meta.viewBox??[Math.max(720,Math.ceil(r/100)*100),Math.max(400,Math.ceil(i/100)*100)],o=[];if(o.push(`<svg viewBox="0 0 ${a[0]} ${a[1]}" role="img" aria-label="${x(e.meta.title)}">`),o.push(j()),o.push(`<rect width="100%" height="100%" fill="url(#grid)"/>`),e.boundaries)for(let t of e.boundaries){let e=new Set(t.wraps),r=[...n.values()].filter(t=>e.has(t.id));if(r.length===0)continue;let i=Math.min(...r.map(e=>e.x))-30,a=Math.min(...r.map(e=>e.y))-30,s=Math.max(...r.map(e=>e.x+e.width))+30,c=Math.max(...r.map(e=>e.y+e.height))+30,l=t.kind===`security-group`?` stroke-dasharray="8,4"`:` stroke-dasharray="6,4"`,u=t.kind===`security-group`?`var(--c-security-stroke)`:`var(--c-cloud-stroke)`;o.push(`<rect x="${i}" y="${a}" width="${s-i}" height="${c-a}" rx="12" fill="var(--lane-fill)" stroke="${u}" stroke-width="1.5"${l}/>`),o.push(`<text x="${i+10}" y="${a+18}" class="t-dim" font-size="10" font-weight="600">${x(t.label)}</text>`)}for(let t of e.connections){let e=n.get(t.from),r=n.get(t.to);if(!e||!r)continue;let i=C(e,E(t.fromSide,w(e,r))),a=C(r,E(t.toSide,T(e,r))),s=(i.y+a.y)/2,c=t.route===`drop`?[i,{x:i.x,y:s},{x:a.x,y:s},a]:[i,a],[l,u]=A[t.variant??`default`]??A.default,d=t.variant===`emphasis`?1.8:1.4;if(o.push(`<path d="${D(c)}" class="${l}" stroke-width="${d}" marker-end="url(#${u})"/>`),t.label){let e={x:(i.x+a.x)/2+(t.labelDx??0),y:i.y-10+(t.labelDy??0)},n=Math.max(30,S(t.label)*4.8+10);o.push(`<rect x="${e.x-n/2}" y="${e.y-10}" width="${n}" height="14" rx="3" class="c-mask"/>`),o.push(`<text x="${e.x}" y="${e.y}" class="t-muted" font-size="8" text-anchor="middle">${x(t.label)}</text>`)}}let s={};for(let e of n.values()){let t=k[e.type]??`c-external`,n=e.x+e.width/2;e.y+e.height/2,o.push(`<g class="node" data-k="${x(e.id)}">`),o.push(`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="6" class="c-mask"/>`),o.push(`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="6" class="${t}" stroke-width="1.5"/>`),o.push(`<text x="${n}" y="${e.y+24}" class="t-primary" font-size="11" font-weight="600" text-anchor="middle">${x(e.label)}</text>`),e.sublabel&&o.push(`<text x="${n}" y="${e.y+42}" class="t-muted" font-size="9" text-anchor="middle">${x(e.sublabel)}</text>`),o.push(`</g>`);let r=e.type.charAt(0).toUpperCase()+e.type.slice(1),i=e.sublabel?` · ${x(e.sublabel)}`:``;s[e.id]={t:x(e.label),m:`${r}${i}`,b:`${x(e.label)} (${r})`}}new Set(e.components.map(e=>e.type));let c=Math.max(...[...n.values()].map(e=>e.y+e.height))+60;o.push(`<text x="40" y="${c}" class="t-primary" font-size="10" font-weight="600">Legend</text>`);let l=[[`c-frontend`,`User UI`],[`c-backend`,`Service`],[`c-database`,`Data Store`],[`c-cloud`,`Infra`],[`c-security`,`Security`],[`c-messagebus`,`Queue`],[`c-external`,`External`]],u=40;for(let[e,t]of l)o.push(`<rect x="${u}" y="${c+14}" width="14" height="9" rx="2" class="${e}" stroke-width="1"/><text x="${u+20}" y="${c+22}" class="t-muted" font-size="7">${t}</text>`),u+=80;o.push(`</svg>`);let d=se(e.cards);return{svg:o.join(`
|
|
43
|
+
`),cardsHtml:d,detailData:s}}function oe(e){let t=[];e.schema_version!==1&&t.push(`schema_version must be 1`),e.meta?.title||t.push(`meta.title is required`),e.components?.length||t.push(`At least one component required`);let n=new Set(e.components?.map(e=>e.id));n.size!==e.components?.length&&t.push(`Component IDs must be unique`);for(let r of e.connections??[])n.has(r.from)||t.push(`Connection references unknown source "${r.from}"`),n.has(r.to)||t.push(`Connection references unknown target "${r.to}"`);let r=e.components.map(e=>({id:e.id,x:e.pos.x,y:e.pos.y,width:e.size?.[0]??120,height:e.size?.[1]??60}));for(let e=0;e<r.length;e++)for(let n=e+1;n<r.length;n++)ie(r[e],r[n],10)&&t.push(`"${r[e].id}" overlaps "${r[n].id}" — move one component`);return t}function se(e){return e?.length?e.map(e=>`<div class="card"><div class="card-header"><div class="card-dot ${x(e.dot)}"></div><h3>${x(e.title)}</h3></div><ul>${e.items.map(e=>`<li>• ${x(e)}</li>`).join(``)}</ul></div>`).join(`
|
|
44
|
+
`):``}const M={stageY:46,stageH:36,stageBottomPad:74,leftX:100,colGap:215,stageW:168,nodeW:112,nodeH:58,rowYs:[128,242,356,470,584],labelH:16,defaultViewBox:[940,720]};function ce(e){let t=le(e);if(t.length>0)throw Error(`Data-flow validation failed:\n${t.join(`
|
|
45
|
+
`)}`);let n=e.meta.viewBox??M.defaultViewBox;function r(e){return M.leftX+e*M.colGap}let i=new Map;for(let t of e.nodes){let e=t.width??M.nodeW,n=t.height??M.nodeH,a=r(t.stage),o=M.rowYs[t.row]+(t.yOffset??0);i.set(t.id,{...t,width:e,height:n,cx:a,cy:o+n/2,x:a-e/2,y:o})}let a=[];a.push(`<svg viewBox="0 0 ${n[0]} ${n[1]}" role="img" aria-label="${x(e.meta.title)}">`),a.push(j()),a.push(`<rect width="100%" height="100%" fill="url(#grid)"/>`);let o=n[1]-M.stageY-M.stageBottomPad;for(let t=0;t<e.stages.length;t++){let n=r(t),i=n-M.stageW/2;a.push(`<rect x="${i}" y="${M.stageY}" width="${M.stageW}" height="${o}" rx="10" fill="var(--lane-fill)" stroke="var(--lane-stroke)" stroke-width="1"/>`,`<text x="${n}" y="${M.stageY+22}" class="t-dim" font-size="9" font-weight="600" text-anchor="middle">${String(t+1).padStart(2,`0`)} / ${x(e.stages[t].label)}</text>`)}for(let t of e.flows){let e=i.get(t.from),n=i.get(t.to);if(!e||!n)continue;let r=C(e,E(t.fromSide,w(e,n))),o=C(n,E(t.toSide,T(e,n))),s=r.x+(o.x-r.x)/2,c=[r,...t.route===`vertical-channel`?[{x:t.channelX??r.x+44,y:r.y},{x:t.channelX??r.x+44,y:o.y}]:Math.abs(r.y-o.y)<4?[r,o]:[{x:s,y:r.y},{x:s,y:o.y}],o],[l,u]=A[t.variant??`default`]??A.default,d=t.variant===`emphasis`||t.variant===`animated`?1.8:1.4;a.push(`<path d="${D(c)}" class="${l}" stroke-width="${d}" marker-end="url(#${u})"/>`);let f={x:(r.x+o.x)/2+(t.labelDx??0),y:(r.y+o.y)/2-10+(t.labelDy??0)},p=Math.max(S(t.label),S(t.classification??``)),m=Math.max(34,p*4.9+12),h=t.classification?27:M.labelH;a.push(`<rect x="${f.x-m/2}" y="${f.y-11}" width="${m}" height="${h}" rx="4" class="c-mask"/>`),a.push(`<text x="${f.x}" y="${f.y}" class="t-muted" font-size="8" text-anchor="middle">${x(t.label)}</text>`),t.classification&&a.push(`<text x="${f.x}" y="${f.y+11}" class="t-dim" font-size="7" text-anchor="middle">${x(t.classification)}</text>`)}let s={};for(let e of i.values()){let t=k[e.type]??`c-external`,n=e.tag?`\n <text x="${e.cx}" y="${e.y+e.height-11}" class="t-muted" font-size="7" text-anchor="middle">${x(e.tag)}</text>`:``;a.push(`<g class="node" data-k="${x(e.id)}">`),a.push(`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="6" class="c-mask"/>`,`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="6" class="${t}" stroke-width="1.5"/>`,`<text x="${e.cx}" y="${e.y+21}" class="t-primary" font-size="10" font-weight="600" text-anchor="middle">${x(e.label)}</text>`,`<text x="${e.cx}" y="${e.y+37}" class="t-muted" font-size="7" text-anchor="middle">${x(e.sublabel??``)}</text>${n}`),a.push(`</g>`);let r=e.type.charAt(0).toUpperCase()+e.type.slice(1);s[e.id]={t:x(e.label),m:r,b:`${x(e.label)} (${r})`}}let c=n[1]-36;a.push(`<text x="40" y="${c-20}" class="t-primary" font-size="10" font-weight="600">Legend</text>`);let l=[[`M`,`a-emphasis`,`arrowhead-emphasis`,`primary data`],[`M`,`a-security`,`arrowhead-security`,`policy / PII`],[`M`,`a-dashed`,`arrowhead-dashed`,`async batch`]],u=40;for(let[,e,,t]of l){let n=t===`primary data`?`arrowhead-emphasis`:t===`policy / PII`?`arrowhead-security`:`arrowhead-dashed`;a.push(`<path d="M ${u} ${c} L ${u+34} ${c}" class="${e}" stroke-width="1.4" marker-end="url(#${n})"/>`),a.push(`<text x="${u+40}" y="${c+3}" class="t-muted" font-size="8">${t}</text>`),u+=130}a.push(`</svg>`);let d=ue(e.cards);return{svg:a.join(`
|
|
46
|
+
`),cardsHtml:d,detailData:s}}function le(e){let t=[];e.schema_version!==1&&t.push(`schema_version must be 1`),e.meta?.title||t.push(`meta.title required`),(!e.stages?.length||e.stages.length<2)&&t.push(`Need at least 2 stages`),e.nodes?.length||t.push(`At least one node required`);let n=new Set(e.nodes?.map(e=>e.id));for(let r of e.flows??[])n.has(r.from)||t.push(`Flow references unknown source "${r.from}"`),n.has(r.to)||t.push(`Flow references unknown target "${r.to}"`);return t}function ue(e){return e?.length?e.map(e=>`<div class="card"><div class="card-header"><div class="card-dot ${x(e.dot)}"></div><h3>${x(e.title)}</h3></div><ul>${e.items.map(e=>`<li>• ${x(e)}</li>`).join(``)}</ul></div>`).join(`
|
|
47
|
+
`):``}const N={phaseY:126,eventY:278,outcomeY:450,phaseW:118,phaseH:62,eventW:126,eventH:58,outcomeW:118,outcomeH:58,phaseXs:[94,248,402,556,710],eventXs:[402,556,710],outcomeXs:[402,556,710],defaultViewBox:[980,660]},de={start:`c-frontend`,active:`c-backend`,waiting:`c-cloud`,decision:`c-security`,success:`c-database`,failure:`c-security`,neutral:`c-external`,external:`c-external`};function P(e){let t=F(e);if(t.length>0)throw Error(`Lifecycle validation failed:\n${t.join(`
|
|
48
|
+
`)}`);let n=e.meta.viewBox??N.defaultViewBox;function r(e){return e===`main`?`phase`:e===`terminal`?`outcome`:`event`}let i=new Map;for(let t of e.states){let e=r(t.lane),n=e===`phase`,a=e===`outcome`,o=t.width??(n?N.phaseW:a?N.outcomeW:N.eventW),s=t.height??(n?N.phaseH:a?N.outcomeH:N.eventH),c=n?N.phaseXs:a?N.outcomeXs:N.eventXs,l=c[t.col]??c[c.length-1],u=(n?N.phaseY:a?N.outcomeY:N.eventY)+(t.yOffset??0);i.set(t.id,{...t,width:o,height:s,x:l-o/2,y:u,cx:l,cy:u+s/2})}let a=[];a.push(`<svg viewBox="0 0 ${n[0]} ${n[1]}" role="img" aria-label="${x(e.meta.title)}">`),a.push(j()),a.push(`<rect width="100%" height="100%" fill="url(#grid)"/>`);let o=n[0]-72,s=e.lanes.find(e=>e.id===`main`),c=e.lanes.find(e=>e.id===`terminal`),l=e.lanes.filter(e=>e.id!==`main`&&e.id!==`terminal`),u=[s?.label??`Lifecycle phases`,l.length?l.map(e=>e.label).join(` + `):`Interruptions`,c?.label??`Outcomes`],d=[112,264,436];for(let e=0;e<3;e++)a.push(`<path d="M 72 ${d[e]} L ${o} ${d[e]}" class="a-default" stroke-width="0.8" stroke-dasharray="3,8"/>`),a.push(`<text x="72" y="${d[e]-12}" class="t-dim" font-size="10" font-weight="600">${String(e+1).padStart(2,`0`)} / ${x(u[e])}</text>`);for(let t of e.transitions){let e=i.get(t.from),n=i.get(t.to);if(!e||!n)continue;let r=C(e,E(t.fromSide,w(e,n))),o=C(n,E(t.toSide,T(e,n))),s=(r.y+o.y)/2,c=[];c=(t.route??`auto`)===`straight`||e.lane===n.lane?[]:[{x:r.x,y:s},{x:o.x,y:s}];let l=[r,...c,o],[u,d]=A[t.variant??`default`]??A.default,f=t.variant===`emphasis`||t.variant===`animated`?2:1.1,p=O(l,t.cornerRadius??10);a.push(`<path d="${p}" class="${u}" stroke-width="${f}" marker-end="url(#${d})"/>`)}let f={};for(let e of i.values()){let t=de[e.type]??`c-external`,n=e.step?`\n <text x="${e.x+10}" y="${e.y+14}" class="t-muted" font-size="7" font-weight="700">${x(e.step)}</text>`:``,r=e.tag?`\n <text x="${e.cx}" y="${e.y+e.height-11}" class="t-muted" font-size="7" text-anchor="middle">${x(e.tag)}</text>`:``;a.push(`<g class="node" data-k="${x(e.id)}">`),a.push(`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="7" class="c-mask"/>`,`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="7" class="${t}" stroke-width="1.5"/>${n}`,`<text x="${e.cx}" y="${e.y+21}" class="t-primary" font-size="10" font-weight="600" text-anchor="middle">${x(e.label)}</text>`,`<text x="${e.cx}" y="${e.y+37}" class="t-muted" font-size="7" text-anchor="middle">${x(e.sublabel??``)}</text>${r}`),a.push(`</g>`);let i=e.type.charAt(0).toUpperCase()+e.type.slice(1);f[e.id]={t:x(e.label),m:i,b:`${x(e.label)} (${i})`}}let p=n[1]-98;a.push(`<text x="40" y="${p-20}" class="t-primary" font-size="10" font-weight="600">Legend</text>`);let m=[[`c-backend`,`active state`],[`c-cloud`,`waiting`],[`c-database`,`terminal success`],[`c-security`,`failure / exit`]],h=40;for(let[e,t]of m)a.push(`<rect x="${h}" y="${p-8}" width="14" height="9" rx="2" class="${e}" stroke-width="1"/><text x="${h+20}" y="${p}" class="t-muted" font-size="7">${t}</text>`),h+=110;a.push(`</svg>`);let g=I(e.cards);return{svg:a.join(`
|
|
49
|
+
`),cardsHtml:g,detailData:f}}function F(e){let t=[];e.schema_version!==1&&t.push(`schema_version must be 1`),e.meta?.title||t.push(`meta.title required`),e.lanes?.length||t.push(`At least one lane required`),(!e.states?.length||e.states.length<2)&&t.push(`Need at least 2 states`),e.lanes.some(e=>e.id===`main`)||t.push(`Need a lane with id "main"`);let n=new Set(e.states?.map(e=>e.id));for(let r of e.transitions??[])n.has(r.from)||t.push(`Transition references unknown source "${r.from}"`),n.has(r.to)||t.push(`Transition references unknown target "${r.to}"`);return t}function I(e){return e?.length?e.map(e=>`<div class="card"><div class="card-header"><div class="card-dot ${x(e.dot)}"></div><h3>${x(e.title)}</h3></div><ul>${e.items.map(e=>`<li>• ${x(e)}</li>`).join(``)}</ul></div>`).join(`
|
|
50
|
+
`):``}const L={topY:72,participantW:86,participantH:54,lifelineTop:142,legendY:0,leftX:62,colGap:108,labelH:16,defaultViewBox:[920,760]};function R(e){let t=z(e);if(t.length>0)throw Error(`Sequence validation failed:\n${t.join(`
|
|
51
|
+
`)}`);let n=e.meta.viewBox??L.defaultViewBox;L.legendY=n[1]-54,L.lifelineTop=142;let r=n[1]-65,i=new Map(e.participants.map((e,t)=>[e.id,{...e,index:t,cx:L.leftX+t*L.colGap}])),a=[];if(a.push(`<svg viewBox="0 0 ${n[0]} ${n[1]}" role="img" aria-label="${x(e.meta.title)}">`),a.push(j()),a.push(`<rect width="100%" height="100%" fill="url(#grid)"/>`),e.segments)for(let t of e.segments)a.push(`<rect x="48" y="${t.from}" width="${n[0]-96}" height="${t.to-t.from}" rx="10" fill="var(--lane-fill)" stroke="var(--lane-stroke)" stroke-width="1"/>`,`<text x="62" y="${t.from+18}" class="t-dim" font-size="9" font-weight="600">${x(t.label)}</text>`);for(let e of i.values())a.push(`<path d="M ${e.cx} ${L.lifelineTop} L ${e.cx} ${r}" class="a-default" stroke-width="0.8" stroke-dasharray="3,7"/>`);let o={...A,return:[`a-default`,`arrowhead`]};for(let t of e.messages){let e=i.get(t.from),n=i.get(t.to);if(!e||!n)continue;let r=n.cx>e.cx?1:-1,s=e.cx+r*7,c=n.cx-r*7,l=t.variant??`default`,[u,d]=o[l]??o.default,f=l===`emphasis`?1.8:1.4,p=l===`return`||l===`dashed`?` stroke-dasharray="3,5"`:``;a.push(`<path d="M ${s} ${t.y} L ${c} ${t.y}" class="${u}" stroke-width="${f}"${p} marker-end="url(#${d})"/>`);let m=(s+c)/2,h=Math.max(34,S(t.label)*5.2+12),g=l===`security`?`t-security`:l===`dashed`?`t-messagebus`:l===`return`?`t-muted`:`t-backend`;a.push(`<rect x="${m-h/2}" y="${t.y-20}" width="${h}" height="${L.labelH}" rx="3" class="c-mask"/>`),a.push(`<text x="${m}" y="${t.y-10}" class="${g}" font-size="9" text-anchor="middle">${x(t.label)}</text>`),t.note&&a.push(`<text x="${Math.min(s,c)+12}" y="${t.y+18}" class="t-dim" font-size="7">${x(t.note)}</text>`)}if(e.activations)for(let t of e.activations){let e=i.get(t.participant);if(!e)continue;let n=k[t.type]??`c-external`,r=e.cx-5,o=t.to-t.from;a.push(`<rect x="${r}" y="${t.from}" width="10" height="${o}" rx="3" class="c-mask"/>`,`<rect x="${r}" y="${t.from}" width="10" height="${o}" rx="3" class="${n}" stroke-width="1"/>`)}let s={};for(let e of i.values()){let t=e.cx-L.participantW/2,n=k[e.type]??`c-external`;a.push(`<g class="node" data-k="${x(e.id)}">`),a.push(`<rect x="${t}" y="${L.topY}" width="${L.participantW}" height="${L.participantH}" rx="6" class="c-mask"/>`,`<rect x="${t}" y="${L.topY}" width="${L.participantW}" height="${L.participantH}" rx="6" class="${n}" stroke-width="1.5"/>`,`<text x="${e.cx}" y="${L.topY+22}" class="t-primary" font-size="11" font-weight="600" text-anchor="middle">${x(e.label)}</text>`,e.sublabel?`<text x="${e.cx}" y="${L.topY+39}" class="t-muted" font-size="7" text-anchor="middle">${x(e.sublabel)}</text>`:``),a.push(`</g>`);let r=e.type.charAt(0).toUpperCase()+e.type.slice(1);s[e.id]={t:x(e.label),m:r,b:`${x(e.label)} (${r})`}}let c=L.legendY;a.push(`<text x="40" y="${c-20}" class="t-primary" font-size="10" font-weight="600">Legend</text>`);let l=[[`M`,`a-emphasis`,`arrowhead-emphasis`,`request`],[`M`,`a-default`,`arrowhead`,`return`],[`M`,`a-security`,`arrowhead-security`,`security`],[`M`,`a-dashed`,`arrowhead-dashed`,`async trace`]],u=40;for(let[,e,,t]of l){let n=t===`return`?` stroke-dasharray="3,5"`:``;a.push(`<path d="M ${u} ${c} L ${u+34} ${c}" class="${e}" stroke-width="1.4"${n} marker-end="url(#${t===`request`?`arrowhead-emphasis`:t===`return`?`arrowhead`:t===`security`?`arrowhead-security`:`arrowhead-dashed`})"/>`),a.push(`<text x="${u+40}" y="${c+3}" class="t-muted" font-size="8">${t}</text>`),u+=120}a.push(`</svg>`);let d=B(e.cards);return{svg:a.join(`
|
|
52
|
+
`),cardsHtml:d,detailData:s}}function z(e){let t=[];e.schema_version!==1&&t.push(`schema_version must be 1`),e.meta?.title||t.push(`meta.title required`),(!e.participants?.length||e.participants.length<2)&&t.push(`Need at least 2 participants`),e.messages?.length||t.push(`At least one message required`);let n=new Set(e.participants?.map(e=>e.id));for(let r of e.messages??[])n.has(r.from)||t.push(`Message references unknown source "${r.from}"`),n.has(r.to)||t.push(`Message references unknown target "${r.to}"`);return t}function B(e){return e?.length?e.map(e=>`<div class="card"><div class="card-header"><div class="card-dot ${x(e.dot)}"></div><h3>${x(e.title)}</h3></div><ul>${e.items.map(e=>`<li>• ${x(e)}</li>`).join(``)}</ul></div>`).join(`
|
|
53
|
+
`):``}const V={laneX:40,laneY:52,laneW:640,laneH:104,laneGap:20,laneTitleH:30,colXs:[88,220,300,430,500,625],nodeW:92,nodeH:52,defaultViewBox:[720,600]};function H(e){let t=fe(e);if(t.length>0)throw Error(`Workflow validation failed:\n${t.join(`
|
|
54
|
+
`)}`);let n=new Map(e.lanes.map((e,t)=>[e.id,t]));function r(e){return V.laneY+(n.get(e)??0)*(V.laneH+V.laneGap)}function i(){return V.laneY+e.lanes.length*V.laneH+(e.lanes.length-1)*V.laneGap}let a=new Map;for(let t of e.nodes){let e=t.width??V.nodeW,n=t.height??(t.tag?68:V.nodeH),i=V.colXs[t.col],o=V.laneH-V.laneTitleH,s=r(t.lane)+V.laneTitleH+(o-n)/2+(t.yOffset??0);a.set(t.id,{...t,width:e,height:n,x:i-e/2,y:s,cx:i,cy:s+n/2})}let o=V.laneY+e.lanes.length*V.laneH+(e.lanes.length-1)*V.laneGap+124,s=e.meta.viewBox??[V.defaultViewBox[0],o],c=[];c.push(`<svg viewBox="0 0 ${s[0]} ${s[1]}" role="img" aria-label="${x(e.meta.title)}">`),c.push(j()),c.push(`<rect width="100%" height="100%" fill="url(#grid)"/>`);for(let t=0;t<e.lanes.length;t++){let n=V.laneY+t*(V.laneH+V.laneGap);c.push(`<rect x="${V.laneX}" y="${n}" width="${V.laneW}" height="${V.laneH}" rx="10" class="c-lane" fill="var(--lane-fill)" stroke="var(--lane-stroke)" stroke-width="1"/>`),c.push(`<text x="${V.laneX+14}" y="${n+22}" class="t-dim" font-size="10" font-weight="600">${String(t+1).padStart(2,`0`)} / ${x(e.lanes[t].label)}</text>`)}let l=new Map;function u(e){let t=`${e.from}->${e.to}`;if(l.has(t))return l.get(t);let n=a.get(e.from),i=a.get(e.to),o=e=>({x:e.x,y:e.y,width:e.width,height:e.height}),s=C(o(n),E(e.fromSide,w(o(n),o(i)))),c=C(o(i),E(e.toSide,T(o(n),o(i)))),u=[];if(e.via)u=e.via;else{let t=e.route??`auto`;if(t===`straight`)u=[];else if(t===`drop`||t===`auto`&&n.lane!==i.lane){let t=r(n.lane)+V.laneH,a=t+(r(i.lane)-t)*(e.bias??.5);u=[{x:s.x,y:a},{x:c.x,y:a}]}else if(t===`outside-right`){let t=e.channelX??V.laneX+V.laneW+12;u=[{x:t,y:s.y},{x:t,y:c.y}]}else if(t===`return-left`){let t=e.channelX??Math.min(n.x,i.x)-28;u=[{x:t,y:s.y},{x:t,y:c.y}]}else if(t===`bottom-channel`){let t=e.channelY??Math.max(n.y+n.height,i.y+i.height)+32;u=[{x:s.x,y:t},{x:c.x,y:t}]}}let d=[s,...u,c],f={d:D(d),points:d};return l.set(t,f),f}for(let t of e.edges){let e=a.get(t.from),n=a.get(t.to);if(!e||!n)continue;let[r,i]=A[t.variant??`default`]??A.default,o=u(t),s=t.variant===`emphasis`||t.variant===`animated`?1.8:1.4;c.push(`<path d="${o.d}" class="${r}" stroke-width="${s}" marker-end="url(#${i})"/>`)}let d={};for(let e of a.values()){let t=k[e.type]??`c-external`,n=e.tag?`\n <text x="${e.cx}" y="${e.y+e.height-12}" class="t-muted" font-size="7" text-anchor="middle">${x(e.tag)}</text>`:``;c.push(`<g class="node" data-k="${x(e.id)}">`),c.push(`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="6" class="c-mask"/>`,`<rect x="${e.x}" y="${e.y}" width="${e.width}" height="${e.height}" rx="6" class="${t}" stroke-width="1.5"/>`,`<text x="${e.cx}" y="${e.y+21}" class="t-primary" font-size="11" font-weight="600" text-anchor="middle">${x(e.label)}</text>`,`<text x="${e.cx}" y="${e.y+38}" class="t-muted" font-size="8" text-anchor="middle">${x(e.sublabel??``)}</text>${n}`),c.push(`</g>`);let r=e.type.charAt(0).toUpperCase()+e.type.slice(1);d[e.id]={t:x(e.label),m:`${r}`,b:`${x(e.label)} (${r})`}}for(let t of e.edges){if(!t.label)continue;let e=u(t),n={x:(e.points[0].x+e.points[e.points.length-1].x)/2+(t.labelDx??0),y:e.points[0].y-10+(t.labelDy??0)},r=Math.max(30,S(t.label)*4.8+10);c.push(`<rect x="${n.x-r/2}" y="${n.y-10}" width="${r}" height="14" rx="3" class="c-mask"/>`),c.push(`<text x="${n.x}" y="${n.y}" class="t-muted" font-size="8" text-anchor="middle">${x(t.label)}</text>`)}let f=i()+44;c.push(`<text x="40" y="${f}" class="t-primary" font-size="10" font-weight="600">Legend</text>`);let p=[[`c-frontend`,`User UI`,``],[`c-backend`,`Agent logic`,``],[`c-security`,`Policy`,``],[`c-messagebus`,`Tool action`,``],[`c-database`,`Context / trace`,``]],m=40;for(let[e,t]of p)c.push(`<rect x="${m}" y="${f+14}" width="14" height="9" rx="2" class="${e}" stroke-width="1"/><text x="${m+20}" y="${f+22}" class="t-muted" font-size="7">${t}</text>`),m+=80;c.push(`</svg>`);let h=pe(e.cards);return{svg:c.join(`
|
|
55
|
+
`),cardsHtml:h,detailData:d}}function fe(e){let t=[];e.schema_version!==1&&t.push(`schema_version must be 1`),e.meta?.title||t.push(`meta.title required`),e.lanes?.length||t.push(`At least one lane required`),e.nodes?.length||t.push(`At least one node required`),e.edges?.length||t.push(`At least one edge required`);let n=new Set(e.lanes?.map(e=>e.id)),r=new Set(e.nodes?.map(e=>e.id));r.size!==e.nodes?.length&&t.push(`Node IDs must be unique`);for(let r of e.nodes??[])n.has(r.lane)||t.push(`Node "${r.id}" uses unknown lane "${r.lane}"`),(r.col<0||r.col>=V.colXs.length)&&t.push(`Node "${r.id}" column ${r.col} out of range 0-${V.colXs.length-1}`);for(let n of e.edges??[])r.has(n.from)||t.push(`Edge references unknown source "${n.from}"`),r.has(n.to)||t.push(`Edge references unknown target "${n.to}"`);return t}function pe(e){return e?.length?e.map(e=>`<div class="card"><div class="card-header"><div class="card-dot ${x(e.dot)}"></div><h3>${x(e.title)}</h3></div><ul>${e.items.map(e=>`<li>• ${x(e)}</li>`).join(``)}</ul></div>`).join(`
|
|
56
|
+
`):``}function me(){return`<!DOCTYPE html>
|
|
57
57
|
<html lang="en" data-theme="dark"[PALETTE]>
|
|
58
58
|
<head>
|
|
59
59
|
<meta charset="UTF-8">
|
|
60
60
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
61
61
|
<meta name="generator" content="aikit-diagram 1.0">
|
|
62
62
|
<title>[TITLE]</title>
|
|
63
|
-
<script>
|
|
63
|
+
<script>
|
|
64
|
+
// Apply-before-paint: URL param > localStorage > prefers-color-scheme
|
|
65
|
+
// Runs synchronously in <head> — zero flash, no FOUC.
|
|
66
|
+
(function(){var t=null;try{var p=new URLSearchParams(location.search).get('theme');if(p==='light'||p==='dark')t=p}catch(_){}if(!t){try{t=localStorage.getItem('aikit-diagram-theme')}catch(_){}}if(t!=='light'&&t!=='dark')t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light';document.documentElement.setAttribute('data-theme',t)})();
|
|
67
|
+
<\/script>
|
|
64
68
|
<style>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
--
|
|
71
|
-
--
|
|
72
|
-
--
|
|
73
|
-
--security-fill:rgba(136,19,55,0.4);--security-stroke:#fb7185;
|
|
74
|
-
--messagebus-fill:rgba(251,146,60,0.3);--messagebus-stroke:#fb923c;
|
|
75
|
-
--external-fill:rgba(30,41,59,0.5);--external-stroke:#94a3b8;
|
|
76
|
-
--toolbar-bg:rgba(15,23,42,0.8);--toolbar-border:#334155;--toolbar-text:#e2e8f0;--toolbar-hover:rgba(15,23,42,0.95);--toolbar-menu-bg:#0f172a;
|
|
69
|
+
/* ═══════════════════════════════════════════════
|
|
70
|
+
Design Tokens — warm semantic palette
|
|
71
|
+
Inspired by effective-html's clay/olive/oat system
|
|
72
|
+
═══════════════════════════════════════════════ */
|
|
73
|
+
:root {
|
|
74
|
+
--serif: ui-serif, Georgia, "Times New Roman", serif;
|
|
75
|
+
--sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
76
|
+
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
|
|
77
77
|
}
|
|
78
|
-
[data-theme="
|
|
79
|
-
|
|
80
|
-
--
|
|
81
|
-
|
|
82
|
-
--
|
|
83
|
-
|
|
84
|
-
--
|
|
85
|
-
|
|
86
|
-
--
|
|
87
|
-
--
|
|
88
|
-
--
|
|
89
|
-
|
|
78
|
+
:root,[data-theme="dark"] {
|
|
79
|
+
/* Chrome — 3-level background hierarchy */
|
|
80
|
+
--bg: #141413; --surface: #1F1F1D; --surface2: #2A2A28;
|
|
81
|
+
/* Text — contrast cascade */
|
|
82
|
+
--ink: #FAF9F5; --body: #D1CFC5; --muted: #87867F; --dim: #57534E;
|
|
83
|
+
/* Borders */
|
|
84
|
+
--line: #3D3D3A; --line-soft: #2A2A28;
|
|
85
|
+
/* Brand accents — warm earth tones */
|
|
86
|
+
--clay: #E48A6E; --clay-soft: rgba(228,138,110,0.14);
|
|
87
|
+
--olive: #9DB07C; --olive-soft: rgba(157,176,124,0.16);
|
|
88
|
+
--gold: #D4B36F; --blue: #7FA3BC;
|
|
89
|
+
/* Diagram chrome */
|
|
90
|
+
--panel: rgba(31,31,29,0.5); --panel-border: #3D3D3A;
|
|
91
|
+
--lane-fill: rgba(31,31,29,0.22); --lane-stroke: #57534E;
|
|
92
|
+
--arrow: #87867F; --arrow-emphasis: #E48A6E; --mask: #1F1F1D;
|
|
93
|
+
/* Component fills — semantic type colors */
|
|
94
|
+
--c-frontend-fill: rgba(228,138,110,0.20); --c-frontend-stroke: #E48A6E;
|
|
95
|
+
--c-backend-fill: rgba(157,176,124,0.20); --c-backend-stroke: #9DB07C;
|
|
96
|
+
--c-database-fill: rgba(127,163,188,0.20); --c-database-stroke: #7FA3BC;
|
|
97
|
+
--c-cloud-fill: rgba(212,179,111,0.18); --c-cloud-stroke: #D4B36F;
|
|
98
|
+
--c-security-fill: rgba(248,113,113,0.18); --c-security-stroke: #f87171;
|
|
99
|
+
--c-messagebus-fill: rgba(251,146,60,0.18);--c-messagebus-stroke: #fb923c;
|
|
100
|
+
--c-external-fill: rgba(135,134,127,0.18); --c-external-stroke: #87867F;
|
|
101
|
+
/* Toolbar */
|
|
102
|
+
--toolbar-bg: rgba(31,31,29,0.9); --toolbar-border: #3D3D3A;
|
|
103
|
+
--toolbar-text: #D1CFC5; --toolbar-hover: rgba(42,42,40,0.95);
|
|
104
|
+
--toolbar-menu-bg: #1F1F1D;
|
|
90
105
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
--
|
|
94
|
-
--
|
|
95
|
-
--
|
|
96
|
-
--
|
|
97
|
-
--
|
|
98
|
-
--
|
|
99
|
-
--
|
|
100
|
-
--
|
|
101
|
-
--
|
|
102
|
-
--
|
|
103
|
-
--
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
--
|
|
107
|
-
--
|
|
108
|
-
--
|
|
109
|
-
--
|
|
110
|
-
--
|
|
111
|
-
--database-fill:rgba(168,162,158,0.2);--database-stroke:#78716c;
|
|
112
|
-
--cloud-fill:rgba(245,158,11,0.15);--cloud-stroke:#d97706;
|
|
113
|
-
--security-fill:rgba(239,68,68,0.12);--security-stroke:#dc2626;
|
|
114
|
-
--messagebus-fill:rgba(234,88,12,0.12);--messagebus-stroke:#c2410c;
|
|
115
|
-
--external-fill:rgba(120,113,108,0.15);--external-stroke:#78716c;
|
|
116
|
-
--toolbar-bg:rgba(255,255,255,0.92);--toolbar-border:#d6d3d1;--toolbar-text:#44403c;--toolbar-hover:#fff;--toolbar-menu-bg:#fff;
|
|
106
|
+
[data-theme="light"] {
|
|
107
|
+
--bg: #FAF9F5; --surface: #FFFFFF; --surface2: #F0EEE6;
|
|
108
|
+
--ink: #141413; --body: #3D3D3A; --muted: #87867F; --dim: #A8A29E;
|
|
109
|
+
--line: #D1CFC5; --line-soft: #E6E3DA;
|
|
110
|
+
--clay: #D97757; --clay-soft: rgba(217,119,87,0.10);
|
|
111
|
+
--olive: #788C5D; --olive-soft: rgba(120,140,93,0.12);
|
|
112
|
+
--gold: #C9A45C; --blue: #5B7E96;
|
|
113
|
+
--panel: rgba(255,255,255,0.5); --panel-border: #D1CFC5;
|
|
114
|
+
--lane-fill: rgba(250,249,245,0.65); --lane-stroke: #D1CFC5;
|
|
115
|
+
--arrow: #87867F; --arrow-emphasis: #D97757; --mask: #FFFFFF;
|
|
116
|
+
--c-frontend-fill: rgba(217,119,87,0.12); --c-frontend-stroke: #D97757;
|
|
117
|
+
--c-backend-fill: rgba(120,140,93,0.15); --c-backend-stroke: #788C5D;
|
|
118
|
+
--c-database-fill: rgba(91,126,150,0.18); --c-database-stroke: #5B7E96;
|
|
119
|
+
--c-cloud-fill: rgba(201,164,92,0.18); --c-cloud-stroke: #C9A45C;
|
|
120
|
+
--c-security-fill: rgba(239,68,68,0.12); --c-security-stroke: #ef4444;
|
|
121
|
+
--c-messagebus-fill: rgba(234,88,12,0.12);--c-messagebus-stroke: #ea580c;
|
|
122
|
+
--c-external-fill: rgba(135,134,127,0.15);--c-external-stroke: #87867F;
|
|
123
|
+
--toolbar-bg: rgba(255,255,255,0.92); --toolbar-border: #D1CFC5;
|
|
124
|
+
--toolbar-text: #3D3D3A; --toolbar-hover: #FFFFFF;
|
|
125
|
+
--toolbar-menu-bg: #FFFFFF;
|
|
117
126
|
}
|
|
127
|
+
/* ═══════════════════════════════════════════════
|
|
128
|
+
Base + Reset
|
|
129
|
+
═══════════════════════════════════════════════ */
|
|
118
130
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
131
|
+
html{scroll-behavior:smooth}
|
|
132
|
+
body{
|
|
133
|
+
font-family:var(--sans);background:var(--bg);min-height:100vh;
|
|
134
|
+
padding:1.5rem;color:var(--body);-webkit-font-smoothing:antialiased;
|
|
135
|
+
transition:background .2s ease,color .2s ease
|
|
136
|
+
}
|
|
137
|
+
.container{max-width:1200px;margin:0 auto}
|
|
138
|
+
|
|
139
|
+
/* Typography */
|
|
140
|
+
h1{font-family:var(--serif);font-size:1.75rem;font-weight:500;margin-bottom:.2rem;color:var(--ink);letter-spacing:-0.01em}
|
|
141
|
+
.subtitle{font-family:var(--sans);font-size:.85rem;color:var(--muted);margin-bottom:1.5rem}
|
|
142
|
+
svg .t-primary{fill:var(--ink)}
|
|
143
|
+
svg .t-muted{fill:var(--muted)}
|
|
144
|
+
svg .t-dim{fill:var(--dim)}
|
|
145
|
+
svg .subtitle-text{fill:var(--muted)}
|
|
146
|
+
svg .edge-label{fill:var(--muted)}
|
|
147
|
+
/* Line/edge fills must reference arrow var for dark mode compat */
|
|
148
|
+
svg .c-grid{stroke:var(--line-soft)}
|
|
149
|
+
svg .m-default{fill:var(--arrow)}
|
|
150
|
+
svg .m-emphasis{fill:var(--arrow-emphasis)}
|
|
151
|
+
svg .m-security{fill:var(--c-security-stroke)}
|
|
152
|
+
svg .m-dashed{fill:var(--arrow)}
|
|
153
|
+
svg .c-mask{fill:var(--mask)}
|
|
154
|
+
|
|
155
|
+
/* ═══════════════════════════════════════════════
|
|
156
|
+
Animations
|
|
157
|
+
═══════════════════════════════════════════════ */
|
|
119
158
|
@keyframes flow-dash{to{stroke-dashoffset:-20}}
|
|
120
159
|
@keyframes march-ants{0%{stroke-dashoffset:0}100%{stroke-dashoffset:-40}}
|
|
160
|
+
@keyframes march{to{stroke-dashoffset:-12}}
|
|
121
161
|
.a-animated{stroke-dasharray:6 4;animation:flow-dash .6s linear infinite}
|
|
122
|
-
.a-marching-ants{stroke-dasharray:8 4;animation:march-ants .8s linear infinite;stroke-width:2.5!important;stroke
|
|
123
|
-
|
|
124
|
-
.
|
|
125
|
-
|
|
126
|
-
.
|
|
127
|
-
.
|
|
128
|
-
.
|
|
162
|
+
.a-marching-ants{stroke-dasharray:8 4;animation:march-ants .8s linear infinite;stroke-width:2.5!important;stroke:var(--arrow-emphasis)!important}
|
|
163
|
+
/* Flow spotlight — dim inactive, highlight lit paths */
|
|
164
|
+
.stage-flowing .edge{opacity:.13}.stage-flowing .edge-label{opacity:.13}
|
|
165
|
+
.stage-flowing .node{opacity:.30}.stage-flowing .zone{opacity:.45}
|
|
166
|
+
.stage-flowing .edge.lit{opacity:1;stroke:var(--clay);marker-end:url(#arrowhead-emphasis);stroke-dasharray:7 5;animation:march .9s linear infinite}
|
|
167
|
+
.stage-flowing .node.lit{opacity:1}.stage-flowing .zone.lit{opacity:1}
|
|
168
|
+
.stage-flowing .edge-label.lit{opacity:1;fill:var(--clay)}
|
|
169
|
+
|
|
170
|
+
@media (prefers-reduced-motion:reduce){
|
|
171
|
+
html{scroll-behavior:auto}
|
|
172
|
+
*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
|
|
173
|
+
.stage-flowing .edge.lit{animation:none}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* ═══════════════════════════════════════════════
|
|
177
|
+
Toolbar
|
|
178
|
+
═══════════════════════════════════════════════ */
|
|
179
|
+
.toolbar{
|
|
180
|
+
position:fixed;top:.5rem;right:.5rem;z-index:100;
|
|
181
|
+
display:flex;gap:.25rem;font-family:var(--mono)
|
|
182
|
+
}
|
|
183
|
+
.toolbar .chip{
|
|
184
|
+
background:var(--toolbar-bg);border:1px solid var(--toolbar-border);
|
|
185
|
+
color:var(--toolbar-text);padding:.25rem .55rem;border-radius:999px;
|
|
186
|
+
cursor:pointer;font-size:.75rem;font-family:inherit;
|
|
187
|
+
backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
|
|
188
|
+
transition:all .15s ease;display:flex;align-items:center;gap:.3rem
|
|
189
|
+
}
|
|
129
190
|
.toolbar .chip:hover{background:var(--toolbar-hover)}
|
|
130
|
-
.toolbar .chip.active{background:var(--
|
|
191
|
+
.toolbar .chip.active{background:var(--clay);color:#fff;border-color:var(--clay)}
|
|
131
192
|
.toolbar .chip svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
|
|
132
|
-
.toolbar .menu{
|
|
193
|
+
.toolbar .menu{
|
|
194
|
+
position:absolute;top:100%;right:0;background:var(--toolbar-menu-bg);
|
|
195
|
+
border:1px solid var(--toolbar-border);border-radius:12px;
|
|
196
|
+
padding:.25rem 0;display:none;min-width:180px;
|
|
197
|
+
backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
|
|
198
|
+
box-shadow:0 8px 24px rgba(0,0,0,.3)
|
|
199
|
+
}
|
|
133
200
|
.toolbar .menu.show{display:block}
|
|
134
|
-
.toolbar .menu button{
|
|
201
|
+
.toolbar .menu button{
|
|
202
|
+
display:block;width:100%;text-align:left;background:0 0;
|
|
203
|
+
border:none;border-radius:0;color:var(--toolbar-text);
|
|
204
|
+
padding:.4rem .8rem;font-size:.8rem;font-family:inherit;cursor:pointer
|
|
205
|
+
}
|
|
135
206
|
.toolbar .menu button:hover{background:var(--toolbar-hover)}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
207
|
+
|
|
208
|
+
/* ═══════════════════════════════════════════════
|
|
209
|
+
SVG
|
|
210
|
+
═══════════════════════════════════════════════ */
|
|
211
|
+
svg{display:block;margin:0 auto;max-width:100%;height:auto}
|
|
212
|
+
svg text{fill:var(--body);font-family:var(--sans);font-size:12px}
|
|
213
|
+
/* Component type fills (from geometry.ts componentFill / arrowClassMap) */
|
|
214
|
+
.c-frontend{fill:var(--c-frontend-fill);stroke:var(--c-frontend-stroke)}
|
|
215
|
+
.c-backend{fill:var(--c-backend-fill);stroke:var(--c-backend-stroke)}
|
|
216
|
+
.c-database{fill:var(--c-database-fill);stroke:var(--c-database-stroke)}
|
|
217
|
+
.c-cloud{fill:var(--c-cloud-fill);stroke:var(--c-cloud-stroke)}
|
|
218
|
+
.c-security{fill:var(--c-security-fill);stroke:var(--c-security-stroke)}
|
|
219
|
+
.c-messagebus{fill:var(--c-messagebus-fill);stroke:var(--c-messagebus-stroke)}
|
|
220
|
+
.c-external{fill:var(--c-external-fill);stroke:var(--c-external-stroke)}
|
|
221
|
+
/* Edge classes */
|
|
222
|
+
.a-default{stroke:var(--arrow);fill:none;marker-end:url(#arrowhead)}
|
|
223
|
+
.a-emphasis{stroke:var(--arrow-emphasis);fill:none;marker-end:url(#arrowhead-emphasis)}
|
|
224
|
+
.a-security{stroke:var(--c-security-stroke);fill:none;marker-end:url(#arrowhead-security)}
|
|
225
|
+
.a-dashed{stroke:var(--arrow);fill:none;stroke-dasharray:5 4;marker-end:url(#arrowhead-dashed)}
|
|
226
|
+
|
|
227
|
+
/* ═══════════════════════════════════════════════
|
|
228
|
+
Cards
|
|
229
|
+
═══════════════════════════════════════════════ */
|
|
140
230
|
.card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1rem;margin-top:2rem}
|
|
141
231
|
.card{background:var(--panel);border:1px solid var(--panel-border);border-radius:8px;padding:1rem;break-inside:avoid}
|
|
142
|
-
.card h3{font-size:.9rem;margin-bottom:.4rem;font-weight:500;color:var(--
|
|
143
|
-
.card p{font-size:.8rem;color:var(--
|
|
144
|
-
.card code{font-size:.75rem;background:
|
|
145
|
-
.card .meta{font-size:.7rem;color:var(--
|
|
146
|
-
|
|
147
|
-
|
|
232
|
+
.card h3{font-family:var(--serif);font-size:.9rem;margin-bottom:.4rem;font-weight:500;color:var(--ink)}
|
|
233
|
+
.card p{font-size:.8rem;color:var(--muted);line-height:1.5}
|
|
234
|
+
.card code{font-size:.75rem;background:var(--surface2);padding:.1rem .3rem;border-radius:3px;font-family:var(--mono)}
|
|
235
|
+
.card .meta{font-size:.7rem;color:var(--dim);margin-top:.3rem}
|
|
236
|
+
|
|
237
|
+
/* ═══════════════════════════════════════════════
|
|
238
|
+
Legend
|
|
239
|
+
═══════════════════════════════════════════════ */
|
|
240
|
+
.legend{display:flex;flex-wrap:wrap;gap:.75rem;justify-content:center;margin:1.5rem 0;font-size:.75rem;font-family:var(--mono);color:var(--muted)}
|
|
241
|
+
.legend-item{display:flex;align-items:center;gap:.35rem}
|
|
148
242
|
.legend-swatch{width:12px;height:12px;border-radius:3px;border:1px solid}
|
|
243
|
+
|
|
244
|
+
/* ═══════════════════════════════════════════════
|
|
245
|
+
Interactive node system (optional — activate when data-k attrs present)
|
|
246
|
+
═══════════════════════════════════════════════ */
|
|
247
|
+
.node{cursor:pointer;transition:transform .12s ease}
|
|
248
|
+
.node:hover rect{filter:brightness(1.08)}
|
|
249
|
+
.node.sel rect{stroke:var(--clay)!important;stroke-width:2}
|
|
250
|
+
.node .mono{font-family:var(--mono);font-size:10px;fill:var(--muted)}
|
|
251
|
+
.node .kind{font-family:var(--mono);font-size:9px;letter-spacing:.08em;text-transform:uppercase;fill:var(--clay)}
|
|
252
|
+
|
|
253
|
+
/* Detail card — floating panel for node info */
|
|
254
|
+
.detail-card{
|
|
255
|
+
position:fixed;right:1rem;bottom:1rem;width:340px;max-width:calc(100vw - 2rem);
|
|
256
|
+
background:var(--surface);border:1px solid var(--line);border-radius:12px;
|
|
257
|
+
padding:1rem 1.25rem;box-shadow:0 8px 32px rgba(0,0,0,.15);
|
|
258
|
+
font-family:var(--sans);z-index:90;display:none;max-height:40vh;overflow-y:auto
|
|
259
|
+
}
|
|
260
|
+
.detail-card.show{display:block}
|
|
261
|
+
.detail-card h3{font-family:var(--serif);font-weight:500;font-size:1rem;color:var(--ink);margin-bottom:2px}
|
|
262
|
+
.detail-card .meta{font-family:var(--mono);font-size:.7rem;color:var(--muted);margin-bottom:8px}
|
|
263
|
+
.detail-card p{font-size:.8rem;line-height:1.55;color:var(--body)}
|
|
264
|
+
.detail-card p code{font-family:var(--mono);font-size:.75rem;color:var(--clay);background:var(--clay-soft);padding:1px 4px;border-radius:3px}
|
|
265
|
+
|
|
266
|
+
/* ═══════════════════════════════════════════════
|
|
267
|
+
Responsive
|
|
268
|
+
═══════════════════════════════════════════════ */
|
|
269
|
+
@media (max-width:880px){
|
|
270
|
+
body{padding:1rem;overflow:auto}
|
|
271
|
+
.toolbar{top:.35rem;right:.35rem}
|
|
272
|
+
.toolbar .chip{font-size:.7rem;padding:.2rem .45rem}
|
|
273
|
+
.container{overflow-x:auto}
|
|
274
|
+
h1{font-size:1.4rem}
|
|
275
|
+
.detail-card{position:static;width:auto;margin-top:1rem;max-height:none}
|
|
276
|
+
}
|
|
277
|
+
@media (max-width:480px){
|
|
278
|
+
body{padding:.75rem}
|
|
279
|
+
h1{font-size:1.2rem}
|
|
280
|
+
.card-grid{grid-template-columns:1fr}
|
|
281
|
+
}
|
|
149
282
|
</style>
|
|
150
283
|
</head>
|
|
151
284
|
<body>
|
|
152
|
-
<div class="toolbar">
|
|
153
|
-
<button class="chip" onclick="var e=document.querySelectorAll('svg .edge,svg line,svg path,a-animated');e.forEach(function(l){l.classList.toggle('a-animated')});this.classList.toggle('active')" title="Toggle flow animation">
|
|
154
|
-
<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
|
|
285
|
+
<div class="toolbar" role="toolbar" aria-label="Diagram controls">
|
|
286
|
+
<button class="chip" onclick="var e=document.querySelectorAll('svg .edge,svg line,svg path,a-animated');e.forEach(function(l){l.classList.toggle('a-animated')});this.classList.toggle('active')" title="Toggle flow animation" aria-label="Toggle flow animation">
|
|
287
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
|
|
155
288
|
Flow
|
|
156
289
|
</button>
|
|
157
|
-
<button class="chip" onclick="var e=document.querySelectorAll('svg .edge,svg line,svg path');e.forEach(function(l){l.classList.toggle('a-marching-ants')});this.classList.toggle('active')" title="Toggle
|
|
158
|
-
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="12" cy="12" r="2"/></svg>
|
|
290
|
+
<button class="chip" onclick="var e=document.querySelectorAll('svg .edge,svg line,svg path');e.forEach(function(l){l.classList.toggle('a-marching-ants')});this.classList.toggle('active')" title="Toggle trace highlight" aria-label="Toggle trace highlight">
|
|
291
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="12" cy="12" r="2"/></svg>
|
|
159
292
|
Trace
|
|
160
293
|
</button>
|
|
161
|
-
<button class="chip" onclick="var m=this.nextElementSibling;m.classList.toggle('show')" title="Export">☰ Export</button>
|
|
162
|
-
<div class="menu">
|
|
163
|
-
<button onclick="var s=new XMLSerializer;var d=document.querySelector('svg');if(!d)return;var b=new Blob(['<svg xmlns=\\'http://www.w3.org/2000/svg\\'>'+d.innerHTML.replace(/<g[^>]*>/g,'').replace(/<\\/g>/g,'')+'</svg>'],{type:'image/svg+xml'});var a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='diagram.svg';a.click()">Download SVG</button>
|
|
164
|
-
<button onclick="var d=document.querySelector('svg');if(!d){alert('No SVG found');return}var r=(new XMLSerializer).serializeToString(d);var c=document.createElement('canvas');c.width=d.getAttribute('width')||1200;c.height=d.getAttribute('height')||800;var i=new Image;i.onload=function(){c.getContext('2d').drawImage(i,0,0);c.toBlob(function(b){var a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='diagram.png';a.click()})};i.src='data:image/svg+xml;base64,'+btoa(unescape(encodeURIComponent(r)))">Download PNG</button>
|
|
294
|
+
<button class="chip" onclick="var m=this.nextElementSibling;m.classList.toggle('show')" title="Export diagram" aria-label="Export diagram" aria-haspopup="true">☰ Export</button>
|
|
295
|
+
<div class="menu" role="menu">
|
|
296
|
+
<button role="menuitem" onclick="var s=new XMLSerializer;var d=document.querySelector('svg');if(!d)return;var b=new Blob(['<svg xmlns=\\'http://www.w3.org/2000/svg\\'>'+d.innerHTML.replace(/<g[^>]*>/g,'').replace(/<\\/g>/g,'')+'</svg>'],{type:'image/svg+xml'});var a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='diagram.svg';a.click()">Download SVG</button>
|
|
297
|
+
<button role="menuitem" onclick="var d=document.querySelector('svg');if(!d){alert('No SVG found');return}var r=(new XMLSerializer).serializeToString(d);var c=document.createElement('canvas');c.width=d.getAttribute('width')||1200;c.height=d.getAttribute('height')||800;var i=new Image;i.onload=function(){c.getContext('2d').drawImage(i,0,0);c.toBlob(function(b){var a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='diagram.png';a.click()})};i.src='data:image/svg+xml;base64,'+btoa(unescape(encodeURIComponent(r)))">Download PNG</button>
|
|
165
298
|
</div>
|
|
166
299
|
</div>
|
|
167
300
|
<div class="container">
|
|
@@ -170,6 +303,52 @@ svg .edge-label{fill:var(--text-muted)}
|
|
|
170
303
|
<!-- DIAGRAM:SVG -->
|
|
171
304
|
<!-- DIAGRAM:CARDS -->
|
|
172
305
|
</div>
|
|
306
|
+
<!-- Interactive node detail card (hidden until a node is clicked) -->
|
|
307
|
+
<div class="detail-card" id="detailCard">
|
|
308
|
+
<h3 id="dTitle">Click a node</h3>
|
|
309
|
+
<div class="meta" id="dMeta"></div>
|
|
310
|
+
<p id="dBody">Click any component in the diagram to see details.</p>
|
|
311
|
+
</div>
|
|
312
|
+
<!-- Interactive flow data injected by renderer (optional) -->
|
|
313
|
+
<script>
|
|
314
|
+
(function(){
|
|
315
|
+
var nodes = document.querySelectorAll('.node');
|
|
316
|
+
var detailCard = document.getElementById('detailCard');
|
|
317
|
+
var dTitle = document.getElementById('dTitle');
|
|
318
|
+
var dMeta = document.getElementById('dMeta');
|
|
319
|
+
var dBody = document.getElementById('dBody');
|
|
320
|
+
if (!nodes.length || !detailCard) return;
|
|
321
|
+
// DETAIL data injected by renderer as JSON in a <script id="diagram-node-data"> tag
|
|
322
|
+
var detailData = {};
|
|
323
|
+
try {
|
|
324
|
+
var script = document.getElementById('diagram-node-data');
|
|
325
|
+
if (script) detailData = JSON.parse(script.textContent);
|
|
326
|
+
} catch(_) {}
|
|
327
|
+
nodes.forEach(function(n){
|
|
328
|
+
n.addEventListener('click', function(){
|
|
329
|
+
nodes.forEach(function(x){ x.classList.remove('sel'); });
|
|
330
|
+
n.classList.add('sel');
|
|
331
|
+
var key = n.getAttribute('data-k');
|
|
332
|
+
var d = detailData[key];
|
|
333
|
+
if (!d) { dTitle.textContent = key || 'Node'; dMeta.textContent = ''; dBody.textContent = 'No details available.'; return; }
|
|
334
|
+
dTitle.textContent = d.t || key;
|
|
335
|
+
dMeta.textContent = d.m || '';
|
|
336
|
+
dBody.textContent = d.b || '';
|
|
337
|
+
detailCard.classList.add('show');
|
|
338
|
+
});
|
|
339
|
+
// Keyboard accessibility
|
|
340
|
+
n.setAttribute('tabindex', '0');
|
|
341
|
+
n.setAttribute('role', 'button');
|
|
342
|
+
n.addEventListener('keydown', function(e){
|
|
343
|
+
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); n.click(); }
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
// Close on Escape
|
|
347
|
+
document.addEventListener('keydown', function(e){
|
|
348
|
+
if (e.key === 'Escape') { detailCard.classList.remove('show'); nodes.forEach(function(x){ x.classList.remove('sel'); }); }
|
|
349
|
+
});
|
|
350
|
+
})();
|
|
351
|
+
<\/script>
|
|
173
352
|
</body>
|
|
174
|
-
</html>`}const
|
|
175
|
-
`)}function
|
|
353
|
+
</html>`}const U=`<!-- DIAGRAM:SVG -->`;function W(e){let t=e.indexOf(U);if(t===-1)return null;let n=t+20,r=e.indexOf(U,n);if(r===-1)return null;let i=e.slice(n,r).trim();if(i.startsWith(`<svg`))return i;let a=e.slice(Math.max(0,t),r+20),o=a.match(/viewBox="([^"]+)"/),s=o?o[1]:`0 0 1200 800`,c=a.match(/width="(\d+)"/),l=c?c[1]:`1200`,u=a.match(/height="(\d+)"/);return[`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${s}" width="${l}" height="${u?u[1]:`800`}">`,` <defs>`,` <style>`,` text { font-family: system-ui, -apple-system, sans-serif; }`,` .title { font-size: 20px; font-weight: 600; fill: #fff; }`,` .subtitle { font-size: 14px; fill: #94a3b8; }`,` </style>`,` </defs>`,i,`</svg>`].join(`
|
|
354
|
+
`)}function he(e){let t=e.match(/<title>([^<]+)<\/title>/);return t?t[1]:`diagram`}async function ge(e,t,n){let r=m(n);await h(r,{recursive:!0});let i=he(e).replace(/[^a-zA-Z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``).toLowerCase().slice(0,80)||`diagram`,a=p(r,`${i}.html`);await g(a,e,`utf-8`);let o=null,s=W(e);s&&(o=p(r,`${i}.svg`),await g(o,s,`utf-8`));let c=null;return t&&(c=p(r,`${i}.md`),await g(c,t,`utf-8`)),{htmlPath:a,svgPath:o,mdPath:c}}const G=10*1024*1024,K=2e3;function _e(e){try{return JSON.stringify(e)}catch{return``}}function ve(e){switch(e.diagram_type){case`architecture`:return ae(e);case`workflow`:return H(e);case`sequence`:return R(e);case`dataflow`:return ce(e);case`lifecycle`:return P(e)}}function q(e,t={}){Y(e);let n=J(e);if(n.length>0)throw Error(`Diagram validation failed: ${n.join(`; `)}`);let r=t.title??e.meta.title,i=t.subtitle??e.meta.subtitle,a=t.dualOutput??!0,{svg:o,cardsHtml:s,detailData:c}=ve(e),l=c&&Object.keys(c).length>0?`\n<script id="diagram-node-data" type="application/json">${_e(c)}<\/script>`:``,u=e.meta?.palette===`warm`?`warm`:`technical`;return{html:me().replaceAll(`[TITLE]`,X(r)).replaceAll(`[SUBTITLE]`,X(i??``)).replaceAll(`[PALETTE]`,u===`warm`?` data-palette="warm"`:``).replaceAll(`<!-- DIAGRAM:SVG -->`,o).replaceAll(`<!-- DIAGRAM:CARDS -->`,s).replace(`</body>`,`${l}\n</body>`),markdown:a?_(e):void 0}}function ye(e,t={}){return q(e,{...t,dualOutput:!1}).html}function be(e){return _(e)}function xe(e){try{return Y(e),J(e)}catch(e){return[e.message]}}function J(e){if(!e||typeof e!=`object`)return[`Input must be an object`];if(!e.diagram_type)return[`Missing diagram_type`];if(!e.meta?.title)return[`meta.title is required`];if(e.schema_version!==1)return[`schema_version must be 1`];let t=e.diagram_type,n=e,r=n.components??n.nodes??n.participants??n.states??[],i=n.connections??n.edges??n.messages??n.flows??n.transitions??[],a=new Set(r.map(e=>e.id));if(a.size!==r.length)return[`${t}: Node/component IDs must be unique`];for(let e of i){if(e.from&&!a.has(e.from))return[`${t}: Edge references unknown source "${e.from}"`];if(e.to&&!a.has(e.to))return[`${t}: Edge references unknown target "${e.to}"`]}return[]}function Y(e){let t=JSON.stringify(e),n=Buffer.byteLength(t,`utf-8`);if(n>G)throw Error(`Input too large: ${(n/1024/1024).toFixed(1)}MB (max ${G/1024/1024}MB)`);let r=e,i=r.components??r.nodes??r.participants??[];if(i.length>500)throw Error(`Too many components/nodes: ${i.length} (max 500)`);let a=r.connections??r.edges??r.messages??r.flows??r.transitions??[];if(a.length>K)throw Error(`Too many edges/connections: ${a.length} (max ${K})`)}function Se(e){return e.replace(/[^a-zA-Z0-9-_]/g,`_`).toLowerCase().slice(0,120)}function X(e){let t={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`};return String(e??``).replace(/[&<>"']/g,e=>t[e]??e)}const Z=d(`server`);function Q(e,t){return t?{version:e,...f(t)}:{version:e}}function $(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function Ce(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===l(e).href}catch{return!1}}function we(){return Ce()?u({allowPositionals:!0,options:{transport:{type:`string`,default:$()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:$(),port:process.env.AIKIT_PORT??`3210`}}async function Te(){let e=t=>{t.name===`ExperimentalWarning`&&t.message.includes(`SQLite`)||(process.off(`warning`,e),process.emitWarning(t),process.on(`warning`,e))};process.on(`warning`,e);let n=t(),r=we();if(process.on(`unhandledRejection`,e=>{Z.error(`Unhandled rejection`,Q(n,e))}),process.on(`uncaughtException`,e=>{Z.error(`Uncaught exception — exiting`,Q(n,e)),process.exit(1)}),Z.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let{startHttpMode:e}=await import(`./server-http-AarbD3gm.js`);await e(n,r.port)}else{let{startStdioMode:e}=await import(`./server-stdio-BWoMqXU8.js`);await e(n)}}export{c as CuratedKnowledgeManager,s as applyWorkspaceRoots,a as bootstrapWorkspaceRoots,i as createSlidingWindowRateLimiter,ge as exportDiagram,W as extractSvg,n as getSessionIdHeader,Te as main,r as readPositiveIntEnv,t as readVersion,ye as renderHtml,be as renderMd,q as renderToResult,e as resolveCorsOrigin,Se as sanitizeTitle,o as selectWorkspaceRoot,xe as validate};
|