diff --git a/apps/cockpit/src/lib/render-markdown.spec.ts b/apps/cockpit/src/lib/render-markdown.spec.ts index e895ff7a0..525da8402 100644 --- a/apps/cockpit/src/lib/render-markdown.spec.ts +++ b/apps/cockpit/src/lib/render-markdown.spec.ts @@ -51,6 +51,13 @@ describe('renderMarkdown', () => { expect(result.html).toContain('Build a streaming chat.'); }); + it('parses inline markdown inside Summary blocks', async () => { + const md = '# Test\n\n\nUse `agent()` from [`@ngaf/langgraph`](/docs/langgraph).\n'; + const result = await renderMarkdown(md); + expect(result.html).toContain('agent()'); + expect(result.html).toContain(''); + }); + it('renders Tip callout blocks', async () => { const md = '# Test\n\n\nNo service layer needed.\n'; const result = await renderMarkdown(md); @@ -89,6 +96,15 @@ describe('renderMarkdown', () => { expect(result.html).toContain('data-copy-prompt'); }); + it('renders Related blocks as markdown link lists', async () => { + const md = '# Test\n\n\n- [Chat Messages](/chat/core-capabilities/messages/overview/python) - Learn how messages render\n'; + const result = await renderMarkdown(md); + expect(result.html).toContain('doc-related'); + expect(result.html).toContain(''); + expect(result.html).toContain('Chat Messages'); + expect(result.html).not.toContain('- [Chat Messages]'); + }); + it('renders ApiTable blocks as styled tables', async () => { const md = '# Test\n\n\n| Signal | Type |\n|--------|------|\n| `messages()` | `BaseMessage[]` |\n'; const result = await renderMarkdown(md); diff --git a/apps/cockpit/src/lib/render-markdown.ts b/apps/cockpit/src/lib/render-markdown.ts index 3529a9937..0ac11cfe0 100644 --- a/apps/cockpit/src/lib/render-markdown.ts +++ b/apps/cockpit/src/lib/render-markdown.ts @@ -13,7 +13,7 @@ interface ExtractedBlock { attrs: Record; } -const COMPONENT_TAGS = ['Summary', 'Tip', 'Note', 'Warning', 'Prompt', 'ApiTable', 'Step', 'Steps']; +const COMPONENT_TAGS = ['Summary', 'Tip', 'Note', 'Warning', 'Prompt', 'ApiTable', 'Related', 'Step', 'Steps']; function extractComponentTags(source: string): { cleaned: string; blocks: ExtractedBlock[] } { const blocks: ExtractedBlock[] = []; @@ -41,14 +41,37 @@ function extractComponentTags(source: string): { cleaned: string; blocks: Extrac return { cleaned, blocks }; } -function renderSummary(content: string): string { - return `${content}`; +async function renderInlineMarkdown(content: string): Promise { + return await marked.parseInline(content); } -function renderCallout(type: 'tip' | 'note' | 'warning', content: string): string { +async function renderSummary(content: string): Promise { + const html = await renderInlineMarkdown(content); + return `${html}`; +} + +async function renderCallout( + type: 'tip' | 'note' | 'warning', + content: string, +): Promise { + const html = await renderInlineMarkdown(content); const icons = { tip: '💡', note: '⚠️', warning: '🚨' }; const labels = { tip: 'Tip', note: 'Note', warning: 'Warning' }; - return `${icons[type]} ${labels[type]}${content}`; + return `${icons[type]} ${labels[type]}${html}`; +} + +async function renderPrompt(content: string): Promise { + const html = await renderInlineMarkdown(content); + return `🤖 Agentic PromptCopy prompt${html}`; +} + +async function renderRelated(content: string): Promise { + const html = await marked.parse(content); + return `${html}`; +} + +function renderApiTable(content: string): string { + return `${content}`; } async function renderSteps( @@ -100,14 +123,6 @@ async function parseStepContent( return html; } -function renderPrompt(content: string): string { - return `🤖 Agentic PromptCopy prompt${content}`; -} - -function renderApiTable(content: string): string { - return `${content}`; -} - function extractFilename(code: string): { filename: string | null; cleanedCode: string } { const firstLine = code.split('\n')[0]; const tsMatch = firstLine?.match(/^\/\/\s*(.+\.\w+)\s*$/); @@ -166,13 +181,14 @@ export async function renderMarkdown(source: string): Promise if (!html.includes(block.placeholder)) continue; let rendered: string; switch (block.type) { - case 'Summary': rendered = renderSummary(block.content); break; - case 'Tip': rendered = renderCallout('tip', block.content); break; - case 'Note': rendered = renderCallout('note', block.content); break; - case 'Warning': rendered = renderCallout('warning', block.content); break; + case 'Summary': rendered = await renderSummary(block.content); break; + case 'Tip': rendered = await renderCallout('tip', block.content); break; + case 'Note': rendered = await renderCallout('note', block.content); break; + case 'Warning': rendered = await renderCallout('warning', block.content); break; case 'Steps': rendered = await renderSteps(block.content, blocks); break; case 'Step': rendered = ''; break; - case 'Prompt': rendered = renderPrompt(block.content); break; + case 'Prompt': rendered = await renderPrompt(block.content); break; + case 'Related': rendered = await renderRelated(block.content); break; case 'ApiTable': { const tableHtml = await marked.parse(block.content); rendered = renderApiTable(tableHtml); diff --git a/apps/cockpit/src/lib/route-resolution.spec.ts b/apps/cockpit/src/lib/route-resolution.spec.ts index b753fd62b..22d92c942 100644 --- a/apps/cockpit/src/lib/route-resolution.spec.ts +++ b/apps/cockpit/src/lib/route-resolution.spec.ts @@ -132,6 +132,24 @@ describe('getCapabilityPresentation', () => { }); }); + it('includes durable execution docs assets from the capability module', () => { + const entry = resolveCockpitEntry({ + manifest: cockpitManifest, + product: 'langgraph', + section: 'core-capabilities', + topic: 'durable-execution', + page: 'overview', + language: 'python', + }); + const presentation = getCapabilityPresentation(entry); + + expect(presentation).toMatchObject({ + kind: 'capability', + docsPath: '/docs/langgraph/core-capabilities/durable-execution/overview/python', + docsAssetPaths: ['cockpit/langgraph/durable-execution/python/docs/guide.md'], + }); + }); + it('presents render capabilities with module-backed metadata', () => { const entry = resolveCockpitEntry({ manifest: cockpitManifest, diff --git a/apps/website/content/docs/chat/api/api-docs.json b/apps/website/content/docs/chat/api/api-docs.json index 3b3a8ae14..691f6fa31 100644 --- a/apps/website/content/docs/chat/api/api-docs.json +++ b/apps/website/content/docs/chat/api/api-docs.json @@ -1132,7 +1132,7 @@ }, { "name": "surface", - "type": "InputSignal", + "type": "InputSignal", "description": "Wire-format surface (legacy path — kept for backwards compat).", "optional": false }, @@ -5331,118 +5331,6 @@ ], "methods": [] }, - { - "name": "A2uiAction", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "context", - "type": "A2uiActionContextEntry[]", - "description": "", - "optional": true - }, - { - "name": "name", - "type": "string", - "description": "", - "optional": false - } - ], - "examples": [] - }, - { - "name": "A2uiActionContextEntry", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "key", - "type": "string", - "description": "", - "optional": false - }, - { - "name": "value", - "type": "DynamicString | DynamicNumber | DynamicBoolean", - "description": "", - "optional": false - } - ], - "examples": [] - }, - { - "name": "A2uiActionMessage", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "action", - "type": "object", - "description": "", - "optional": false - }, - { - "name": "metadata", - "type": "object", - "description": "", - "optional": true - }, - { - "name": "version", - "type": "\"v0.9\"", - "description": "", - "optional": false - } - ], - "examples": [] - }, - { - "name": "A2uiClientDataModel", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "surfaces", - "type": "Record>", - "description": "", - "optional": false - }, - { - "name": "version", - "type": "\"v0.9\"", - "description": "", - "optional": false - } - ], - "examples": [] - }, - { - "name": "A2uiComponent", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "component", - "type": "A2uiComponentDef", - "description": "", - "optional": false - }, - { - "name": "id", - "type": "string", - "description": "", - "optional": false - }, - { - "name": "weight", - "type": "number", - "description": "", - "optional": true - } - ], - "examples": [] - }, { "name": "A2uiComponentView", "kind": "interface", @@ -5487,56 +5375,6 @@ ], "examples": [] }, - { - "name": "A2uiSurface", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "catalogId", - "type": "string", - "description": "", - "optional": false - }, - { - "name": "components", - "type": "Map", - "description": "", - "optional": false - }, - { - "name": "dataModel", - "type": "Record", - "description": "", - "optional": false - }, - { - "name": "sendDataModel", - "type": "boolean", - "description": "", - "optional": true - }, - { - "name": "styles", - "type": "object", - "description": "Styles set by the agent via `beginRendering.styles`. The\ncanonical v1 spec defines exactly two fields: `font` (primary\nfont for the UI) and `primaryColor` (hex `#RRGGBB`). The renderer\napplies these as CSS custom properties on the surface root,\noverriding any consumer-set defaults for the duration of the\nsurface's life. Anything richer (typography scale, spacing,\nelevation, etc.) is the renderer's private vocabulary and not\ncommunicated through this field.", - "optional": true - }, - { - "name": "surfaceId", - "type": "string", - "description": "", - "optional": false - }, - { - "name": "theme", - "type": "A2uiTheme", - "description": "", - "optional": true - } - ], - "examples": [] - }, { "name": "A2uiSurfaceState", "kind": "interface", @@ -5607,32 +5445,6 @@ ], "examples": [] }, - { - "name": "A2uiTheme", - "kind": "interface", - "description": "", - "properties": [ - { - "name": "agentDisplayName", - "type": "string", - "description": "", - "optional": true - }, - { - "name": "iconUrl", - "type": "string", - "description": "", - "optional": true - }, - { - "name": "primaryColor", - "type": "string", - "description": "", - "optional": true - } - ], - "examples": [] - }, { "name": "Agent", "kind": "interface", @@ -6900,17 +6712,10 @@ "examples": [] }, { - "name": "A2uiChildren", - "kind": "type", - "description": "", - "signature": "object | object", - "examples": [] - }, - { - "name": "A2uiComponentDef", + "name": "A2uiActionMessage", "kind": "type", "description": "", - "signature": "object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object", + "signature": "any", "examples": [] }, { @@ -6997,27 +6802,6 @@ "signature": "\"right\" | \"bottom\" | \"left\"", "examples": [] }, - { - "name": "DynamicBoolean", - "kind": "type", - "description": "", - "signature": "object | object", - "examples": [] - }, - { - "name": "DynamicNumber", - "kind": "type", - "description": "", - "signature": "object | object", - "examples": [] - }, - { - "name": "DynamicString", - "kind": "type", - "description": "", - "signature": "object | object", - "examples": [] - }, { "name": "InterruptAction", "kind": "type", @@ -7312,82 +7096,6 @@ }, "examples": [] }, - { - "name": "isLiteralBoolean", - "kind": "function", - "description": "", - "signature": "isLiteralBoolean(value: unknown): value is { literalBoolean: boolean }", - "params": [ - { - "name": "value", - "type": "unknown", - "description": "", - "optional": false - } - ], - "returns": { - "type": "value is { literalBoolean: boolean }", - "description": "" - }, - "examples": [] - }, - { - "name": "isLiteralNumber", - "kind": "function", - "description": "", - "signature": "isLiteralNumber(value: unknown): value is { literalNumber: number }", - "params": [ - { - "name": "value", - "type": "unknown", - "description": "", - "optional": false - } - ], - "returns": { - "type": "value is { literalNumber: number }", - "description": "" - }, - "examples": [] - }, - { - "name": "isLiteralString", - "kind": "function", - "description": "", - "signature": "isLiteralString(value: unknown): value is { literalString: string }", - "params": [ - { - "name": "value", - "type": "unknown", - "description": "", - "optional": false - } - ], - "returns": { - "type": "value is { literalString: string }", - "description": "" - }, - "examples": [] - }, - { - "name": "isPathRef", - "kind": "function", - "description": "", - "signature": "isPathRef(value: unknown): value is { path: string }", - "params": [ - { - "name": "value", - "type": "unknown", - "description": "", - "optional": false - } - ], - "returns": { - "type": "value is { path: string }", - "description": "" - }, - "examples": [] - }, { "name": "isSystemMessage", "kind": "function", diff --git a/cockpit/deep-agents/filesystem/python/docs/guide.md b/cockpit/deep-agents/filesystem/python/docs/guide.md index 9d2cd5a66..59e36d62b 100644 --- a/cockpit/deep-agents/filesystem/python/docs/guide.md +++ b/cockpit/deep-agents/filesystem/python/docs/guide.md @@ -1,4 +1,4 @@ -# File Operations with angular +# File Operations with Angular Build a chat interface that shows real-time file operation logs using `agent()` from diff --git a/cockpit/deep-agents/memory/python/docs/guide.md b/cockpit/deep-agents/memory/python/docs/guide.md index 418dd1f96..389c49669 100644 --- a/cockpit/deep-agents/memory/python/docs/guide.md +++ b/cockpit/deep-agents/memory/python/docs/guide.md @@ -1,4 +1,4 @@ -# Persistent Agent Memory with angular +# Persistent Agent Memory with Angular Build a chat interface where the agent remembers facts about the user across turns using `agent()` from `@ngaf/langgraph`. The agent stores learned facts in `agent_memory` state, and the sidebar displays them in real time. diff --git a/cockpit/deep-agents/planning/python/docs/guide.md b/cockpit/deep-agents/planning/python/docs/guide.md index b6320ff4b..f92ccc52b 100644 --- a/cockpit/deep-agents/planning/python/docs/guide.md +++ b/cockpit/deep-agents/planning/python/docs/guide.md @@ -1,4 +1,4 @@ -# Task Decomposition with angular +# Task Decomposition with Angular Build a chat interface that shows real-time task decomposition using `agent()` from diff --git a/cockpit/deep-agents/sandboxes/python/docs/guide.md b/cockpit/deep-agents/sandboxes/python/docs/guide.md index 886f30d95..06067f0fb 100644 --- a/cockpit/deep-agents/sandboxes/python/docs/guide.md +++ b/cockpit/deep-agents/sandboxes/python/docs/guide.md @@ -1,4 +1,4 @@ -# Code Execution Sandbox with angular +# Code Execution Sandbox with Angular Build a chat interface that shows real-time code execution logs using `agent()` from diff --git a/cockpit/deep-agents/skills/python/docs/guide.md b/cockpit/deep-agents/skills/python/docs/guide.md index 0e514f41b..85bf203df 100644 --- a/cockpit/deep-agents/skills/python/docs/guide.md +++ b/cockpit/deep-agents/skills/python/docs/guide.md @@ -1,4 +1,4 @@ -# Multi-Skill Agent with angular +# Multi-Skill Agent with Angular Build a chat interface that shows real-time skill invocations using `agent()` from diff --git a/cockpit/deep-agents/subagents/python/docs/guide.md b/cockpit/deep-agents/subagents/python/docs/guide.md index 888e6d10e..211c8f739 100644 --- a/cockpit/deep-agents/subagents/python/docs/guide.md +++ b/cockpit/deep-agents/subagents/python/docs/guide.md @@ -1,4 +1,4 @@ -# Child Agent Delegation with angular +# Child Agent Delegation with Angular Build a chat interface that shows real-time subagent activity using `agent()` from diff --git a/cockpit/langgraph/durable-execution/python/docs/guide.md b/cockpit/langgraph/durable-execution/python/docs/guide.md index 647277449..0861692d2 100644 --- a/cockpit/langgraph/durable-execution/python/docs/guide.md +++ b/cockpit/langgraph/durable-execution/python/docs/guide.md @@ -1,4 +1,4 @@ -# Durable Execution with angular +# Durable Execution with Angular Build a fault-tolerant chat interface using `agent()` from diff --git a/cockpit/langgraph/durable-execution/python/src/index.ts b/cockpit/langgraph/durable-execution/python/src/index.ts index 9d896b4f7..5e25532cb 100644 --- a/cockpit/langgraph/durable-execution/python/src/index.ts +++ b/cockpit/langgraph/durable-execution/python/src/index.ts @@ -2,7 +2,7 @@ export interface CockpitCapabilityModule { id: string; manifestIdentity: { product: 'langgraph'; - section: 'fault-tolerance'; + section: 'core-capabilities'; topic: 'durable-execution'; page: 'overview'; language: 'python'; @@ -21,13 +21,13 @@ export const langgraphDurableExecutionPythonModule: CockpitCapabilityModule = { id: 'langgraph-durable-execution-python', manifestIdentity: { product: 'langgraph', - section: 'fault-tolerance', + section: 'core-capabilities', topic: 'durable-execution', page: 'overview', language: 'python', }, title: 'LangGraph Durable Execution (Python)', - docsPath: '/docs/langgraph/fault-tolerance/durable-execution/overview/python', + docsPath: '/docs/langgraph/core-capabilities/durable-execution/overview/python', promptAssetPaths: ['cockpit/langgraph/durable-execution/python/prompts/durable-execution.md'], codeAssetPaths: [ 'cockpit/langgraph/durable-execution/angular/src/app/durable-execution.component.ts', diff --git a/cockpit/langgraph/interrupts/python/docs/guide.md b/cockpit/langgraph/interrupts/python/docs/guide.md index 322ce3cf5..27a023274 100644 --- a/cockpit/langgraph/interrupts/python/docs/guide.md +++ b/cockpit/langgraph/interrupts/python/docs/guide.md @@ -1,4 +1,4 @@ -# Human-in-the-Loop Interrupts with angular +# Human-in-the-Loop Interrupts with Angular Build a chat interface with human-in-the-loop approval using `agent()` from diff --git a/cockpit/langgraph/memory/python/docs/guide.md b/cockpit/langgraph/memory/python/docs/guide.md index 7c62e8c83..7ee41ea9a 100644 --- a/cockpit/langgraph/memory/python/docs/guide.md +++ b/cockpit/langgraph/memory/python/docs/guide.md @@ -1,4 +1,4 @@ -# Cross-Thread Persistent Memory with angular +# Cross-Thread Persistent Memory with Angular Build a chat interface where the agent actively learns and remembers facts about the user. diff --git a/cockpit/langgraph/persistence/python/docs/guide.md b/cockpit/langgraph/persistence/python/docs/guide.md index 96f7e79c7..63b90b3f9 100644 --- a/cockpit/langgraph/persistence/python/docs/guide.md +++ b/cockpit/langgraph/persistence/python/docs/guide.md @@ -1,4 +1,4 @@ -# Thread Persistence with angular +# Thread Persistence with Angular Build a chat interface with thread persistence using `agent()` from diff --git a/cockpit/langgraph/streaming/python/docs/guide.md b/cockpit/langgraph/streaming/python/docs/guide.md index 1e0c96a33..35031afc5 100644 --- a/cockpit/langgraph/streaming/python/docs/guide.md +++ b/cockpit/langgraph/streaming/python/docs/guide.md @@ -1,4 +1,4 @@ -# Streaming with angular +# Streaming with Angular Build a real-time streaming chat interface using `agent()` from diff --git a/cockpit/langgraph/subgraphs/python/docs/guide.md b/cockpit/langgraph/subgraphs/python/docs/guide.md index c4abd5f4d..2cab57075 100644 --- a/cockpit/langgraph/subgraphs/python/docs/guide.md +++ b/cockpit/langgraph/subgraphs/python/docs/guide.md @@ -1,4 +1,4 @@ -# Nested Agent Delegation with Subgraphs and angular +# Nested Agent Delegation with Subgraphs and Angular Build a chat interface that visualizes nested agent delegation using `agent()` from diff --git a/cockpit/langgraph/time-travel/python/docs/guide.md b/cockpit/langgraph/time-travel/python/docs/guide.md index 3b79380d7..f29da99a9 100644 --- a/cockpit/langgraph/time-travel/python/docs/guide.md +++ b/cockpit/langgraph/time-travel/python/docs/guide.md @@ -1,4 +1,4 @@ -# Time Travel with angular +# Time Travel with Angular Build a chat interface with time travel using `agent()` from
agent()