@aglyn/plugins-ai 1.0.0-beta.296 → 1.0.0

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.
Files changed (34) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-job-links.d.ts +2 -1
  3. package/src/lib/components/ai-job-links.js +8 -2
  4. package/src/lib/components/ai-job-links.js.map +1 -1
  5. package/src/lib/components/assist-edit-canvas.d.ts +12 -6
  6. package/src/lib/components/assist-edit-canvas.js +86 -36
  7. package/src/lib/components/assist-edit-canvas.js.map +1 -1
  8. package/src/lib/components/assist-edit-card.component.js +9 -8
  9. package/src/lib/components/assist-edit-card.component.js.map +1 -1
  10. package/src/lib/components/assist-page-change-card.component.d.ts +1 -1
  11. package/src/lib/components/assist-page-change-card.component.js +2 -2
  12. package/src/lib/components/assist-page-change-card.component.js.map +1 -1
  13. package/src/lib/components/assist-panel.component.js +19 -8
  14. package/src/lib/components/assist-panel.component.js.map +1 -1
  15. package/src/lib/jobs/ai-job-edit-step.d.ts +20 -0
  16. package/src/lib/jobs/ai-job-edit-step.js +39 -3
  17. package/src/lib/jobs/ai-job-edit-step.js.map +1 -1
  18. package/src/lib/model/ai-edit-job.js +1 -1
  19. package/src/lib/model/ai-edit-job.js.map +1 -1
  20. package/src/lib/model/ai-job-notice.js +3 -1
  21. package/src/lib/model/ai-job-notice.js.map +1 -1
  22. package/src/lib/model/assist-edit.d.ts +8 -7
  23. package/src/lib/model/assist-edit.js +4 -4
  24. package/src/lib/model/assist-edit.js.map +1 -1
  25. package/src/lib/model/assist-page-change.d.ts +14 -0
  26. package/src/lib/model/assist-page-change.js +21 -0
  27. package/src/lib/model/assist-page-change.js.map +1 -1
  28. package/src/lib/server/assist-chat.js +5 -1
  29. package/src/lib/server/assist-chat.js.map +1 -1
  30. package/src/lib/server/assist-edit.d.ts +12 -7
  31. package/src/lib/server/assist-edit.js +43 -22
  32. package/src/lib/server/assist-edit.js.map +1 -1
  33. package/src/lib/server/assist-page-change.js +1 -1
  34. package/src/lib/server/assist-page-change.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/assist-page-change.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ASSIST_PAGE_CHANGE_ACTION_ID,\n ASSIST_PAGE_CHANGE_SUMMARY_MAX_CHARS,\n ASSIST_PAGE_CHANGE_TOOL_NAME,\n type AssistPageChangeProposal,\n} from '../model/assist-page-change'\nimport { ASSIST_BUILD_TOOL_NAME } from '../model/assist-build'\nimport type { AiTool } from '../providers/contract'\nimport { AI_JOB_BRIEF_MAX_CHARS } from '../jobs/ai-job-text-step'\nimport { assistBuildBriefWithoutGaps } from './assist-build'\n\n/**\n * A change to a page the site already has, from the Assist chat (AGL-4116):\n * the tool the model asks through, the site's pages it picks from, and the\n * resolution the panel starts an `edit` job from. See\n * `model/assist-page-change.ts`.\n */\n\n/** The most pages the chat is shown; a site's pages past it are asked about by name. */\nexport const ASSIST_SITE_PAGES_MAX = 60\n\n/** One of the site's pages, as the chat is shown it. */\nexport interface AssistSitePage {\n id: string\n name: string\n /** The address it is served at, or would be once published. */\n slug: string\n /** Visitors reach it: the site routes its address to it. */\n live: boolean\n /** The site's home page. */\n home: boolean\n}\n\nconst STRING = { type: 'string' } as const\n\nexport function assistPageChangeTool(): AiTool {\n return {\n name: ASSIST_PAGE_CHANGE_TOOL_NAME,\n description:\n 'Change a page this site already has. The change is saved into that page’s draft, or as a new ' +\n 'version when the user asks for one, and the user is given a link to open it in the Besigner, ' +\n 'check it and publish it. Call at most once per message, for one page.',\n inputSchema: {\n type: 'object',\n properties: {\n summary: STRING,\n page: STRING,\n change: STRING,\n newVersion: { type: 'boolean' },\n },\n required: ['summary', 'page', 'change', 'newVersion'],\n additionalProperties: false,\n },\n strict: true,\n }\n}\n\n/** The protocol: the same for every site, so it is cached. */\nexport function assistPageChangeBlock(): string {\n return [\n 'Changing a page the site already has:',\n `- When the user asks to change something on one of the pages under \"The site's pages\" (its words, pictures, sections, layout or look), do not plan a build. Write one sentence saying you will make the change as a draft of that page, then call the ${ASSIST_PAGE_CHANGE_TOOL_NAME} tool once.`,\n '- page: the id of that page from the list. Where two pages share a name or an address, it is the live one unless the user names the other.',\n '- change: exactly what they asked to change on that page, in their words, with what this conversation settled about it. Add nothing they did not ask for.',\n '- summary: one short sentence, such as \"Make the top image fill the background on Home\".',\n '- The change is saved into that page’s draft, on any plan: the published page stays as it is until they publish. When it is ready, the chat shows Open in the Besigner, where Open draft shows the change and they publish it. A further change to the same page is made on that draft.',\n '- newVersion: true only when they ask for the change as a new or separate version of the page; otherwise false. Never offer a new version they did not ask for.',\n '- Nothing is changed when you call the tool: never say it is done. Never say you cannot use a draft, cannot edit the page or cannot give a link.',\n `- One page per message. For changes to several pages, change the first and say to ask for the next. A request that also asks for new pages, forms or anything else to be made is a build: call ${ASSIST_BUILD_TOOL_NAME} with the whole request instead.`,\n ].join('\\n')\n}\n\n/**\n * The site's pages, per site and per moment, so volatile — and, on a plan\n * without version history, that a new version cannot be made, so a request\n * for one is answered with the draft rather than a promise.\n */\nexport function assistSitePagesBlock(\n pages: readonly AssistSitePage[],\n options: { versioning: boolean } = { versioning: true },\n): string | null {\n if (!pages.length) return null\n return [\n \"The site's pages (id · name · address · live or draft):\",\n ...pages.map(\n (page) =>\n `- ${page.id} · ${page.name} · ${page.slug || '/'} · ${page.live ? 'live' : 'draft, not live'}${page.home ? ', the home page' : ''}`,\n ),\n ...(options.versioning\n ? []\n : [\n 'This workspace’s plan keeps no version history (it comes with Pro), so newVersion is always false: if they ask for a new version, say the change goes into the page’s draft instead.',\n ]),\n ].join('\\n')\n}\n\nfunction text(value: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\n/**\n * The site's pages a change may name: not deleted, not a collection's entry\n * template, an email design or an error body. Live ones and the home page\n * first, so a cap keeps the pages a person means.\n */\nexport async function readAssistSitePages(\n firestore: FirebaseFirestore.Firestore,\n hostId: string,\n): Promise<AssistSitePage[]> {\n const host = firestore.collection('hosts').doc(hostId)\n const [hostDoc, screens] = await Promise.all([\n host.get(),\n host\n .collection('screens')\n .select('displayName', 'name', 'slug', 'kind', 'deletedAt')\n .limit(ASSIST_SITE_PAGES_MAX * 3)\n .get(),\n ])\n const routing = (hostDoc.get('screens') ?? {}) as Record<string, unknown>\n const homeId = text(hostDoc.get('defaultHomeScreenId'))\n const pages: AssistSitePage[] = []\n for (const doc of screens.docs) {\n const data = doc.data()\n // A page has no kind; an entry template, an email design and an error\n // body each carry theirs, as the site inventory reads them.\n if (data['deletedAt'] || text(data['kind'])) continue\n const slug = text(data['slug'])\n pages.push({\n id: doc.id,\n name: text(data['displayName']) || text(data['name']) || slug || doc.id,\n slug: slug.startsWith('/') ? slug : `/${slug}`,\n live: typeof routing[doc.id] === 'string',\n home: doc.id === homeId,\n })\n }\n const rank = (page: AssistSitePage) => (page.home ? 0 : page.live ? 1 : 2)\n return pages.sort((a, b) => rank(a) - rank(b) || a.slug.localeCompare(b.slug)).slice(0, ASSIST_SITE_PAGES_MAX)\n}\n\n/**\n * The model's call, held to the site's own pages: a page it named that the\n * site does not have, or a change with nothing in it, proposes nothing.\n */\nexport function resolveAssistPageChange(\n input: Record<string, unknown> | null,\n scope: { hostId: string; pages: readonly AssistSitePage[] },\n): AssistPageChangeProposal | null {\n if (!input) return null\n const page = scope.pages.find((one) => one.id === text(input['page']))\n if (!page) return null\n const change = assistBuildBriefWithoutGaps(text(input['change']))\n if (!change) return null\n const summary = text(input['summary'])\n return {\n id: ASSIST_PAGE_CHANGE_ACTION_ID,\n hostId: scope.hostId,\n pageId: page.id,\n pageName: page.name,\n brief: change.slice(0, AI_JOB_BRIEF_MAX_CHARS),\n summary: (summary || `Change ${page.name}`).slice(0, ASSIST_PAGE_CHANGE_SUMMARY_MAX_CHARS),\n ...(input['newVersion'] === true ? { newVersion: true } : {}),\n }\n}\n"],"names":["ASSIST_PAGE_CHANGE_ACTION_ID","ASSIST_PAGE_CHANGE_SUMMARY_MAX_CHARS","ASSIST_PAGE_CHANGE_TOOL_NAME","ASSIST_BUILD_TOOL_NAME","AI_JOB_BRIEF_MAX_CHARS","assistBuildBriefWithoutGaps","ASSIST_SITE_PAGES_MAX","STRING","type","assistPageChangeTool","name","description","inputSchema","properties","summary","page","change","newVersion","required","additionalProperties","strict","assistPageChangeBlock","join","assistSitePagesBlock","pages","options","versioning","length","map","id","slug","live","home","text","value","trim","readAssistSitePages","firestore","hostId","hostDoc","host","collection","doc","screens","Promise","all","get","select","limit","routing","homeId","docs","data","push","startsWith","rank","sort","a","b","localeCompare","slice","resolveAssistPageChange","input","scope","find","one","pageId","pageName","brief"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/server/assist-page-change.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ASSIST_PAGE_CHANGE_ACTION_ID,\n ASSIST_PAGE_CHANGE_SUMMARY_MAX_CHARS,\n ASSIST_PAGE_CHANGE_TOOL_NAME,\n type AssistPageChangeProposal,\n} from '../model/assist-page-change'\nimport { ASSIST_BUILD_TOOL_NAME } from '../model/assist-build'\nimport type { AiTool } from '../providers/contract'\nimport { AI_JOB_BRIEF_MAX_CHARS } from '../jobs/ai-job-text-step'\nimport { assistBuildBriefWithoutGaps } from './assist-build'\n\n/**\n * A change to a page the site already has, from the Assist chat (AGL-4116):\n * the tool the model asks through, the site's pages it picks from, and the\n * resolution the panel starts an `edit` job from. See\n * `model/assist-page-change.ts`.\n */\n\n/** The most pages the chat is shown; a site's pages past it are asked about by name. */\nexport const ASSIST_SITE_PAGES_MAX = 60\n\n/** One of the site's pages, as the chat is shown it. */\nexport interface AssistSitePage {\n id: string\n name: string\n /** The address it is served at, or would be once published. */\n slug: string\n /** Visitors reach it: the site routes its address to it. */\n live: boolean\n /** The site's home page. */\n home: boolean\n}\n\nconst STRING = { type: 'string' } as const\n\nexport function assistPageChangeTool(): AiTool {\n return {\n name: ASSIST_PAGE_CHANGE_TOOL_NAME,\n description:\n 'Change a page this site already has. The change is saved into that page’s draft, or as a new ' +\n 'version when the user asks for one, and the user is given a link to open it in the Besigner, ' +\n 'check it and publish it. Call at most once per message, for one page.',\n inputSchema: {\n type: 'object',\n properties: {\n summary: STRING,\n page: STRING,\n change: STRING,\n newVersion: { type: 'boolean' },\n },\n required: ['summary', 'page', 'change', 'newVersion'],\n additionalProperties: false,\n },\n strict: true,\n }\n}\n\n/** The protocol: the same for every site, so it is cached. */\nexport function assistPageChangeBlock(): string {\n return [\n 'Changing a page the site already has:',\n `- When the user asks to change something on one of the pages under \"The site's pages\" (its words, pictures, sections, layout or look), do not plan a build. Write one sentence saying you will make the change as a draft of that page, then call the ${ASSIST_PAGE_CHANGE_TOOL_NAME} tool once.`,\n '- page: the id of that page from the list. Where two pages share a name or an address, it is the live one unless the user names the other.',\n '- change: exactly what they asked to change on that page, in their words, with what this conversation settled about it. Add nothing they did not ask for.',\n '- summary: one short sentence, such as \"Make the top image fill the background on Home\".',\n '- The change is saved into that page’s draft, on any plan: the published page stays as it is until they publish. When it is ready, the chat shows Open in the Besigner, which opens that draft, and they publish it there. A further change to the same page is made on that draft.',\n '- newVersion: true only when they ask for the change as a new or separate version of the page; otherwise false. Never offer a new version they did not ask for.',\n '- Nothing is changed when you call the tool: never say it is done. Never say you cannot use a draft, cannot edit the page or cannot give a link.',\n `- One page per message. For changes to several pages, change the first and say to ask for the next. A request that also asks for new pages, forms or anything else to be made is a build: call ${ASSIST_BUILD_TOOL_NAME} with the whole request instead.`,\n ].join('\\n')\n}\n\n/**\n * The site's pages, per site and per moment, so volatile — and, on a plan\n * without version history, that a new version cannot be made, so a request\n * for one is answered with the draft rather than a promise.\n */\nexport function assistSitePagesBlock(\n pages: readonly AssistSitePage[],\n options: { versioning: boolean } = { versioning: true },\n): string | null {\n if (!pages.length) return null\n return [\n \"The site's pages (id · name · address · live or draft):\",\n ...pages.map(\n (page) =>\n `- ${page.id} · ${page.name} · ${page.slug || '/'} · ${page.live ? 'live' : 'draft, not live'}${page.home ? ', the home page' : ''}`,\n ),\n ...(options.versioning\n ? []\n : [\n 'This workspace’s plan keeps no version history (it comes with Pro), so newVersion is always false: if they ask for a new version, say the change goes into the page’s draft instead.',\n ]),\n ].join('\\n')\n}\n\nfunction text(value: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n\n/**\n * The site's pages a change may name: not deleted, not a collection's entry\n * template, an email design or an error body. Live ones and the home page\n * first, so a cap keeps the pages a person means.\n */\nexport async function readAssistSitePages(\n firestore: FirebaseFirestore.Firestore,\n hostId: string,\n): Promise<AssistSitePage[]> {\n const host = firestore.collection('hosts').doc(hostId)\n const [hostDoc, screens] = await Promise.all([\n host.get(),\n host\n .collection('screens')\n .select('displayName', 'name', 'slug', 'kind', 'deletedAt')\n .limit(ASSIST_SITE_PAGES_MAX * 3)\n .get(),\n ])\n const routing = (hostDoc.get('screens') ?? {}) as Record<string, unknown>\n const homeId = text(hostDoc.get('defaultHomeScreenId'))\n const pages: AssistSitePage[] = []\n for (const doc of screens.docs) {\n const data = doc.data()\n // A page has no kind; an entry template, an email design and an error\n // body each carry theirs, as the site inventory reads them.\n if (data['deletedAt'] || text(data['kind'])) continue\n const slug = text(data['slug'])\n pages.push({\n id: doc.id,\n name: text(data['displayName']) || text(data['name']) || slug || doc.id,\n slug: slug.startsWith('/') ? slug : `/${slug}`,\n live: typeof routing[doc.id] === 'string',\n home: doc.id === homeId,\n })\n }\n const rank = (page: AssistSitePage) => (page.home ? 0 : page.live ? 1 : 2)\n return pages.sort((a, b) => rank(a) - rank(b) || a.slug.localeCompare(b.slug)).slice(0, ASSIST_SITE_PAGES_MAX)\n}\n\n/**\n * The model's call, held to the site's own pages: a page it named that the\n * site does not have, or a change with nothing in it, proposes nothing.\n */\nexport function resolveAssistPageChange(\n input: Record<string, unknown> | null,\n scope: { hostId: string; pages: readonly AssistSitePage[] },\n): AssistPageChangeProposal | null {\n if (!input) return null\n const page = scope.pages.find((one) => one.id === text(input['page']))\n if (!page) return null\n const change = assistBuildBriefWithoutGaps(text(input['change']))\n if (!change) return null\n const summary = text(input['summary'])\n return {\n id: ASSIST_PAGE_CHANGE_ACTION_ID,\n hostId: scope.hostId,\n pageId: page.id,\n pageName: page.name,\n brief: change.slice(0, AI_JOB_BRIEF_MAX_CHARS),\n summary: (summary || `Change ${page.name}`).slice(0, ASSIST_PAGE_CHANGE_SUMMARY_MAX_CHARS),\n ...(input['newVersion'] === true ? { newVersion: true } : {}),\n }\n}\n"],"names":["ASSIST_PAGE_CHANGE_ACTION_ID","ASSIST_PAGE_CHANGE_SUMMARY_MAX_CHARS","ASSIST_PAGE_CHANGE_TOOL_NAME","ASSIST_BUILD_TOOL_NAME","AI_JOB_BRIEF_MAX_CHARS","assistBuildBriefWithoutGaps","ASSIST_SITE_PAGES_MAX","STRING","type","assistPageChangeTool","name","description","inputSchema","properties","summary","page","change","newVersion","required","additionalProperties","strict","assistPageChangeBlock","join","assistSitePagesBlock","pages","options","versioning","length","map","id","slug","live","home","text","value","trim","readAssistSitePages","firestore","hostId","hostDoc","host","collection","doc","screens","Promise","all","get","select","limit","routing","homeId","docs","data","push","startsWith","rank","sort","a","b","localeCompare","slice","resolveAssistPageChange","input","scope","find","one","pageId","pageName","brief"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,4BAA4B,EAC5BC,oCAAoC,EACpCC,4BAA4B,QAEvB,iCAA6B;AACpC,SAASC,sBAAsB,QAAQ,2BAAuB;AAE9D,SAASC,sBAAsB,QAAQ,8BAA0B;AACjE,SAASC,2BAA2B,QAAQ,oBAAgB;AAE5D;;;;;CAKC,GAED,sFAAsF,GACtF,OAAO,MAAMC,wBAAwB,GAAE;AAcvC,MAAMC,SAAS;IAAEC,MAAM;AAAS;AAEhC,OAAO,SAASC;IACd,OAAO;QACLC,MAAMR;QACNS,aACE,kGACA,kGACA;QACFC,aAAa;YACXJ,MAAM;YACNK,YAAY;gBACVC,SAASP;gBACTQ,MAAMR;gBACNS,QAAQT;gBACRU,YAAY;oBAAET,MAAM;gBAAU;YAChC;YACAU,UAAU;gBAAC;gBAAW;gBAAQ;gBAAU;aAAa;YACrDC,sBAAsB;QACxB;QACAC,QAAQ;IACV;AACF;AAEA,4DAA4D,GAC5D,OAAO,SAASC;IACd,OAAO;QACL;QACA,CAAC,sPAAsP,EAAEnB,6BAA6B,WAAW,CAAC;QAClS;QACA;QACA;QACA;QACA;QACA;QACA,CAAC,+LAA+L,EAAEC,uBAAuB,gCAAgC,CAAC;KAC3P,CAACmB,IAAI,CAAC;AACT;AAEA;;;;CAIC,GACD,OAAO,SAASC,qBACdC,KAAgC,EAChCC,UAAmC;IAAEC,YAAY;AAAK,CAAC;IAEvD,IAAI,CAACF,MAAMG,MAAM,EAAE,OAAO;IAC1B,OAAO;QACL;WACGH,MAAMI,GAAG,CACV,CAACb,OACC,CAAC,EAAE,EAAEA,KAAKc,EAAE,CAAC,GAAG,EAAEd,KAAKL,IAAI,CAAC,GAAG,EAAEK,KAAKe,IAAI,IAAI,IAAI,GAAG,EAAEf,KAAKgB,IAAI,GAAG,SAAS,oBAAoBhB,KAAKiB,IAAI,GAAG,oBAAoB,IAAI;WAEpIP,QAAQC,UAAU,GAClB,EAAE,GACF;YACE;SACD;KACN,CAACJ,IAAI,CAAC;AACT;AAEA,SAASW,KAAKC,KAAc;IAC1B,OAAO,OAAOA,UAAU,WAAWA,MAAMC,IAAI,KAAK;AACpD;AAEA;;;;CAIC,GACD,OAAO,eAAeC,oBACpBC,SAAsC,EACtCC,MAAc;QAWGC;IATjB,MAAMC,OAAOH,UAAUI,UAAU,CAAC,SAASC,GAAG,CAACJ;IAC/C,MAAM,CAACC,SAASI,QAAQ,GAAG,MAAMC,QAAQC,GAAG,CAAC;QAC3CL,KAAKM,GAAG;QACRN,KACGC,UAAU,CAAC,WACXM,MAAM,CAAC,eAAe,QAAQ,QAAQ,QAAQ,aAC9CC,KAAK,CAAC1C,wBAAwB,GAC9BwC,GAAG;KACP;IACD,MAAMG,WAAWV,eAAAA,QAAQO,GAAG,CAAC,sBAAZP,eAA0B,CAAC;IAC5C,MAAMW,SAASjB,KAAKM,QAAQO,GAAG,CAAC;IAChC,MAAMtB,QAA0B,EAAE;IAClC,KAAK,MAAMkB,OAAOC,QAAQQ,IAAI,CAAE;QAC9B,MAAMC,OAAOV,IAAIU,IAAI;QACrB,sEAAsE;QACtE,4DAA4D;QAC5D,IAAIA,IAAI,CAAC,YAAY,IAAInB,KAAKmB,IAAI,CAAC,OAAO,GAAG;QAC7C,MAAMtB,OAAOG,KAAKmB,IAAI,CAAC,OAAO;QAC9B5B,MAAM6B,IAAI,CAAC;YACTxB,IAAIa,IAAIb,EAAE;YACVnB,MAAMuB,KAAKmB,IAAI,CAAC,cAAc,KAAKnB,KAAKmB,IAAI,CAAC,OAAO,KAAKtB,QAAQY,IAAIb,EAAE;YACvEC,MAAMA,KAAKwB,UAAU,CAAC,OAAOxB,OAAO,CAAC,CAAC,EAAEA,MAAM;YAC9CC,MAAM,OAAOkB,OAAO,CAACP,IAAIb,EAAE,CAAC,KAAK;YACjCG,MAAMU,IAAIb,EAAE,KAAKqB;QACnB;IACF;IACA,MAAMK,OAAO,CAACxC,OAA0BA,KAAKiB,IAAI,GAAG,IAAIjB,KAAKgB,IAAI,GAAG,IAAI;IACxE,OAAOP,MAAMgC,IAAI,CAAC,CAACC,GAAGC,IAAMH,KAAKE,KAAKF,KAAKG,MAAMD,EAAE3B,IAAI,CAAC6B,aAAa,CAACD,EAAE5B,IAAI,GAAG8B,KAAK,CAAC,GAAGtD;AAC1F;AAEA;;;CAGC,GACD,OAAO,SAASuD,wBACdC,KAAqC,EACrCC,KAA2D;IAE3D,IAAI,CAACD,OAAO,OAAO;IACnB,MAAM/C,OAAOgD,MAAMvC,KAAK,CAACwC,IAAI,CAAC,CAACC,MAAQA,IAAIpC,EAAE,KAAKI,KAAK6B,KAAK,CAAC,OAAO;IACpE,IAAI,CAAC/C,MAAM,OAAO;IAClB,MAAMC,SAASX,4BAA4B4B,KAAK6B,KAAK,CAAC,SAAS;IAC/D,IAAI,CAAC9C,QAAQ,OAAO;IACpB,MAAMF,UAAUmB,KAAK6B,KAAK,CAAC,UAAU;IACrC,OAAO;QACLjC,IAAI7B;QACJsC,QAAQyB,MAAMzB,MAAM;QACpB4B,QAAQnD,KAAKc,EAAE;QACfsC,UAAUpD,KAAKL,IAAI;QACnB0D,OAAOpD,OAAO4C,KAAK,CAAC,GAAGxD;QACvBU,SAAS,AAACA,CAAAA,WAAW,CAAC,OAAO,EAAEC,KAAKL,IAAI,EAAE,AAAD,EAAGkD,KAAK,CAAC,GAAG3D;OACjD6D,KAAK,CAAC,aAAa,KAAK,OAAO;QAAE7C,YAAY;IAAK,IAAI,CAAC;AAE/D"}