@aglyn/plugins-ai 1.0.0-beta.230 → 1.0.0-beta.231

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 (139) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-assist-provider-on-host.component.d.ts +66 -0
  3. package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
  4. package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
  5. package/src/lib/components/ai-assist-provider.component.js +9 -10
  6. package/src/lib/components/ai-assist-provider.component.js.map +1 -1
  7. package/src/lib/components/ai-job-plan.component.js +3 -1
  8. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  9. package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
  10. package/src/lib/components/ai-permissions-on-host.component.js +5 -53
  11. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
  12. package/src/lib/components/ai-site-build-page.component.js +20 -8
  13. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  14. package/src/lib/jobs/ai-build-unit-outcome.js +4 -2
  15. package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -1
  16. package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
  17. package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
  18. package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
  19. package/src/lib/jobs/ai-job-build-step.js +11 -0
  20. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  21. package/src/lib/jobs/ai-job-generation.d.ts +8 -0
  22. package/src/lib/jobs/ai-job-generation.js +13 -2
  23. package/src/lib/jobs/ai-job-generation.js.map +1 -1
  24. package/src/lib/jobs/ai-job-insight-step.js +8 -1
  25. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  26. package/src/lib/jobs/ai-job-layout-language.d.ts +73 -0
  27. package/src/lib/jobs/ai-job-layout-language.js +194 -0
  28. package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
  29. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
  30. package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
  31. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  32. package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
  33. package/src/lib/jobs/ai-job-layout-step.js +105 -5
  34. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  35. package/src/lib/jobs/ai-job-page-language.d.ts +149 -0
  36. package/src/lib/jobs/ai-job-page-language.js +355 -0
  37. package/src/lib/jobs/ai-job-page-language.js.map +1 -0
  38. package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
  39. package/src/lib/jobs/ai-job-page-sections.js +93 -11
  40. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  41. package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
  42. package/src/lib/jobs/ai-job-page-step.js +105 -14
  43. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  44. package/src/lib/jobs/ai-job-plan-step.d.ts +1 -1
  45. package/src/lib/jobs/ai-job-plan-step.js +8 -2
  46. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  47. package/src/lib/jobs/ai-job-site-step.d.ts +4 -0
  48. package/src/lib/jobs/ai-job-site-step.js +20 -3
  49. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  50. package/src/lib/jobs/ai-job-workflow-step.js +2 -2
  51. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  52. package/src/lib/jobs/ai-jobs.d.ts +1 -1
  53. package/src/lib/jobs/ai-jobs.js +17 -8
  54. package/src/lib/jobs/ai-jobs.js.map +1 -1
  55. package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
  56. package/src/lib/jobs/ai-layout-full-height.js +82 -0
  57. package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
  58. package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
  59. package/src/lib/jobs/ai-layout-site-facts.js +153 -0
  60. package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
  61. package/src/lib/layout-language/ai-layout-compiler.d.ts +145 -0
  62. package/src/lib/layout-language/ai-layout-compiler.js +1148 -0
  63. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
  64. package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
  65. package/src/lib/layout-language/ai-layout-copy.js +137 -0
  66. package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
  67. package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
  68. package/src/lib/layout-language/ai-layout-frame.js +457 -0
  69. package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
  70. package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
  71. package/src/lib/layout-language/ai-layout-gaps.js +345 -0
  72. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
  73. package/src/lib/layout-language/ai-layout-language.d.ts +161 -0
  74. package/src/lib/layout-language/ai-layout-language.js +446 -0
  75. package/src/lib/layout-language/ai-layout-language.js.map +1 -0
  76. package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
  77. package/src/lib/layout-language/ai-layout-links.js +109 -0
  78. package/src/lib/layout-language/ai-layout-links.js.map +1 -0
  79. package/src/lib/layout-language/ai-layout-store.d.ts +39 -0
  80. package/src/lib/layout-language/ai-layout-store.js +69 -0
  81. package/src/lib/layout-language/ai-layout-store.js.map +1 -0
  82. package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
  83. package/src/lib/layout-language/ai-layout-tree.js +84 -0
  84. package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
  85. package/src/lib/lazy-widget.d.ts +45 -0
  86. package/src/lib/lazy-widget.js +53 -0
  87. package/src/lib/lazy-widget.js.map +1 -0
  88. package/src/lib/model/ai-build-job.js +2 -1
  89. package/src/lib/model/ai-build-job.js.map +1 -1
  90. package/src/lib/model/ai-build-progress.d.ts +20 -3
  91. package/src/lib/model/ai-build-progress.js +48 -6
  92. package/src/lib/model/ai-build-progress.js.map +1 -1
  93. package/src/lib/model/ai-host-publish-context.d.ts +51 -0
  94. package/src/lib/model/ai-host-publish-context.js +104 -0
  95. package/src/lib/model/ai-host-publish-context.js.map +1 -0
  96. package/src/lib/model/ai-job-activity.d.ts +22 -0
  97. package/src/lib/model/ai-job-activity.js +22 -1
  98. package/src/lib/model/ai-job-activity.js.map +1 -1
  99. package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
  100. package/src/lib/model/ai-job-failure-copy.js +56 -1
  101. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  102. package/src/lib/model/ai-job-notice.d.ts +3 -1
  103. package/src/lib/model/ai-job-notice.js +31 -9
  104. package/src/lib/model/ai-job-notice.js.map +1 -1
  105. package/src/lib/model/ai-jobs.types.d.ts +19 -0
  106. package/src/lib/model/ai-jobs.types.js.map +1 -1
  107. package/src/lib/model/ai-site-build-progress.d.ts +5 -1
  108. package/src/lib/model/ai-site-build-progress.js +27 -4
  109. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  110. package/src/lib/model/ai-site-job.d.ts +8 -0
  111. package/src/lib/model/ai-site-job.js +9 -0
  112. package/src/lib/model/ai-site-job.js.map +1 -1
  113. package/src/lib/model/ai-site-start-seo.d.ts +1 -1
  114. package/src/lib/model/ai-site-start.d.ts +5 -2
  115. package/src/lib/model/ai-site-start.js +5 -2
  116. package/src/lib/model/ai-site-start.js.map +1 -1
  117. package/src/lib/plugin.js +79 -47
  118. package/src/lib/plugin.js.map +1 -1
  119. package/src/lib/providers/catalog.d.ts +1 -1
  120. package/src/lib/providers/catalog.js +3 -3
  121. package/src/lib/providers/catalog.js.map +1 -1
  122. package/src/lib/runtime/ai-doctrine-validators.d.ts +82 -0
  123. package/src/lib/runtime/ai-doctrine-validators.js +436 -4
  124. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  125. package/src/lib/runtime/ai-doctrine.js +12 -3
  126. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  127. package/src/lib/runtime/ai-icon-library.d.ts +257 -0
  128. package/src/lib/runtime/ai-icon-library.js +254 -0
  129. package/src/lib/runtime/ai-icon-library.js.map +1 -0
  130. package/src/lib/runtime/ai-node-tree.d.ts +9 -0
  131. package/src/lib/runtime/ai-node-tree.js +30 -4
  132. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  133. package/src/lib/runtime/ai-palette.d.ts +6 -0
  134. package/src/lib/runtime/ai-palette.generated.js +70 -0
  135. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  136. package/src/lib/runtime/ai-palette.js.map +1 -1
  137. package/src/lib/tools/ai-workflow-tool.d.ts +6 -2
  138. package/src/lib/tools/ai-workflow-tool.js +16 -14
  139. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { aiPageLinkSection } from "../runtime/ai-page-links.js";
