openplanr 2.2639.4 → 2.2640.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 (204) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cli/commands/github.d.ts.map +1 -1
  3. package/dist/cli/commands/github.js +4 -3
  4. package/dist/cli/commands/github.js.map +1 -1
  5. package/dist/dashboard/.vite/manifest.json +1 -1
  6. package/dist/dashboard/assets/{index-p83hrHZD.js → index-9DLb9EO5.js} +2 -2
  7. package/dist/dashboard/assets/{index-p83hrHZD.js.map → index-9DLb9EO5.js.map} +1 -1
  8. package/dist/dashboard/dashboard-manifest.json +13 -13
  9. package/dist/dashboard/index.html +1 -1
  10. package/dist/models/schema.d.ts.map +1 -1
  11. package/dist/models/schema.js +24 -1
  12. package/dist/models/schema.js.map +1 -1
  13. package/dist/services/artifact-service.js +2 -2
  14. package/dist/services/artifact-service.js.map +1 -1
  15. package/dist/services/github-service.d.ts +6 -4
  16. package/dist/services/github-service.d.ts.map +1 -1
  17. package/dist/services/github-service.js +7 -2
  18. package/dist/services/github-service.js.map +1 -1
  19. package/dist/services/id-service.d.ts +4 -1
  20. package/dist/services/id-service.d.ts.map +1 -1
  21. package/dist/services/id-service.js +28 -15
  22. package/dist/services/id-service.js.map +1 -1
  23. package/dist/services/landing/receipt-custody.d.ts.map +1 -1
  24. package/dist/services/landing/receipt-custody.js +2 -0
  25. package/dist/services/landing/receipt-custody.js.map +1 -1
  26. package/dist/services/report-linter-service.d.ts.map +1 -1
  27. package/dist/services/report-linter-service.js +2 -4
  28. package/dist/services/report-linter-service.js.map +1 -1
  29. package/docs/CLI.md +2 -0
  30. package/lib/host-packages/adapter-registry.json +5 -5
  31. package/lib/host-packages/capability-map.json +1 -1
  32. package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
  33. package/lib/host-packages/claude/openplanr/.claude-plugin/icon.svg +11 -0
  34. package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +8 -3
  35. package/lib/host-packages/claude/openplanr/.openplanr-content.json +160 -28
  36. package/lib/host-packages/claude/openplanr/README.md +4 -3
  37. package/lib/host-packages/claude/openplanr/skills/ceo-review/SKILL.md +1 -1
  38. package/lib/host-packages/claude/openplanr/skills/chair-review/SKILL.md +1 -1
  39. package/lib/host-packages/claude/openplanr/skills/challenger-review/SKILL.md +1 -1
  40. package/lib/host-packages/claude/openplanr/skills/cmo-review/SKILL.md +1 -1
  41. package/lib/host-packages/claude/openplanr/skills/coo-review/SKILL.md +1 -1
  42. package/lib/host-packages/claude/openplanr/skills/cpo-review/SKILL.md +1 -1
  43. package/lib/host-packages/claude/openplanr/skills/cto-review/SKILL.md +1 -1
  44. package/lib/host-packages/claude/openplanr/skills/design/openplanr.skill.json +88 -0
  45. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-artifact-shell.mjs +2506 -0
  46. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-document.mjs +3674 -0
  47. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-entities.mjs +489 -0
  48. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-parse5-parser.mjs +3970 -0
  49. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-parse5-tokenizer.mjs +3501 -0
  50. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-review-handoff.mjs +4408 -0
  51. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-sandbox-guards.mjs +1073 -0
  52. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-share.mjs +2127 -0
  53. package/lib/host-packages/claude/openplanr/skills/design/scripts/design.mjs +83 -21459
  54. package/lib/host-packages/claude/openplanr/skills/design/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  55. package/lib/host-packages/claude/openplanr/skills/design/scripts/runtime/packages/protocol/package.json +1 -1
  56. package/lib/host-packages/claude/openplanr/skills/design-loop/openplanr.skill.json +88 -0
  57. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-artifact-shell.mjs +2506 -0
  58. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-document.mjs +3674 -0
  59. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-entities.mjs +489 -0
  60. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-parse5-parser.mjs +3970 -0
  61. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-parse5-tokenizer.mjs +3501 -0
  62. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-review-handoff.mjs +4408 -0
  63. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-sandbox-guards.mjs +1073 -0
  64. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-share.mjs +2127 -0
  65. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design.mjs +83 -21459
  66. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  67. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/runtime/packages/protocol/package.json +1 -1
  68. package/lib/host-packages/claude/openplanr/skills/design-review/openplanr.skill.json +88 -0
  69. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-artifact-shell.mjs +2506 -0
  70. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-document.mjs +3674 -0
  71. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-entities.mjs +489 -0
  72. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-parse5-parser.mjs +3970 -0
  73. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-parse5-tokenizer.mjs +3501 -0
  74. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-review-handoff.mjs +4408 -0
  75. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-sandbox-guards.mjs +1073 -0
  76. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-share.mjs +2127 -0
  77. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design.mjs +83 -21459
  78. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  79. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/runtime/packages/protocol/package.json +1 -1
  80. package/lib/host-packages/claude/openplanr/skills/plan/openplanr.skill.json +88 -0
  81. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-artifact-shell.mjs +2506 -0
  82. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-document.mjs +3674 -0
  83. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-entities.mjs +489 -0
  84. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-parse5-parser.mjs +3970 -0
  85. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-parse5-tokenizer.mjs +3501 -0
  86. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-review-handoff.mjs +4408 -0
  87. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-sandbox-guards.mjs +1073 -0
  88. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-share.mjs +2127 -0
  89. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design.mjs +83 -21459
  90. package/lib/host-packages/claude/openplanr/skills/plan/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  91. package/lib/host-packages/claude/openplanr/skills/plan/scripts/runtime/packages/protocol/package.json +1 -1
  92. package/lib/host-packages/claude/openplanr/skills/sync/SKILL.md +17 -6
  93. package/lib/host-packages/claude/openplanr/skills/sync/scripts/sync.mjs +7 -104
  94. package/lib/host-packages/cursor/openplanr/.openplanr-content.json +144 -16
  95. package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
  96. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-artifact-shell.mjs +2506 -0
  97. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-document.mjs +3674 -0
  98. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-entities.mjs +489 -0
  99. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-parse5-parser.mjs +3970 -0
  100. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-parse5-tokenizer.mjs +3501 -0
  101. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-review-handoff.mjs +4408 -0
  102. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-sandbox-guards.mjs +1073 -0
  103. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-share.mjs +2127 -0
  104. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design.mjs +83 -21459
  105. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  106. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/runtime/packages/protocol/package.json +1 -1
  107. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-artifact-shell.mjs +2506 -0
  108. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-document.mjs +3674 -0
  109. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-entities.mjs +489 -0
  110. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-parse5-parser.mjs +3970 -0
  111. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-parse5-tokenizer.mjs +3501 -0
  112. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-review-handoff.mjs +4408 -0
  113. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-sandbox-guards.mjs +1073 -0
  114. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-share.mjs +2127 -0
  115. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design.mjs +83 -21459
  116. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  117. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/runtime/packages/protocol/package.json +1 -1
  118. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-artifact-shell.mjs +2506 -0
  119. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-document.mjs +3674 -0
  120. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-entities.mjs +489 -0
  121. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-parse5-parser.mjs +3970 -0
  122. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-parse5-tokenizer.mjs +3501 -0
  123. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-review-handoff.mjs +4408 -0
  124. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-sandbox-guards.mjs +1073 -0
  125. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-share.mjs +2127 -0
  126. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design.mjs +83 -21459
  127. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  128. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/runtime/packages/protocol/package.json +1 -1
  129. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-artifact-shell.mjs +2506 -0
  130. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-document.mjs +3674 -0
  131. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-entities.mjs +489 -0
  132. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-parse5-parser.mjs +3970 -0
  133. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-parse5-tokenizer.mjs +3501 -0
  134. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-review-handoff.mjs +4408 -0
  135. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-sandbox-guards.mjs +1073 -0
  136. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-share.mjs +2127 -0
  137. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design.mjs +83 -21459
  138. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  139. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/runtime/packages/protocol/package.json +1 -1
  140. package/lib/host-packages/cursor/openplanr/rules/planr-sync/scripts/sync.mjs +7 -104
  141. package/lib/host-packages/cursor/openplanr/rules/planr-sync.mdc +17 -6
  142. package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
  143. package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +3 -2
  144. package/lib/host-packages/openai/openplanr/.openplanr-content.json +155 -27
  145. package/lib/host-packages/openai/openplanr/skills/ceo-review/SKILL.md +1 -1
  146. package/lib/host-packages/openai/openplanr/skills/chair-review/SKILL.md +1 -1
  147. package/lib/host-packages/openai/openplanr/skills/challenger-review/SKILL.md +1 -1
  148. package/lib/host-packages/openai/openplanr/skills/cmo-review/SKILL.md +1 -1
  149. package/lib/host-packages/openai/openplanr/skills/coo-review/SKILL.md +1 -1
  150. package/lib/host-packages/openai/openplanr/skills/cpo-review/SKILL.md +1 -1
  151. package/lib/host-packages/openai/openplanr/skills/cto-review/SKILL.md +1 -1
  152. package/lib/host-packages/openai/openplanr/skills/design/openplanr.skill.json +88 -0
  153. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-artifact-shell.mjs +2506 -0
  154. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-document.mjs +3674 -0
  155. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-entities.mjs +489 -0
  156. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-parse5-parser.mjs +3970 -0
  157. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-parse5-tokenizer.mjs +3501 -0
  158. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-review-handoff.mjs +4408 -0
  159. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-sandbox-guards.mjs +1073 -0
  160. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-share.mjs +2127 -0
  161. package/lib/host-packages/openai/openplanr/skills/design/scripts/design.mjs +83 -21459
  162. package/lib/host-packages/openai/openplanr/skills/design/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  163. package/lib/host-packages/openai/openplanr/skills/design/scripts/runtime/packages/protocol/package.json +1 -1
  164. package/lib/host-packages/openai/openplanr/skills/design-loop/openplanr.skill.json +88 -0
  165. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-artifact-shell.mjs +2506 -0
  166. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-document.mjs +3674 -0
  167. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-entities.mjs +489 -0
  168. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-parse5-parser.mjs +3970 -0
  169. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-parse5-tokenizer.mjs +3501 -0
  170. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-review-handoff.mjs +4408 -0
  171. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-sandbox-guards.mjs +1073 -0
  172. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-share.mjs +2127 -0
  173. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design.mjs +83 -21459
  174. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  175. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/runtime/packages/protocol/package.json +1 -1
  176. package/lib/host-packages/openai/openplanr/skills/design-review/openplanr.skill.json +88 -0
  177. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-artifact-shell.mjs +2506 -0
  178. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-document.mjs +3674 -0
  179. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-entities.mjs +489 -0
  180. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-parse5-parser.mjs +3970 -0
  181. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-parse5-tokenizer.mjs +3501 -0
  182. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-review-handoff.mjs +4408 -0
  183. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-sandbox-guards.mjs +1073 -0
  184. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-share.mjs +2127 -0
  185. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design.mjs +83 -21459
  186. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  187. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/runtime/packages/protocol/package.json +1 -1
  188. package/lib/host-packages/openai/openplanr/skills/plan/openplanr.skill.json +88 -0
  189. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-artifact-shell.mjs +2506 -0
  190. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-document.mjs +3674 -0
  191. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-entities.mjs +489 -0
  192. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-parse5-parser.mjs +3970 -0
  193. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-parse5-tokenizer.mjs +3501 -0
  194. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-review-handoff.mjs +4408 -0
  195. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-sandbox-guards.mjs +1073 -0
  196. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-share.mjs +2127 -0
  197. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design.mjs +83 -21459
  198. package/lib/host-packages/openai/openplanr/skills/plan/scripts/runtime/packages/design/templates/studio/studio.js +1 -0
  199. package/lib/host-packages/openai/openplanr/skills/plan/scripts/runtime/packages/protocol/package.json +1 -1
  200. package/lib/host-packages/openai/openplanr/skills/sync/SKILL.md +17 -6
  201. package/lib/host-packages/openai/openplanr/skills/sync/scripts/sync.mjs +7 -104
  202. package/lib/integrations.d.mts +0 -10
  203. package/lib/integrations.mjs +7 -104
  204. package/package.json +2 -2
