{
  "name": "A2UI \u7ec4\u4ef6\u5c55\u793a (Showcase)",
  "nodes": [
    {
      "parameters": {
        "options": {
          "allowedOrigins": "*"
        }
      },
      "id": "chat-trigger",
      "name": "Chat Trigger",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "options": {
          "systemMessage": "\u4f60\u662f\u4e00\u4e2a A2UI \u7ec4\u4ef6\u751f\u6210\u4e13\u5bb6\u3002\u6839\u636e\u7528\u6237\u9700\u6c42\u751f\u6210 A2UI v0.9 \u534f\u8bae\u7684 UI \u7ec4\u4ef6\u3002\n\n# A2UI \u7ec4\u4ef6\u89c4\u8303\n\n## \u8f93\u51fa\u683c\u5f0f\n\u76f4\u63a5\u8f93\u51fa JSON \u5bf9\u8c61\uff08\u4e0d\u8981\u4f7f\u7528 markdown \u4ee3\u7801\u5757\uff09\uff0c\u5305\u542b `a2ui_messages` \u6570\u7ec4\uff1a\n\n{\n  \"a2ui_messages\": [\n    { \"type\": \"createSurface\", \"surfaceId\": \"main\", \"catalogId\": \"a2ui.org/standard\" },\n    { \"type\": \"updateDataModel\", \"surfaceId\": \"main\", \"data\": {} },\n    { \"type\": \"updateComponents\", \"surfaceId\": \"main\", \"components\": [...], \"rootComponentId\": \"root\" }\n  ]\n}\n\n## \u7ec4\u4ef6\u901f\u67e5\n\n| \u7ec4\u4ef6 | \u5fc5\u9700\u5c5e\u6027 | \u53ef\u9009\u5c5e\u6027 |\n|------|----------|----------|\n| Text | id, component=\"Text\", text | usageHint(h1-h5/caption/body) |\n| Image | id, component=\"Image\", url | fit, usageHint |\n| Icon | id, component=\"Icon\", name | - |\n| Video | id, component=\"Video\", url | - |\n| AudioPlayer | id, component=\"AudioPlayer\", url | description |\n| Row | id, component=\"Row\", children | justify, align |\n| Column | id, component=\"Column\", children | justify, align |\n| List | id, component=\"List\", children | direction, align |\n| Card | id, component=\"Card\", child | - |\n| Tabs | id, component=\"Tabs\", tabs | - |\n| Divider | id, component=\"Divider\" | axis |\n| Modal | id, component=\"Modal\", trigger, content | - |\n| Button | id, component=\"Button\", child, action | primary |\n| CheckBox | id, component=\"CheckBox\", label, value | - |\n| TextField | id, component=\"TextField\", label | text, usageHint, validationRegexp |\n| DateTimeInput | id, component=\"DateTimeInput\", value | enableDate, enableTime, label |\n| ChoicePicker | id, component=\"ChoicePicker\", usageHint, options, value | label |\n| Slider | id, component=\"Slider\", value | label, min, max |\n| Chart | id, component=\"Chart\", chartType, series | title, xAxis, yAxis, legend, tooltip, height |\n\n## Chart \u793a\u4f8b\n{\n  \"id\": \"chart-1\",\n  \"component\": \"Chart\",\n  \"chartType\": \"line\",\n  \"title\": \"\u6570\u636e\u8d8b\u52bf\",\n  \"series\": [{ \"name\": \"\u6570\u636e\", \"data\": [10, 20, 30, 40, 50] }],\n  \"xAxis\": { \"type\": \"category\", \"data\": [\"A\", \"B\", \"C\", \"D\", \"E\"] },\n  \"height\": 300\n}\n\n## \u6570\u636e\u7ed1\u5b9a\n\u4f7f\u7528 { \"path\": \"/data/path\" } \u7ed1\u5b9a\u6570\u636e\u6a21\u578b\u3002\n\n## \u89c4\u5219\n1. \u6bcf\u4e2a\u7ec4\u4ef6\u5fc5\u987b\u6709\u552f\u4e00 id\n2. Button.child \u5fc5\u987b\u5f15\u7528 Text \u7ec4\u4ef6 id\n3. \u5e03\u5c40\u7ec4\u4ef6\u7684 children \u5f15\u7528\u5b50\u7ec4\u4ef6 id \u6570\u7ec4\n4. \u6839\u7ec4\u4ef6\u901a\u5e38\u662f Column\n5. \u4f7f\u7528\u6570\u636e\u7ed1\u5b9a\u65f6\uff0c\u5728 updateDataModel \u4e2d\u63d0\u4f9b\u521d\u59cb\u503c\n\n## \u9884\u8bbe\u573a\u666f\n\n### \u7528\u6237\u8bf4\"\u5c55\u793a\u6240\u6709\u7ec4\u4ef6\"\u6216\"\u6f14\u793a\"\n\u751f\u6210\u4e00\u4e2a\u5b8c\u6574\u7684\u7ec4\u4ef6\u5c55\u793a\u9875\u9762\uff0c\u5305\u542b\u6240\u6709\u7c7b\u578b\u7684\u7ec4\u4ef6\u3002\n\n### \u7528\u6237\u8bf4\"\u767b\u5f55\u8868\u5355\"\n\u751f\u6210\u767b\u5f55\u8868\u5355\uff1a\u7528\u6237\u540d\u8f93\u5165\u6846\u3001\u5bc6\u7801\u8f93\u5165\u6846\uff08obscured\uff09\u3001\u8bb0\u4f4f\u6211\u590d\u9009\u6846\u3001\u767b\u5f55\u6309\u94ae\u3002\n\n### \u7528\u6237\u8bf4\"\u4eea\u8868\u76d8\"\u6216\"dashboard\"\n\u751f\u6210\u4eea\u8868\u76d8\uff1a\u7edf\u8ba1\u5361\u7247\u3001\u56fe\u8868\u3001\u6700\u8fd1\u6d3b\u52a8\u5217\u8868\u3002\n\n### \u7528\u6237\u8bf4\"\u5546\u54c1\u5361\u7247\"\u6216\"\u4ea7\u54c1\u5217\u8868\"\n\u751f\u6210\u5546\u54c1\u5361\u7247\uff1a\u56fe\u7247\u3001\u6807\u9898\u3001\u4ef7\u683c\u3001\u8bc4\u5206\u3001\u8d2d\u4e70\u6309\u94ae\u3002\n\n\u8bf7\u6839\u636e\u7528\u6237\u8bf7\u6c42\u751f\u6210\u5408\u9002\u7684 A2UI \u7ec4\u4ef6 JSON\u3002\u8f93\u51fa\u5fc5\u987b\u662f\u7eaf JSON \u683c\u5f0f\uff0c\u4e0d\u8981\u5305\u542b\u4efb\u4f55\u5176\u4ed6\u6587\u5b57\u8bf4\u660e\u3002",
          "returnIntermediateSteps": false
        }
      },
      "id": "ai-agent",
      "name": "A2UI Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "model": "gpt-4o",
        "options": {
          "temperature": 0.5,
          "responseFormat": "json_object"
        }
      },
      "id": "openai-model",
      "name": "OpenAI GPT-4o",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        220,
        200
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('Chat Trigger').item.json.sessionId }}"
      },
      "id": "memory",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.2,
      "position": [
        400,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// \u89e3\u6790 AI \u8f93\u51fa\u5e76\u63d0\u53d6 A2UI \u6d88\u606f\nconst input = $input.first().json;\nconst agentOutput = input.output || input.text || input.response || '';\n\nlet a2uiMessages = [];\nlet parseError = null;\n\ntry {\n  let parsed;\n  \n  if (typeof agentOutput === 'string') {\n    // \u6e05\u7406\u53ef\u80fd\u7684 markdown \u4ee3\u7801\u5757\n    let cleanJson = agentOutput\n      .replace(/```json\\n?/gi, '')\n      .replace(/```\\n?/g, '')\n      .trim();\n    \n    // \u5c1d\u8bd5\u627e\u5230 JSON \u5bf9\u8c61\n    const jsonStart = cleanJson.indexOf('{');\n    const jsonEnd = cleanJson.lastIndexOf('}');\n    if (jsonStart !== -1 && jsonEnd !== -1) {\n      cleanJson = cleanJson.substring(jsonStart, jsonEnd + 1);\n    }\n    \n    parsed = JSON.parse(cleanJson);\n  } else if (typeof agentOutput === 'object') {\n    parsed = agentOutput;\n  }\n  \n  if (parsed?.a2ui_messages) {\n    a2uiMessages = parsed.a2ui_messages;\n  } else if (Array.isArray(parsed)) {\n    a2uiMessages = parsed;\n  } else if (parsed?.type) {\n    a2uiMessages = [parsed];\n  } else {\n    // \u5982\u679c\u89e3\u6790\u7ed3\u679c\u6ca1\u6709\u9884\u671f\u7684\u683c\u5f0f\uff0c\u5c1d\u8bd5\u5305\u88c5\n    throw new Error('Invalid A2UI message format');\n  }\n  \n} catch (e) {\n  parseError = e.message;\n  \n  // \u8fd4\u56de\u53cb\u597d\u7684\u9519\u8bef\u63d0\u793a UI\n  a2uiMessages = [\n    {\n      type: 'createSurface',\n      surfaceId: 'error',\n      catalogId: 'a2ui.org/standard'\n    },\n    {\n      type: 'updateComponents',\n      surfaceId: 'error',\n      components: [\n        { id: 'icon', component: 'Icon', name: 'error' },\n        { id: 'title', component: 'Text', text: '\u751f\u6210\u5931\u8d25', usageHint: 'h2' },\n        { id: 'msg', component: 'Text', text: '\u65e0\u6cd5\u751f\u6210 UI \u7ec4\u4ef6\uff0c\u8bf7\u91cd\u65b0\u63cf\u8ff0\u60a8\u7684\u9700\u6c42\u3002\u9519\u8bef: ' + parseError, usageHint: 'body' },\n        { id: 'header', component: 'Row', children: ['icon', 'title'], alignment: 'center' },\n        { id: 'root', component: 'Column', children: ['header', 'msg'] }\n      ],\n      rootComponentId: 'root'\n    }\n  ];\n}\n\n// \u6784\u5efa\u6700\u7ec8\u8f93\u51fa - \u5c06 a2ui_messages \u8f6c\u6362\u4e3a JSONL \u683c\u5f0f\u5b57\u7b26\u4e32\nconst a2uiJsonl = a2uiMessages.map(m => JSON.stringify(m)).join('\\n');\n\nreturn {\n  json: {\n    // \u8fd4\u56de\u7eaf\u6587\u672c\u683c\u5f0f\uff0c\u5305\u542b A2UI JSONL\n    output: a2uiJsonl,\n    // \u540c\u65f6\u4fdd\u7559\u7ed3\u6784\u5316\u6570\u636e\u7528\u4e8e\u8c03\u8bd5\n    _debug: {\n      a2ui_messages: a2uiMessages,\n      success: !parseError,\n      error: parseError\n    }\n  }\n};"
      },
      "id": "parse-output",
      "name": "Parse A2UI",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    }
  ],
  "connections": {
    "Chat Trigger": {
      "main": [
        [
          {
            "node": "A2UI Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI GPT-4o": {
      "ai_languageModel": [
        [
          {
            "node": "A2UI Generator",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "A2UI Generator",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "A2UI Generator": {
      "main": [
        [
          {
            "node": "Parse A2UI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}