diff --git a/phases/16-multi-agent-and-swarms/03-communication-protocols/docs/en.md b/phases/16-multi-agent-and-swarms/03-communication-protocols/docs/en.md index 237772ba9..ff6776538 100644 --- a/phases/16-multi-agent-and-swarms/03-communication-protocols/docs/en.md +++ b/phases/16-multi-agent-and-swarms/03-communication-protocols/docs/en.md @@ -38,16 +38,11 @@ This lesson goes deep. You will read real wire formats from each spec, build wor Think of these four protocols as layers, each addressing a different question: ```mermaid -block-beta - columns 1 - block:ANP["ANP — How do agents trust strangers?\nDecentralized identity (DID), E2EE, meta-protocol"] - end - block:A2A["A2A — How do agents collaborate on goals?\nAgent Cards, task lifecycle, streaming, negotiation"] - end - block:ACP["ACP — How do agents talk in auditable systems?\nRuns, trajectory metadata, session continuity"] - end - block:MCP["MCP — How does an agent use a tool?\nTool discovery, execution, context sharing"] - end +flowchart TD + ANP["ANP — How do agents trust strangers?
Decentralized identity (DID), E2EE, meta-protocol"] + A2A["A2A — How do agents collaborate on goals?
Agent Cards, task lifecycle, streaming, negotiation"] + ACP["ACP — How do agents talk in auditable systems?
Runs, trajectory metadata, session continuity"] + MCP["MCP — How does an agent use a tool?
Tool discovery, execution, context sharing"] style ANP fill:#f3e8ff,stroke:#7c3aed style A2A fill:#dbeafe,stroke:#2563eb @@ -191,7 +186,11 @@ stateDiagram-v2 canceled --> [*] rejected --> [*] - note right of completed: Terminal states are immutable.\nFollow-ups create new tasks\nwithin the same contextId. + note right of completed + Terminal states are immutable. + Follow-ups create new tasks + within the same contextId. + end note ``` All 8 states (the spec also defines `UNSPECIFIED` as a sentinel, omitted here): diff --git a/site/lesson.html b/site/lesson.html index 6ab9b8782..ad76aa84d 100644 --- a/site/lesson.html +++ b/site/lesson.html @@ -2094,7 +2094,7 @@ } function parseMd(md) { - var lines = md.split('\n'); + var lines = md.split(/\r?\n/); var out = ''; var inCodeBlock = false; var codeLang = ''; @@ -2149,7 +2149,7 @@ for (var ri = 2; ri < tableRows.length; ri++) { var cells = tableRows[ri]; h += ''; - for (var ci = 0; ci < cells.length; ci++) { + for (var ci = 0; ci < headers.length; ci++) { var cls = ''; if (isKeyTerms) { var headerLower = (headers[ci] || '').toLowerCase(); @@ -2216,12 +2216,11 @@ continue; } - if (line.match(/^\|.+\|/)) { + if (line.match(/^\s*\|.*\|\s*$/)) { out += flushList(); out += flushBlockquote(); if (!inTable) inTable = true; - var cells = line.split('|').slice(1, -1); - tableRows.push(cells.map(function (c) { return c.trim(); })); + tableRows.push(splitTableRow(line)); continue; } else if (inTable) { out += flushTable(); @@ -2361,6 +2360,37 @@ return out; } + function splitTableRow(line) { + // Split a markdown table row on cell delimiters while respecting + // escaped pipes (P(X\|Y)) and pipes inside inline-code spans (`a | b`). + var cells = []; + var cur = ''; + var inCode = false; + for (var i = 0; i < line.length; i++) { + var ch = line.charAt(i); + if (ch === '\\' && line.charAt(i + 1) === '|') { + cur += '|'; + i++; + continue; + } + if (ch === '`') { + inCode = !inCode; + cur += ch; + continue; + } + if (ch === '|' && !inCode) { + cells.push(cur); + cur = ''; + continue; + } + cur += ch; + } + cells.push(cur); + if (cells.length && cells[0].trim() === '') cells.shift(); + if (cells.length && cells[cells.length - 1].trim() === '') cells.pop(); + return cells.map(function (c) { return c.trim(); }); + } + function inlineFormat(text) { text = text.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); text = text.replace(/\*\*\*(.+?)\*\*\*/g, '$1'); @@ -2462,6 +2492,62 @@ return document.documentElement.getAttribute('data-theme') === 'light' ? 'default' : 'dark'; } + // Lessons hard-code node fills (light pastels that vanish on the dark + // default theme, and dark navies that vanish in light mode). Rather than + // maintain a hex table, flip the lightness band while preserving hue, so + // color-coding survives and labels stay legible in either theme. + function hexToHsl(hex) { + var r = parseInt(hex.slice(1, 3), 16) / 255; + var g = parseInt(hex.slice(3, 5), 16) / 255; + var b = parseInt(hex.slice(5, 7), 16) / 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b), h = 0, s = 0, l = (max + min) / 2; + if (max !== min) { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + if (max === r) h = (g - b) / d + (g < b ? 6 : 0); + else if (max === g) h = (b - r) / d + 2; + else h = (r - g) / d + 4; + h /= 6; + } + return [h, s, l]; + } + + function hslToHex(h, s, l) { + function hue(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + var r, g, b; + if (s === 0) { + r = g = b = l; + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue(p, q, h + 1 / 3); + g = hue(p, q, h); + b = hue(p, q, h - 1 / 3); + } + function c(x) { + x = Math.round(Math.max(0, Math.min(1, x)) * 255); + return ('0' + x.toString(16)).slice(-2); + } + return '#' + c(r) + c(g) + c(b); + } + + function mermaidPreprocess(def) { + var dark = mermaidTheme() === 'dark'; + return def.replace(/fill\s*:\s*(#[0-9a-fA-F]{6})/g, function (m, hex) { + var hsl = hexToHsl(hex.toLowerCase()); + if (dark && hsl[2] > 0.65) return 'fill:' + hslToHex(hsl[0], hsl[1], 0.26); + if (!dark && hsl[2] < 0.30) return 'fill:' + hslToHex(hsl[0], Math.min(hsl[1], 0.5), 0.86); + return m; + }); + } + function updateMermaidThemeAndRerender() { if (!window._mermaidReady) return; try { @@ -2486,7 +2572,7 @@ if (!idx) return; var target = document.getElementById('mermaid-render-' + idx); if (!target) return; - var def = pre.textContent; + var def = mermaidPreprocess(pre.textContent); target.innerHTML = '
Rendering diagram...
'; var token = ++mermaidRenderSeq; @@ -2598,7 +2684,7 @@ var pre = document.getElementById('mermaid-' + openMermaidIndex); if (!pre) return; - var def = pre.textContent; + var def = mermaidPreprocess(pre.textContent); center.innerHTML = '
Rendering diagram...
'; var token = ++mermaidRenderSeq;