@@ -0,0 +1,1073 @@
1
+ // packages/artifact/lib/artifact/ui/generated/sandbox-guards.mjs
2
+ var ARTIFACT_WORKER_GUARD_SOURCE = '// lib/artifact/ui/sandbox/worker-guard.mjs\n(() => {\n "use strict";\n const blocked = () => new DOMException("Blocked by OpenPlanr artifact sandbox", "SecurityError");\n const replace = (owner, key, value) => {\n try {\n Object.defineProperty(owner, key, { value, writable: false, configurable: false });\n } catch {\n try {\n owner[key] = value;\n } catch {\n }\n }\n };\n const reject = () => Promise.reject(blocked());\n replace(globalThis, "fetch", reject);\n for (const key of [\n "XMLHttpRequest",\n "WebSocket",\n "EventSource",\n "WebTransport",\n "RTCPeerConnection",\n "webkitRTCPeerConnection"\n ]) {\n if (key in globalThis)\n replace(\n globalThis,\n key,\n class {\n constructor() {\n throw blocked();\n }\n }\n );\n }\n for (const key of ["indexedDB", "caches", "cookieStore"]) {\n try {\n Object.defineProperty(globalThis, key, {\n get() {\n throw blocked();\n },\n configurable: false\n });\n } catch {\n }\n }\n try {\n replace(Navigator.prototype, "sendBeacon", () => false);\n } catch {\n }\n try {\n Object.defineProperty(Navigator.prototype, "serviceWorker", {\n get() {\n throw blocked();\n },\n configurable: false\n });\n } catch {\n }\n try {\n Object.defineProperty(Navigator.prototype, "clipboard", {\n get() {\n throw blocked();\n },\n configurable: false\n });\n } catch {\n }\n try {\n if (typeof StorageManager === "function" && "getDirectory" in StorageManager.prototype)\n replace(StorageManager.prototype, "getDirectory", reject);\n } catch {\n }\n try {\n if (typeof StorageManager === "function" && "persist" in StorageManager.prototype)\n replace(StorageManager.prototype, "persist", reject);\n } catch {\n }\n for (const key of ["Worker", "SharedWorker"]) {\n if (key in globalThis)\n replace(\n globalThis,\n key,\n class {\n constructor() {\n throw blocked();\n }\n }\n );\n }\n const nativeImportScripts = typeof importScripts === "function" ? importScripts.bind(globalThis) : null;\n if (nativeImportScripts)\n replace(globalThis, "importScripts", (...urls) => {\n if (!urls.every((value) => /^(?:blob:|data:)/i.test(String(value)))) throw blocked();\n return nativeImportScripts(...urls);\n });\n})();\n';
3
+ var ARTIFACT_FRAME_GUARD_TEMPLATE = `// lib/artifact/ui/sandbox/frame-guard.mjs
4
+ (() => {
5
+ "use strict";
6
+ const injectedScript = document.currentScript;
7
+ injectedScript?.remove();
8
+ const contract = __PLANR_SANDBOX_CONTRACT__;
9
+ __PLANR_SANDBOX_BRIDGE_TOOLS__;
10
+ const inspectionTools = createArtifactBridgeTools(document, globalThis);
11
+ const postToParent = parent.postMessage.bind(parent);
12
+ const elementFromPoint = document.elementFromPoint.bind(document);
13
+ const queryAll = document.querySelectorAll.bind(document);
14
+ const elementClosest = Element.prototype.closest;
15
+ const elementGetAttribute = Element.prototype.getAttribute;
16
+ const elementSetAttribute = Element.prototype.setAttribute;
17
+ const elementRect = Element.prototype.getBoundingClientRect;
18
+ const nativeCloneNode = Node.prototype.cloneNode;
19
+ const nativeAppendChild = Node.prototype.appendChild;
20
+ const nativeCreateElement = Document.prototype.createElement;
21
+ const nativeGetComputedStyle = globalThis.getComputedStyle.bind(globalThis);
22
+ const nativeSerializeToString = XMLSerializer.prototype.serializeToString;
23
+ const NativeImage = globalThis.Image;
24
+ const nativeExecCommand = Document.prototype.execCommand;
25
+ const nativeDocumentWrite = Document.prototype.write;
26
+ const nativeDocumentWriteln = Document.prototype.writeln;
27
+ const NativeWorker = globalThis.Worker;
28
+ const NativeSharedWorker = globalThis.SharedWorker;
29
+ const NativeBlob = globalThis.Blob;
30
+ const NativeResizeObserver = globalThis.ResizeObserver;
31
+ const nativeCreateObjectURL = URL.createObjectURL.bind(URL);
32
+ const nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
33
+ const workerGuard = __PLANR_SANDBOX_WORKER_GUARD__;
34
+ const blocked = () => new DOMException("Blocked by OpenPlanr artifact sandbox", "SecurityError");
35
+ const replace = (owner, key, value) => {
36
+ try {
37
+ Object.defineProperty(owner, key, { value, writable: false, configurable: false });
38
+ } catch {
39
+ try {
40
+ owner[key] = value;
41
+ } catch {
42
+ }
43
+ }
44
+ };
45
+ const reject = () => Promise.reject(blocked());
46
+ const workerUrls = /* @__PURE__ */ new Set();
47
+ let liveWorkerCount = 0;
48
+ replace(globalThis, "fetch", reject);
49
+ for (const key of [
50
+ "XMLHttpRequest",
51
+ "WebSocket",
52
+ "EventSource",
53
+ "WebTransport",
54
+ "RTCPeerConnection",
55
+ "webkitRTCPeerConnection"
56
+ ]) {
57
+ if (key in globalThis)
58
+ replace(
59
+ globalThis,
60
+ key,
61
+ class {
62
+ constructor() {
63
+ throw blocked();
64
+ }
65
+ }
66
+ );
67
+ }
68
+ replace(globalThis, "open", () => null);
69
+ try {
70
+ replace(Navigator.prototype, "sendBeacon", () => false);
71
+ } catch {
72
+ }
73
+ try {
74
+ Object.defineProperty(Navigator.prototype, "serviceWorker", {
75
+ get() {
76
+ throw blocked();
77
+ },
78
+ configurable: false
79
+ });
80
+ } catch {
81
+ }
82
+ try {
83
+ Object.defineProperty(Navigator.prototype, "clipboard", {
84
+ get() {
85
+ throw blocked();
86
+ },
87
+ configurable: false
88
+ });
89
+ } catch {
90
+ }
91
+ try {
92
+ if ("share" in Navigator.prototype) replace(Navigator.prototype, "share", reject);
93
+ } catch {
94
+ }
95
+ try {
96
+ if (typeof StorageManager === "function" && "getDirectory" in StorageManager.prototype)
97
+ replace(StorageManager.prototype, "getDirectory", reject);
98
+ } catch {
99
+ }
100
+ try {
101
+ if (typeof StorageManager === "function" && "persist" in StorageManager.prototype)
102
+ replace(StorageManager.prototype, "persist", reject);
103
+ } catch {
104
+ }
105
+ for (const key of ["localStorage", "sessionStorage", "indexedDB", "caches", "cookieStore"]) {
106
+ try {
107
+ Object.defineProperty(globalThis, key, {
108
+ get() {
109
+ throw blocked();
110
+ },
111
+ configurable: false
112
+ });
113
+ } catch {
114
+ }
115
+ }
116
+ try {
117
+ replace(HTMLFormElement.prototype, "submit", function() {
118
+ throw blocked();
119
+ });
120
+ replace(HTMLFormElement.prototype, "requestSubmit", function() {
121
+ throw blocked();
122
+ });
123
+ } catch {
124
+ }
125
+ try {
126
+ replace(Document.prototype, "open", function() {
127
+ throw blocked();
128
+ });
129
+ } catch {
130
+ }
131
+ try {
132
+ if (typeof nativeDocumentWrite === "function")
133
+ replace(Document.prototype, "write", function(...values) {
134
+ if (this.readyState !== "loading") throw blocked();
135
+ return nativeDocumentWrite.apply(this, values);
136
+ });
137
+ } catch {
138
+ }
139
+ try {
140
+ if (typeof nativeDocumentWriteln === "function")
141
+ replace(Document.prototype, "writeln", function(...values) {
142
+ if (this.readyState !== "loading") throw blocked();
143
+ return nativeDocumentWriteln.apply(this, values);
144
+ });
145
+ } catch {
146
+ }
147
+ try {
148
+ if (typeof nativeExecCommand === "function")
149
+ replace(Document.prototype, "execCommand", function(command, ...args) {
150
+ if (["copy", "cut", "paste"].includes(String(command).toLowerCase())) throw blocked();
151
+ return nativeExecCommand.call(this, command, ...args);
152
+ });
153
+ } catch {
154
+ }
155
+ const workerWrapper = (url, options, Shared) => {
156
+ if (liveWorkerCount >= 32) throw blocked();
157
+ const source = String(url);
158
+ if (!/^(?:blob:|data:)/i.test(source)) throw blocked();
159
+ const module = options && options.type === "module";
160
+ if (module) throw blocked();
161
+ const loader = "__planrLoadWorker(" + JSON.stringify(source) + ")";
162
+ const body = "(function(__planrLoadWorker){" + workerGuard + ";" + loader + "})(globalThis.importScripts.bind(globalThis));";
163
+ const wrapper = nativeCreateObjectURL(new NativeBlob([body], { type: "text/javascript" }));
164
+ workerUrls.add(wrapper);
165
+ liveWorkerCount += 1;
166
+ try {
167
+ const instance = Shared ? new NativeSharedWorker(wrapper, options) : new NativeWorker(wrapper, options);
168
+ let released = false;
169
+ const release = () => {
170
+ if (released) return;
171
+ released = true;
172
+ liveWorkerCount = Math.max(0, liveWorkerCount - 1);
173
+ workerUrls.delete(wrapper);
174
+ nativeRevokeObjectURL(wrapper);
175
+ };
176
+ if (!Shared && typeof instance.terminate === "function") {
177
+ const terminate = instance.terminate.bind(instance);
178
+ replace(instance, "terminate", () => {
179
+ release();
180
+ return terminate();
181
+ });
182
+ }
183
+ if (Shared && instance.port && typeof instance.port.close === "function") {
184
+ const close = instance.port.close.bind(instance.port);
185
+ replace(instance.port, "close", () => {
186
+ release();
187
+ return close();
188
+ });
189
+ }
190
+ return instance;
191
+ } catch (error) {
192
+ liveWorkerCount = Math.max(0, liveWorkerCount - 1);
193
+ workerUrls.delete(wrapper);
194
+ nativeRevokeObjectURL(wrapper);
195
+ throw error;
196
+ }
197
+ };
198
+ const installWorker = (name, Native, Shared) => {
199
+ if (typeof Native !== "function") return;
200
+ const Wrapped = function(url, options) {
201
+ return workerWrapper(url, options, Shared);
202
+ };
203
+ try {
204
+ Object.defineProperty(Wrapped, "name", { value: name });
205
+ Object.setPrototypeOf(Wrapped, Native);
206
+ Object.defineProperty(Wrapped, "prototype", { value: Native.prototype });
207
+ } catch {
208
+ }
209
+ replace(globalThis, name, Wrapped);
210
+ };
211
+ try {
212
+ installWorker("Worker", NativeWorker, false);
213
+ } catch {
214
+ }
215
+ try {
216
+ installWorker("SharedWorker", NativeSharedWorker, true);
217
+ } catch {
218
+ }
219
+ try {
220
+ replace(Location.prototype, "assign", function() {
221
+ throw blocked();
222
+ });
223
+ replace(Location.prototype, "replace", function() {
224
+ throw blocked();
225
+ });
226
+ } catch {
227
+ }
228
+ try {
229
+ navigation?.addEventListener("navigate", (event) => {
230
+ if (event.cancelable) event.preventDefault();
231
+ });
232
+ } catch {
233
+ }
234
+ addEventListener(
235
+ "click",
236
+ (event) => {
237
+ if (event.target?.closest?.("a,[formaction]")) event.preventDefault();
238
+ },
239
+ true
240
+ );
241
+ addEventListener("submit", (event) => event.preventDefault(), true);
242
+ for (const type of ["copy", "cut", "paste"])
243
+ addEventListener(
244
+ type,
245
+ (event) => {
246
+ event.preventDefault();
247
+ event.stopImmediatePropagation();
248
+ },
249
+ true
250
+ );
251
+ addEventListener(
252
+ "pagehide",
253
+ () => {
254
+ for (const url of workerUrls) nativeRevokeObjectURL(url);
255
+ workerUrls.clear();
256
+ liveWorkerCount = 0;
257
+ },
258
+ { once: true }
259
+ );
260
+ const plain = (value) => {
261
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
262
+ const prototype = Object.getPrototypeOf(value);
263
+ return prototype === Object.prototype || prototype === null;
264
+ };
265
+ const own = (value, key) => {
266
+ const descriptor = plain(value) ? Object.getOwnPropertyDescriptor(value, key) : null;
267
+ return descriptor && Object.hasOwn(descriptor, "value") ? descriptor.value : void 0;
268
+ };
269
+ const exact = (value, keys) => plain(value) && Object.keys(value).length === keys.length && Object.keys(value).every((key) => keys.includes(key));
270
+ const validText = (value, max) => typeof value === "string" && value.length > 0 && value.length <= max;
271
+ const validId = (value) => validText(value, 512) && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,511}$/.test(value);
272
+ const validScreen = (value) => (
273
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: a screen name must not contain control characters.
274
+ typeof value === "string" && /^[^\\u0000-\\u001f\\u007f]{1,128}$/.test(value)
275
+ );
276
+ const validRequestId = (value) => validText(value, 128) && /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/.test(value);
277
+ const validBase = (data, type, keys) => exact(data, keys) && own(data, "channel") === contract.channel && own(data, "schemaVersion") === contract.schemaVersion && own(data, "type") === type && own(data, "artifactId") === contract.artifactId && validRequestId(own(data, "requestId"));
278
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
279
+ const closest = (element, selector) => element ? elementClosest.call(element, selector) : null;
280
+ const attribute = (element, name) => element ? elementGetAttribute.call(element, name) : null;
281
+ const screenFor = (element) => attribute(closest(element, "[data-planr-screen]"), "data-planr-screen") || void 0;
282
+ const anchorFor = (element) => {
283
+ const anchor = closest(element, "[data-planr-id]");
284
+ if (!anchor) return null;
285
+ const planrId = attribute(anchor, "data-planr-id");
286
+ if (!validText(planrId, 512)) return null;
287
+ const rect = elementRect.call(anchor);
288
+ const width = Math.max(1, innerWidth), height = Math.max(1, innerHeight);
289
+ const x = clamp(rect.left, 0, width), y = clamp(rect.top, 0, height);
290
+ const right = clamp(rect.right, 0, width), bottom = clamp(rect.bottom, 0, height);
291
+ const screen = screenFor(anchor);
292
+ return {
293
+ planrId,
294
+ ...screen === void 0 ? {} : { screen },
295
+ rect: { x, y, width: Math.max(0, right - x), height: Math.max(0, bottom - y) },
296
+ viewport: { width, height }
297
+ };
298
+ };
299
+ const findById = (id, screen) => {
300
+ for (const element of queryAll("[data-planr-id]")) {
301
+ if (attribute(element, "data-planr-id") !== id) continue;
302
+ if (screen !== void 0 && screenFor(element) !== screen) continue;
303
+ return element;
304
+ }
305
+ return null;
306
+ };
307
+ const exportTarget = (target) => {
308
+ if (target === "full") return { node: document.body, label: "full" };
309
+ let node = elementFromPoint(innerWidth / 2, innerHeight / 2);
310
+ node = closest(node, "[data-planr-id],[data-dc-slot],[data-planr-screen],section[id]") || document.body;
311
+ const label = attribute(node, "data-planr-screen") || attribute(node, "data-dc-slot") || attribute(node, "data-planr-id") || attribute(node, "id") || "screen";
312
+ return { node, label };
313
+ };
314
+ const exportPng = async (target) => {
315
+ const selected = exportTarget(target), node = selected.node;
316
+ const width = Math.ceil(
317
+ Math.max(node.scrollWidth || 0, node.clientWidth || 0, elementRect.call(node).width || 0)
318
+ );
319
+ const height = Math.ceil(
320
+ Math.max(node.scrollHeight || 0, node.clientHeight || 0, elementRect.call(node).height || 0)
321
+ );
322
+ if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1 || width > __PLANR_SANDBOX_EXPORT_MAX_EDGE__ || height > __PLANR_SANDBOX_EXPORT_MAX_EDGE__ || width * height > 4e7)
323
+ throw new Error("export dimensions are unavailable or too large");
324
+ let count = 0;
325
+ const cloneStyled = (src) => {
326
+ if (++count > 1e4) throw new Error("export node limit exceeded");
327
+ if (src.nodeType === 8 || src.nodeType === 1 && src.tagName === "SCRIPT")
328
+ return document.createTextNode("");
329
+ const dst = nativeCloneNode.call(src, false);
330
+ if (src.nodeType === 1) {
331
+ const style = nativeGetComputedStyle(src);
332
+ let css = "";
333
+ for (let index = 0; index < style.length; index += 1) {
334
+ const name = style[index];
335
+ css += name + ":" + style.getPropertyValue(name) + ";";
336
+ }
337
+ elementSetAttribute.call(dst, "style", css + "animation:none;transition:none;");
338
+ if (src.tagName === "CANVAS") {
339
+ try {
340
+ const image2 = nativeCreateElement.call(document, "img");
341
+ image2.src = src.toDataURL("image/png");
342
+ elementSetAttribute.call(image2, "style", css);
343
+ return image2;
344
+ } catch {
345
+ }
346
+ }
347
+ }
348
+ for (let child = src.firstChild; child; child = child.nextSibling)
349
+ nativeAppendChild.call(dst, cloneStyled(child));
350
+ return dst;
351
+ };
352
+ await (document.fonts?.ready?.catch(() => {
353
+ }) ?? Promise.resolve());
354
+ const clone = cloneStyled(node);
355
+ if (clone.nodeType === 1) {
356
+ elementSetAttribute.call(clone, "xmlns", "http://www.w3.org/1999/xhtml");
357
+ clone.style.boxShadow = "none";
358
+ clone.style.borderRadius = "0";
359
+ }
360
+ const markup = nativeSerializeToString.call(new XMLSerializer(), clone);
361
+ if (markup.length > 10 * 1024 * 1024) throw new Error("export markup limit exceeded");
362
+ const scale = clamp(
363
+ Math.floor(__PLANR_SANDBOX_EXPORT_MAX_EDGE__ / Math.max(width, height)) || 1,
364
+ 1,
365
+ 3
366
+ );
367
+ const outputWidth = width * scale, outputHeight = height * scale;
368
+ const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + outputWidth + '" height="' + outputHeight + '" viewBox="0 0 ' + width + " " + height + '"><foreignObject width="' + width + '" height="' + height + '">' + markup + "</foreignObject></svg>";
369
+ const image = new NativeImage();
370
+ await new Promise((resolve, reject2) => {
371
+ image.onload = resolve;
372
+ image.onerror = () => reject2(new Error("render failed"));
373
+ image.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
374
+ });
375
+ const canvas = nativeCreateElement.call(document, "canvas");
376
+ canvas.width = outputWidth;
377
+ canvas.height = outputHeight;
378
+ canvas.getContext("2d").drawImage(image, 0, 0, outputWidth, outputHeight);
379
+ const dataUrl = canvas.toDataURL("image/png");
380
+ if (typeof dataUrl !== "string" || dataUrl.length > __PLANR_SANDBOX_EXPORT_MAX_DATA_URL__)
381
+ throw new Error("export PNG limit exceeded");
382
+ return {
383
+ dataUrl,
384
+ width: outputWidth,
385
+ height: outputHeight,
386
+ label: String(selected.label).slice(0, 128)
387
+ };
388
+ };
389
+ const send = (type, requestId, anchor) => {
390
+ const message = {
391
+ channel: contract.channel,
392
+ schemaVersion: contract.schemaVersion,
393
+ type,
394
+ nonce: contract.nonce,
395
+ artifactId: contract.artifactId
396
+ };
397
+ if (requestId) message.requestId = requestId;
398
+ if (anchor) message.anchor = anchor;
399
+ postToParent(message, contract.parentOrigin === "null" ? "*" : contract.parentOrigin);
400
+ };
401
+ const sendExport = (type, requestId, value) => {
402
+ const message = {
403
+ channel: contract.channel,
404
+ schemaVersion: contract.schemaVersion,
405
+ type,
406
+ nonce: contract.nonce,
407
+ artifactId: contract.artifactId,
408
+ requestId
409
+ };
410
+ if (type === "export.result") Object.assign(message, value);
411
+ else message.reason = String(value || "export failed").slice(0, 256);
412
+ postToParent(message, contract.parentOrigin === "null" ? "*" : contract.parentOrigin);
413
+ };
414
+ const viewportGestures = createArtifactViewportGestures(
415
+ window,
416
+ (type, value) => postToParent(
417
+ {
418
+ channel: contract.channel,
419
+ schemaVersion: contract.schemaVersion,
420
+ type,
421
+ nonce: contract.nonce,
422
+ artifactId: contract.artifactId,
423
+ ...value
424
+ },
425
+ contract.parentOrigin === "null" ? "*" : contract.parentOrigin
426
+ )
427
+ );
428
+ let lastLayout = "";
429
+ let layoutTimer = 0;
430
+ const measureLayout = () => {
431
+ layoutTimer = 0;
432
+ const root = document.documentElement, body = document.body;
433
+ const width = Math.ceil(
434
+ Math.max(
435
+ root?.scrollWidth || 0,
436
+ root?.clientWidth || 0,
437
+ body?.scrollWidth || 0,
438
+ body?.clientWidth || 0,
439
+ innerWidth || 0
440
+ )
441
+ );
442
+ const height = Math.ceil(
443
+ Math.max(
444
+ root?.scrollHeight || 0,
445
+ root?.clientHeight || 0,
446
+ body?.scrollHeight || 0,
447
+ body?.clientHeight || 0,
448
+ innerHeight || 0
449
+ )
450
+ );
451
+ if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1 || width > __PLANR_SANDBOX_LAYOUT_MAX_WIDTH__ || height > __PLANR_SANDBOX_LAYOUT_MAX_HEIGHT__)
452
+ return;
453
+ const signature = width + "x" + height;
454
+ if (signature === lastLayout) return;
455
+ lastLayout = signature;
456
+ postToParent(
457
+ {
458
+ channel: contract.channel,
459
+ schemaVersion: contract.schemaVersion,
460
+ type: "layout.measurement",
461
+ nonce: contract.nonce,
462
+ artifactId: contract.artifactId,
463
+ layout: { width, height }
464
+ },
465
+ contract.parentOrigin === "null" ? "*" : contract.parentOrigin
466
+ );
467
+ };
468
+ const scheduleLayout = () => {
469
+ if (layoutTimer) return;
470
+ layoutTimer = setTimeout(measureLayout, 80);
471
+ };
472
+ try {
473
+ if (typeof NativeResizeObserver === "function") {
474
+ const observer = new NativeResizeObserver(scheduleLayout);
475
+ observer.observe(document.documentElement);
476
+ if (document.body) observer.observe(document.body);
477
+ }
478
+ } catch {
479
+ }
480
+ let windowStart = performance.now(), messageCount = 0;
481
+ addEventListener("message", (event) => {
482
+ if (event.source !== parent || event.origin !== contract.parentOrigin) return;
483
+ const now = performance.now();
484
+ if (now - windowStart > 1e3) {
485
+ windowStart = now;
486
+ messageCount = 0;
487
+ }
488
+ if (++messageCount > 60) return;
489
+ const data = event.data;
490
+ if (validBase(data, "bridge.challenge", [
491
+ "channel",
492
+ "schemaVersion",
493
+ "type",
494
+ "artifactId",
495
+ "requestId"
496
+ ])) {
497
+ send("bridge.challenge-ack", data.requestId);
498
+ scheduleLayout();
499
+ return;
500
+ }
501
+ if (validBase(data, "viewport.gestures", [
502
+ "channel",
503
+ "schemaVersion",
504
+ "type",
505
+ "artifactId",
506
+ "requestId",
507
+ "enabled"
508
+ ]) && typeof own(data, "enabled") === "boolean") {
509
+ viewportGestures.setEnabled(own(data, "enabled"));
510
+ return;
511
+ }
512
+ const toolReply = (type, value = {}) => postToParent(
513
+ {
514
+ channel: contract.channel,
515
+ schemaVersion: contract.schemaVersion,
516
+ type,
517
+ nonce: contract.nonce,
518
+ artifactId: contract.artifactId,
519
+ requestId: data.requestId,
520
+ ...value
521
+ },
522
+ contract.parentOrigin === "null" ? "*" : contract.parentOrigin
523
+ );
524
+ if (validBase(data, "thumbnail.request", [
525
+ "channel",
526
+ "schemaVersion",
527
+ "type",
528
+ "artifactId",
529
+ "requestId"
530
+ ])) {
531
+ inspectionTools.thumbnail().then((value) => toolReply("thumbnail.result", value)).catch(() => toolReply("thumbnail.error", { reason: "Thumbnail capture unavailable." }));
532
+ return;
533
+ }
534
+ if (validBase(data, "inspect.point", [
535
+ "channel",
536
+ "schemaVersion",
537
+ "type",
538
+ "artifactId",
539
+ "requestId",
540
+ "x",
541
+ "y"
542
+ ])) {
543
+ const inspection = inspectionTools.inspectAt(own(data, "x"), own(data, "y"));
544
+ toolReply(inspection ? "inspect.result" : "inspect.miss", inspection ? { inspection } : {});
545
+ return;
546
+ }
547
+ const inspectionKeys = own(data, "screen") === void 0 ? ["channel", "schemaVersion", "type", "artifactId", "requestId", "planrId"] : ["channel", "schemaVersion", "type", "artifactId", "requestId", "planrId", "screen"];
548
+ if (validBase(data, "inspect.anchor", inspectionKeys)) {
549
+ const inspection = inspectionTools.inspect({
550
+ planrId: own(data, "planrId"),
551
+ ...own(data, "screen") === void 0 ? {} : { screen: own(data, "screen") }
552
+ });
553
+ toolReply(inspection ? "inspect.result" : "inspect.miss", inspection ? { inspection } : {});
554
+ return;
555
+ }
556
+ if (validBase(data, "export.request", [
557
+ "channel",
558
+ "schemaVersion",
559
+ "type",
560
+ "artifactId",
561
+ "requestId",
562
+ "target"
563
+ ]) && ["screen", "full"].includes(own(data, "target"))) {
564
+ exportPng(own(data, "target")).then((value) => sendExport("export.result", data.requestId, value)).catch((error) => sendExport("export.error", data.requestId, error?.message));
565
+ return;
566
+ }
567
+ if (validBase(data, "anchor.hit-test", [
568
+ "channel",
569
+ "schemaVersion",
570
+ "type",
571
+ "artifactId",
572
+ "requestId",
573
+ "x",
574
+ "y"
575
+ ])) {
576
+ const x = own(data, "x"), y = own(data, "y");
577
+ if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || y < 0 || x > innerWidth || y > innerHeight)
578
+ return;
579
+ const anchor = anchorFor(elementFromPoint(x, y));
580
+ send(anchor ? "anchor.result" : "anchor.miss", data.requestId, anchor);
581
+ return;
582
+ }
583
+ const resolveKeys = own(data, "screen") === void 0 ? ["channel", "schemaVersion", "type", "artifactId", "requestId", "planrId"] : ["channel", "schemaVersion", "type", "artifactId", "requestId", "planrId", "screen"];
584
+ if (validBase(data, "anchor.resolve", resolveKeys)) {
585
+ const planrId = own(data, "planrId"), screen = own(data, "screen");
586
+ if (!validId(planrId) || screen !== void 0 && !validScreen(screen)) return;
587
+ const anchor = anchorFor(findById(planrId, screen));
588
+ send(anchor ? "anchor.result" : "anchor.miss", data.requestId, anchor);
589
+ }
590
+ });
591
+ const ready = () => send("bridge.ready");
592
+ if (document.readyState === "loading")
593
+ document.addEventListener(
594
+ "DOMContentLoaded",
595
+ () => {
596
+ ready();
597
+ scheduleLayout();
598
+ },
599
+ { once: true }
600
+ );
601
+ else
602
+ queueMicrotask(() => {
603
+ ready();
604
+ scheduleLayout();
605
+ });
606
+ })();
607
+ `;
608
+ var ARTIFACT_HOST_GUARD_TEMPLATE = `// lib/artifact/ui/sandbox/host-guard.mjs
609
+ (() => {
610
+ "use strict";
611
+ const config = __PLANR_SANDBOX_CONFIG__;
612
+ __PLANR_SANDBOX_BRIDGE_TOOLS__;
613
+ const requestId = () => crypto.randomUUID?.() || "request-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2);
614
+ const bridgeClient = {
615
+ attach({ artifact, frame, getState }) {
616
+ const pending = /* @__PURE__ */ new Map();
617
+ let windowStart = performance.now(), messageCount = 0;
618
+ let immutableSource = "", trustedLoad = false, recovering = false, navigationAttempts = 0, failedClosed = false;
619
+ let inertSource = "";
620
+ let pendingChallenge = null;
621
+ let measuredLayout = null;
622
+ let viewportGesturesEnabled = false, disposed = false;
623
+ const syncViewportGestures = () => {
624
+ if (trustedLoad && !disposed)
625
+ frame.contentWindow?.postMessage(
626
+ {
627
+ channel: config.channel,
628
+ schemaVersion: config.schemaVersion,
629
+ type: "viewport.gestures",
630
+ artifactId: artifact.id,
631
+ requestId: requestId(),
632
+ enabled: viewportGesturesEnabled
633
+ },
634
+ "*"
635
+ );
636
+ };
637
+ const plain = (value) => {
638
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
639
+ const prototype = Object.getPrototypeOf(value);
640
+ return prototype === Object.prototype || prototype === null;
641
+ };
642
+ const own = (value, key) => {
643
+ const descriptor = plain(value) ? Object.getOwnPropertyDescriptor(value, key) : null;
644
+ return descriptor && Object.hasOwn(descriptor, "value") ? descriptor.value : void 0;
645
+ };
646
+ const exact = (value, keys) => plain(value) && Object.keys(value).length === keys.length && Object.keys(value).every((key) => keys.includes(key));
647
+ const validText = (value, max) => typeof value === "string" && value.length > 0 && value.length <= max;
648
+ const validId = (value) => validText(value, 512) && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,511}$/.test(value);
649
+ const validScreen = (value) => (
650
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: a screen name must not contain control characters.
651
+ typeof value === "string" && /^[^\\u0000-\\u001f\\u007f]{1,128}$/.test(value)
652
+ );
653
+ const validRequestId = (value) => validText(value, 128) && /^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/.test(value);
654
+ const validNumber = (value) => typeof value === "number" && Number.isFinite(value);
655
+ const originalPointerEvents = frame.style.pointerEvents;
656
+ const originalInert = frame.inert;
657
+ const quarantine = (active) => {
658
+ frame.inert = active ? true : originalInert;
659
+ frame.style.pointerEvents = active ? "none" : originalPointerEvents;
660
+ if (active) frame.setAttribute("aria-busy", "true");
661
+ else frame.removeAttribute("aria-busy");
662
+ frame.dataset.planrBridgeTrusted = String(!active);
663
+ };
664
+ frame.setAttribute("csp", config.frameCsp);
665
+ quarantine(true);
666
+ const receive = (event) => {
667
+ if (event.source !== frame.contentWindow || event.origin !== "null") return;
668
+ const now = performance.now();
669
+ if (now - windowStart > 1e3) {
670
+ windowStart = now;
671
+ messageCount = 0;
672
+ }
673
+ if (++messageCount > 120) return;
674
+ const data = event.data;
675
+ if (!data || typeof data !== "object" || Array.isArray(data)) return;
676
+ if (own(data, "channel") !== config.channel || own(data, "schemaVersion") !== config.schemaVersion || own(data, "nonce") !== config.nonce || own(data, "artifactId") !== artifact.id)
677
+ return;
678
+ const type = own(data, "type");
679
+ if (type === "bridge.ready") {
680
+ if (!exact(data, ["channel", "schemaVersion", "type", "nonce", "artifactId"])) return;
681
+ return;
682
+ }
683
+ if (type === "bridge.challenge-ack") {
684
+ if (!exact(data, [
685
+ "channel",
686
+ "schemaVersion",
687
+ "type",
688
+ "nonce",
689
+ "artifactId",
690
+ "requestId"
691
+ ]) || !validRequestId(own(data, "requestId")) || !pendingChallenge || own(data, "requestId") !== pendingChallenge.id)
692
+ return;
693
+ clearTimeout(pendingChallenge.timer);
694
+ pendingChallenge = null;
695
+ trustedLoad = true;
696
+ recovering = false;
697
+ quarantine(false);
698
+ syncViewportGestures();
699
+ frame.dispatchEvent(
700
+ new CustomEvent(config.readyEvent, {
701
+ detail: { artifactId: artifact.id, authenticated: true }
702
+ })
703
+ );
704
+ return;
705
+ }
706
+ if (type === "viewport.zoom") {
707
+ if (!trustedLoad || !viewportGesturesEnabled || disposed || !exact(data, [
708
+ "channel",
709
+ "schemaVersion",
710
+ "type",
711
+ "nonce",
712
+ "artifactId",
713
+ "x",
714
+ "y",
715
+ "deltaY"
716
+ ]))
717
+ return;
718
+ const value2 = normalizeArtifactViewportZoom(
719
+ { x: own(data, "x"), y: own(data, "y"), deltaY: own(data, "deltaY") },
720
+ artifact.viewport
721
+ );
722
+ if (value2)
723
+ frame.dispatchEvent(
724
+ new CustomEvent(config.viewportZoomEvent, { bubbles: true, detail: value2 })
725
+ );
726
+ return;
727
+ }
728
+ if (type === "viewport.pan") {
729
+ if (!trustedLoad || !viewportGesturesEnabled || disposed || !exact(data, [
730
+ "channel",
731
+ "schemaVersion",
732
+ "type",
733
+ "nonce",
734
+ "artifactId",
735
+ "deltaX",
736
+ "deltaY"
737
+ ]))
738
+ return;
739
+ const value2 = normalizeArtifactViewportPan({
740
+ deltaX: own(data, "deltaX"),
741
+ deltaY: own(data, "deltaY")
742
+ });
743
+ if (value2)
744
+ frame.dispatchEvent(
745
+ new CustomEvent(config.viewportPanEvent, { bubbles: true, detail: value2 })
746
+ );
747
+ return;
748
+ }
749
+ if (type === "layout.measurement") {
750
+ const layout = own(data, "layout");
751
+ if (!trustedLoad || !exact(data, ["channel", "schemaVersion", "type", "nonce", "artifactId", "layout"]) || !exact(layout, ["width", "height"]) || !Number.isInteger(layout.width) || !Number.isInteger(layout.height) || layout.width < 1 || layout.width > __PLANR_SANDBOX_LAYOUT_MAX_WIDTH__ || layout.height < 1 || layout.height > __PLANR_SANDBOX_LAYOUT_MAX_HEIGHT__)
752
+ return;
753
+ measuredLayout = Object.freeze({ width: layout.width, height: layout.height });
754
+ frame.dispatchEvent(new CustomEvent(config.layoutEvent, { detail: measuredLayout }));
755
+ return;
756
+ }
757
+ const receivedRequestId = own(data, "requestId");
758
+ if (!trustedLoad || !validRequestId(receivedRequestId) || !pending.has(receivedRequestId))
759
+ return;
760
+ const settle = pending.get(receivedRequestId);
761
+ if (["inspect.point", "inspect.anchor", "thumbnail.request"].includes(settle.type)) {
762
+ const result = normalizeArtifactBridgeToolResult(settle.type, data, artifact.viewport);
763
+ if (!result.valid) return;
764
+ pending.delete(receivedRequestId);
765
+ clearTimeout(settle.timer);
766
+ settle.resolve(result.value);
767
+ return;
768
+ }
769
+ if (settle.type === "export.request") {
770
+ if (type === "export.error") {
771
+ if (!exact(data, [
772
+ "channel",
773
+ "schemaVersion",
774
+ "type",
775
+ "nonce",
776
+ "artifactId",
777
+ "requestId",
778
+ "reason"
779
+ ]) || typeof own(data, "reason") !== "string" || own(data, "reason").length > 256)
780
+ return;
781
+ pending.delete(receivedRequestId);
782
+ clearTimeout(settle.timer);
783
+ settle.resolve(null);
784
+ return;
785
+ }
786
+ if (type !== "export.result" || !exact(data, [
787
+ "channel",
788
+ "schemaVersion",
789
+ "type",
790
+ "nonce",
791
+ "artifactId",
792
+ "requestId",
793
+ "dataUrl",
794
+ "width",
795
+ "height",
796
+ "label"
797
+ ]))
798
+ return;
799
+ const dataUrl = own(data, "dataUrl"), width = own(data, "width"), height = own(data, "height"), label = own(data, "label");
800
+ pending.delete(receivedRequestId);
801
+ clearTimeout(settle.timer);
802
+ if (typeof dataUrl !== "string" || dataUrl.length > __PLANR_SANDBOX_EXPORT_MAX_DATA_URL__ || !/^data:image\\/png;base64,[A-Za-z0-9+/]+=*$/.test(dataUrl) || !Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1 || width > __PLANR_SANDBOX_EXPORT_MAX_EDGE__ || height > __PLANR_SANDBOX_EXPORT_MAX_EDGE__ || !validText(label, 128)) {
803
+ settle.resolve(null);
804
+ return;
805
+ }
806
+ settle.resolve(Object.freeze({ dataUrl, width, height, label }));
807
+ return;
808
+ }
809
+ if (!["anchor.result", "anchor.miss"].includes(type)) return;
810
+ if (type === "anchor.miss" && !exact(data, ["channel", "schemaVersion", "type", "nonce", "artifactId", "requestId"]))
811
+ return;
812
+ if (type === "anchor.result" && !exact(data, [
813
+ "channel",
814
+ "schemaVersion",
815
+ "type",
816
+ "nonce",
817
+ "artifactId",
818
+ "requestId",
819
+ "anchor"
820
+ ]))
821
+ return;
822
+ pending.delete(receivedRequestId);
823
+ clearTimeout(settle.timer);
824
+ if (type === "anchor.miss") {
825
+ settle.resolve(null);
826
+ return;
827
+ }
828
+ const anchor = data.anchor, rect = anchor?.rect, viewport = anchor?.viewport;
829
+ const frozen = getState?.()?.presentation === "document" && measuredLayout ? measuredLayout : artifact.viewport;
830
+ const anchorKeys = anchor?.screen === void 0 ? ["planrId", "rect", "viewport"] : ["planrId", "screen", "rect", "viewport"];
831
+ if (!exact(anchor, anchorKeys) || !exact(rect, ["x", "y", "width", "height"]) || !exact(viewport, ["width", "height"]) || !validId(anchor?.planrId) || anchor.screen !== void 0 && !validScreen(anchor.screen) || !["x", "y", "width", "height"].every((key) => validNumber(rect?.[key])) || viewport?.width !== frozen.width || viewport?.height !== frozen.height || rect.x < 0 || rect.y < 0 || rect.width < 0 || rect.height < 0 || rect.x + rect.width > frozen.width || rect.y + rect.height > frozen.height) {
832
+ settle.resolve(null);
833
+ return;
834
+ }
835
+ const value = Object.freeze({
836
+ artifactId: artifact.id,
837
+ planrId: anchor.planrId,
838
+ ...anchor.screen === void 0 ? {} : { screen: anchor.screen },
839
+ rect: Object.freeze({ ...rect }),
840
+ viewport: frozen
841
+ });
842
+ settle.resolve(value);
843
+ frame.dispatchEvent(new CustomEvent(config.anchorEvent, { detail: value }));
844
+ };
845
+ addEventListener("message", receive);
846
+ const rememberSource = () => {
847
+ if (immutableSource) return;
848
+ const html = frame.getAttribute("srcdoc") || "";
849
+ if (html) {
850
+ immutableSource = { type: "srcdoc", value: html };
851
+ return;
852
+ }
853
+ const value = frame.getAttribute("src") || "";
854
+ if (value.startsWith("blob:")) immutableSource = { type: "url", value };
855
+ };
856
+ const sourceObserver = new MutationObserver(rememberSource);
857
+ sourceObserver.observe(frame, { attributes: true, attributeFilter: ["src", "srcdoc"] });
858
+ const settlePending = () => {
859
+ for (const value of pending.values()) {
860
+ clearTimeout(value.timer);
861
+ value.resolve(null);
862
+ }
863
+ pending.clear();
864
+ };
865
+ const clearChallenge = () => {
866
+ if (pendingChallenge) {
867
+ clearTimeout(pendingChallenge.timer);
868
+ pendingChallenge = null;
869
+ }
870
+ };
871
+ const failClosed = () => {
872
+ if (failedClosed) return;
873
+ failedClosed = true;
874
+ recovering = false;
875
+ clearChallenge();
876
+ settlePending();
877
+ quarantine(true);
878
+ const inertPolicy = config.frameCsp.replaceAll("&", "&amp;").replaceAll('"', "&quot;");
879
+ inertSource = URL.createObjectURL(
880
+ new Blob(
881
+ [
882
+ '<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="' + inertPolicy + '"><meta name="referrer" content="no-referrer"><title>Artifact blocked</title><p>Artifact navigation was blocked.</p>'
883
+ ],
884
+ { type: "text/html" }
885
+ )
886
+ );
887
+ frame.dispatchEvent(
888
+ new CustomEvent(config.navigationEvent, {
889
+ detail: {
890
+ artifactId: artifact.id,
891
+ recovered: false,
892
+ failedClosed: true,
893
+ attempts: navigationAttempts
894
+ }
895
+ })
896
+ );
897
+ frame.removeAttribute("srcdoc");
898
+ frame.src = inertSource;
899
+ };
900
+ const recoverNavigation = () => {
901
+ if (failedClosed || !immutableSource) return;
902
+ navigationAttempts += 1;
903
+ if (navigationAttempts >= 3) {
904
+ failClosed();
905
+ return;
906
+ }
907
+ recovering = true;
908
+ trustedLoad = false;
909
+ quarantine(true);
910
+ clearChallenge();
911
+ frame.dispatchEvent(
912
+ new CustomEvent(config.navigationEvent, {
913
+ detail: {
914
+ artifactId: artifact.id,
915
+ recovered: true,
916
+ failedClosed: false,
917
+ attempts: navigationAttempts
918
+ }
919
+ })
920
+ );
921
+ if (immutableSource.type === "srcdoc") {
922
+ frame.removeAttribute("src");
923
+ frame.removeAttribute("srcdoc");
924
+ frame.srcdoc = immutableSource.value;
925
+ } else {
926
+ frame.removeAttribute("srcdoc");
927
+ frame.src = immutableSource.value;
928
+ }
929
+ };
930
+ const challengeCurrentDocument = () => {
931
+ if (failedClosed) return;
932
+ clearChallenge();
933
+ const id = requestId();
934
+ const timer = setTimeout(() => {
935
+ if (pendingChallenge?.id !== id) return;
936
+ pendingChallenge = null;
937
+ recoverNavigation();
938
+ }, 750);
939
+ pendingChallenge = { id, timer };
940
+ frame.contentWindow?.postMessage(
941
+ {
942
+ channel: config.channel,
943
+ schemaVersion: config.schemaVersion,
944
+ type: "bridge.challenge",
945
+ artifactId: artifact.id,
946
+ requestId: id
947
+ },
948
+ "*"
949
+ );
950
+ };
951
+ const onFrameLoad = () => {
952
+ rememberSource();
953
+ trustedLoad = false;
954
+ measuredLayout = null;
955
+ quarantine(true);
956
+ challengeCurrentDocument();
957
+ };
958
+ frame.addEventListener("load", onFrameLoad);
959
+ const send = (type, payload = {}) => new Promise((resolve) => {
960
+ if (!trustedLoad || pending.size >= 32) {
961
+ resolve(null);
962
+ return;
963
+ }
964
+ const id = requestId();
965
+ const timer = setTimeout(() => {
966
+ pending.delete(id);
967
+ resolve(null);
968
+ }, ARTIFACT_BRIDGE_OPERATION_TIMEOUTS[type] || 750);
969
+ pending.set(id, { resolve, timer, type });
970
+ frame.contentWindow?.postMessage(
971
+ {
972
+ channel: config.channel,
973
+ schemaVersion: config.schemaVersion,
974
+ type,
975
+ artifactId: artifact.id,
976
+ requestId: id,
977
+ ...payload
978
+ },
979
+ "*"
980
+ );
981
+ });
982
+ Object.defineProperty(frame, "__openPlanrBridge", {
983
+ value: Object.freeze({
984
+ setViewportGestures: (enabled) => {
985
+ if (typeof enabled !== "boolean" || disposed) return false;
986
+ if (enabled === viewportGesturesEnabled) return true;
987
+ viewportGesturesEnabled = enabled;
988
+ syncViewportGestures();
989
+ return true;
990
+ },
991
+ hitTest: (x, y) => Number.isFinite(x) && Number.isFinite(y) ? send("anchor.hit-test", { x, y }) : Promise.resolve(null),
992
+ resolve: (planrId, screen) => validText(planrId, 512) ? send("anchor.resolve", { planrId, ...screen ? { screen } : {} }) : Promise.resolve(null),
993
+ inspectAt: (x, y) => Number.isFinite(x) && Number.isFinite(y) && x >= 0 && y >= 0 ? send("inspect.point", { x, y }) : Promise.resolve(null),
994
+ inspect: (anchor) => validId(anchor?.planrId) && (anchor.screen === void 0 || validScreen(anchor.screen)) ? send("inspect.anchor", {
995
+ planrId: anchor.planrId,
996
+ ...anchor.screen === void 0 ? {} : { screen: anchor.screen }
997
+ }) : Promise.resolve(null),
998
+ thumbnail: () => send("thumbnail.request"),
999
+ exportPng: (target) => ["screen", "full"].includes(target) ? send("export.request", { target }) : Promise.resolve(null)
1000
+ }),
1001
+ configurable: true
1002
+ });
1003
+ return () => {
1004
+ viewportGesturesEnabled = false;
1005
+ syncViewportGestures();
1006
+ disposed = true;
1007
+ removeEventListener("message", receive);
1008
+ frame.removeEventListener("load", onFrameLoad);
1009
+ sourceObserver.disconnect();
1010
+ clearChallenge();
1011
+ settlePending();
1012
+ if (inertSource) URL.revokeObjectURL(inertSource);
1013
+ frame.inert = originalInert;
1014
+ frame.style.pointerEvents = originalPointerEvents;
1015
+ frame.removeAttribute("aria-busy");
1016
+ frame.removeAttribute("csp");
1017
+ delete frame.dataset.planrBridgeTrusted;
1018
+ try {
1019
+ delete frame.__openPlanrBridge;
1020
+ } catch {
1021
+ }
1022
+ };
1023
+ }
1024
+ };
1025
+ globalThis.__OPENPLANR_ARTIFACT_STAGE_OPTIONS__ = Object.freeze({
1026
+ async resolveArtifactSource(artifact) {
1027
+ if (config.inlineArtifacts) {
1028
+ const html = config.inlineArtifacts[artifact.id];
1029
+ if (typeof html !== "string") throw new Error("Artifact source unavailable");
1030
+ return new Blob([html], { type: "text/html" });
1031
+ }
1032
+ const response = await fetch(config.artifactBaseUrl + encodeURIComponent(artifact.id), {
1033
+ cache: "no-store",
1034
+ credentials: "omit",
1035
+ referrerPolicy: "no-referrer"
1036
+ });
1037
+ if (!response.ok || !(response.headers.get("content-type") || "").toLowerCase().startsWith("application/octet-stream"))
1038
+ throw new Error("Artifact source unavailable");
1039
+ return new Blob([await response.arrayBuffer()], { type: "text/html" });
1040
+ },
1041
+ bridgeClient,
1042
+ onState(state) {
1043
+ dispatchEvent(new CustomEvent("planr:artifact-state", { detail: state }));
1044
+ }
1045
+ });
1046
+ const loadStage = () => {
1047
+ const stage = document.createElement("script");
1048
+ stage.src = config.stageRuntimeUrl;
1049
+ stage.async = false;
1050
+ document.head.append(stage);
1051
+ };
1052
+ if (config.adapterRuntimeUrl) {
1053
+ const adapter = document.createElement("script");
1054
+ adapter.src = config.adapterRuntimeUrl;
1055
+ adapter.async = false;
1056
+ adapter.addEventListener("load", loadStage, { once: true });
1057
+ adapter.addEventListener(
1058
+ "error",
1059
+ () => {
1060
+ document.documentElement.dataset.planrAdapterError = "true";
1061
+ },
1062
+ { once: true }
1063
+ );
1064
+ document.head.append(adapter);
1065
+ } else loadStage();
1066
+ })();
1067
+ `;
1068
+
1069
+ export {
1070
+ ARTIFACT_WORKER_GUARD_SOURCE,
1071
+ ARTIFACT_FRAME_GUARD_TEMPLATE,
1072
+ ARTIFACT_HOST_GUARD_TEMPLATE
1073
+ };