17
+ /** The words of a label or a name, as they are compared. */ function wordsOf(text) {
18
+ return text.toLowerCase().split(RegExp("[^\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376-\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0588\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u064A\\u066E-\\u066F\\u0671-\\u06D3\\u06D5\\u06E5-\\u06E6\\u06EE-\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4-\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u0860-\\u086A\\u0870-\\u0887\\u0889-\\u088F\\u08A0-\\u08C9\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F-\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC-\\u09DD\\u09DF-\\u09E1\\u09F0-\\u09F1\\u09FC\\u0A05-\\u0A0A\\u0A0F-\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32-\\u0A33\\u0A35-\\u0A36\\u0A38-\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2-\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0-\\u0AE1\\u0AF9\\u0B05-\\u0B0C\\u0B0F-\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32-\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C-\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99-\\u0B9A\\u0B9C\\u0B9E-\\u0B9F\\u0BA3-\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58-\\u0C5A\\u0C5C-\\u0C5D\\u0C60-\\u0C61\\u0C80\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDC-\\u0CDE\\u0CE0-\\u0CE1\\u0CF1-\\u0CF2\\u0D04-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D54-\\u0D56\\u0D5F-\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32-\\u0E33\\u0E40-\\u0E46\\u0E81-\\u0E82\\u0E84\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB0\\u0EB2-\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065-\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F5\\u13F8-\\u13FD\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16F1-\\u16F8\\u1700-\\u1711\\u171F-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1878\\u1880-\\u1884\\u1887-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4C\\u1B83-\\u1BA0\\u1BAE-\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1C80-\\u1C8A\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1CE9-\\u1CEC\\u1CEE-\\u1CF3\\u1CF5-\\u1CF6\\u1CFA\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183-\\u2184\\u2C00-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3006\\u3031-\\u3035\\u303B-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312F\\u3131-\\u318E\\u31A0-\\u31BF\\u31F0-\\u31FF\\u3400-\\u4DBF\\u4E00-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A-\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA7DC\\uA7F1-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA8FD-\\uA8FE\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5-\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB69\\uAB70-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40-\\uFB41\\uFB43-\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC\\u{10000}-\\u{1000B}\\u{1000D}-\\u{10026}\\u{10028}-\\u{1003A}\\u{1003C}-\\u{1003D}\\u{1003F}-\\u{1004D}\\u{10050}-\\u{1005D}\\u{10080}-\\u{100FA}\\u{10280}-\\u{1029C}\\u{102A0}-\\u{102D0}\\u{10300}-\\u{1031F}\\u{1032D}-\\u{10340}\\u{10342}-\\u{10349}\\u{10350}-\\u{10375}\\u{10380}-\\u{1039D}\\u{103A0}-\\u{103C3}\\u{103C8}-\\u{103CF}\\u{10400}-\\u{1049D}\\u{104B0}-\\u{104D3}\\u{104D8}-\\u{104FB}\\u{10500}-\\u{10527}\\u{10530}-\\u{10563}\\u{10570}-\\u{1057A}\\u{1057C}-\\u{1058A}\\u{1058C}-\\u{10592}\\u{10594}-\\u{10595}\\u{10597}-\\u{105A1}\\u{105A3}-\\u{105B1}\\u{105B3}-\\u{105B9}\\u{105BB}-\\u{105BC}\\u{105C0}-\\u{105F3}\\u{10600}-\\u{10736}\\u{10740}-\\u{10755}\\u{10760}-\\u{10767}\\u{10780}-\\u{10785}\\u{10787}-\\u{107B0}\\u{107B2}-\\u{107BA}\\u{10800}-\\u{10805}\\u{10808}\\u{1080A}-\\u{10835}\\u{10837}-\\u{10838}\\u{1083C}\\u{1083F}-\\u{10855}\\u{10860}-\\u{10876}\\u{10880}-\\u{1089E}\\u{108E0}-\\u{108F2}\\u{108F4}-\\u{108F5}\\u{10900}-\\u{10915}\\u{10920}-\\u{10939}\\u{10940}-\\u{10959}\\u{10980}-\\u{109B7}\\u{109BE}-\\u{109BF}\\u{10A00}\\u{10A10}-\\u{10A13}\\u{10A15}-\\u{10A17}\\u{10A19}-\\u{10A35}\\u{10A60}-\\u{10A7C}\\u{10A80}-\\u{10A9C}\\u{10AC0}-\\u{10AC7}\\u{10AC9}-\\u{10AE4}\\u{10B00}-\\u{10B35}\\u{10B40}-\\u{10B55}\\u{10B60}-\\u{10B72}\\u{10B80}-\\u{10B91}\\u{10C00}-\\u{10C48}\\u{10C80}-\\u{10CB2}\\u{10CC0}-\\u{10CF2}\\u{10D00}-\\u{10D23}\\u{10D4A}-\\u{10D65}\\u{10D6F}-\\u{10D85}\\u{10E80}-\\u{10EA9}\\u{10EB0}-\\u{10EB1}\\u{10EC2}-\\u{10EC7}\\u{10F00}-\\u{10F1C}\\u{10F27}\\u{10F30}-\\u{10F45}\\u{10F70}-\\u{10F81}\\u{10FB0}-\\u{10FC4}\\u{10FE0}-\\u{10FF6}\\u{11003}-\\u{11037}\\u{11071}-\\u{11072}\\u{11075}\\u{11083}-\\u{110AF}\\u{110D0}-\\u{110E8}\\u{11103}-\\u{11126}\\u{11144}\\u{11147}\\u{11150}-\\u{11172}\\u{11176}\\u{11183}-\\u{111B2}\\u{111C1}-\\u{111C4}\\u{111DA}\\u{111DC}\\u{11200}-\\u{11211}\\u{11213}-\\u{1122B}\\u{1123F}-\\u{11240}\\u{11280}-\\u{11286}\\u{11288}\\u{1128A}-\\u{1128D}\\u{1128F}-\\u{1129D}\\u{1129F}-\\u{112A8}\\u{112B0}-\\u{112DE}\\u{11305}-\\u{1130C}\\u{1130F}-\\u{11310}\\u{11313}-\\u{11328}\\u{1132A}-\\u{11330}\\u{11332}-\\u{11333}\\u{11335}-\\u{11339}\\u{1133D}\\u{11350}\\u{1135D}-\\u{11361}\\u{11380}-\\u{11389}\\u{1138B}\\u{1138E}\\u{11390}-\\u{113B5}\\u{113B7}\\u{113D1}\\u{113D3}\\u{11400}-\\u{11434}\\u{11447}-\\u{1144A}\\u{1145F}-\\u{11461}\\u{11480}-\\u{114AF}\\u{114C4}-\\u{114C5}\\u{114C7}\\u{11580}-\\u{115AE}\\u{115D8}-\\u{115DB}\\u{11600}-\\u{1162F}\\u{11644}\\u{11680}-\\u{116AA}\\u{116B8}\\u{11700}-\\u{1171A}\\u{11740}-\\u{11746}\\u{11800}-\\u{1182B}\\u{118A0}-\\u{118DF}\\u{118FF}-\\u{11906}\\u{11909}\\u{1190C}-\\u{11913}\\u{11915}-\\u{11916}\\u{11918}-\\u{1192F}\\u{1193F}\\u{11941}\\u{119A0}-\\u{119A7}\\u{119AA}-\\u{119D0}\\u{119E1}\\u{119E3}\\u{11A00}\\u{11A0B}-\\u{11A32}\\u{11A3A}\\u{11A50}\\u{11A5C}-\\u{11A89}\\u{11A9D}\\u{11AB0}-\\u{11AF8}\\u{11BC0}-\\u{11BE0}\\u{11C00}-\\u{11C08}\\u{11C0A}-\\u{11C2E}\\u{11C40}\\u{11C72}-\\u{11C8F}\\u{11D00}-\\u{11D06}\\u{11D08}-\\u{11D09}\\u{11D0B}-\\u{11D30}\\u{11D46}\\u{11D60}-\\u{11D65}\\u{11D67}-\\u{11D68}\\u{11D6A}-\\u{11D89}\\u{11D98}\\u{11DB0}-\\u{11DDB}\\u{11EE0}-\\u{11EF2}\\u{11F02}\\u{11F04}-\\u{11F10}\\u{11F12}-\\u{11F33}\\u{11FB0}\\u{12000}-\\u{12399}\\u{12480}-\\u{12543}\\u{12F90}-\\u{12FF0}\\u{13000}-\\u{1342F}\\u{13441}-\\u{13446}\\u{13460}-\\u{143FA}\\u{14400}-\\u{14646}\\u{16100}-\\u{1611D}\\u{16800}-\\u{16A38}\\u{16A40}-\\u{16A5E}\\u{16A70}-\\u{16ABE}\\u{16AD0}-\\u{16AED}\\u{16B00}-\\u{16B2F}\\u{16B40}-\\u{16B43}\\u{16B63}-\\u{16B77}\\u{16B7D}-\\u{16B8F}\\u{16D40}-\\u{16D6C}\\u{16E40}-\\u{16E7F}\\u{16EA0}-\\u{16EB8}\\u{16EBB}-\\u{16ED3}\\u{16F00}-\\u{16F4A}\\u{16F50}\\u{16F93}-\\u{16F9F}\\u{16FE0}-\\u{16FE1}\\u{16FE3}\\u{16FF2}-\\u{16FF3}\\u{17000}-\\u{18CD5}\\u{18CFF}-\\u{18D1E}\\u{18D80}-\\u{18DF2}\\u{1AFF0}-\\u{1AFF3}\\u{1AFF5}-\\u{1AFFB}\\u{1AFFD}-\\u{1AFFE}\\u{1B000}-\\u{1B122}\\u{1B132}\\u{1B150}-\\u{1B152}\\u{1B155}\\u{1B164}-\\u{1B167}\\u{1B170}-\\u{1B2FB}\\u{1BC00}-\\u{1BC6A}\\u{1BC70}-\\u{1BC7C}\\u{1BC80}-\\u{1BC88}\\u{1BC90}-\\u{1BC99}\\u{1D400}-\\u{1D454}\\u{1D456}-\\u{1D49C}\\u{1D49E}-\\u{1D49F}\\u{1D4A2}\\u{1D4A5}-\\u{1D4A6}\\u{1D4A9}-\\u{1D4AC}\\u{1D4AE}-\\u{1D4B9}\\u{1D4BB}\\u{1D4BD}-\\u{1D4C3}\\u{1D4C5}-\\u{1D505}\\u{1D507}-\\u{1D50A}\\u{1D50D}-\\u{1D514}\\u{1D516}-\\u{1D51C}\\u{1D51E}-\\u{1D539}\\u{1D53B}-\\u{1D53E}\\u{1D540}-\\u{1D544}\\u{1D546}\\u{1D54A}-\\u{1D550}\\u{1D552}-\\u{1D6A5}\\u{1D6A8}-\\u{1D6C0}\\u{1D6C2}-\\u{1D6DA}\\u{1D6DC}-\\u{1D6FA}\\u{1D6FC}-\\u{1D714}\\u{1D716}-\\u{1D734}\\u{1D736}-\\u{1D74E}\\u{1D750}-\\u{1D76E}\\u{1D770}-\\u{1D788}\\u{1D78A}-\\u{1D7A8}\\u{1D7AA}-\\u{1D7C2}\\u{1D7C4}-\\u{1D7CB}\\u{1DF00}-\\u{1DF1E}\\u{1DF25}-\\u{1DF2A}\\u{1E030}-\\u{1E06D}\\u{1E100}-\\u{1E12C}\\u{1E137}-\\u{1E13D}\\u{1E14E}\\u{1E290}-\\u{1E2AD}\\u{1E2C0}-\\u{1E2EB}\\u{1E4D0}-\\u{1E4EB}\\u{1E5D0}-\\u{1E5ED}\\u{1E5F0}\\u{1E6C0}-\\u{1E6DE}\\u{1E6E0}-\\u{1E6E2}\\u{1E6E4}-\\u{1E6E5}\\u{1E6E7}-\\u{1E6ED}\\u{1E6F0}-\\u{1E6F4}\\u{1E6FE}-\\u{1E6FF}\\u{1E7E0}-\\u{1E7E6}\\u{1E7E8}-\\u{1E7EB}\\u{1E7ED}-\\u{1E7EE}\\u{1E7F0}-\\u{1E7FE}\\u{1E800}-\\u{1E8C4}\\u{1E900}-\\u{1E943}\\u{1E94B}\\u{1EE00}-\\u{1EE03}\\u{1EE05}-\\u{1EE1F}\\u{1EE21}-\\u{1EE22}\\u{1EE24}\\u{1EE27}\\u{1EE29}-\\u{1EE32}\\u{1EE34}-\\u{1EE37}\\u{1EE39}\\u{1EE3B}\\u{1EE42}\\u{1EE47}\\u{1EE49}\\u{1EE4B}\\u{1EE4D}-\\u{1EE4F}\\u{1EE51}-\\u{1EE52}\\u{1EE54}\\u{1EE57}\\u{1EE59}\\u{1EE5B}\\u{1EE5D}\\u{1EE5F}\\u{1EE61}-\\u{1EE62}\\u{1EE64}\\u{1EE67}-\\u{1EE6A}\\u{1EE6C}-\\u{1EE72}\\u{1EE74}-\\u{1EE77}\\u{1EE79}-\\u{1EE7C}\\u{1EE7E}\\u{1EE80}-\\u{1EE89}\\u{1EE8B}-\\u{1EE9B}\\u{1EEA1}-\\u{1EEA3}\\u{1EEA5}-\\u{1EEA9}\\u{1EEAB}-\\u{1EEBB}\\u{20000}-\\u{2A6DF}\\u{2A700}-\\u{2B81D}\\u{2B820}-\\u{2CEAD}\\u{2CEB0}-\\u{2EBE0}\\u{2EBF0}-\\u{2EE5D}\\u{2F800}-\\u{2FA1D}\\u{30000}-\\u{3134A}\\u{31350}-\\u{33479}\\u0030-\\u0039\\u00B2-\\u00B3\\u00B9\\u00BC-\\u00BE\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u09F4-\\u09F9\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0B72-\\u0B77\\u0BE6-\\u0BF2\\u0C66-\\u0C6F\\u0C78-\\u0C7E\\u0CE6-\\u0CEF\\u0D58-\\u0D5E\\u0D66-\\u0D78\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F33\\u1040-\\u1049\\u1090-\\u1099\\u1369-\\u137C\\u16EE-\\u16F0\\u17E0-\\u17E9\\u17F0-\\u17F9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19DA\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\u2070\\u2074-\\u2079\\u2080-\\u2089\\u2150-\\u2182\\u2185-\\u2189\\u2460-\\u249B\\u24EA-\\u24FF\\u2776-\\u2793\\u2CFD\\u3007\\u3021-\\u3029\\u3038-\\u303A\\u3192-\\u3195\\u3220-\\u3229\\u3248-\\u324F\\u3251-\\u325F\\u3280-\\u3289\\u32B1-\\u32BF\\uA620-\\uA629\\uA6E6-\\uA6EF\\uA830-\\uA835\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19\\u{10107}-\\u{10133}\\u{10140}-\\u{10178}\\u{1018A}-\\u{1018B}\\u{102E1}-\\u{102FB}\\u{10320}-\\u{10323}\\u{10341}\\u{1034A}\\u{103D1}-\\u{103D5}\\u{104A0}-\\u{104A9}\\u{10858}-\\u{1085F}\\u{10879}-\\u{1087F}\\u{108A7}-\\u{108AF}\\u{108FB}-\\u{108FF}\\u{10916}-\\u{1091B}\\u{109BC}-\\u{109BD}\\u{109C0}-\\u{109CF}\\u{109D2}-\\u{109FF}\\u{10A40}-\\u{10A48}\\u{10A7D}-\\u{10A7E}\\u{10A9D}-\\u{10A9F}\\u{10AEB}-\\u{10AEF}\\u{10B58}-\\u{10B5F}\\u{10B78}-\\u{10B7F}\\u{10BA9}-\\u{10BAF}\\u{10CFA}-\\u{10CFF}\\u{10D30}-\\u{10D39}\\u{10D40}-\\u{10D49}\\u{10E60}-\\u{10E7E}\\u{10F1D}-\\u{10F26}\\u{10F51}-\\u{10F54}\\u{10FC5}-\\u{10FCB}\\u{11052}-\\u{1106F}\\u{110F0}-\\u{110F9}\\u{11136}-\\u{1113F}\\u{111D0}-\\u{111D9}\\u{111E1}-\\u{111F4}\\u{112F0}-\\u{112F9}\\u{11450}-\\u{11459}\\u{114D0}-\\u{114D9}\\u{11650}-\\u{11659}\\u{116C0}-\\u{116C9}\\u{116D0}-\\u{116E3}\\u{11730}-\\u{1173B}\\u{118E0}-\\u{118F2}\\u{11950}-\\u{11959}\\u{11BF0}-\\u{11BF9}\\u{11C50}-\\u{11C6C}\\u{11D50}-\\u{11D59}\\u{11DA0}-\\u{11DA9}\\u{11DE0}-\\u{11DE9}\\u{11F50}-\\u{11F59}\\u{11FC0}-\\u{11FD4}\\u{12400}-\\u{1246E}\\u{16130}-\\u{16139}\\u{16A60}-\\u{16A69}\\u{16AC0}-\\u{16AC9}\\u{16B50}-\\u{16B59}\\u{16B5B}-\\u{16B61}\\u{16D70}-\\u{16D79}\\u{16E80}-\\u{16E96}\\u{16FF4}-\\u{16FF6}\\u{1CCF0}-\\u{1CCF9}\\u{1D2C0}-\\u{1D2D3}\\u{1D2E0}-\\u{1D2F3}\\u{1D360}-\\u{1D378}\\u{1D7CE}-\\u{1D7FF}\\u{1E140}-\\u{1E149}\\u{1E2F0}-\\u{1E2F9}\\u{1E4F0}-\\u{1E4F9}\\u{1E5F1}-\\u{1E5FA}\\u{1E8C7}-\\u{1E8CF}\\u{1E950}-\\u{1E959}\\u{1EC71}-\\u{1ECAB}\\u{1ECAD}-\\u{1ECAF}\\u{1ECB1}-\\u{1ECB4}\\u{1ED01}-\\u{1ED2D}\\u{1ED2F}-\\u{1ED3D}\\u{1F100}-\\u{1F10C}\\u{1FBF0}-\\u{1FBF9}]+", "u")).filter(Boolean);
19
+ }
20
+ function slugOf(slug) {
21
+ return `/${slug.replace(/^\/+|\/+$/g, '')}`.toLowerCase();
22
+ }
23
+ const HOME_WORDS = /\bhome(?:\s?page)?\b/i;
24
+ /** Words that ask a visitor to get in touch, which the site's form answers. */ const CONTACT_WORDS = /\b(?:contact|book|booking|call|quote|estimate|appointment|schedule|reserve|reservation|get in touch|request|visit|enquire|inquire|enquiry|inquiry|message|talk|consult|consultation|order|sign up|join|apply|start)\b/i;
25
+ /** The page a word names: an id, a label or an address. */ function pageNamed(word, targets) {
26
+ var _targets_pages_find, _targets_pages_find1;
27
+ const value = word.trim();
28
+ if (!value) return null;
29
+ const byId = targets.pages.find((page)=>page.id === value);
30
+ if (byId) return byId;
31
+ const lower = value.toLowerCase();
32
+ if (lower.startsWith('/')) return (_targets_pages_find = targets.pages.find((page)=>slugOf(page.slug) === slugOf(lower))) != null ? _targets_pages_find : null;
33
+ const words = wordsOf(value).join(' ');
34
+ return (_targets_pages_find1 = targets.pages.find((page)=>wordsOf(page.label).join(' ') === words)) != null ? _targets_pages_find1 : null;
35
+ }
36
+ /** A destination rule 10 admits, from the page it names, for the words a link shows. */ function pageDestination(page, label, targets) {
37
+ if (!page || page.id === targets.pageId) return null;
38
+ if (targets.homeIds.includes(page.id) && !HOME_WORDS.test(label) && !isHomeSlug(page.slug)) return null;
39
+ if (isHomeSlug(page.slug) && !HOME_WORDS.test(label)) return null;
40
+ return {
41
+ kind: 'page',
42
+ screenId: page.id
43
+ };
44
+ }
45
+ function isHomeSlug(slug) {
46
+ return slugOf(slug) === '/';
47
+ }
48
+ /** Where the site's form is: a section of this page, else the page that places it. */ function formDestination(scope, targets) {
49
+ if (scope.formSection !== null && scope.formSection !== scope.from) return {
50
+ kind: 'section',
51
+ index: scope.formSection
52
+ };
53
+ if (targets.formPageId && targets.formPageId !== targets.pageId) {
54
+ return {
55
+ kind: 'page',
56
+ screenId: targets.formPageId
57
+ };
58
+ }
59
+ return null;
60
+ }
61
+ /**
62
+ * Where a link goes: the destination its `to` names, read the language's
63
+ * way; failing that, for words that ask a visitor to get in touch, the site's
64
+ * form; failing that, a page whose name the words say. `null` is a link with
65
+ * nowhere to go, which is left out.
66
+ */ export function aiLayoutResolveLink(to, label, scope, targets) {
67
+ const named = to ? resolveNamed(to.trim(), label, scope, targets) : null;
68
+ if (named) return named;
69
+ if (CONTACT_WORDS.test(label)) {
70
+ const form = formDestination(scope, targets);
71
+ if (form) return form;
72
+ const contact = targets.pages.find((page)=>page.id !== targets.pageId && !isHomeSlug(page.slug) && CONTACT_WORDS.test(page.label));
73
+ if (contact) return {
74
+ kind: 'page',
75
+ screenId: contact.id
76
+ };
77
+ }
78
+ const labelWords = new Set(wordsOf(label));
79
+ const said = targets.pages.filter((page)=>page.id !== targets.pageId && !isHomeSlug(page.slug) && wordsOf(page.label).length > 0 && wordsOf(page.label).every((word)=>labelWords.has(word)));
80
+ return said.length === 1 ? {
81
+ kind: 'page',
82
+ screenId: said[0].id
83
+ } : null;
84
+ }
85
+ function resolveNamed(to, label, scope, targets) {
86
+ const lower = to.toLowerCase();
87
+ if (lower === 'form' || lower.startsWith('form:') || targets.forms.some((form)=>form.id === to)) {
88
+ return formDestination(scope, targets);
89
+ }
90
+ if (lower.startsWith('https://')) {
91
+ return targets.facts.includes(to) ? {
92
+ kind: 'href',
93
+ href: to
94
+ } : null;
95
+ }
96
+ const section = lower.startsWith('#') ? to.slice(1) : lower.startsWith('section:') ? to.slice(8) : null;
97
+ if (section !== null) {
98
+ const number = Number(section.trim());
99
+ const index = Number.isInteger(number) && number >= 1 && number <= scope.sections.length ? number - 1 : aiPageLinkSection(section, scope.sections);
100
+ return index !== null && index !== scope.from ? {
101
+ kind: 'section',
102
+ index
103
+ } : null;
104
+ }
105
+ const page = pageNamed(lower.startsWith('page:') ? to.slice(5) : to, targets);
106
+ return pageDestination(page, label, targets);
107
+ }
108
+
109
+ //# sourceMappingURL=ai-layout-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-links.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 { aiPageLinkSection } from '../runtime/ai-page-links'\n\n/**\n * Where a link the layout language names goes (AGL-3660), resolved by code to\n * a destination rule 10 admits: a page of this site by its id, a section of\n * this page by the platform's Scroll to element interaction, or an `https:`\n * address the brief itself gave. A destination that resolves to nothing, or\n * to the home page under words that do not say home, is no destination, and\n * the compiler leaves the button out rather than shipping a dead control.\n */\n\n/** A page of the site a link may go to: built, or minted on a guided start's plan. */\nexport interface AiLayoutPage {\n id: string\n label: string\n slug: string\n}\n\n/** Everything a page's links resolve against. */\nexport interface AiLayoutTargets {\n /** The page being built, which no link of its own goes to. */\n pageId?: string | null\n /** The site's pages a link may go to. */\n pages: readonly AiLayoutPage[]\n /** The site's home pages, which only words that say home link (rule 10). */\n homeIds: readonly string[]\n /** The saved forms a page may place. */\n forms: readonly { id: string; name: string }[]\n /** The page that places the site's form, where that is another page. */\n formPageId?: string | null\n /** The reusable components a page may place, with the props each fills. */\n components: readonly {\n id: string\n name: string\n props: Record<string, string>\n }[]\n /** Every word the job was given: the brief, the site's answers, its profile. */\n facts: string\n}\n\n/** Where a link resolved to. */\nexport type AiLayoutDestination =\n | { kind: 'page'; screenId: string }\n | { kind: 'section'; index: number }\n | { kind: 'href'; href: string }\n\n/** The words of a label or a name, as they are compared. */\nfunction wordsOf(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter(Boolean)\n}\n\nfunction slugOf(slug: string): string {\n return `/${slug.replace(/^\\/+|\\/+$/g, '')}`.toLowerCase()\n}\n\nconst HOME_WORDS = /\\bhome(?:\\s?page)?\\b/i\n\n/** Words that ask a visitor to get in touch, which the site's form answers. */\nconst CONTACT_WORDS =\n /\\b(?:contact|book|booking|call|quote|estimate|appointment|schedule|reserve|reservation|get in touch|request|visit|enquire|inquire|enquiry|inquiry|message|talk|consult|consultation|order|sign up|join|apply|start)\\b/i\n\nexport interface AiLayoutLinkScope {\n /** The page's section names in plan order. */\n sections: readonly string[]\n /** The section the link sits in, which it does not scroll to. */\n from: number\n /** The section of this page that places the site's form, if one does. */\n formSection: number | null\n}\n\n/** The page a word names: an id, a label or an address. */\nfunction pageNamed(\n word: string,\n targets: AiLayoutTargets,\n): AiLayoutPage | null {\n const value = word.trim()\n if (!value) return null\n const byId = targets.pages.find((page) => page.id === value)\n if (byId) return byId\n const lower = value.toLowerCase()\n if (lower.startsWith('/'))\n return (\n targets.pages.find((page) => slugOf(page.slug) === slugOf(lower)) ?? null\n )\n const words = wordsOf(value).join(' ')\n return (\n targets.pages.find((page) => wordsOf(page.label).join(' ') === words) ??\n null\n )\n}\n\n/** A destination rule 10 admits, from the page it names, for the words a link shows. */\nfunction pageDestination(\n page: AiLayoutPage | null,\n label: string,\n targets: AiLayoutTargets,\n): AiLayoutDestination | null {\n if (!page || page.id === targets.pageId) return null\n if (\n targets.homeIds.includes(page.id) &&\n !HOME_WORDS.test(label) &&\n !isHomeSlug(page.slug)\n )\n return null\n if (isHomeSlug(page.slug) && !HOME_WORDS.test(label)) return null\n return { kind: 'page', screenId: page.id }\n}\n\nfunction isHomeSlug(slug: string): boolean {\n return slugOf(slug) === '/'\n}\n\n/** Where the site's form is: a section of this page, else the page that places it. */\nfunction formDestination(\n scope: AiLayoutLinkScope,\n targets: AiLayoutTargets,\n): AiLayoutDestination | null {\n if (scope.formSection !== null && scope.formSection !== scope.from)\n return { kind: 'section', index: scope.formSection }\n if (targets.formPageId && targets.formPageId !== targets.pageId) {\n return { kind: 'page', screenId: targets.formPageId }\n }\n return null\n}\n\n/**\n * Where a link goes: the destination its `to` names, read the language's\n * way; failing that, for words that ask a visitor to get in touch, the site's\n * form; failing that, a page whose name the words say. `null` is a link with\n * nowhere to go, which is left out.\n */\nexport function aiLayoutResolveLink(\n to: string | undefined,\n label: string,\n scope: AiLayoutLinkScope,\n targets: AiLayoutTargets,\n): AiLayoutDestination | null {\n const named = to ? resolveNamed(to.trim(), label, scope, targets) : null\n if (named) return named\n if (CONTACT_WORDS.test(label)) {\n const form = formDestination(scope, targets)\n if (form) return form\n const contact = targets.pages.find(\n (page) =>\n page.id !== targets.pageId &&\n !isHomeSlug(page.slug) &&\n CONTACT_WORDS.test(page.label),\n )\n if (contact) return { kind: 'page', screenId: contact.id }\n }\n const labelWords = new Set(wordsOf(label))\n const said = targets.pages.filter(\n (page) =>\n page.id !== targets.pageId &&\n !isHomeSlug(page.slug) &&\n wordsOf(page.label).length > 0 &&\n wordsOf(page.label).every((word) => labelWords.has(word)),\n )\n return said.length === 1 ? { kind: 'page', screenId: said[0].id } : null\n}\n\nfunction resolveNamed(\n to: string,\n label: string,\n scope: AiLayoutLinkScope,\n targets: AiLayoutTargets,\n): AiLayoutDestination | null {\n const lower = to.toLowerCase()\n if (\n lower === 'form' ||\n lower.startsWith('form:') ||\n targets.forms.some((form) => form.id === to)\n ) {\n return formDestination(scope, targets)\n }\n if (lower.startsWith('https://')) {\n return targets.facts.includes(to) ? { kind: 'href', href: to } : null\n }\n const section = lower.startsWith('#')\n ? to.slice(1)\n : lower.startsWith('section:')\n ? to.slice(8)\n : null\n if (section !== null) {\n const number = Number(section.trim())\n const index =\n Number.isInteger(number) && number >= 1 && number <= scope.sections.length\n ? number - 1\n : aiPageLinkSection(section, scope.sections)\n return index !== null && index !== scope.from\n ? { kind: 'section', index }\n : null\n }\n const page = pageNamed(lower.startsWith('page:') ? to.slice(5) : to, targets)\n return pageDestination(page, label, targets)\n}\n"],"names":["aiPageLinkSection","wordsOf","text","toLowerCase","split","filter","Boolean","slugOf","slug","replace","HOME_WORDS","CONTACT_WORDS","pageNamed","word","targets","value","trim","byId","pages","find","page","id","lower","startsWith","words","join","label","pageDestination","pageId","homeIds","includes","test","isHomeSlug","kind","screenId","formDestination","scope","formSection","from","index","formPageId","aiLayoutResolveLink","to","named","resolveNamed","form","contact","labelWords","Set","said","length","every","has","forms","some","facts","href","section","slice","number","Number","isInteger","sections"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { NodesMap } from '@aglyn/aglyn/types/nodes';
18
+ import { type AiNodeTreeContext } from '../runtime/ai-node-tree';
19
+ import type { AiSurface } from '../runtime/ai-palette';
20
+ import type { AiLayoutRawTree } from './ai-layout-tree';
21
+ /**
22
+ * A compiled tree as a document stores it (AGL-3660): read by the same
23
+ * palette validator every generated tree passes, as a code-built tree, so
24
+ * what is stored is exactly what any other generated document would store.
25
+ * The validator mints fresh ids; the ids a caller names (a page's section
26
+ * roots, which its plan minted) keep their own, and the interactions code
27
+ * wrote — which the validator strips from anything it stores — are carried
28
+ * over onto the stored nodes.
29
+ */
30
+ export type AiLayoutStored = {
31
+ ok: true;
32
+ nodes: NodesMap;
33
+ rootId: string;
34
+ repairs: string[];
35
+ } | {
36
+ ok: false;
37
+ error: string;
38
+ };
39
+ export declare function aiLayoutStoredTree(compiled: AiLayoutRawTree, surface: AiSurface, context: AiNodeTreeContext, keepIds?: readonly string[]): AiLayoutStored;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
18
+ import { validateAiNodeTree } from "../runtime/ai-node-tree.js";
19
+ export function aiLayoutStoredTree(compiled, surface, context, keepIds = []) {
20
+ // The interactions are code's, carried over below; the validator is shown the rest.
21
+ const bare = {
22
+ rootId: compiled.rootId,
23
+ nodes: Object.fromEntries(Object.entries(compiled.nodes).map((_0)=>{
24
+ let [id, _ref] = _0, { interactions: _interactions } = _ref, node = _object_without_properties_loose(_ref, [
25
+ "interactions"
26
+ ]);
27
+ return [
28
+ id,
29
+ node
30
+ ];
31
+ }))
32
+ };
33
+ const validated = validateAiNodeTree(bare, surface, _extends({}, context, {
34
+ codeBuilt: true
35
+ }));
36
+ if (validated.ok === false) return {
37
+ ok: false,
38
+ error: validated.error
39
+ };
40
+ const keep = new Set(keepIds);
41
+ // Minted → the id it is stored under: its own, or the one the caller keeps.
42
+ const storedId = (minted)=>{
43
+ const source = validated.sourceIds[minted];
44
+ return source && keep.has(source) ? source : minted;
45
+ };
46
+ const nodes = {};
47
+ for (const [minted, raw] of Object.entries(validated.nodes)){
48
+ var _validated_sourceIds_minted;
49
+ var _source_interactions;
50
+ const id = storedId(minted);
51
+ const source = compiled.nodes[(_validated_sourceIds_minted = validated.sourceIds[minted]) != null ? _validated_sourceIds_minted : ''];
52
+ nodes[id] = _extends({}, raw, {
53
+ $id: id,
54
+ parentId: raw.parentId === null ? null : storedId(raw.parentId)
55
+ }, Array.isArray(raw.nodes) ? {
56
+ nodes: raw.nodes.map(storedId)
57
+ } : {}, (source == null ? void 0 : (_source_interactions = source.interactions) == null ? void 0 : _source_interactions.length) ? {
58
+ interactions: source.interactions
59
+ } : {});
60
+ }
61
+ return {
62
+ ok: true,
63
+ nodes: nodes,
64
+ rootId: storedId(validated.rootId),
65
+ repairs: validated.repairs
66
+ };
67
+ }
68
+
69
+ //# sourceMappingURL=ai-layout-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-store.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 type { NodesMap } from '@aglyn/aglyn/types/nodes'\nimport {\n validateAiNodeTree,\n type AiNodeTreeContext,\n} from '../runtime/ai-node-tree'\nimport type { AiSurface } from '../runtime/ai-palette'\nimport type { AiLayoutRawTree } from './ai-layout-tree'\n\n/**\n * A compiled tree as a document stores it (AGL-3660): read by the same\n * palette validator every generated tree passes, as a code-built tree, so\n * what is stored is exactly what any other generated document would store.\n * The validator mints fresh ids; the ids a caller names (a page's section\n * roots, which its plan minted) keep their own, and the interactions code\n * wrote — which the validator strips from anything it stores — are carried\n * over onto the stored nodes.\n */\n\nexport type AiLayoutStored =\n | { ok: true; nodes: NodesMap; rootId: string; repairs: string[] }\n | { ok: false; error: string }\n\ntype StoredNode = Record<string, unknown> & {\n $id: string\n parentId: string | null\n nodes?: string[]\n}\n\nexport function aiLayoutStoredTree(\n compiled: AiLayoutRawTree,\n surface: AiSurface,\n context: AiNodeTreeContext,\n keepIds: readonly string[] = [],\n): AiLayoutStored {\n // The interactions are code's, carried over below; the validator is shown the rest.\n const bare = {\n rootId: compiled.rootId,\n nodes: Object.fromEntries(\n Object.entries(compiled.nodes).map(\n ([id, { interactions: _interactions, ...node }]) => [id, node],\n ),\n ),\n }\n const validated = validateAiNodeTree(bare, surface, {\n ...context,\n codeBuilt: true,\n })\n if (validated.ok === false) return { ok: false, error: validated.error }\n const keep = new Set(keepIds)\n // Minted → the id it is stored under: its own, or the one the caller keeps.\n const storedId = (minted: string): string => {\n const source = validated.sourceIds[minted]\n return source && keep.has(source) ? source : minted\n }\n const nodes: Record<string, StoredNode> = {}\n for (const [minted, raw] of Object.entries(\n validated.nodes as unknown as Record<string, StoredNode>,\n )) {\n const id = storedId(minted)\n const source = compiled.nodes[validated.sourceIds[minted] ?? '']\n nodes[id] = {\n ...raw,\n $id: id,\n parentId: raw.parentId === null ? null : storedId(raw.parentId),\n ...(Array.isArray(raw.nodes) ? { nodes: raw.nodes.map(storedId) } : {}),\n ...(source?.interactions?.length\n ? { interactions: source.interactions }\n : {}),\n }\n }\n return {\n ok: true,\n nodes: nodes as unknown as NodesMap,\n rootId: storedId(validated.rootId),\n repairs: validated.repairs,\n }\n}\n"],"names":["validateAiNodeTree","aiLayoutStoredTree","compiled","surface","context","keepIds","bare","rootId","nodes","Object","fromEntries","entries","map","id","interactions","_interactions","node","validated","codeBuilt","ok","error","keep","Set","storedId","minted","source","sourceIds","has","raw","$id","parentId","Array","isArray","length","repairs"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;;AAGD,SACEA,kBAAkB,QAEb,6BAAyB;AAwBhC,OAAO,SAASC,mBACdC,QAAyB,EACzBC,OAAkB,EAClBC,OAA0B,EAC1BC,UAA6B,EAAE;IAE/B,oFAAoF;IACpF,MAAMC,OAAO;QACXC,QAAQL,SAASK,MAAM;QACvBC,OAAOC,OAAOC,WAAW,CACvBD,OAAOE,OAAO,CAACT,SAASM,KAAK,EAAEI,GAAG,CAChC;gBAAC,CAACC,SAA6C,OAAzC,EAAEC,cAAcC,aAAa,EAAW,SAANC;;;mBAAY;gBAACH;gBAAIG;aAAK;;IAGpE;IACA,MAAMC,YAAYjB,mBAAmBM,MAAMH,SAAS,aAC/CC;QACHc,WAAW;;IAEb,IAAID,UAAUE,EAAE,KAAK,OAAO,OAAO;QAAEA,IAAI;QAAOC,OAAOH,UAAUG,KAAK;IAAC;IACvE,MAAMC,OAAO,IAAIC,IAAIjB;IACrB,4EAA4E;IAC5E,MAAMkB,WAAW,CAACC;QAChB,MAAMC,SAASR,UAAUS,SAAS,CAACF,OAAO;QAC1C,OAAOC,UAAUJ,KAAKM,GAAG,CAACF,UAAUA,SAASD;IAC/C;IACA,MAAMhB,QAAoC,CAAC;IAC3C,KAAK,MAAM,CAACgB,QAAQI,IAAI,IAAInB,OAAOE,OAAO,CACxCM,UAAUT,KAAK,EACd;YAE6BS;YAMxBQ;QAPN,MAAMZ,KAAKU,SAASC;QACpB,MAAMC,SAASvB,SAASM,KAAK,EAACS,8BAAAA,UAAUS,SAAS,CAACF,OAAO,YAA3BP,8BAA+B,GAAG;QAChET,KAAK,CAACK,GAAG,GAAG,aACPe;YACHC,KAAKhB;YACLiB,UAAUF,IAAIE,QAAQ,KAAK,OAAO,OAAOP,SAASK,IAAIE,QAAQ;WAC1DC,MAAMC,OAAO,CAACJ,IAAIpB,KAAK,IAAI;YAAEA,OAAOoB,IAAIpB,KAAK,CAACI,GAAG,CAACW;QAAU,IAAI,CAAC,GACjEE,CAAAA,2BAAAA,uBAAAA,OAAQX,YAAY,qBAApBW,qBAAsBQ,MAAM,IAC5B;YAAEnB,cAAcW,OAAOX,YAAY;QAAC,IACpC,CAAC;IAET;IACA,OAAO;QACLK,IAAI;QACJX,OAAOA;QACPD,QAAQgB,SAASN,UAAUV,MAAM;QACjC2B,SAASjB,UAAUiB,OAAO;IAC5B;AACF"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * The node map the layout language compiler writes (AGL-3660), in the shape a
19
+ * model's answer arrives in — `{ rootId, nodes: { id: { componentId, props,
20
+ * sx, nodes } } }` — so the palette validator and the doctrine read it exactly
21
+ * as they read any other tree, and nothing downstream knows code wrote it.
22
+ */
23
+ export interface AiLayoutRawNode {
24
+ componentId: string;
25
+ props?: Record<string, unknown>;
26
+ sx?: Record<string, unknown>;
27
+ nodes?: string[];
28
+ /**
29
+ * The platform's interactions, written by code: a link to a section of its
30
+ * page scrolls there (AGL-3097). The palette validator strips every
31
+ * interaction from what it stores, so the page step carries these over
32
+ * onto the stored nodes after it.
33
+ */
34
+ interactions?: unknown[];
35
+ }
36
+ export interface AiLayoutRawTree {
37
+ rootId: string;
38
+ nodes: Record<string, AiLayoutRawNode>;
39
+ }
40
+ /** Elements that only frame what they hold, and so mean nothing empty. */
41
+ export declare const AI_LAYOUT_FRAMES: ReadonlySet<string>;
42
+ /** A node map built in document order, with ids that read in a review: `ll3-heading`. */
43
+ export declare class AiLayoutTreeBuilder {
44
+ private readonly prefix;
45
+ readonly nodes: Record<string, AiLayoutRawNode>;
46
+ private count;
47
+ constructor(prefix?: string);
48
+ /** A node, with only the props, styles and children it was given; returns its id. */
49
+ add(componentId: string, props?: Record<string, unknown> | null, sx?: Record<string, unknown> | null, children?: readonly (string | null | undefined)[] | null, role?: string, fixedId?: string): string;
50
+ /**
51
+ * Takes out every frame left holding nothing — a card whose words were all
52
+ * filler, the cell that held it — from the leaves up, so no element meant
53
+ * to hold content is stored empty (rule 16). `keep` names the ones that
54
+ * stay whatever they hold.
55
+ */
56
+ prune(rootId: string, keep?: ReadonlySet<string>): void;
57
+ /** The tree rooted at `rootId`. */
58
+ tree(rootId: string): AiLayoutRawTree;
59
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /**
17
+ * The node map the layout language compiler writes (AGL-3660), in the shape a
18
+ * model's answer arrives in — `{ rootId, nodes: { id: { componentId, props,
19
+ * sx, nodes } } }` — so the palette validator and the doctrine read it exactly
20
+ * as they read any other tree, and nothing downstream knows code wrote it.
21
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
22
+ /** Elements that only frame what they hold, and so mean nothing empty. */ export const AI_LAYOUT_FRAMES = new Set([
23
+ 'muiStack',
24
+ 'muiBox',
25
+ 'muiGrid',
26
+ 'muiCard',
27
+ 'muiCardContent',
28
+ 'muiContainer',
29
+ 'muiList',
30
+ 'muiListItem',
31
+ 'muiAccordion',
32
+ 'muiAccordionDetails',
33
+ 'muiDrawer',
34
+ 'section'
35
+ ]);
36
+ /** A node map built in document order, with ids that read in a review: `ll3-heading`. */ export class AiLayoutTreeBuilder {
37
+ /** A node, with only the props, styles and children it was given; returns its id. */ add(componentId, props, sx, children, role = componentId, fixedId) {
38
+ this.count += 1;
39
+ const id = fixedId != null ? fixedId : `${this.prefix}${this.count}-${role.replace(/[^A-Za-z0-9]/g, '').slice(0, 16)}`;
40
+ const node = {
41
+ componentId
42
+ };
43
+ const kept = props ? Object.fromEntries(Object.entries(props).filter(([, value])=>value !== undefined)) : {};
44
+ if (Object.keys(kept).length) node.props = kept;
45
+ if (sx && Object.keys(sx).length) node.sx = _extends({}, sx);
46
+ const list = (children != null ? children : []).filter((child)=>typeof child === 'string');
47
+ if (list.length) node.nodes = list;
48
+ this.nodes[id] = node;
49
+ return id;
50
+ }
51
+ /**
52
+ * Takes out every frame left holding nothing — a card whose words were all
53
+ * filler, the cell that held it — from the leaves up, so no element meant
54
+ * to hold content is stored empty (rule 16). `keep` names the ones that
55
+ * stay whatever they hold.
56
+ */ prune(rootId, keep = new Set()) {
57
+ const visit = (id)=>{
58
+ var _node_nodes;
59
+ const node = this.nodes[id];
60
+ if (!node) return false;
61
+ if (node.nodes) {
62
+ node.nodes = node.nodes.filter(visit);
63
+ if (!node.nodes.length) delete node.nodes;
64
+ }
65
+ if (id === rootId || keep.has(id) || ((_node_nodes = node.nodes) == null ? void 0 : _node_nodes.length) || !AI_LAYOUT_FRAMES.has(node.componentId)) return true;
66
+ delete this.nodes[id];
67
+ return false;
68
+ };
69
+ visit(rootId);
70
+ }
71
+ /** The tree rooted at `rootId`. */ tree(rootId) {
72
+ return {
73
+ rootId,
74
+ nodes: this.nodes
75
+ };
76
+ }
77
+ constructor(prefix = 'll'){
78
+ this.prefix = prefix;
79
+ this.nodes = {};
80
+ this.count = 0;
81
+ }
82
+ }
83
+
84
+ //# sourceMappingURL=ai-layout-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/layout-language/ai-layout-tree.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\n/**\n * The node map the layout language compiler writes (AGL-3660), in the shape a\n * model's answer arrives in — `{ rootId, nodes: { id: { componentId, props,\n * sx, nodes } } }` — so the palette validator and the doctrine read it exactly\n * as they read any other tree, and nothing downstream knows code wrote it.\n */\n\nexport interface AiLayoutRawNode {\n componentId: string\n props?: Record<string, unknown>\n sx?: Record<string, unknown>\n nodes?: string[]\n /**\n * The platform's interactions, written by code: a link to a section of its\n * page scrolls there (AGL-3097). The palette validator strips every\n * interaction from what it stores, so the page step carries these over\n * onto the stored nodes after it.\n */\n interactions?: unknown[]\n}\n\nexport interface AiLayoutRawTree {\n rootId: string\n nodes: Record<string, AiLayoutRawNode>\n}\n\n/** Elements that only frame what they hold, and so mean nothing empty. */\nexport const AI_LAYOUT_FRAMES: ReadonlySet<string> = new Set([\n 'muiStack',\n 'muiBox',\n 'muiGrid',\n 'muiCard',\n 'muiCardContent',\n 'muiContainer',\n 'muiList',\n 'muiListItem',\n 'muiAccordion',\n 'muiAccordionDetails',\n 'muiDrawer',\n 'section',\n])\n\n/** A node map built in document order, with ids that read in a review: `ll3-heading`. */\nexport class AiLayoutTreeBuilder {\n readonly nodes: Record<string, AiLayoutRawNode> = {}\n private count = 0\n\n constructor(private readonly prefix = 'll') {}\n\n /** A node, with only the props, styles and children it was given; returns its id. */\n add(\n componentId: string,\n props?: Record<string, unknown> | null,\n sx?: Record<string, unknown> | null,\n children?: readonly (string | null | undefined)[] | null,\n role = componentId,\n fixedId?: string,\n ): string {\n this.count += 1\n const id =\n fixedId ??\n `${this.prefix}${this.count}-${role.replace(/[^A-Za-z0-9]/g, '').slice(0, 16)}`\n const node: AiLayoutRawNode = { componentId }\n const kept = props\n ? Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n )\n : {}\n if (Object.keys(kept).length) node.props = kept\n if (sx && Object.keys(sx).length) node.sx = { ...sx }\n const list = (children ?? []).filter(\n (child): child is string => typeof child === 'string',\n )\n if (list.length) node.nodes = list\n this.nodes[id] = node\n return id\n }\n\n /**\n * Takes out every frame left holding nothing — a card whose words were all\n * filler, the cell that held it — from the leaves up, so no element meant\n * to hold content is stored empty (rule 16). `keep` names the ones that\n * stay whatever they hold.\n */\n prune(rootId: string, keep: ReadonlySet<string> = new Set()): void {\n const visit = (id: string): boolean => {\n const node = this.nodes[id]\n if (!node) return false\n if (node.nodes) {\n node.nodes = node.nodes.filter(visit)\n if (!node.nodes.length) delete node.nodes\n }\n if (\n id === rootId ||\n keep.has(id) ||\n node.nodes?.length ||\n !AI_LAYOUT_FRAMES.has(node.componentId)\n )\n return true\n delete this.nodes[id]\n return false\n }\n visit(rootId)\n }\n\n /** The tree rooted at `rootId`. */\n tree(rootId: string): AiLayoutRawTree {\n return { rootId, nodes: this.nodes }\n }\n}\n"],"names":["AI_LAYOUT_FRAMES","Set","AiLayoutTreeBuilder","add","componentId","props","sx","children","role","fixedId","count","id","prefix","replace","slice","node","kept","Object","fromEntries","entries","filter","value","undefined","keys","length","list","child","nodes","prune","rootId","keep","visit","has","tree"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;CAKC;AAqBD,wEAAwE,GACxE,OAAO,MAAMA,mBAAwC,IAAIC,IAAI;IAC3D;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,EAAC;AAEF,uFAAuF,GACvF,OAAO,MAAMC;IAMX,mFAAmF,GACnFC,IACEC,WAAmB,EACnBC,KAAsC,EACtCC,EAAmC,EACnCC,QAAwD,EACxDC,OAAOJ,WAAW,EAClBK,OAAgB,EACR;QACR,IAAI,CAACC,KAAK,IAAI;QACd,MAAMC,KACJF,kBAAAA,UACA,GAAG,IAAI,CAACG,MAAM,GAAG,IAAI,CAACF,KAAK,CAAC,CAAC,EAAEF,KAAKK,OAAO,CAAC,iBAAiB,IAAIC,KAAK,CAAC,GAAG,KAAK;QACjF,MAAMC,OAAwB;YAAEX;QAAY;QAC5C,MAAMY,OAAOX,QACTY,OAAOC,WAAW,CAChBD,OAAOE,OAAO,CAACd,OAAOe,MAAM,CAAC,CAAC,GAAGC,MAAM,GAAKA,UAAUC,cAExD,CAAC;QACL,IAAIL,OAAOM,IAAI,CAACP,MAAMQ,MAAM,EAAET,KAAKV,KAAK,GAAGW;QAC3C,IAAIV,MAAMW,OAAOM,IAAI,CAACjB,IAAIkB,MAAM,EAAET,KAAKT,EAAE,GAAG,aAAKA;QACjD,MAAMmB,OAAO,CAAClB,mBAAAA,WAAY,EAAE,EAAEa,MAAM,CAClC,CAACM,QAA2B,OAAOA,UAAU;QAE/C,IAAID,KAAKD,MAAM,EAAET,KAAKY,KAAK,GAAGF;QAC9B,IAAI,CAACE,KAAK,CAAChB,GAAG,GAAGI;QACjB,OAAOJ;IACT;IAEA;;;;;GAKC,GACDiB,MAAMC,MAAc,EAAEC,OAA4B,IAAI7B,KAAK,EAAQ;QACjE,MAAM8B,QAAQ,CAACpB;gBAUXI;YATF,MAAMA,OAAO,IAAI,CAACY,KAAK,CAAChB,GAAG;YAC3B,IAAI,CAACI,MAAM,OAAO;YAClB,IAAIA,KAAKY,KAAK,EAAE;gBACdZ,KAAKY,KAAK,GAAGZ,KAAKY,KAAK,CAACP,MAAM,CAACW;gBAC/B,IAAI,CAAChB,KAAKY,KAAK,CAACH,MAAM,EAAE,OAAOT,KAAKY,KAAK;YAC3C;YACA,IACEhB,OAAOkB,UACPC,KAAKE,GAAG,CAACrB,SACTI,cAAAA,KAAKY,KAAK,qBAAVZ,YAAYS,MAAM,KAClB,CAACxB,iBAAiBgC,GAAG,CAACjB,KAAKX,WAAW,GAEtC,OAAO;YACT,OAAO,IAAI,CAACuB,KAAK,CAAChB,GAAG;YACrB,OAAO;QACT;QACAoB,MAAMF;IACR;IAEA,iCAAiC,GACjCI,KAAKJ,MAAc,EAAmB;QACpC,OAAO;YAAEA;YAAQF,OAAO,IAAI,CAACA,KAAK;QAAC;IACrC;IA7DA,YAAY,AAAiBf,SAAS,IAAI,CAAE;aAAfA,SAAAA;aAHpBe,QAAyC,CAAC;aAC3CjB,QAAQ;IAE6B;AA8D/C"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { type ComponentType, type ReactNode } from 'react';
18
+ /**
19
+ * A component registered by name whose code loads the first time it is
20
+ * drawn. `load` resolves to the component itself — the module's export —
21
+ * so a spec can hold a registration to the component it stands for.
22
+ */
23
+ export type LazyWidget<P = any> = ComponentType<P> & {
24
+ load: () => Promise<ComponentType<P>>;
25
+ };
26
+ /**
27
+ * Registers a component without loading it (AGL-3649).
28
+ *
29
+ * The console loads this plugin on every screen, because it fills the dock
30
+ * and the top bar, so anything `plugin.ts` imports statically is downloaded
31
+ * by every reader of every page, whichever card it is. A registration needs
32
+ * only a name and a component to call; this hands the registry a small
33
+ * stand-in that imports the real one when the shell first draws it.
34
+ *
35
+ * The stand-in carries its own `Suspense`. The shell's zones draw widgets
36
+ * with no boundary of their own, and the dock and the top bar sit above every
37
+ * route's boundary, so a bare `React.lazy` there would suspend the shell
38
+ * itself while one card's code arrived. Here the wait is the card's alone:
39
+ * it draws `fallback` (nothing, unless the caller says otherwise) in its own
40
+ * place, which is what a widget held by a gate already draws.
41
+ *
42
+ * Every gate stays on the registration — feature flag, permission, release
43
+ * flag — so a widget the shell withholds is never drawn and never loaded.
44
+ */
45
+ export declare function lazyWidget<P extends object>(name: string, load: () => Promise<ComponentType<P>>, fallback?: ReactNode): LazyWidget<P>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { _ as _extends } from "@swc/helpers/_/_extends";
18
+ import { jsx as _jsx } from "react/jsx-runtime";
19
+ import { Suspense, lazy } from "react";
20
+ /**
21
+ * Registers a component without loading it (AGL-3649).
22
+ *
23
+ * The console loads this plugin on every screen, because it fills the dock
24
+ * and the top bar, so anything `plugin.ts` imports statically is downloaded
25
+ * by every reader of every page, whichever card it is. A registration needs
26
+ * only a name and a component to call; this hands the registry a small
27
+ * stand-in that imports the real one when the shell first draws it.
28
+ *
29
+ * The stand-in carries its own `Suspense`. The shell's zones draw widgets
30
+ * with no boundary of their own, and the dock and the top bar sit above every
31
+ * route's boundary, so a bare `React.lazy` there would suspend the shell
32
+ * itself while one card's code arrived. Here the wait is the card's alone:
33
+ * it draws `fallback` (nothing, unless the caller says otherwise) in its own
34
+ * place, which is what a widget held by a gate already draws.
35
+ *
36
+ * Every gate stays on the registration — feature flag, permission, release
37
+ * flag — so a widget the shell withholds is never drawn and never loaded.
38
+ */ export function lazyWidget(name, load, fallback = null) {
39
+ let loading;
40
+ const loadOnce = ()=>loading != null ? loading : loading = load();
41
+ const Loaded = /*#__PURE__*/ lazy(()=>loadOnce().then((Component)=>({
42
+ default: Component
43
+ })));
44
+ const Widget = (props)=>/*#__PURE__*/ _jsx(Suspense, {
45
+ fallback: fallback,
46
+ children: /*#__PURE__*/ _jsx(Loaded, _extends({}, props))
47
+ });
48
+ Widget.displayName = name;
49
+ Widget.load = loadOnce;
50
+ return Widget;
51
+ }
52
+
53
+ //# sourceMappingURL=lazy-widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/plugins/ai/src/lib/lazy-widget.tsx"],"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\n'use client'\n\nimport { Suspense, lazy, type ComponentType, type ReactNode } from 'react'\n\n/**\n * A component registered by name whose code loads the first time it is\n * drawn. `load` resolves to the component itself — the module's export —\n * so a spec can hold a registration to the component it stands for.\n */\nexport type LazyWidget<P = any> = ComponentType<P> & {\n load: () => Promise<ComponentType<P>>\n}\n\n/**\n * Registers a component without loading it (AGL-3649).\n *\n * The console loads this plugin on every screen, because it fills the dock\n * and the top bar, so anything `plugin.ts` imports statically is downloaded\n * by every reader of every page, whichever card it is. A registration needs\n * only a name and a component to call; this hands the registry a small\n * stand-in that imports the real one when the shell first draws it.\n *\n * The stand-in carries its own `Suspense`. The shell's zones draw widgets\n * with no boundary of their own, and the dock and the top bar sit above every\n * route's boundary, so a bare `React.lazy` there would suspend the shell\n * itself while one card's code arrived. Here the wait is the card's alone:\n * it draws `fallback` (nothing, unless the caller says otherwise) in its own\n * place, which is what a widget held by a gate already draws.\n *\n * Every gate stays on the registration — feature flag, permission, release\n * flag — so a widget the shell withholds is never drawn and never loaded.\n */\nexport function lazyWidget<P extends object>(\n name: string,\n load: () => Promise<ComponentType<P>>,\n fallback: ReactNode = null,\n): LazyWidget<P> {\n let loading: Promise<ComponentType<P>> | undefined\n const loadOnce = () => (loading ??= load())\n const Loaded = lazy(() =>\n loadOnce().then((Component) => ({ default: Component })),\n )\n const Widget = (props: P) => (\n <Suspense fallback={fallback}>\n <Loaded {...(props as any)} />\n </Suspense>\n )\n Widget.displayName = name\n Widget.load = loadOnce\n return Widget\n}\n"],"names":["Suspense","lazy","lazyWidget","name","load","fallback","loading","loadOnce","Loaded","then","Component","default","Widget","props","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;AAEA,SAASA,QAAQ,EAAEC,IAAI,QAA4C,QAAO;AAW1E;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,SAASC,WACdC,IAAY,EACZC,IAAqC,EACrCC,WAAsB,IAAI;IAE1B,IAAIC;IACJ,MAAMC,WAAW,IAAOD,kBAAAA,UAAAA,UAAYF;IACpC,MAAMI,uBAASP,KAAK,IAClBM,WAAWE,IAAI,CAAC,CAACC,YAAe,CAAA;gBAAEC,SAASD;YAAU,CAAA;IAEvD,MAAME,SAAS,CAACC,sBACd,KAACb;YAASK,UAAUA;sBAClB,cAAA,KAACG,qBAAYK;;IAGjBD,OAAOE,WAAW,GAAGX;IACrBS,OAAOR,IAAI,GAAGG;IACd,OAAOK;AACT"}
@@ -439,7 +439,8 @@ const OPEN = [
439
439
  attemptCredits: 0,
440
440
  failure: null,
441
441
  note: null,
442
- degradedBy: []
442
+ degradedBy: [],
443
+ settledAt: null
443
444
  });
444
445
  }
445
446
  if (row.status === 'degraded' && downstream.has(row.slot) && row.outputs.length) {