[{"data":1,"prerenderedAt":1817},["ShallowReactive",2],{"navigation_docs":3,"-tutorial-ai":412,"-tutorial-ai-surround":1812},[4,38,84,326,386],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":37},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20,24,28,32],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-book-open",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":6},"Quick start: Nuxt","\u002Fgetting-started\u002Fquick-start-nuxt","1.getting-started\u002F3.quick-start-nuxt",{"title":25,"path":26,"stem":27,"icon":6},"Quick start: plain Vue","\u002Fgetting-started\u002Fquick-start-vue","1.getting-started\u002F4.quick-start-vue",{"title":29,"path":30,"stem":31,"icon":6},"Quick start: React","\u002Fgetting-started\u002Fquick-start-react","1.getting-started\u002F5.quick-start-react",{"title":33,"path":34,"stem":35,"icon":36},"Glossary","\u002Fgetting-started\u002Fglossary","1.getting-started\u002F6.glossary","i-lucide-book-a",false,{"title":39,"icon":40,"path":41,"stem":42,"children":43,"page":37},"Tutorial","i-lucide-graduation-cap","\u002Ftutorial","2.tutorial",[44,49,54,59,64,69,74,79],{"title":45,"path":46,"stem":47,"icon":48},"Tutorial: overview","\u002Ftutorial\u002Foverview","2.tutorial\u002F1.overview","i-lucide-map",{"title":50,"path":51,"stem":52,"icon":53},"Chapter 2: A simple editor","\u002Ftutorial\u002Fsimple-editor","2.tutorial\u002F2.simple-editor","i-lucide-pencil",{"title":55,"path":56,"stem":57,"icon":58},"Chapter 3: Compose features","\u002Ftutorial\u002Fcompose-features","2.tutorial\u002F3.compose-features","i-lucide-blocks",{"title":60,"path":61,"stem":62,"icon":63},"Chapter 4: Your own block, path A","\u002Ftutorial\u002Fown-block-path-a","2.tutorial\u002F4.own-block-path-a","i-lucide-square-plus",{"title":65,"path":66,"stem":67,"icon":68},"Chapter 5: Your own feature, path B","\u002Ftutorial\u002Fown-feature-path-b","2.tutorial\u002F5.own-feature-path-b","i-lucide-puzzle",{"title":70,"path":71,"stem":72,"icon":73},"Chapter 6: Backend and collaboration","\u002Ftutorial\u002Fbackend-and-collaboration","2.tutorial\u002F6.backend-and-collaboration","i-lucide-users",{"title":75,"path":76,"stem":77,"icon":78},"Chapter 7: AI","\u002Ftutorial\u002Fai","2.tutorial\u002F7.ai","i-lucide-sparkles",{"title":80,"path":81,"stem":82,"icon":83},"Chapter 8: The React surface","\u002Ftutorial\u002Freact-surface","2.tutorial\u002F8.react-surface","i-lucide-atom",{"title":85,"icon":14,"path":86,"stem":87,"children":88,"page":37},"Guides","\u002Fguides","3.guides",[89,93,98,103,108,112,116,121,126,130,134,139,144,149,154,159,164,169,174,179,184,189,194,199,204,209,213,218,223,228,233,237,242,247,251,256,261,266,271,276,281,286,291,295,302,307,311,316,321],{"title":90,"path":91,"stem":92,"icon":58},"Feature composition and entries","\u002Fguides\u002Fcomposition","3.guides\u002F1.composition",{"title":94,"path":95,"stem":96,"icon":97},"Media, mentions and transcript features","\u002Fguides\u002Fmedia-mentions-transcript","3.guides\u002F10.media-mentions-transcript","i-lucide-image",{"title":99,"path":100,"stem":101,"icon":102},"Authors and comments","\u002Fguides\u002Fauthors-and-comments","3.guides\u002F11.authors-and-comments","i-lucide-message-square-text",{"title":104,"path":105,"stem":106,"icon":107},"Themes (Obsidian)","\u002Fguides\u002Fthemes","3.guides\u002F12.themes","i-lucide-palette",{"title":109,"path":110,"stem":111,"icon":58},"Composites and the settings UI","\u002Fguides\u002Fcomposites","3.guides\u002F13.composites",{"title":113,"path":114,"stem":115,"icon":78},"AI","\u002Fguides\u002Fai","3.guides\u002F14.ai",{"title":117,"path":118,"stem":119,"icon":120},"Document tree","\u002Fguides\u002Fdocument-tree","3.guides\u002F15.document-tree","i-lucide-folder-tree",{"title":122,"path":123,"stem":124,"icon":125},"Markdown and code","\u002Fguides\u002Fmarkdown-and-code","3.guides\u002F16.markdown-and-code","i-lucide-file-code",{"title":127,"path":128,"stem":129,"icon":83},"Advanced editor in React","\u002Fguides\u002Fadvanced-react","3.guides\u002F17.advanced-react",{"title":131,"path":132,"stem":133,"icon":6},"Kitchen sink: learning path","\u002Fguides\u002Fadvanced-nuxt-example","3.guides\u002F18.advanced-nuxt-example",{"title":135,"path":136,"stem":137,"icon":138},"Production","\u002Fguides\u002Fproduction","3.guides\u002F19.production","i-lucide-server",{"title":140,"path":141,"stem":142,"icon":143},"Register the Nuxt module","\u002Fguides\u002Fnuxt-module","3.guides\u002F2.nuxt-module","i-lucide-package",{"title":145,"path":146,"stem":147,"icon":148},"Storage adapters, comment stores, Nitro host","\u002Fguides\u002Fstorage-adapters","3.guides\u002F20.storage-adapters","i-lucide-database",{"title":150,"path":151,"stem":152,"icon":153},"Migrating from #tiptap-editor","\u002Fguides\u002Fmigration","3.guides\u002F21.migration","i-lucide-arrow-right-left",{"title":155,"path":156,"stem":157,"icon":158},"Content tree mechanics","\u002Fguides\u002Fcontent-tree","3.guides\u002F22.content-tree","i-lucide-git-fork",{"title":160,"path":161,"stem":162,"icon":163},"Block capabilities, abilities and actions","\u002Fguides\u002Fblock-capabilities","3.guides\u002F23.block-capabilities","i-lucide-shield-check",{"title":165,"path":166,"stem":167,"icon":168},"Block types in code and JSON","\u002Fguides\u002Fblock-types","3.guides\u002F24.block-types","i-lucide-shapes",{"title":170,"path":171,"stem":172,"icon":173},"Derive methods and the Derivation index","\u002Fguides\u002Fderive-methods","3.guides\u002F25.derive-methods","i-lucide-git-branch-plus",{"title":175,"path":176,"stem":177,"icon":178},"Block properties and Property definitions","\u002Fguides\u002Fblock-properties","3.guides\u002F26.block-properties","i-lucide-sliders-horizontal",{"title":180,"path":181,"stem":182,"icon":183},"Image studio","\u002Fguides\u002Fimage-studio","3.guides\u002F27.image-studio","i-lucide-image-plus",{"title":185,"path":186,"stem":187,"icon":188},"Prüfung and Freigabestatus","\u002Fguides\u002Fpruefung","3.guides\u002F28.pruefung","i-lucide-stamp",{"title":190,"path":191,"stem":192,"icon":193},"Workspace: find, read, reference and embed Blocks across Documents","\u002Fguides\u002Fworkspace","3.guides\u002F29.workspace","i-lucide-network",{"title":195,"path":196,"stem":197,"icon":198},"EditorPorts: auth and storage","\u002Fguides\u002Feditor-ports","3.guides\u002F3.editor-ports","i-lucide-plug",{"title":200,"path":201,"stem":202,"icon":203},"Collections: an ordered list of Blocks","\u002Fguides\u002Fcollections","3.guides\u002F30.collections","i-lucide-list-checks",{"title":205,"path":206,"stem":207,"icon":208},"Data views: a query shown as table, list or board","\u002Fguides\u002Fdata-views","3.guides\u002F31.data-views","i-lucide-table-properties",{"title":210,"path":211,"stem":212,"icon":193},"Explore: backlinks, related Blocks and the trail","\u002Fguides\u002Fexplore","3.guides\u002F32.explore",{"title":214,"path":215,"stem":216,"icon":217},"Render: export a Block or a Document to a file","\u002Fguides\u002Frender","3.guides\u002F33.render","i-lucide-file-output",{"title":219,"path":220,"stem":221,"icon":222},"Importers: what a dropped file becomes","\u002Fguides\u002Fimporters","3.guides\u002F34.importers","i-lucide-file-input",{"title":224,"path":225,"stem":226,"icon":227},"Templates: start a Document from a Dokumentvorlage","\u002Fguides\u002Ftemplates","3.guides\u002F35.templates","i-lucide-file-stack",{"title":229,"path":230,"stem":231,"icon":232},"Citations","\u002Fguides\u002Fcitations","3.guides\u002F36.citations","i-lucide-quote",{"title":234,"path":235,"stem":236,"icon":163},"AI proposals and the export check","\u002Fguides\u002Fexport-check","3.guides\u002F37.export-check",{"title":238,"path":239,"stem":240,"icon":241},"Query: filter, sort, group and total Blocks","\u002Fguides\u002Fquery","3.guides\u002F38.query","i-lucide-list-filter",{"title":243,"path":244,"stem":245,"icon":246},"Edges: backlinks and authored connections","\u002Fguides\u002Fedges","3.guides\u002F39.edges","i-lucide-link-2",{"title":248,"path":249,"stem":250,"icon":163},"Server routes and authentication","\u002Fguides\u002Froutes-and-auth","3.guides\u002F4.routes-and-auth",{"title":252,"path":253,"stem":254,"icon":255},"Speech: text to audio, and subtitle files","\u002Fguides\u002Fspeech","3.guides\u002F41.speech","i-lucide-audio-lines",{"title":257,"path":258,"stem":259,"icon":260},"Graph: the Edges around a Block","\u002Fguides\u002Fgraph","3.guides\u002F42.graph","i-lucide-waypoints",{"title":262,"path":263,"stem":264,"icon":265},"PDF viewer: passages, anchors and quotes","\u002Fguides\u002Fpdf-viewer","3.guides\u002F43.pdf-viewer","i-lucide-file-search",{"title":267,"path":268,"stem":269,"icon":270},"Obsidian: import and export a vault","\u002Fguides\u002Fobsidian","3.guides\u002F44.obsidian","i-lucide-folder-input",{"title":272,"path":273,"stem":274,"icon":275},"Typst: render a Document as a PDF with citations","\u002Fguides\u002Ftypst","3.guides\u002F45.typst","i-lucide-file-text",{"title":277,"path":278,"stem":279,"icon":280},"Audio: read aloud, mixdown and ElevenLabs","\u002Fguides\u002Faudio","3.guides\u002F46.audio","i-lucide-audio-waveform",{"title":282,"path":283,"stem":284,"icon":285},"Slides: decks, slide layouts and exports","\u002Fguides\u002Fslides","3.guides\u002F47.slides","i-lucide-presentation",{"title":287,"path":288,"stem":289,"icon":290},"Knowledge graph: sources and concepts beside the Documents","\u002Fguides\u002Fknowledge-graph","3.guides\u002F49.knowledge-graph","i-lucide-share-2",{"title":292,"path":293,"stem":294,"icon":78},"AI configuration and secrets","\u002Fguides\u002Fai-configuration","3.guides\u002F5.ai-configuration",{"title":296,"path":297,"stem":298,"children":299,"icon":301},"Index on Postgres: typos, meaning and SQL pushdown","\u002Fguides\u002Findex-pg","3.guides\u002F50.index-pg",[300],{"title":296,"path":297,"stem":298,"icon":301},"i-lucide-database-zap",{"title":303,"path":304,"stem":305,"icon":306},"Charts: bar, line, pie and scatter over a query","\u002Fguides\u002Fcharts","3.guides\u002F51.charts","i-lucide-chart-column",{"title":308,"path":309,"stem":310,"icon":73},"Collaboration on the client","\u002Fguides\u002Fcollaboration","3.guides\u002F6.collaboration",{"title":312,"path":313,"stem":314,"icon":315},"Block UI (drag handle, hover actions)","\u002Fguides\u002Fblock-ui","3.guides\u002F7.block-ui","i-lucide-grip-vertical",{"title":317,"path":318,"stem":319,"icon":320},"Settings and app lifetime","\u002Fguides\u002Fsettings","3.guides\u002F8.settings","i-lucide-settings",{"title":322,"path":323,"stem":324,"icon":325},"Language","\u002Fguides\u002Flanguage","3.guides\u002F9.language","i-lucide-languages",{"title":327,"icon":14,"path":328,"stem":329,"children":330,"page":37},"Reference","\u002Freference","4.reference",[331,335,339,344,348,352,356,360,364,368,373,378,382],{"title":332,"path":333,"stem":334,"icon":143},"Public exports","\u002Freference\u002Fexports","4.reference\u002F1.exports",{"title":336,"path":337,"stem":338,"icon":173},"Derive method contract","\u002Freference\u002Fderive-methods","4.reference\u002F10.derive-methods",{"title":340,"path":341,"stem":342,"icon":343},"Changelog","\u002Freference\u002Fchangelog","4.reference\u002F11.changelog","i-lucide-history",{"title":345,"path":346,"stem":347,"icon":217},"Renderer port","\u002Freference\u002Frenderer-port","4.reference\u002F12.renderer-port",{"title":349,"path":350,"stem":351,"icon":255},"Speech port","\u002Freference\u002Fspeech-port","4.reference\u002F13.speech-port",{"title":353,"path":354,"stem":355,"icon":58},"Presets and features","\u002Freference\u002Fpresets-and-features","4.reference\u002F2.presets-and-features",{"title":357,"path":358,"stem":359,"icon":68},"Feature contract","\u002Freference\u002Ffeature-contract","4.reference\u002F3.feature-contract",{"title":361,"path":362,"stem":363,"icon":107},"CSS and UI-provider requirements","\u002Freference\u002Fcss-and-ui","4.reference\u002F4.css-and-ui",{"title":365,"path":366,"stem":367,"icon":148},"Vue-free advanced schema","\u002Freference\u002Fadvanced-schema","4.reference\u002F5.advanced-schema",{"title":369,"path":370,"stem":371,"icon":372},"Dependency rules","\u002Freference\u002Fdependency-rules","4.reference\u002F6.dependency-rules","i-lucide-git-branch",{"title":374,"path":375,"stem":376,"icon":377},"Commands","\u002Freference\u002Fcommands","4.reference\u002F7.commands","i-lucide-terminal",{"title":379,"path":380,"stem":381,"icon":163},"Block capability contract","\u002Freference\u002Fblock-capabilities","4.reference\u002F8.block-capabilities",{"title":383,"path":384,"stem":385,"icon":168},"Block type contract","\u002Freference\u002Fblock-types","4.reference\u002F9.block-types",{"title":387,"path":388,"stem":389,"children":390,"icon":393},"AI agents","\u002Fai-agents","5.ai-agents\u002F1.index",[391,394,398,402,407],{"title":392,"path":388,"stem":389,"icon":393},"Overview","i-lucide-bot",{"title":395,"path":396,"stem":397,"icon":198},"Integrate the editor","\u002Fai-agents\u002Fintegrate","5.ai-agents\u002F2.integrate",{"title":399,"path":400,"stem":401,"icon":68},"Add a block or feature","\u002Fai-agents\u002Fextend","5.ai-agents\u002F3.extend",{"title":403,"path":404,"stem":405,"icon":406},"Pitfalls and invariants","\u002Fai-agents\u002Finvariants","5.ai-agents\u002F4.invariants","i-lucide-shield-alert",{"title":408,"path":409,"stem":410,"icon":411},"Verify","\u002Fai-agents\u002Fverify","5.ai-agents\u002F5.verify","i-lucide-check-check",{"id":413,"title":75,"body":414,"description":1805,"extension":1806,"links":1807,"meta":1808,"navigation":1809,"path":76,"seo":1810,"stem":77,"__hash__":1811},"docs\u002F2.tutorial\u002F7.ai.md",{"type":415,"value":416,"toc":1795},"minimark",[417,426,452,457,486,1009,1063,1067,1083,1170,1177,1207,1228,1232,1251,1304,1307,1455,1465,1536,1539,1628,1635,1654,1658,1677,1746,1775,1779,1782,1786,1791],[418,419,420,421,425],"p",{},"The meeting-notes editor can summarise, rewrite and extend text, and a sidebar can chat with the document and propose edits. All of it is one feature, ",[422,423,424],"code",{},"aiFeature()",". This chapter adds it, shows what the server side needs, and then does the one thing only you can do: tell the model that a „Callout“ block exists and how to write it.",[418,427,428,429,432,433,436,437,440,441,444,445,448,449,451],{},"This chapter has no live demo, because the model calls need a server and a provider key. Run the repository's Nuxt app (",[422,430,431],{},"bun run dev",", port 3056) with a key in ",[422,434,435],{},".env"," and open ",[422,438,439],{},"\u002Fkitchen-sink\u002Fsurface"," (the callout feature with the AI sidebar) or ",[422,442,443],{},"\u002Fkitchen-sink\u002Fsimple"," (",[422,446,447],{},"SimpleEditor"," with ",[422,450,424],{},") to try it.",[453,454,456],"h2",{"id":455},"add-the-feature","Add the feature",[418,458,459,461,462,465,466,469,470,473,474,477,478,481,482,485],{},[422,460,424],{}," adds a selection menu (rewrite tasks such as shorter, formal or translate, plus free prompts), the ",[422,463,464],{},"\u002Fai"," command and a „KI“ toolbar group, in-document review of rewrites (accept or reject per change), ghost autocomplete while typing (Tab accepts, Esc dismisses), model profiles and the ",[422,467,468],{},"ai"," settings tab. The sidebar (document chat and block generation) and the quick model switch are components you place yourself; the sidebar comes from ",[422,471,472],{},"@skaile\u002Fforge-editor\u002Fai\u002Fvue\u002Fchat"," and needs the optional peer ",[422,475,476],{},"@skaile\u002Fforge-chat",". It needs no Typed blocks, transcript, media, mentions or Yjs; ",[422,479,480],{},"bun run check:editor-entries"," proves it with a ",[422,483,484],{},"core + ai"," fixture.",[487,488,493],"pre",{"className":489,"code":490,"language":491,"meta":492,"style":492},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nimport { aiFeature } from '@skaile\u002Fforge-editor\u002Fai\u002Fvue'\nimport { AiSidebar } from '@skaile\u002Fforge-editor\u002Fai\u002Fvue\u002Fchat'\nimport { coreContentFeature, coreUiFeature, defineEditor } from '@skaile\u002Fforge-editor\u002Fcore'\nimport { EditorSurface, EditorToolbar } from '@skaile\u002Fforge-editor\u002Fvue'\nimport type { Editor } from '@tiptap\u002Fvue-3'\nimport { shallowRef } from 'vue'\n\nconst preset = defineEditor({ features: [coreContentFeature(), coreUiFeature(), aiFeature()] })\nconst editor = shallowRef\u003CEditor>()\nconst sidebarOpen = shallowRef(false)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CEditorToolbar :editor=\"editor\" \u002F>\n  \u003Cdiv class=\"flex\">\n    \u003CEditorSurface v-model=\"content\" v-model:sidebar-open=\"sidebarOpen\" :preset=\"preset\" class=\"flex-1\" @ready=\"editor = $event\" \u002F>\n    \u003CAiSidebar v-model:open=\"sidebarOpen\" :editor=\"editor\" class=\"w-[380px]\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","vue","",[422,494,495,530,559,579,611,637,661,681,688,742,766,786,796,801,811,837,859,942,990,1000],{"__ignoreMap":492},[496,497,500,504,508,512,515,518,521,525,527],"span",{"class":498,"line":499},"line",1,[496,501,503],{"class":502},"sMK4o","\u003C",[496,505,507],{"class":506},"swJcz","script",[496,509,511],{"class":510},"spNyl"," setup",[496,513,514],{"class":510}," lang",[496,516,517],{"class":502},"=",[496,519,520],{"class":502},"\"",[496,522,524],{"class":523},"sfazB","ts",[496,526,520],{"class":502},[496,528,529],{"class":502},">\n",[496,531,533,537,540,544,547,550,553,556],{"class":498,"line":532},2,[496,534,536],{"class":535},"s7zQu","import",[496,538,539],{"class":502}," {",[496,541,543],{"class":542},"sTEyZ"," aiFeature",[496,545,546],{"class":502}," }",[496,548,549],{"class":535}," from",[496,551,552],{"class":502}," '",[496,554,555],{"class":523},"@skaile\u002Fforge-editor\u002Fai\u002Fvue",[496,557,558],{"class":502},"'\n",[496,560,562,564,566,569,571,573,575,577],{"class":498,"line":561},3,[496,563,536],{"class":535},[496,565,539],{"class":502},[496,567,568],{"class":542}," AiSidebar",[496,570,546],{"class":502},[496,572,549],{"class":535},[496,574,552],{"class":502},[496,576,472],{"class":523},[496,578,558],{"class":502},[496,580,582,584,586,589,592,595,597,600,602,604,606,609],{"class":498,"line":581},4,[496,583,536],{"class":535},[496,585,539],{"class":502},[496,587,588],{"class":542}," coreContentFeature",[496,590,591],{"class":502},",",[496,593,594],{"class":542}," coreUiFeature",[496,596,591],{"class":502},[496,598,599],{"class":542}," defineEditor",[496,601,546],{"class":502},[496,603,549],{"class":535},[496,605,552],{"class":502},[496,607,608],{"class":523},"@skaile\u002Fforge-editor\u002Fcore",[496,610,558],{"class":502},[496,612,614,616,618,621,623,626,628,630,632,635],{"class":498,"line":613},5,[496,615,536],{"class":535},[496,617,539],{"class":502},[496,619,620],{"class":542}," EditorSurface",[496,622,591],{"class":502},[496,624,625],{"class":542}," EditorToolbar",[496,627,546],{"class":502},[496,629,549],{"class":535},[496,631,552],{"class":502},[496,633,634],{"class":523},"@skaile\u002Fforge-editor\u002Fvue",[496,636,558],{"class":502},[496,638,640,642,645,647,650,652,654,656,659],{"class":498,"line":639},6,[496,641,536],{"class":535},[496,643,644],{"class":535}," type",[496,646,539],{"class":502},[496,648,649],{"class":542}," Editor",[496,651,546],{"class":502},[496,653,549],{"class":535},[496,655,552],{"class":502},[496,657,658],{"class":523},"@tiptap\u002Fvue-3",[496,660,558],{"class":502},[496,662,664,666,668,671,673,675,677,679],{"class":498,"line":663},7,[496,665,536],{"class":535},[496,667,539],{"class":502},[496,669,670],{"class":542}," shallowRef",[496,672,546],{"class":502},[496,674,549],{"class":535},[496,676,552],{"class":502},[496,678,491],{"class":523},[496,680,558],{"class":502},[496,682,684],{"class":498,"line":683},8,[496,685,687],{"emptyLinePlaceholder":686},true,"\n",[496,689,691,694,697,699,702,705,708,711,714,717,720,723,725,727,729,731,733,736,739],{"class":498,"line":690},9,[496,692,693],{"class":510},"const",[496,695,696],{"class":542}," preset ",[496,698,517],{"class":502},[496,700,599],{"class":701},"s2Zo4",[496,703,704],{"class":542},"(",[496,706,707],{"class":502},"{",[496,709,710],{"class":506}," features",[496,712,713],{"class":502},":",[496,715,716],{"class":542}," [",[496,718,719],{"class":701},"coreContentFeature",[496,721,722],{"class":542},"()",[496,724,591],{"class":502},[496,726,594],{"class":701},[496,728,722],{"class":542},[496,730,591],{"class":502},[496,732,543],{"class":701},[496,734,735],{"class":542},"()] ",[496,737,738],{"class":502},"}",[496,740,741],{"class":542},")\n",[496,743,745,747,750,752,754,756,760,763],{"class":498,"line":744},10,[496,746,693],{"class":510},[496,748,749],{"class":542}," editor ",[496,751,517],{"class":502},[496,753,670],{"class":701},[496,755,503],{"class":502},[496,757,759],{"class":758},"sBMFI","Editor",[496,761,762],{"class":502},">",[496,764,765],{"class":542},"()\n",[496,767,769,771,774,776,778,780,784],{"class":498,"line":768},11,[496,770,693],{"class":510},[496,772,773],{"class":542}," sidebarOpen ",[496,775,517],{"class":502},[496,777,670],{"class":701},[496,779,704],{"class":542},[496,781,783],{"class":782},"sfNiH","false",[496,785,741],{"class":542},[496,787,789,792,794],{"class":498,"line":788},12,[496,790,791],{"class":502},"\u003C\u002F",[496,793,507],{"class":506},[496,795,529],{"class":502},[496,797,799],{"class":498,"line":798},13,[496,800,687],{"emptyLinePlaceholder":686},[496,802,804,806,809],{"class":498,"line":803},14,[496,805,503],{"class":502},[496,807,808],{"class":506},"template",[496,810,529],{"class":502},[496,812,814,817,820,823,826,828,830,832,834],{"class":498,"line":813},15,[496,815,816],{"class":502},"  \u003C",[496,818,819],{"class":506},"EditorToolbar",[496,821,822],{"class":502}," :",[496,824,825],{"class":510},"editor",[496,827,517],{"class":502},[496,829,520],{"class":502},[496,831,825],{"class":542},[496,833,520],{"class":502},[496,835,836],{"class":502}," \u002F>\n",[496,838,840,842,845,848,850,852,855,857],{"class":498,"line":839},16,[496,841,816],{"class":502},[496,843,844],{"class":506},"div",[496,846,847],{"class":510}," class",[496,849,517],{"class":502},[496,851,520],{"class":502},[496,853,854],{"class":523},"flex",[496,856,520],{"class":502},[496,858,529],{"class":502},[496,860,862,865,868,871,873,875,878,880,882,884,887,889,891,894,896,898,901,903,905,907,909,911,913,915,918,920,923,926,928,930,932,935,938,940],{"class":498,"line":861},17,[496,863,864],{"class":502},"    \u003C",[496,866,867],{"class":506},"EditorSurface",[496,869,870],{"class":510}," v-model",[496,872,517],{"class":502},[496,874,520],{"class":502},[496,876,877],{"class":542},"content",[496,879,520],{"class":502},[496,881,870],{"class":510},[496,883,713],{"class":502},[496,885,886],{"class":510},"sidebar-open",[496,888,517],{"class":502},[496,890,520],{"class":502},[496,892,893],{"class":542},"sidebarOpen",[496,895,520],{"class":502},[496,897,822],{"class":502},[496,899,900],{"class":510},"preset",[496,902,517],{"class":502},[496,904,520],{"class":502},[496,906,900],{"class":542},[496,908,520],{"class":502},[496,910,847],{"class":510},[496,912,517],{"class":502},[496,914,520],{"class":502},[496,916,917],{"class":523},"flex-1",[496,919,520],{"class":502},[496,921,922],{"class":502}," @",[496,924,925],{"class":510},"ready",[496,927,517],{"class":502},[496,929,520],{"class":502},[496,931,825],{"class":542},[496,933,934],{"class":502}," = ",[496,936,937],{"class":542},"$event",[496,939,520],{"class":502},[496,941,836],{"class":502},[496,943,945,947,950,952,954,957,959,961,963,965,967,969,971,973,975,977,979,981,983,986,988],{"class":498,"line":944},18,[496,946,864],{"class":502},[496,948,949],{"class":506},"AiSidebar",[496,951,870],{"class":510},[496,953,713],{"class":502},[496,955,956],{"class":510},"open",[496,958,517],{"class":502},[496,960,520],{"class":502},[496,962,893],{"class":542},[496,964,520],{"class":502},[496,966,822],{"class":502},[496,968,825],{"class":510},[496,970,517],{"class":502},[496,972,520],{"class":502},[496,974,825],{"class":542},[496,976,520],{"class":502},[496,978,847],{"class":510},[496,980,517],{"class":502},[496,982,520],{"class":502},[496,984,985],{"class":523},"w-[380px]",[496,987,520],{"class":502},[496,989,836],{"class":502},[496,991,993,996,998],{"class":498,"line":992},19,[496,994,995],{"class":502},"  \u003C\u002F",[496,997,844],{"class":506},[496,999,529],{"class":502},[496,1001,1003,1005,1007],{"class":498,"line":1002},20,[496,1004,791],{"class":502},[496,1006,808],{"class":506},[496,1008,529],{"class":502},[418,1010,1011,1013,1014,1017,1018,1021,1022,1024,1025,1028,1029,1032,1033,1036,1037,1017,1040,1043,1044,1047,1048,1051,1052,1055,1056,1058,1059,1062],{},[422,1012,424],{}," needs no component setup: the model profiles come from the app's editor context, and its notices (rate limits, import problems) go to the surface's notifier. Import ",[422,1015,1016],{},"@skaile\u002Fforge-editor\u002Fstyles\u002Fai.css"," after ",[422,1019,1020],{},"core.css",". The Vue sidebar renders on ",[422,1023,476],{}," (its ",[422,1026,1027],{},"ChatPanel","), an optional peer of the editor package: install it, import ",[422,1030,1031],{},"@skaile\u002Fforge-chat\u002Fstyles\u002Fchat.css"," and add ",[422,1034,1035],{},"@source \"…\u002Fnode_modules\u002F@skaile\u002Fforge-chat\u002Fdist\";"," next to the one for the library; a Nuxt host also lists ",[422,1038,1039],{},"'@skaile\u002Fforge-chat\u002Fnuxt'",[422,1041,1042],{},"'@nuxt\u002Fui'"," in ",[422,1045,1046],{},"modules",". The ",[422,1049,1050],{},"AdvancedEditor"," of chapter 6 already contains the feature (",[422,1053,1054],{},"ai: true","); ",[422,1057,447],{}," takes it through its ",[422,1060,1061],{},"add"," prop.",[453,1064,1066],{"id":1065},"the-server-side","The server side",[418,1068,1069,1070,1072,1073,1082],{},"The feature talks to its endpoints through the backend's ",[422,1071,468],{}," port. The Nuxt module mounts the routes for you; with another transport you provide them yourself. The handlers in ",[1074,1075,1079],"a",{"href":1076,"rel":1077},"https:\u002F\u002Fgithub.com\u002Fskaile-ai\u002Fforge-editor\u002Fblob\u002Fmain\u002Fpackages\u002Feditor\u002Fsrc\u002Fserver\u002Fhandlers\u002Fai.ts",[1078],"nofollow",[422,1080,1081],{},"packages\u002Feditor\u002Fsrc\u002Fserver\u002Fhandlers\u002Fai.ts"," are the reference implementation.",[1084,1085,1086,1099],"table",{},[1087,1088,1089],"thead",{},[1090,1091,1092,1096],"tr",{},[1093,1094,1095],"th",{},"Endpoint",[1093,1097,1098],{},"Purpose",[1100,1101,1102,1127,1147,1157],"tbody",{},[1090,1103,1104,1110],{},[1105,1106,1107],"td",{},[422,1108,1109],{},"GET \u002Fapi\u002Fai\u002Fmodels",[1105,1111,1112,1115,1116,1119,1120,1119,1123,1126],{},[422,1113,1114],{},"{ presets: ModelProfile[], roles: Record\u003CModelRole, string> }",": the server Model presets as Model profiles (no keys) and the default Model preset per Model role (",[422,1117,1118],{},"complete",", ",[422,1121,1122],{},"rewrite",[422,1124,1125],{},"generate",")",[1090,1128,1129,1134],{},[1105,1130,1131],{},[422,1132,1133],{},"POST \u002Fapi\u002Fai\u002Fgenerate",[1105,1135,1136,1137,1119,1140,1119,1143,1146],{},"SSE (",[422,1138,1139],{},"delta",[422,1141,1142],{},"done",[422,1144,1145],{},"error",") for selection tasks and block generation",[1090,1148,1149,1154],{},[1105,1150,1151],{},[422,1152,1153],{},"POST \u002Fapi\u002Fai\u002Fchat",[1105,1155,1156],{},"SSE for the sidebar's document chat with edit operations",[1090,1158,1159,1164],{},[1105,1160,1161],{},[422,1162,1163],{},"POST \u002Fapi\u002Fai\u002Fcomplete",[1105,1165,1166,1169],{},[422,1167,1168],{},"{ text }"," continuation for ghost autocomplete",[418,1171,1172,1173,1176],{},"API keys never reach the client. In Nuxt the module's ",[422,1174,1175],{},"tiptapEditor.ai"," options (Model presets, default Model preset per Model role, rate limit) and these environment variables supply the server side:",[1178,1179,1180,1187,1201],"ul",{},[1181,1182,1183,1186],"li",{},[422,1184,1185],{},"NUXT_TIPTAP_EDITOR_AI_API_KEY",": the shared fallback key for every preset.",[1181,1188,1189,1192,1193,1196,1197,1200],{},[422,1190,1191],{},"NUXT_TIPTAP_EDITOR_AI_PRESETS_\u003CID>_API_KEY",": the key of one preset (",[422,1194,1195],{},"flashLite"," becomes ",[422,1198,1199],{},"NUXT_TIPTAP_EDITOR_AI_PRESETS_FLASH_LITE_API_KEY",").",[1181,1202,1203,1206],{},[422,1204,1205],{},"NUXT_TIPTAP_EDITOR_AI_TRANSCRIPTION_API_KEY",": a Deepgram key; the repository's config enables transcription only when it is set.",[418,1208,1209,1210,1213,1214,1217,1218,1220,1221,1224,1225,1227],{},"Public AI configuration is inert data passed to ",[422,1211,1212],{},"createEditor",", for example ",[422,1215,1216],{},"createEditor({ ai: { roles: { complete: 'flashLite', rewrite: 'sonnet', generate: 'sonnet' }, transcription: false } })",": the default Model preset per Model role until the user picks one in the ",[422,1219,468],{}," settings tab. The full description is in ",[1074,1222,1223],{"href":293},"AI configuration"," and ",[1074,1226,113],{"href":114},".",[453,1229,1231],{"id":1230},"teach-the-model-about-the-callout","Teach the model about the callout",[418,1233,1234,1235,1238,1239,1242,1243,1247,1248,713],{},"Without help the model sees a flat document with no custom Block types. Features adjust that through the ",[422,1236,1237],{},"aiContext"," hook, and a block feature uses its ",[422,1240,1241],{},"blocks"," list. First what the model ",[1244,1245,1246],"strong",{},"sees"," and what it ",[1244,1249,1250],{},"can write",[1178,1252,1253,1288],{},[1181,1254,1255,1258,1259,1262,1263,1266,1267,1270,1271,1275,1276,1279,1280,1283,1284,1287],{},[1244,1256,1257],{},"What the model sees."," ",[422,1260,1261],{},"editor.getMarkdown()"," and every ",[422,1264,1265],{},"editor.markdown.serialize(…)"," (selection text, document context, summaries) use your ",[422,1268,1269],{},"renderMarkdown"," from chapter 4. The chat's document view lists ",[1272,1273,1274],"em",{},"text blocks"," as ",[422,1277,1278],{},"[\u003Cblock id>] \u003CMarkdown>"," lines. A wrapper block like the callout appears as a header line with the block's own ID and its Markdown opener, ",[422,1281,1282],{},"[\u003Cid>] !!! info","; its body blocks follow two spaces further in, each with its own ID. This is why ",[422,1285,1286],{},"editorBlock: true"," matters: the model can address, update, delete, extend or convert a block by that ID.",[1181,1289,1290,1293,1294,1297,1298,1301,1302,1227],{},[1244,1291,1292],{},"What the model can write."," AI results are parsed by the block pipeline (",[422,1295,1296],{},"parseBlocks","), so Markdown in your syntax becomes your node. The model knows the syntax only if you describe it in ",[422,1299,1300],{},"aiContext.blocks","; the library does not guess it from ",[422,1303,1269],{},[418,1305,1306],{},"The callout contributes its description like this:",[487,1308,1312],{"className":1309,"code":1310,"filename":1311,"language":524,"meta":492,"style":492},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","    aiContext: () => ({\n      blocks: [{\n        id: 'callout',\n        label: 'Callout',\n        description: 'A colour-highlighted box for a note (info), a warning (warning) or something completed (success). Holds paragraphs, lists or quotes, no headings.',\n        syntax: '!!! \u003Cinfo|warning|success>\\n\u003Ccontent, blocks separated by a line break; a blank line ends the callout>',\n        example: '!!! warning\\nPlease check the figures before sending.',\n      }],\n    }),\n","app\u002Feditor\u002Fcallout\u002Ffeature.ts",[422,1313,1314,1332,1343,1361,1377,1393,1415,1436,1446],{"__ignoreMap":492},[496,1315,1316,1319,1321,1324,1327,1329],{"class":498,"line":499},[496,1317,1318],{"class":758},"    aiContext",[496,1320,713],{"class":502},[496,1322,1323],{"class":502}," ()",[496,1325,1326],{"class":510}," =>",[496,1328,444],{"class":542},[496,1330,1331],{"class":502},"{\n",[496,1333,1334,1337,1339,1341],{"class":498,"line":532},[496,1335,1336],{"class":506},"      blocks",[496,1338,713],{"class":502},[496,1340,716],{"class":542},[496,1342,1331],{"class":502},[496,1344,1345,1348,1350,1352,1355,1358],{"class":498,"line":561},[496,1346,1347],{"class":506},"        id",[496,1349,713],{"class":502},[496,1351,552],{"class":502},[496,1353,1354],{"class":523},"callout",[496,1356,1357],{"class":502},"'",[496,1359,1360],{"class":502},",\n",[496,1362,1363,1366,1368,1370,1373,1375],{"class":498,"line":581},[496,1364,1365],{"class":506},"        label",[496,1367,713],{"class":502},[496,1369,552],{"class":502},[496,1371,1372],{"class":523},"Callout",[496,1374,1357],{"class":502},[496,1376,1360],{"class":502},[496,1378,1379,1382,1384,1386,1389,1391],{"class":498,"line":613},[496,1380,1381],{"class":506},"        description",[496,1383,713],{"class":502},[496,1385,552],{"class":502},[496,1387,1388],{"class":523},"A colour-highlighted box for a note (info), a warning (warning) or something completed (success). Holds paragraphs, lists or quotes, no headings.",[496,1390,1357],{"class":502},[496,1392,1360],{"class":502},[496,1394,1395,1398,1400,1402,1405,1408,1411,1413],{"class":498,"line":639},[496,1396,1397],{"class":506},"        syntax",[496,1399,713],{"class":502},[496,1401,552],{"class":502},[496,1403,1404],{"class":523},"!!! \u003Cinfo|warning|success>",[496,1406,1407],{"class":542},"\\n",[496,1409,1410],{"class":523},"\u003Ccontent, blocks separated by a line break; a blank line ends the callout>",[496,1412,1357],{"class":502},[496,1414,1360],{"class":502},[496,1416,1417,1420,1422,1424,1427,1429,1432,1434],{"class":498,"line":663},[496,1418,1419],{"class":506},"        example",[496,1421,713],{"class":502},[496,1423,552],{"class":502},[496,1425,1426],{"class":523},"!!! warning",[496,1428,1407],{"class":542},[496,1430,1431],{"class":523},"Please check the figures before sending.",[496,1433,1357],{"class":502},[496,1435,1360],{"class":502},[496,1437,1438,1441,1444],{"class":498,"line":683},[496,1439,1440],{"class":502},"      }",[496,1442,1443],{"class":542},"]",[496,1445,1360],{"class":502},[496,1447,1448,1451,1453],{"class":498,"line":690},[496,1449,1450],{"class":502},"    }",[496,1452,1126],{"class":542},[496,1454,1360],{"class":502},[418,1456,1457,1458,1461,1462,1464],{},"Each ",[422,1459,1460],{},"AiBlock"," (a type exported from ",[422,1463,608],{},") describes one host block:",[1084,1466,1467,1477],{},[1087,1468,1469],{},[1090,1470,1471,1474],{},[1093,1472,1473],{},"Field",[1093,1475,1476],{},"Meaning",[1100,1478,1479,1496,1506,1516,1526],{},[1090,1480,1481,1486],{},[1105,1482,1483],{},[422,1484,1485],{},"id",[1105,1487,1488,1489,1491,1492,1495],{},"The node type name (",[422,1490,1354],{},"); doubles as the ",[422,1493,1494],{},"convert"," target id",[1090,1497,1498,1503],{},[1105,1499,1500],{},[422,1501,1502],{},"label",[1105,1504,1505],{},"The block's name in the document's language",[1090,1507,1508,1513],{},[1105,1509,1510],{},[422,1511,1512],{},"description",[1105,1514,1515],{},"One or two sentences on its purpose and allowed content",[1090,1517,1518,1523],{},[1105,1519,1520],{},[422,1521,1522],{},"syntax",[1105,1524,1525],{},"The Markdown form with placeholders in angle brackets",[1090,1527,1528,1533],{},[1105,1529,1530],{},[422,1531,1532],{},"example",[1105,1534,1535],{},"One complete Markdown example",[418,1537,1538],{},"What happens with it:",[1178,1540,1541,1583,1597],{},[1181,1542,1543,1548,1549,1552,1553,1224,1556,1558,1559,1562,1563,1566,1567,1570,1571,1573,1574,1576,1577,1580,1581,1227],{},[1244,1544,1545,1547],{},[422,1546,1237],{}," is additive."," Any number of features may contribute. ",[422,1550,1551],{},"defineEditor"," merges the contributions: ",[422,1554,1555],{},"blockTypes",[422,1557,1241],{}," concatenate in feature order, and ",[422,1560,1561],{},"structure"," (the Structure mode: ",[422,1564,1565],{},"'flat'"," or ",[422,1568,1569],{},"'structured'",") may come from one feature only. A block ",[422,1572,1485],{}," described twice, or two features that set ",[422,1575,1561],{},", is reported when the merged context is first read (",[422,1578,1579],{},"aiContextOf(editor)","), not when you call ",[422,1582,1551],{},[1181,1584,1585,1588,1589,1224,1591,1593,1594,1596],{},[1244,1586,1587],{},"The prompts."," The chat lists the blocks in its system prompt and sends them with each request; the generate tasks (sidebar and selection menu) list them too. A result may then contain the block in your syntax, and the block pipeline turns it into your node. ",[422,1590,1522],{},[422,1592,1532],{}," must match ",[422,1595,1269],{}," and the tokenizer, or the result will not parse back into the node.",[1181,1598,1599,1604,1605,1607,1608,1611,1612,1614,1615,1618,1619,1621,1622,1566,1624,1627],{},[1244,1600,1601,1603],{},[422,1602,1494],{}," targets."," The chat sends the model its list of ",[422,1606,1494],{}," targets: the core ids, the Block types of ",[422,1609,1610],{},"aiContext.blockTypes",", and each ",[422,1613,1241],{}," entry whose id a registered conversion provider parses. The callout's ",[422,1616,1617],{},"conversions"," from chapter 5 do, so „Umwandeln in Callout“ is also an agent operation. A block without such a provider is not a ",[422,1620,1494],{}," target, but the model may still ",[422,1623,1061],{},[422,1625,1626],{},"update"," it through Markdown in its syntax.",[1629,1630,1632],"h3",{"id":1631},"aiblockdata",[422,1633,1634],{},"aiBlockData",[418,1636,1637,1638,1641,1642,1645,1646,1649,1650,1653],{},"A second hook, ",[422,1639,1640],{},"aiBlockData: ({ editor, node, pos, signal }) => AiBlockDatum[] | Promise\u003CAiBlockDatum[]>",", supplies material for one Typed block (examples, a record) before „Block füllen (KI)“ asks the model. All contributions run in parallel and concatenate in feature order. The library only collects and caps the entries; the fetch belongs to your feature, and ",[422,1643,1644],{},"signal"," aborts it with the editor. The callout does not need it; the repository's Epikrise host feature (",[422,1647,1648],{},"app\u002Feditor\u002Fepikrise\u002Ffeature.ts",", on ",[422,1651,1652],{},"\u002Fkitchen-sink\u002Fepikrise",") shows one that does.",[453,1655,1657],{"id":1656},"what-an-agent-edit-does","What an agent edit does",[418,1659,1660,1661,1664,1665,1668,1669,1672,1673,1676],{},"The model proposes changes to the document through the ",[422,1662,1663],{},"edit_document"," tool. The server checks them (",[422,1666,1667],{},"checkAgentOps",", from ",[422,1670,1671],{},"@skaile\u002Fforge-editor\u002Fai\u002Fprotocol",") and streams the valid ones; the client shows each as an in-document review change the user accepts or rejects. There are four operation types (",[422,1674,1675],{},"AGENT_OP_TYPES","):",[1084,1678,1679,1689],{},[1087,1680,1681],{},[1090,1682,1683,1686],{},[1093,1684,1685],{},"Type",[1093,1687,1688],{},"Effect",[1100,1690,1691,1711,1723,1733],{},[1090,1692,1693,1697],{},[1105,1694,1695],{},[422,1696,1061],{},[1105,1698,1699,1700,1703,1704,1706,1707,1710],{},"Insert block(s) after a block ID; ",[422,1701,1702],{},"afterId: null"," is the document start. For the callout, ",[422,1705,1061],{}," after a body block inserts ",[1272,1708,1709],{},"inside"," the callout.",[1090,1712,1713,1717],{},[1105,1714,1715],{},[422,1716,1626],{},[1105,1718,1719,1720,1722],{},"Replace block ",[422,1721,1485],{},"; a single paragraph is diffed within the block.",[1090,1724,1725,1730],{},[1105,1726,1727],{},[422,1728,1729],{},"delete",[1105,1731,1732],{},"Remove the block.",[1090,1734,1735,1739],{},[1105,1736,1737],{},[422,1738,1494],{},[1105,1740,1741,1742,1745],{},"Change the block type, keeping the content; ",[422,1743,1744],{},"to"," must be one of the request's targets.",[418,1747,1748,1749,1751,1752,1119,1755,1119,1758,1119,1761,1119,1764,1119,1767,1119,1770,1772,1773,1227],{},"So after this chapter the model can write ",[422,1750,1426],{}," blocks into your notes, change an existing hint's text through its ID, or convert a paragraph into a callout. Invalid operations are dropped with a reason (",[422,1753,1754],{},"unknown",[422,1756,1757],{},"scope",[422,1759,1760],{},"field",[422,1762,1763],{},"duplicate",[422,1765,1766],{},"limit",[422,1768,1769],{},"target",[422,1771,1709],{},") and the outcome of every operation is fed back to the model with the next message. The complete tables, limits and the Typed block Markdown fence format are in ",[1074,1774,113],{"href":114},[453,1776,1778],{"id":1777},"what-you-have-now","What you have now",[418,1780,1781],{},"An editor with AI on every level: selection rewrites, ghost autocomplete, a chat sidebar with reviewable edit operations, and a model that knows the „Callout“ block exists, how to write it, and that it can convert into it.",[453,1783,1785],{"id":1784},"next","Next",[418,1787,1788,1790],{},[1074,1789,80],{"href":81}," shows the same editor on React.",[1792,1793,1794],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":492,"searchDepth":532,"depth":532,"links":1796},[1797,1798,1799,1802,1803,1804],{"id":455,"depth":532,"text":456},{"id":1065,"depth":532,"text":1066},{"id":1230,"depth":532,"text":1231,"children":1800},[1801],{"id":1631,"depth":561,"text":1634},{"id":1656,"depth":532,"text":1657},{"id":1777,"depth":532,"text":1778},{"id":1784,"depth":532,"text":1785},"Add aiFeature() to the meeting-notes editor, provide the \u002Fapi\u002Fai endpoints and keys, and describe the callout to the model with aiContext.","md",null,{},{"icon":78},{"title":75,"description":1805},"SVha3PsTNkfxgJBtDaHOeYhaTLbcCW6Bsn5cpJyPKYo",[1813,1815],{"title":70,"path":71,"stem":72,"description":1814,"icon":73,"children":-1},"Register the Nuxt module, hand it EditorPorts for identity and storage, and open one document in two browsers with the collaboration session.",{"title":80,"path":81,"stem":82,"description":1816,"icon":83,"children":-1},"Run the meeting-notes editor on React: EditorContextProvider, EditorSurface, EditorToolbar, SimpleEditor and the Toaster, and where the callout would go.",1793178230297]