@songsid/agend 2.3.3-beta.4 → 2.3.3-beta.5

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 (234) hide show
  1. package/dist/agent-cli.js +13 -112
  2. package/dist/agent-cli.js.map +1 -1
  3. package/dist/agent-endpoint.d.ts +0 -1
  4. package/dist/agent-endpoint.js +1 -9
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/agent-whats-new.d.ts +3 -6
  7. package/dist/agent-whats-new.js +7 -18
  8. package/dist/agent-whats-new.js.map +1 -1
  9. package/dist/auth-api.d.ts +0 -7
  10. package/dist/auth-api.js +1 -15
  11. package/dist/auth-api.js.map +1 -1
  12. package/dist/backend/codex.d.ts +1 -0
  13. package/dist/backend/codex.js +106 -15
  14. package/dist/backend/codex.js.map +1 -1
  15. package/dist/backend/types.d.ts +17 -0
  16. package/dist/backend/types.js.map +1 -1
  17. package/dist/bundled-skills.d.ts +4 -6
  18. package/dist/bundled-skills.js +10 -14
  19. package/dist/bundled-skills.js.map +1 -1
  20. package/dist/channel/mcp-server.js +5 -5
  21. package/dist/channel/mcp-server.js.map +1 -1
  22. package/dist/channel/mcp-tools.d.ts +1 -3
  23. package/dist/channel/mcp-tools.js +4 -58
  24. package/dist/channel/mcp-tools.js.map +1 -1
  25. package/dist/cli.js +3 -1
  26. package/dist/cli.js.map +1 -1
  27. package/dist/config-validator.js +6 -3
  28. package/dist/config-validator.js.map +1 -1
  29. package/dist/daemon.d.ts +11 -3
  30. package/dist/daemon.js +59 -107
  31. package/dist/daemon.js.map +1 -1
  32. package/dist/dashboard-live.d.ts +1 -1
  33. package/dist/dashboard-live.js +3 -3
  34. package/dist/dashboard-live.js.map +1 -1
  35. package/dist/dashboard-permissions.d.ts +1 -1
  36. package/dist/dashboard-permissions.js +1 -3
  37. package/dist/dashboard-permissions.js.map +1 -1
  38. package/dist/fleet-manager.d.ts +26 -44
  39. package/dist/fleet-manager.js +70 -226
  40. package/dist/fleet-manager.js.map +1 -1
  41. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +11 -1
  42. package/dist/general-knowledge/skills/session-management/SKILL.md +6 -0
  43. package/dist/general-knowledge/skills/web-appearance/SKILL.md +13 -204
  44. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +26 -63
  45. package/dist/instance-lifecycle.js +1 -1
  46. package/dist/instance-lifecycle.js.map +1 -1
  47. package/dist/locale.js +2 -0
  48. package/dist/locale.js.map +1 -1
  49. package/dist/outbound-handlers.js +19 -7
  50. package/dist/outbound-handlers.js.map +1 -1
  51. package/dist/outbound-schemas.d.ts +0 -62
  52. package/dist/outbound-schemas.js +2 -41
  53. package/dist/outbound-schemas.js.map +1 -1
  54. package/dist/public-web-gateway.js +0 -9
  55. package/dist/public-web-gateway.js.map +1 -1
  56. package/dist/public-web-link.d.ts +2 -0
  57. package/dist/public-web-link.js +5 -0
  58. package/dist/public-web-link.js.map +1 -1
  59. package/dist/search/search-docs.d.ts +1 -1
  60. package/dist/search/search-docs.js +2 -2
  61. package/dist/search/search-docs.js.map +1 -1
  62. package/dist/settings-api.d.ts +6 -0
  63. package/dist/settings-api.js +14 -2
  64. package/dist/settings-api.js.map +1 -1
  65. package/dist/settings-change.js +3 -1
  66. package/dist/settings-change.js.map +1 -1
  67. package/dist/tool-permissions.js +3 -10
  68. package/dist/tool-permissions.js.map +1 -1
  69. package/dist/topic-commands.d.ts +6 -2
  70. package/dist/topic-commands.js +2 -0
  71. package/dist/topic-commands.js.map +1 -1
  72. package/dist/types.d.ts +2 -1
  73. package/dist/ui/chat-ambient.js +4 -4
  74. package/dist/ui/chat-commands.js +3 -2
  75. package/dist/ui/chat-store.js +4 -1
  76. package/dist/ui/chat-strings.js +6 -42
  77. package/dist/ui/chat-thread.js +6 -44
  78. package/dist/ui/panel-chat.js +21 -50
  79. package/dist/ui/preview-panel.js +3 -15
  80. package/dist/ui/search-dialog.js +30 -14
  81. package/dist/ui/settings-appearance.js +1 -3
  82. package/dist/ui/settings-guests.js +13 -4
  83. package/dist/ui/settings-learn.js +1 -1
  84. package/dist/ui/settings-mods.js +5 -12
  85. package/dist/ui/settings-registry.js +0 -1
  86. package/dist/ui/settings-strings.js +6 -6
  87. package/dist/ui/shared/app-prefs.js +17 -17
  88. package/dist/ui/shared/app-shell.js +12 -8
  89. package/dist/ui/shared/app-store.js +6 -2
  90. package/dist/ui/shared/app.css +4 -36
  91. package/dist/ui/shared/app.js +5 -4
  92. package/dist/ui/shared/instance-nav.js +9 -9
  93. package/dist/ui/shared/instance-switch.js +8 -2
  94. package/dist/ui/shared/panel-view.js +22 -8
  95. package/dist/ui/shared/view-strings.js +6 -0
  96. package/dist/usage/usage-api.d.ts +3 -0
  97. package/dist/usage/usage-api.js +5 -1
  98. package/dist/usage/usage-api.js.map +1 -1
  99. package/dist/view-api.d.ts +2 -0
  100. package/dist/view-api.js +64 -0
  101. package/dist/view-api.js.map +1 -1
  102. package/dist/web-api.d.ts +9 -17
  103. package/dist/web-api.js +255 -371
  104. package/dist/web-api.js.map +1 -1
  105. package/dist/web-appearance-tools.d.ts +0 -2
  106. package/dist/web-appearance-tools.js +2 -5
  107. package/dist/web-appearance-tools.js.map +1 -1
  108. package/dist/web-appearance-view.d.ts +0 -6
  109. package/dist/web-appearance-view.js +0 -1
  110. package/dist/web-appearance-view.js.map +1 -1
  111. package/dist/web-appearance.d.ts +14 -7
  112. package/dist/web-appearance.js +5 -6
  113. package/dist/web-appearance.js.map +1 -1
  114. package/dist/web-asset-parts.d.ts +1 -17
  115. package/dist/web-asset-parts.js +1 -15
  116. package/dist/web-asset-parts.js.map +1 -1
  117. package/dist/web-auth.js +1 -7
  118. package/dist/web-auth.js.map +1 -1
  119. package/dist/web-chat-history.d.ts +3 -7
  120. package/dist/web-chat-history.js +10 -17
  121. package/dist/web-chat-history.js.map +1 -1
  122. package/dist/web-commands.d.ts +9 -1
  123. package/dist/web-commands.js +13 -0
  124. package/dist/web-commands.js.map +1 -1
  125. package/dist/web-experimental.d.ts +2 -11
  126. package/dist/web-experimental.js +8 -36
  127. package/dist/web-experimental.js.map +1 -1
  128. package/dist/web-guest-access.d.ts +40 -2
  129. package/dist/web-guest-access.js +50 -14
  130. package/dist/web-guest-access.js.map +1 -1
  131. package/dist/web-mod-bundle.d.ts +2 -45
  132. package/dist/web-mod-bundle.js +15 -63
  133. package/dist/web-mod-bundle.js.map +1 -1
  134. package/dist/web-mod-store.d.ts +3 -48
  135. package/dist/web-mod-store.js +30 -97
  136. package/dist/web-mod-store.js.map +1 -1
  137. package/dist/web-prefs.d.ts +13 -0
  138. package/dist/web-prefs.js +38 -0
  139. package/dist/web-prefs.js.map +1 -1
  140. package/dist/web-preview.d.ts +1 -11
  141. package/dist/web-preview.js +6 -20
  142. package/dist/web-preview.js.map +1 -1
  143. package/dist/web-session.d.ts +11 -3
  144. package/dist/web-session.js +22 -11
  145. package/dist/web-session.js.map +1 -1
  146. package/dist/web-settings-patch.d.ts +1 -0
  147. package/dist/web-settings-patch.js +6 -3
  148. package/dist/web-settings-patch.js.map +1 -1
  149. package/dist/web-settings-tools.d.ts +0 -13
  150. package/dist/web-settings-tools.js +12 -84
  151. package/dist/web-settings-tools.js.map +1 -1
  152. package/package.json +1 -1
  153. package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +0 -376
  154. package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +0 -672
  155. package/dist/ui/app-effects.js +0 -251
  156. package/dist/ui/chat-effect-posters.js +0 -42
  157. package/dist/ui/chat-effects.js +0 -167
  158. package/dist/ui/effect-trial-controller.js +0 -124
  159. package/dist/ui/effect-trial-offer.js +0 -2
  160. package/dist/ui/effect-trial-panel.js +0 -40
  161. package/dist/ui/effects-waker.js +0 -2
  162. package/dist/ui/settings-effects.js +0 -202
  163. package/dist/ui/settings-owner-effects.js +0 -82
  164. package/dist/ui/shared/effect-app-runtime.js +0 -299
  165. package/dist/ui/shared/effect-baseline.js +0 -64
  166. package/dist/ui/shared/effect-chat-runtime.js +0 -162
  167. package/dist/ui/shared/effect-cursor.js +0 -126
  168. package/dist/ui/shared/effect-display-metadata.js +0 -39
  169. package/dist/ui/shared/effect-frame.js +0 -146
  170. package/dist/ui/shared/effect-geometry.js +0 -137
  171. package/dist/ui/shared/effect-host-style.js +0 -10
  172. package/dist/ui/shared/effect-owner-regions.js +0 -74
  173. package/dist/ui/shared/effect-owner-source.js +0 -122
  174. package/dist/ui/shared/effect-policy.js +0 -151
  175. package/dist/ui/shared/effect-poster-reader.js +0 -98
  176. package/dist/ui/shared/effect-posters.js +0 -117
  177. package/dist/ui/shared/effect-profiler.js +0 -184
  178. package/dist/ui/shared/effect-profiles.js +0 -65
  179. package/dist/ui/shared/effect-registry.js +0 -545
  180. package/dist/ui/shared/effect-runtime-loader.js +0 -236
  181. package/dist/ui/shared/effect-safety.js +0 -153
  182. package/dist/ui/shared/effect-stock-snapshot.js +0 -43
  183. package/dist/ui/shared/effect-stock-trust.js +0 -217
  184. package/dist/ui/shared/effect-trial-shadow.js +0 -62
  185. package/dist/ui/shared/effect-trial-source.js +0 -103
  186. package/dist/ui/shared/effect-trial-stage.js +0 -170
  187. package/dist/ui/shared/effect-trial.css +0 -40
  188. package/dist/ui/shared/feature-flags.js +0 -127
  189. package/dist/ui/shared/owner-effect-prefs.js +0 -117
  190. package/dist/web-effect-bootstrap.d.ts +0 -12
  191. package/dist/web-effect-bootstrap.js +0 -49
  192. package/dist/web-effect-bootstrap.js.map +0 -1
  193. package/dist/web-effect-bundle.d.ts +0 -28
  194. package/dist/web-effect-bundle.js +0 -171
  195. package/dist/web-effect-bundle.js.map +0 -1
  196. package/dist/web-effect-canonical.d.ts +0 -8
  197. package/dist/web-effect-canonical.js +0 -27
  198. package/dist/web-effect-canonical.js.map +0 -1
  199. package/dist/web-effect-library.d.ts +0 -114
  200. package/dist/web-effect-library.js +0 -530
  201. package/dist/web-effect-library.js.map +0 -1
  202. package/dist/web-effect-playback.d.ts +0 -30
  203. package/dist/web-effect-playback.js +0 -71
  204. package/dist/web-effect-playback.js.map +0 -1
  205. package/dist/web-effect-poster.d.ts +0 -8
  206. package/dist/web-effect-poster.js +0 -52
  207. package/dist/web-effect-poster.js.map +0 -1
  208. package/dist/web-effect-profiles.d.ts +0 -118
  209. package/dist/web-effect-profiles.js +0 -181
  210. package/dist/web-effect-profiles.js.map +0 -1
  211. package/dist/web-effect-service.d.ts +0 -93
  212. package/dist/web-effect-service.js +0 -335
  213. package/dist/web-effect-service.js.map +0 -1
  214. package/dist/web-effect-tools.d.ts +0 -48
  215. package/dist/web-effect-tools.js +0 -129
  216. package/dist/web-effect-tools.js.map +0 -1
  217. package/dist/web-effect-trials.d.ts +0 -86
  218. package/dist/web-effect-trials.js +0 -204
  219. package/dist/web-effect-trials.js.map +0 -1
  220. package/dist/web-effect-upload.d.ts +0 -27
  221. package/dist/web-effect-upload.js +0 -185
  222. package/dist/web-effect-upload.js.map +0 -1
  223. package/dist/web-effect-worker.d.ts +0 -8
  224. package/dist/web-effect-worker.js +0 -170
  225. package/dist/web-effect-worker.js.map +0 -1
  226. package/dist/web-effect.d.ts +0 -103
  227. package/dist/web-effect.js +0 -153
  228. package/dist/web-effect.js.map +0 -1
  229. package/dist/web-experimental-http.d.ts +0 -2
  230. package/dist/web-experimental-http.js +0 -12
  231. package/dist/web-experimental-http.js.map +0 -1
  232. package/dist/web-mod-agent.d.ts +0 -50
  233. package/dist/web-mod-agent.js +0 -207
  234. package/dist/web-mod-agent.js.map +0 -1
@@ -1,217 +0,0 @@
1
- /** #1629: stock shell inventory/paint prerequisite. No frame creation, effect code, content or network reads. */
2
- const SPECS = [
3
- ["composer", ".shell .p-chat .chat-main > .dock"],
4
- ["reply", ".shell .thread .rb-row, .shell .thread .poll-voters"],
5
- ["navigation", ".shell .side-head, .shell .side-nav, .shell .side-section, .shell .side-foot, .shell .tabs, .shell .skip, .shell .side-resize"],
6
- ["header", ".shell .panel-head"], ["status", ".shell .main > .conn"], ["usage", ".shell > .u-rail"],
7
- ["widget", ".shell .aw, .shell .side-widget"], ["card", ".shell .p-chat > .chat-card"], ["permission", ".shell .n-item, .shell .dock .prompts"],
8
- ["menu", ".shell .menu-list[role=menu]"], ["session", ".shell .side-foot .pop[role=dialog]"],
9
- ["popover", ".shell .prefs-pop > .pop"], ["dialog", ".shell dialog.dlg"], ["lightbox", ".shell dialog.lb"],
10
- ["tour", "body > #tour.tour[role=dialog]"], ["keep", ".shell > .oc-keep"], ["toast", ".shell > .toasts"],
11
- ["confirmation", ".shell > .pending-stack, .shell .p-settings > .panel-body > .col > .pending-stack.inline"], ["preview", ".shell .chat-split > .pv-panel, .shell .chat-split > .pv-divider"],
12
- ["preview-menu", ".shell .thread details.pv-menu"], ["palette", ".shell .dock .cmd-palette"],
13
- ["drop", ".shell .p-chat > .drop-overlay"],
14
- ["thread-control", ".shell .chat-main > .amb-note, .shell .p-chat .jump-latest, .shell .thread .msg-tools, .shell .thread .msg > div.msg-actions, .shell .thread .msg > button.msg-quote, .shell .thread .st-more, .shell .thread .cb-head, .shell .thread .cb-more, .shell .thread .tc-head, .shell .thread .tc-more, .shell .thread .pv-head, .shell .thread .pv-note, .shell .thread .pv-banner, .shell .thread .effect-trial-offer, .shell .thread .click-chip"],
15
- ["link", ".shell .thread .md a, .shell .thread .st-text > a.st-link, .shell .dock .prompts .txt > a.st-link"], ["attachment", ".shell .thread .atts"], ["media", ".shell .thread .att-media"],
16
- ["panel-navigation", ".shell .p-fleet > .seg, .shell .p-settings > .seg"],
17
- ["panel-content", ".shell .p-fleet > .panel-body, .shell .p-needs > .panel-body, .shell .p-settings > .panel-body, .shell .p-log > .panel-body, .shell .p-details > .panel-body, .shell .p-view > .panel-body, .shell .p-view > .v-term, .shell .p-view > .v-id"],
18
- ["panel-controls", ".shell .p-log > .log-bar, .shell .p-settings > .s-pending"],
19
- ["session-ended", "body > .agend-session-ended[role=alert]"],
20
- ];
21
- export const STOCK_TRUST_INVENTORY = Object.freeze(SPECS.map(([kind, selector]) => Object.freeze({ kind, selector })));
22
- const STRUCTURAL = ["html", "body", "#app", "#app > .shell", ".shell > .main", ".main > .p-chat", ".p-chat > .chat-split", ".chat-split > .chat-main"];
23
- const CONTENT = [".main > .conn", ".p-chat > .panel-head", ".p-chat > .chat-card", ".p-chat > .aw-chat_header", ".chat-main > .amb-note", ".chat-main > .scroller", ".chat-main > .dock", ".sidebar > .side-head", ".sidebar > .side-nav", ".sidebar > .side-section", ".sidebar > .side-widget", ".sidebar > .side-foot", ".u-rail > .u-rail-head", ".u-rail > .u-rail-body"];
24
- // Closed producer/topology inventory. Bare Outlet loading/error panels never become an effect surface.
25
- const PANELS = Object.freeze({
26
- fleet: { required: [".panel-head", ".seg", ".panel-body"], optional: [] },
27
- needs: { required: [".panel-head", ".panel-body"], optional: [] },
28
- settings: { required: [".panel-head", ".seg", ".panel-body"], optional: [".s-pending"] },
29
- log: { required: [".panel-head", ".panel-body"], optional: [".log-bar"] },
30
- details: { required: [".panel-head", ".panel-body"], optional: [] },
31
- view: { required: [".panel-head"], optional: [".panel-body", ".v-term", ".v-id"] },
32
- });
33
- function panelSurface(doc, chat) {
34
- if (chat) return { panel: chat, structural: STRUCTURAL, content: CONTENT, kind: "chat" };
35
- const panel = doc.querySelector(".main > .panel"), kind = panel?.getAttribute("data-effect-panel"), spec = Object.hasOwn(PANELS, kind) ? PANELS[kind] : null;
36
- if (!spec || panel.className !== `panel p-${kind}` || [...panel.childNodes].some(node => node.nodeType === 3 && node.textContent.trim())) return null;
37
- const children = [...panel.children], count = selector => children.filter(el => el.matches(selector)).length;
38
- if (spec.required.some(selector => count(selector) !== 1) || spec.optional.some(selector => count(selector) > 1)
39
- || children.some(el => !el.matches([...spec.required, ...spec.optional, "dialog.dlg", "dialog.lb"].join(",")))) return null;
40
- if (kind === "view" && !(count(".panel-body") === 1 && !count(".v-term") && !count(".v-id")
41
- || !count(".panel-body") && count(".v-term") === 1 && count(".v-id") === 1)) return null;
42
- const prefix = `.p-${kind} > `;
43
- return { panel, kind, structural: [...STRUCTURAL.slice(0, 5), `.main > .p-${kind}`],
44
- content: [...CONTENT.filter(selector => !selector.startsWith(".p-chat") && !selector.startsWith(".chat-main")),
45
- ...[...spec.required, ...spec.optional].map(selector => prefix + selector)] };
46
- }
47
- const BARRIERS = '[role=menu],[role=dialog],[role=alertdialog],[role=listbox],dialog[open],details[open],.toast,.pending-stack:not(.inline),.oc-keep,.shell.sb-open,.p-chat.dragging,.agend-session-ended,audio[controls],video[controls],.effect-trial-panel';
48
- /** Shared closed overlay list; a trial may exclude only its own positively identified panel. */
49
- export const STOCK_EFFECT_BARRIERS = BARRIERS;
50
- const finite = n => typeof n === "number" && Number.isFinite(n) && Math.abs(n) <= 1e7;
51
- const none = x => x === "" || x === undefined || x === "none";
52
- // The stock narrow header fades its own pixels inside its already bounded content context.
53
- // This exception is never applied to an ancestor or another content surface.
54
- function stockWidgetMask(host, selector, style) {
55
- return selector === ".p-chat > .aw-chat_header" && host.innerWidth < 900
56
- && typeof style.maskImage === "string"
57
- && /^linear-gradient\(to right, (?:rgb\(0, 0, 0\)|rgb\(0 0 0\)) calc\(100% - 32px\), (?:rgba\(0, 0, 0, 0\)|rgb\(0 0 0 \/ 0\))\)$/.test(style.maskImage);
58
- }
59
- function neutral(style, allowStockMask = false) {
60
- return !!style && ["transform", "perspective", "filter", "backdropFilter", "rotate", "scale", "translate", "offsetPath", "clipPath"].every(k => none(style[k])) && (none(style.maskImage) || allowStockMask)
61
- && style.opacity === "1" && style.isolation === "auto" && style.mixBlendMode === "normal" && style.contain === "none" && style.willChange === "auto"
62
- && (style.contentVisibility === undefined || ["", "visible"].includes(style.contentVisibility)) && (style.zoom === undefined || ["", "1", "normal"].includes(style.zoom));
63
- }
64
- function rect(el) {
65
- const r = el.getBoundingClientRect();
66
- return [r.x, r.y, r.width, r.height].every(finite) && r.width >= 0 && r.height >= 0 ? { x: r.x, y: r.y, width: r.width, height: r.height } : null;
67
- }
68
- function visible(host, el) {
69
- if (!el || el.isConnected !== true) return false;
70
- // A descendant of a closed details/dialog may have a styled box but no painted client rect.
71
- const s = host.getComputedStyle(el);
72
- return s.display !== "none" && s.visibility === "visible" && s.opacity !== "0" && el.getClientRects().length > 0;
73
- }
74
- /** Conservatively include stock outer shadows and focus outlines, not only the border box. Unknown paint refuses. */
75
- function outset(style) {
76
- let pad = 0;
77
- if (!none(style.textShadow)) return null;
78
- if (style.outlineStyle !== "none") {
79
- const width = parseFloat(style.outlineWidth), offset = parseFloat(style.outlineOffset);
80
- if (![width, offset].every(Number.isFinite)) return null;
81
- pad = Math.max(pad, width + Math.max(0, offset));
82
- }
83
- if (!none(style.boxShadow)) {
84
- // Computed colors may contain commas; remove closed color functions before splitting the shadow list.
85
- const shadow = style.boxShadow.replace(/(?:rgba?|color|color-mix)\([^()]*\)/g, "color");
86
- for (const part of shadow.split(",")) {
87
- if (/\binset\b/.test(part)) continue;
88
- const lengths = [...part.matchAll(/(-?\d+(?:\.\d+)?)px\b/g)].map(m => Number(m[1]));
89
- if (lengths.length < 2 || lengths.length > 4 || !lengths.every(Number.isFinite)) return null;
90
- const [x, y, blur = 0, spread = 0] = lengths;
91
- if (blur < 0) return null;
92
- // Stock blur support is bounded generously; no arbitrary constant padding is the security argument.
93
- pad = Math.max(pad, Math.abs(x) + 3 * blur + Math.max(0, spread), Math.abs(y) + 3 * blur + Math.max(0, spread));
94
- }
95
- }
96
- return pad <= 256 ? Math.ceil(pad) : null;
97
- }
98
- /**
99
- * #2086: the identity card's banner fill (a blurred copy beside a centred banner) — the one filter stock admits. Only
100
- * this exact value, on exactly `.id-banner-box > img.id-banner-fill`, absolutely positioned in that box (so the box is
101
- * its containing block — #2089 review: a fixed fill is the viewport's, and no box clips it), and the box positioned and
102
- * clipping on both axes; its paint is then that box's rectangle (the blur and its scale never leave it). The box must
103
- * also be a real block box that the browser reports as the fill's offset parent (#2089 review r3: `display: contents`
104
- * keeps the computed position and overflow but generates no box, so an outer ancestor would place the fill, and an inline
105
- * box clips differently). Anything else with a filter refuses.
106
- */
107
- export const STOCK_BANNER_FILL_FILTER = "blur(24px) saturate(0.75) brightness(0.7)";
108
- function stockBannerFill(host, el) {
109
- const box = el.parentElement;
110
- if (typeof el.matches !== "function" || !el.matches(".id-banner-box > img.id-banner-fill") || !box) return null;
111
- const s = host.getComputedStyle(el), b = host.getComputedStyle(box);
112
- if (s.filter !== STOCK_BANNER_FILL_FILTER || !none(s.backdropFilter) || !none(b.filter) || !none(b.backdropFilter)) return null;
113
- if (!["hidden", "clip"].includes(b.overflowX) || !["hidden", "clip"].includes(b.overflowY)) return null;
114
- if (s.position !== "absolute" || !["relative", "absolute"].includes(b.position)) return null;
115
- if (b.display !== "block" || el.offsetParent !== box) return null;
116
- return rect(box);
117
- }
118
- function zeroClipMargin(host, style) {
119
- const margin = style.overflowClipMargin ?? style.getPropertyValue?.("overflow-clip-margin");
120
- // WebKit versions without this property still implement paint containment. An absent
121
- // computed value is usable only when the engine explicitly reports it unsupported;
122
- // unknown capability or a supported but unreadable/expanded margin cannot prove a box.
123
- return margin === "0px" || [undefined, ""].includes(margin)
124
- && host.CSS?.supports?.("overflow-clip-margin", "1px") === false;
125
- }
126
- function protectedPaint(host, root, budget) {
127
- // These two stock toolbar boxes physically clip ALL descendants, including fixed-position
128
- // children. Their entire box is a hole; descendant ink cannot escape it. Inline, fragmented,
129
- // expanded-clip or CSS-overridden boxes take the ordinary bounded walk instead.
130
- const s = host.getComputedStyle(root);
131
- if (root.matches?.(".shell .thread .msg-tools, .shell .thread .codeblock > .cb-head") && s.contain === "paint"
132
- && s.display === "flex" && s.overflowX === "clip" && s.overflowY === "clip" && zeroClipMargin(host, s)
133
- && none(s.filter) && none(s.backdropFilter) && s.borderImageSource === "none" && [undefined, "", "visible"].includes(s.contentVisibility) && root.getClientRects().length === 1) {
134
- if (++budget.n > 4096) { budget.exceeded = true; return null; }
135
- const r = rect(root), pad = outset(s);
136
- // Containment clips descendants, not the root's own ink. Do not infer a world-space
137
- // outset from local CSS lengths under a potentially transformed content ancestor.
138
- if (!r || pad !== 0) return null;
139
- return r;
140
- }
141
- const nodes = [root, ...root.querySelectorAll("*")]; budget.n += nodes.length;
142
- if (budget.n > 4096) { budget.exceeded = true; return null; }
143
- let union = null;
144
- for (const el of nodes) {
145
- if (!visible(host, el)) continue;
146
- const style = host.getComputedStyle(el), pad = outset(style);
147
- if (style.borderImageSource !== undefined && style.borderImageSource !== "none" || ![undefined, "", "visible"].includes(style.contentVisibility)) return null;
148
- const r = none(style.filter) ? rect(el) : stockBannerFill(host, el);
149
- if (!r || pad === null || !none(style.backdropFilter)) return null;
150
- const a = { x: r.x - pad, y: r.y - pad, width: r.width + pad * 2, height: r.height + pad * 2 };
151
- if (!union) union = a;
152
- else { const x = Math.min(union.x, a.x), y = Math.min(union.y, a.y); union = { x, y, width: Math.max(union.x + union.width, a.x + a.width) - x, height: Math.max(union.y + union.height, a.y + a.height) - y }; }
153
- }
154
- return union || { x: 0, y: 0, width: 0, height: 0 };
155
- }
156
- /** Snapshot immediately before reveal; callers must hide first on mutations/scroll/resize. No observer is installed here. */
157
- export function stockEffectTrust(host, { frameRoot = null, ownerCss = "unknown" } = {}) {
158
- const fail = reason => ({ ok: false, reason, rects: [], front: false });
159
- try {
160
- const doc = host.document, app = doc.getElementById("app"), shell = doc.querySelector("#app > .shell"), chat = doc.querySelector(".main > .p-chat");
161
- if (!app || app.parentElement !== doc.body || !shell || doc.querySelectorAll("#app > .shell").length !== 1 || doc.querySelectorAll(".main > .panel").length !== 1) return fail("stock_route_unknown");
162
- const surface = panelSurface(doc, chat);
163
- if (!surface) return fail("stock_route_unknown");
164
- if (frameRoot && (frameRoot.ownerDocument !== doc || frameRoot.parentElement !== doc.body || !frameRoot.classList.contains("agend-effect-layer") || !neutral(host.getComputedStyle(frameRoot)) || !["static", "relative"].includes(host.getComputedStyle(frameRoot).position) || host.getComputedStyle(frameRoot).zIndex !== "auto")) return fail("stock_frame_root_unknown");
165
- for (const selector of surface.structural) {
166
- const el = doc.querySelector(selector), s = el && host.getComputedStyle(el);
167
- if (!el || el.isConnected !== true || !neutral(s) || s.zIndex !== "auto" || !["static", "relative"].includes(s.position)) return fail("stock_order_unknown");
168
- }
169
- for (const selector of surface.content) for (const el of doc.querySelectorAll(selector)) {
170
- if (!visible(host, el)) { const children = [...el.querySelectorAll("*")]; if (children.length > 4096 || children.some(child => visible(host, child))) return fail("stock_order_unknown"); continue; }
171
- const s = host.getComputedStyle(el);
172
- if (s.position !== (selector === ".p-settings > .s-pending" ? "sticky" : "relative") || s.zIndex !== (selector.endsWith(" > .panel-head") ? "2" : "1") || !neutral(s, stockWidgetMask(host, selector, s))) return fail("stock_order_unknown");
173
- }
174
- // The resize separator has no bounded content parent; prove its own level and neutral sidebar/usage ancestors.
175
- for (const el of doc.querySelectorAll(".shell > .sidebar, .shell > .u-rail")) {
176
- if (!visible(host, el)) { const children = [...el.querySelectorAll("*")]; if (children.length > 4096 || children.some(child => visible(host, child))) return fail("stock_order_unknown"); continue; }
177
- const s = host.getComputedStyle(el);
178
- if (!neutral(s) || s.zIndex !== "auto" || !["static", "relative"].includes(s.position)) return fail("stock_order_unknown");
179
- }
180
- for (const el of doc.querySelectorAll(".shell .side-resize")) if (visible(host, el)) {
181
- const s = host.getComputedStyle(el);
182
- if (!neutral(s) || s.position !== "absolute" || s.zIndex !== "5") return fail("stock_order_unknown");
183
- }
184
- // Desktop split preview is a stock level1 content owner too. Narrow preview is a modal sheet, handled below.
185
- if (host.innerWidth >= 900) for (const el of doc.querySelectorAll(".chat-split > .pv-panel, .chat-split > .pv-divider")) {
186
- if (!visible(host, el)) { const children = [...el.querySelectorAll("*")]; if (children.length > 4096 || children.some(child => visible(host, child))) return fail("stock_order_unknown"); continue; }
187
- const s = host.getComputedStyle(el);
188
- if (s.position !== "relative" || s.zIndex !== "1" || !neutral(s)) return fail("stock_order_unknown");
189
- }
190
- const marked = [...doc.querySelectorAll("[data-trust]")], expected = new Set(), rects = [], budget = { n: 0 };
191
- if (marked.length > 4096) return fail("stock_marker_limit");
192
- for (const { kind, selector } of STOCK_TRUST_INVENTORY) for (const el of doc.querySelectorAll(selector)) {
193
- if (el.ownerDocument !== doc || el.isConnected !== true || el.getAttribute("data-trust") !== kind) return fail("stock_trust_unknown");
194
- expected.add(el);
195
- }
196
- if (marked.some(el => !expected.has(el)) || surface.kind === "chat" && !chat.querySelector('.dock[data-trust="composer"]') || !surface.panel.querySelector('.panel-head[data-trust="header"]')) return fail("stock_trust_unknown");
197
- for (const el of marked) {
198
- const bounds = protectedPaint(host, el, budget); if (!bounds) return fail(budget.exceeded ? "stock_paint_limit" : "stock_paint_unknown");
199
- // Off-screen history remains inventoried and paint-checked; it need not consume a
200
- // viewport hole. Include the clip algorithm's extra 8px protection margin.
201
- if (bounds.width && bounds.height && (!finite(host.innerHeight) || bounds.x + bounds.width + 8 >= 0 && bounds.y + bounds.height + 8 >= 0 && bounds.x - 8 <= host.innerWidth && bounds.y - 8 <= host.innerHeight)) rects.push(bounds);
202
- }
203
- // Keep the existing 128-hole transport bound. Conservative union may hide extra
204
- // effect pixels; it can never reveal protected pixels, even for a dense viewport.
205
- if (rects.length > 128) {
206
- const rest = rects.splice(127), x = Math.min(...rest.map(r => r.x)), y = Math.min(...rest.map(r => r.y));
207
- rects.push({ x, y, width: Math.max(...rest.map(r => r.x + r.width)) - x, height: Math.max(...rest.map(r => r.y + r.height)) - y });
208
- }
209
- if (doc.querySelector(".agend-session-ended")) return fail("session_ended");
210
- let barrier = [...doc.querySelectorAll(BARRIERS)].some(el => visible(host, el));
211
- if (host.innerWidth < 900 && [...doc.querySelectorAll(".pv-panel")].some(el => visible(host, el))) barrier = true;
212
- if (doc.fullscreenElement || doc.pictureInPictureElement) barrier = true;
213
- // Focus alone does not change protected paint bounds. Composer/controls stay clipped; editable focus
214
- // separately suppresses pointer delivery in the registry, and keyboard events never enter a Worker.
215
- return { ok: true, rects, front: !barrier, reason: barrier ? "stock_overlay" : "stock", agentFront: !barrier && ownerCss === "off", agentReason: barrier ? "stock_overlay" : ownerCss === "off" ? "stock" : "owner_css", settingsHref: "/settings/look" };
216
- } catch { return fail("stock_trust_unknown"); }
217
- }
@@ -1,62 +0,0 @@
1
- /** #2039: fixed host-only closed shadow shell. Owner CSS has no exported parts or slots into it. */
2
- const roots = new WeakMap();
3
- const clear = root => { while (root.firstChild) root.removeChild(root.firstChild); };
4
- function sheetOf(host, record) {
5
- try {
6
- const link = record.link, sheet = link?.sheet;
7
- return record.ready && !record.dead && roots.get(record.panel)?.current === record && record.root.mode === "closed" && record.root.host === record.panel
8
- && link.getRootNode() === record.root && link.isConnected && link.disabled === false && sheet?.ownerNode === link && sheet.disabled === false
9
- && sheet.href === new URL("/assets/effect-trial.css", host.location.origin).href && typeof sheet.insertRule === "function" && typeof sheet.deleteRule === "function" && sheet.cssRules ? sheet : null;
10
- } catch { return null; }
11
- }
12
- /** Reflect only a shell issued here, after its fixed same-origin stylesheet loaded. Never a serialized capability. */
13
- export function effectTrialShadow(host, panel) {
14
- const record = roots.get(panel)?.current;
15
- return record && sheetOf(host, record) === record.proof?.sheet ? record.proof : null;
16
- }
17
- export function createEffectTrialShadow({ window: host, panel, title, labels, onStop, onClose, onReady, onError } = {}) {
18
- if (!host?.document || panel?.ownerDocument !== host.document || typeof panel.attachShadow !== "function" || typeof onReady !== "function" || typeof onError !== "function") return null;
19
- let slot = roots.get(panel), cleanup = null;
20
- const clock = () => (host.performance ?? globalThis.performance).now(), later = host.setTimeout?.bind(host) ?? globalThis.setTimeout, cancel = host.clearTimeout?.bind(host) ?? globalThis.clearTimeout;
21
- try {
22
- if (slot?.current && !slot.current.dead) return null;
23
- if (!slot) { slot = { root: panel.attachShadow({ mode: "closed" }), current: null }; roots.set(panel, slot); }
24
- const root = slot.root; clear(root);
25
- const doc = host.document, element = (tag, cls) => { const el = doc.createElement(tag); el.className = cls; return el; };
26
- const link = element("link", "effect-trial-style"); link.setAttribute("rel", "stylesheet"); link.setAttribute("href", "/assets/effect-trial.css");
27
- const head = element("header", "effect-trial-head"), label = element("strong", "effect-trial-label"), name = element("span", "effect-trial-title"), close = element("button", "effect-trial-close"), controls = element("div", "effect-trial-controls"), stop = element("button", "effect-trial-stop"), body = element("div", "effect-trial-body"), stage = element("div", "effect-trial-stage"), note = element("p", "effect-trial-note");
28
- close.setAttribute("type", "button"); stop.setAttribute("type", "button"); stage.setAttribute("aria-hidden", "true");
29
- head.append(label, name, close); controls.append(stop); body.append(stage);
30
- const nodes = [head, controls, body, note]; for (const el of nodes) el.setAttribute("hidden", "");
31
- const began = clock(); if (!Number.isFinite(began) || began < 0) return null;
32
- let timer = null;
33
- const record = { panel, root, link, stage, head, controls, body, note, close, stop, ready: false, dead: false, proof: null }; slot.current = record;
34
- const text = (nextTitle, nextLabels) => {
35
- if (record.dead || !nextLabels) return;
36
- label.textContent = nextLabels.label; name.textContent = typeof nextTitle === "string" ? nextTitle : "";
37
- close.textContent = nextLabels.close; stop.textContent = nextLabels.stop; note.textContent = nextLabels.note;
38
- panel.setAttribute("data-effect-trial-theme", doc.documentElement.dataset.theme === "dark" ? "dark" : "light");
39
- };
40
- const failed = () => { if (!record.dead) { dispose(); try { onError("stage_unavailable"); } catch { /* cleanup already owns failure */ } } };
41
- const loaded = () => {
42
- if (record.dead || record.ready || slot.current !== record) return;
43
- const at = clock(); if (!Number.isFinite(at) || at < began || at - began >= 10000) { failed(); return; }
44
- record.ready = true; const sheet = sheetOf(host, record);
45
- if (!sheet) { failed(); return; }
46
- cancel(timer); timer = null;
47
- record.proof = Object.freeze({ panel, root, link, sheet, stage, head, controls, body, note, close, stop });
48
- for (const el of nodes) el.removeAttribute("hidden");
49
- try { onReady(record.proof); } catch { failed(); }
50
- };
51
- const stopClick = () => { if (!record.dead) onStop?.(); }, closeClick = () => { if (!record.dead) onClose?.(); };
52
- function dispose() {
53
- if (record.dead) return; record.dead = true; cancel(timer); timer = null;
54
- link.removeEventListener("load", loaded); link.removeEventListener("error", failed); stop.removeEventListener("click", stopClick); close.removeEventListener("click", closeClick);
55
- if (slot.current === record) { slot.current = null; clear(root); }
56
- }
57
- cleanup = dispose;
58
- link.addEventListener("load", loaded); link.addEventListener("error", failed); stop.addEventListener("click", stopClick); close.addEventListener("click", closeClick);
59
- text(title, labels); timer = later(failed, 10000); root.append(link, ...nodes);
60
- return Object.freeze({ dispose, text });
61
- } catch { cleanup?.(); return null; }
62
- }
@@ -1,103 +0,0 @@
1
- /** #1629: one private Trial contribution. No frame, pool, Start/Stop HTTP or durable profile writes. */
2
- import { checkEffectTrialStart } from "./effect-runtime-loader.js";
3
- import { effectTrialStageIdentity, effectTrialStage, watchEffectTrialStage, disposeEffectTrialStage, constrainEffectTrialStage } from "./effect-trial-stage.js";
4
- const safe = fn => { try { return fn(); } catch { return null; } };
5
- const plain = x => !!x && [Object.prototype, null].includes(Object.getPrototypeOf(x));
6
- function fields(value, required, optional = []) {
7
- try {
8
- if (!plain(value)) return null;
9
- const keys = Reflect.ownKeys(value), out = Object.create(null);
10
- if (keys.some(k => typeof k !== "string" || !required.includes(k) && !optional.includes(k)) || required.some(k => !keys.includes(k))) return null;
11
- for (const k of keys) { const d = Object.getOwnPropertyDescriptor(value, k); if (!d || !("value" in d) || !d.enumerable) return null; out[k] = d.value; }
12
- return out;
13
- } catch { return null; }
14
- }
15
- const canonical = x => JSON.stringify(x, function(_key, value) {
16
- return value && !Array.isArray(value) && typeof value === "object" ? Object.fromEntries(Object.keys(value).sort().map(k => [k, value[k]])) : value;
17
- });
18
- export function createEffectTrialSource({ window: host, current, ownerCurrent, stock, readResource, onChange = () => {} }) {
19
- let dead = false, active = null, previous = null, clockBroken = false, clockBusy = false;
20
- const used = new WeakSet();
21
- function now() {
22
- if (clockBroken || clockBusy) { clockBroken = true; return null; }
23
- clockBusy = true; let value; try { value = host.performance.now(); } catch { value = null; } finally { clockBusy = false; }
24
- if (clockBroken || typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER || previous !== null && value < previous) { clockBroken = true; return null; }
25
- previous = value; return value;
26
- }
27
- function stop(lease, reason = "stopped") {
28
- if (!lease || lease.dead) return false;
29
- lease.dead = true; if (active === lease) active = null;
30
- safe(() => host.clearTimeout(lease.timer)); safe(() => lease.off?.()); lease.off = null;
31
- for (const controller of lease.pending) safe(() => controller.abort());
32
- safe(() => disposeEffectTrialStage(lease.stage.receipt)); // Remove physical paint before callbacks can replace this contribution.
33
- safe(onChange); safe(() => lease.onStop(reason)); return true;
34
- }
35
- function valid(lease) {
36
- if (dead || !lease || active !== lease || lease.dead || lease.checking) return false;
37
- lease.checking = true; let yes = false;
38
- try {
39
- const time = now();
40
- yes = time !== null && time >= lease.startedAt && time < lease.until && current() === true && ownerCurrent(lease.owner, lease.identity.instance) === true && lease.current() === true;
41
- const accepted = now(); yes = yes && accepted !== null && accepted >= lease.startedAt && accepted < lease.until;
42
- } catch { /* unknown is not a lease */ } finally { lease.checking = false; }
43
- return !dead && active === lease && !lease.dead && yes;
44
- }
45
- const checked = lease => { if (valid(lease)) return true; stop(lease, "trial_ended"); return false; };
46
- function arm(lease) {
47
- if (!checked(lease)) return;
48
- const time = now(); if (time === null || time >= lease.until) { stop(lease, "trial_expired"); return; }
49
- lease.timer = host.setTimeout(() => { if (active === lease && !lease.dead) arm(lease); }, Math.max(1, Math.ceil(lease.until - time)));
50
- }
51
- function attach(input, owner) {
52
- if (dead || clockBroken) return null;
53
- const x = fields(input, ["reply", "offer", "startedAt", "stage", "current", "onStop"]), stage = x && fields(x.stage, ["receipt", "dispose", "hide"]);
54
- const identity = stage && effectTrialStageIdentity(stage.receipt), reply = identity && checkEffectTrialStart(x.reply, x.offer, identity.id);
55
- const time = now(), until = reply && typeof x.startedAt === "number" ? x.startedAt + reply.remainingMs : null;
56
- if (dead || !x || !stage || !identity || !reply || used.has(stage.receipt) || typeof stage.dispose !== "function" || typeof stage.hide !== "function"
57
- || typeof x.current !== "function" || typeof x.onStop !== "function" || typeof x.startedAt !== "number" || !Number.isFinite(x.startedAt) || x.startedAt < 0
58
- || time === null || x.startedAt > time || typeof until !== "number" || !Number.isFinite(until) || until > Number.MAX_SAFE_INTEGER || time >= until) return null;
59
- const candidate = active;
60
- if (safe(() => current() === true && ownerCurrent(owner, identity.instance) === true && x.current() === true) !== true || active !== candidate || dead) return null;
61
- stop(candidate, "replaced");
62
- // A stop callback may have installed a newer contribution. Never replace it from this older operation.
63
- if (dead || active !== null) return null;
64
- const lease = { identity, reply, stage, owner, current: x.current, onStop: x.onStop, startedAt: x.startedAt, until, dead: false, checking: false, pending: new Set(), timer: null, off: null, binding: null };
65
- lease.binding = Object.freeze({ kind: "trial", key: identity.key, id: identity.id, source: lease, generation: identity.generation });
66
- active = lease; used.add(stage.receipt);
67
- lease.off = watchEffectTrialStage(stage.receipt, reason => stop(lease, typeof reason === "string" ? reason : "stage_ended"));
68
- if (typeof lease.off !== "function" || constrainEffectTrialStage(stage.receipt, () => checked(lease)) !== true || !checked(lease)) { stop(lease, "stage_unavailable"); return null; }
69
- try { arm(lease); } catch { stop(lease, "trial_unavailable"); return null; }
70
- if (!checked(lease)) return null;
71
- safe(onChange);
72
- return checked(lease) ? Object.freeze({ current: () => checked(lease), stop: () => stop(lease), snapshot: () => { if (!checked(lease)) return null; const t = now(); return t !== null && t < lease.until && active === lease ? { id: identity.id, key: identity.key, trial: reply.trial, remainingMs: lease.until - t } : null; } }) : null;
73
- }
74
- function descriptor() {
75
- const lease = active; if (!lease || !checked(lease)) return [];
76
- const proof = safe(stock), local = safe(() => effectTrialStage(lease.stage.receipt, lease.identity, proof));
77
- if (!checked(lease)) return [];
78
- if (!local?.root || local.root.isConnected !== true) { stop(lease, "stage_unavailable"); return []; }
79
- return [{ key: lease.identity.key, id: lease.identity.id, by: "agent", region: "chat", layer: lease.reply.manifest.layer, order: 0, paused: false, visible: true,
80
- instance: lease.identity.instance, generation: lease.identity.generation, trialStage: lease.stage.receipt, params: lease.reply.params, element: local.root }];
81
- }
82
- function binding(key, id) { const lease = active; return lease && lease.binding.key === key && lease.binding.id === id && checked(lease) ? lease.binding : null; }
83
- function bindingCurrent(b) { return !!b && active?.binding === b && checked(b.source); }
84
- async function load(b, signal) {
85
- if (!bindingCurrent(b) || signal?.aborted) return null;
86
- const lease = b.source; if (lease.pending.size) return null;
87
- const controller = new host.AbortController(), abort = () => controller.abort(); lease.pending.add(controller);
88
- signal?.addEventListener("abort", abort, { once: true });
89
- try {
90
- if (!bindingCurrent(b) || signal?.aborted) { abort(); return null; }
91
- const value = await readResource({ trial: lease.reply.trial, id: b.id, instance: lease.identity.instance }, controller.signal);
92
- if (!bindingCurrent(b) || signal?.aborted || controller.signal.aborted) return null;
93
- if (!value || value.id !== b.id || canonical(value.manifest) !== canonical(lease.reply.manifest) || canonical(value.params) !== canonical(lease.reply.params)) { stop(lease, "resource_unavailable"); return null; }
94
- return bindingCurrent(b) && !signal?.aborted && !controller.signal.aborted ? value : null;
95
- } catch { if (active === lease) stop(lease, "resource_unavailable"); return null; }
96
- finally { signal?.removeEventListener("abort", abort); lease.pending.delete(controller); }
97
- }
98
- return Object.freeze({ attach, descriptors: descriptor, binding, current: bindingCurrent, load,
99
- stopFor(owner) { const lease = active; return lease?.owner === owner ? stop(lease, "chat_ended") : false; },
100
- stop() { return stop(active); },
101
- dispose() { if (dead) return; dead = true; stop(active, "disposed"); },
102
- });
103
- }
@@ -1,170 +0,0 @@
1
- /** #1629: host-issued LOCAL trial paint receipt. No authority, loader, frame factory or pool is created here. */
2
- import { effectTrialShadow } from "./effect-trial-shadow.js";
3
- import { effectHostStyle } from "./effect-host-style.js";
4
- import { effectStockSnapshot, effectStockRefusal } from "./effect-stock-snapshot.js";
5
- import { STOCK_EFFECT_BARRIERS } from "./effect-stock-trust.js";
6
- const receipts = new WeakMap(), owners = new WeakMap();
7
- let serial = 0;
8
- const none = v => v === undefined || v === "" || v === "none";
9
- const number = n => typeof n === "number" && Number.isFinite(n) && Math.abs(n) <= 1e7;
10
- function binding(raw) {
11
- try {
12
- if (!raw || ![Object.prototype, null].includes(Object.getPrototypeOf(raw))) return null;
13
- const fields = ["key", "id", "run", "instance", "generation"], keys = Reflect.ownKeys(raw), out = {};
14
- if (keys.length !== fields.length || keys.some(k => typeof k !== "string" || !fields.includes(k))) return null;
15
- for (const k of fields) { const d = Object.getOwnPropertyDescriptor(raw, k); if (!d || !Object.hasOwn(d, "value") || !d.enumerable) return null; out[k] = d.value; }
16
- if (typeof out.key !== "string" || !out.key.length || out.key.length > 256 || typeof out.id !== "string" || !/^[0-9a-f]{32}$/.test(out.id)
17
- || typeof out.run !== "string" || !/^[0-9a-f]{32}$/.test(out.run) || typeof out.instance !== "string" || !out.instance.length || out.instance.length > 128
18
- || !Number.isSafeInteger(out.generation) || out.generation < 1) return null;
19
- return Object.freeze(out);
20
- } catch { return null; }
21
- }
22
- function rect(el) {
23
- try { const r = el.getBoundingClientRect(); return [r.x, r.y, r.width, r.height].every(number) && r.width > 0 && r.height > 0 ? { x: r.x, y: r.y, width: r.width, height: r.height } : null; } catch { return null; }
24
- }
25
- function visible(host, el) { const s = host.getComputedStyle(el); return s.display !== "none" && s.visibility === "visible" && !!rect(el); }
26
- function neutral(s) {
27
- return ["transform", "perspective", "filter", "backdropFilter", "rotate", "scale", "translate", "offsetPath", "clipPath", "maskImage"].every(k => none(s[k]))
28
- && s.isolation === "auto" && s.mixBlendMode === "normal" && s.willChange === "auto" && (s.zoom === undefined || ["", "normal", "1"].includes(s.zoom)) && [undefined, "", "visible"].includes(s.contentVisibility);
29
- }
30
- /** Inspect immutable identity only; this is NOT current paint permission or a serialized grant. */
31
- export function effectTrialStageIdentity(receipt) { return receipts.get(receipt)?.identity ?? null; }
32
- /** Host-only lifetime observation. Physical removal precedes notification; subscribers never grant paint. */
33
- export function watchEffectTrialStage(receipt, listener) {
34
- const owner = receipts.get(receipt);
35
- if (!owner || typeof listener !== "function") return null;
36
- owner.listeners.add(listener);
37
- return () => owner.listeners.delete(listener);
38
- }
39
- /** Add one host lease veto before a frame exists. It can only reduce the original owner's permission. */
40
- export function constrainEffectTrialStage(receipt, current) {
41
- const owner = receipts.get(receipt); return !!owner && owner.constrain(current) === true;
42
- }
43
- /** Retire through the issued owner; caller-supplied cleanup functions are never the physical boundary. */
44
- export function disposeEffectTrialStage(receipt) {
45
- const owner = receipts.get(receipt); if (!owner) return false;
46
- owner.invalidate("stopped"); return true;
47
- }
48
- /** Missing/forged/old receipts never turn the ordinary stock front flag on. */
49
- export function effectTrialStage(receipt, expected, stock) {
50
- try {
51
- const owner = receipts.get(receipt);
52
- if (!owner || !expected || ![Object.prototype, null].includes(Object.getPrototypeOf(expected))) return null;
53
- for (const key of ["key", "id", "instance", "generation"]) {
54
- const d = Object.getOwnPropertyDescriptor(expected, key);
55
- if (!d || !Object.hasOwn(d, "value") || d.value !== owner.identity[key]) return null;
56
- }
57
- return owner.project(stock);
58
- } catch { return null; }
59
- }
60
-
61
- /** Only the fixed host TrialPanel supplies these elements and a current server-run lease. Not an agent manifest. */
62
- export function createEffectTrialStage({ window: host, panel, stage, binding: raw, current, onStop = () => {} } = {}) {
63
- const own = binding(raw);
64
- if (!own || typeof current !== "function" || typeof onStop !== "function" || !host?.document || !panel || !stage || owners.has(stage)) return null;
65
- const shell = effectTrialShadow(host, panel), hostSheet = effectHostStyle(host);
66
- let sheet; try { sheet = shell?.sheet; if (!shell || shell.stage !== stage || !hostSheet || !sheet || host.CSS?.supports("contain", "paint") !== true || host.CSS.supports("overflow", "clip") !== true) return null; } catch { return null; }
67
- const receipt = Object.freeze(Object.create(null)), frames = new Set(), listeners = new Set(); let dead = false, constraint = null, failure = "stage_unavailable";
68
- const reject = reason => { failure = reason; return null; };
69
- const identity = Object.freeze({ key: own.key, id: own.id, instance: own.instance, generation: own.generation, serial: ++serial });
70
- const invalidate = reason => {
71
- if (dead) return; dead = true; receipts.delete(receipt); if (owners.get(stage) === receipt) owners.delete(stage);
72
- try { host.removeEventListener("blur", blur); } catch { /* no revival */ }
73
- for (const f of [...frames]) f.remove();
74
- const notify = [...listeners]; listeners.clear();
75
- for (const fn of notify) { try { fn(reason); } catch { /* one host owner cannot block another cleanup */ } }
76
- try { onStop(reason); } catch { /* cleanup already won */ }
77
- };
78
- const blur = event => { if (event.target === host) invalidate("blur"); };
79
- function check(stock) {
80
- failure = "trial_layout_unverified";
81
- try {
82
- // This callback may reenter disposal or replace the owner. Recheck identity after it returns.
83
- if (dead || current(own) !== true || constraint !== null && constraint() !== true || dead || owners.get(stage) !== receipt || dead) return reject("trial_current_changed");
84
- const proof = effectStockSnapshot(stock), doc = host.document;
85
- if (!proof) return reject(effectStockRefusal(stock));
86
- if (effectHostStyle(host) !== hostSheet || effectTrialShadow(host, panel) !== shell) return reject("trial_style_unavailable");
87
- // The own panel MUST still suppress ordinary foreground effects. Never synthesize front:true.
88
- if (doc.hasFocus?.() !== true) return reject("trial_window_unfocused");
89
- if (doc.visibilityState !== "visible") return reject("hidden");
90
- if (proof.front !== false || doc.fullscreenElement || doc.pictureInPictureElement) return reject("trial_overlay_unverified");
91
- const split = doc.querySelector(".main > .p-chat > .chat-split");
92
- if (!split || doc.querySelectorAll(".main > .p-chat").length !== 1 || doc.querySelectorAll(".chat-split > .pv-panel").length !== 1
93
- || panel.parentElement !== split || panel.ownerDocument !== doc || panel.isConnected !== true || panel.className !== "pv-panel effect-trial-panel" || panel.getAttribute("data-trust") !== "preview") return reject("trial_panel_unavailable");
94
- const children = [...shell.root.children], names = ["effect-trial-style", "effect-trial-head", "effect-trial-controls", "effect-trial-body", "effect-trial-note"];
95
- if (panel.children.length !== 0 || children.length !== names.length || children.some((el, i) => el.className !== names[i]) || children[3].children.length !== 1 || children[3].firstElementChild !== stage
96
- || stage.className !== "effect-trial-stage" || stage.ownerDocument !== doc || stage.isConnected !== true || stage.hasAttribute("tabindex") || stage.hasAttribute("contenteditable")) return reject("trial_shadow_unverified");
97
- for (const control of [shell.head, shell.controls, shell.close, shell.stop, shell.note]) {
98
- const style = host.getComputedStyle(control);
99
- if (style.display === "none" || style.visibility !== "visible" || style.opacity !== "1" || !rect(control)) return reject("trial_controls_unavailable");
100
- }
101
- if ([...doc.querySelectorAll(STOCK_EFFECT_BARRIERS)].some(el => el !== panel && visible(host, el))
102
- || [...doc.querySelectorAll(".pv-panel")].some(el => el !== panel && visible(host, el))) return reject("trial_other_overlay");
103
- const active = doc.activeElement;
104
- if (active && active !== doc.body && active !== doc.documentElement && (active.matches("input,select,textarea,[contenteditable]") || active.isContentEditable)) return reject("trial_editable_focus");
105
- let el = stage, depth = 0;
106
- while (el) { const s = host.getComputedStyle(el); if (++depth > 128 || el.ownerDocument !== doc || !neutral(s) || s.opacity !== "1" || s.visibility !== "visible" || s.display === "none" || s.contain !== (el === stage ? "paint" : "none")) return reject("trial_ancestor_paint"); if (el === doc.documentElement) break; el = el.parentElement ?? (el.getRootNode?.() === shell.root ? panel : null); }
107
- if (el !== doc.documentElement) return reject("trial_ancestor_paint");
108
- const s = host.getComputedStyle(stage), r = rect(stage), p = rect(panel);
109
- if (!r || !p || s.position !== "relative" || s.zIndex !== "0" || s.overflowX !== "clip" || s.overflowY !== "clip"
110
- || s.paddingLeft !== "0px" || s.paddingRight !== "0px" || s.paddingTop !== "0px" || s.paddingBottom !== "0px"
111
- || ["borderLeftWidth", "borderRightWidth", "borderTopWidth", "borderBottomWidth"].some(k => s[k] !== "0px") || !none(s.boxShadow) || s.outlineStyle !== "none"
112
- || r.x < p.x || r.y < p.y || r.x + r.width > p.x + p.width || r.y + r.height > p.y + p.height
113
- || r.x < 0 || r.y < 0 || r.x + r.width > host.innerWidth || r.y + r.height > host.innerHeight) return reject("trial_clip_unverified");
114
- if ([...stage.children].some(child => ![...frames].some(f => f.element === child))) return reject("trial_frame_unknown");
115
- const width = Math.floor(r.width), height = Math.floor(r.height);
116
- if (width < 1 || height < 1 || width > 4096 || height > 4096 || width * height > 8388608 || dead || owners.get(stage) !== receipt) return reject("trial_size_limit");
117
- if (current(own) !== true || constraint !== null && constraint() !== true || dead || owners.get(stage) !== receipt || dead || stage.isConnected !== true || panel.parentElement !== split) return reject("trial_current_changed");
118
- return { x: r.x, y: r.y, width, height };
119
- } catch { return reject("trial_check_failed"); }
120
- }
121
- function project(stock) {
122
- const r = check(stock); if (!r) { invalidate(failure); return null; }
123
- return Object.freeze({ root: stage, rect: Object.freeze(r), identity, bind });
124
- }
125
- function bind(frame, { layer } = {}, stock) {
126
- if (frames.size || !["front", "behind"].includes(layer) || frame?.ownerDocument !== host.document || frame.parentElement !== stage || frame.tagName !== "IFRAME") { frame?.remove?.(); return { ok: false }; }
127
- // The new frame is temporarily known to this owner before the topology check; it remains hidden until sync.
128
- const token = `agend-effect-trial-${identity.serial}`; let rule, removed = false, shown = false;
129
- const remove = () => {
130
- if (removed) return; removed = true; frame.remove(); frames.delete(handle);
131
- try { frame.classList.remove(token); const i = [...sheet.cssRules].indexOf(rule); if (i >= 0) sheet.deleteRule(i); } catch { /* physically removed first */ }
132
- };
133
- const hide = () => {
134
- shown = false;
135
- try { rule.style.setProperty("visibility", "hidden", "important"); if (frame.isConnected && host.getComputedStyle(frame).visibility !== "hidden") { remove(); return false; } return !removed; } catch { remove(); return false; }
136
- };
137
- const handle = { ok: true, element: frame, remove, hide,
138
- sync(proof) {
139
- const r = check(proof); if (!r || removed) { invalidate(failure); return false; }
140
- try {
141
- const matches = visibility => {
142
- const s = host.getComputedStyle(frame), actual = rect(frame);
143
- return !!actual && s.position === "absolute" && s.visibility === visibility && s.pointerEvents === "none" && s.zIndex === "0" && s.opacity === (layer === "front" ? "0.85" : "1") && neutral(s)
144
- && ["x", "y", "width", "height"].every(k => Math.abs(actual[k] - r[k]) < 0.02) && actual.x >= r.x && actual.y >= r.y && actual.x + actual.width <= r.x + r.width && actual.y + actual.height <= r.y + r.height
145
- && frame.isConnected === true && frame.ownerDocument === host.document && frame.parentElement === stage && !dead && !removed && owners.get(stage) === receipt;
146
- };
147
- // Reprove the current stage, clipping and actual frame every tick. Hiding/revealing an
148
- // unchanged iframe each rAF can starve Firefox's OffscreenCanvas presentation.
149
- if (shown && matches("visible")) return true;
150
- if (!hide()) throw Error("local hiding lost");
151
- for (const [k, v] of Object.entries({ left: "0px", top: "0px", width: `${r.width}px`, height: `${r.height}px` })) rule.style.setProperty(k, v, "important");
152
- if (!matches("hidden")) throw Error("local geometry lost");
153
- rule.style.setProperty("visibility", "visible", "important"); shown = true; return true;
154
- } catch { invalidate("trial_frame_geometry"); return false; }
155
- },
156
- };
157
- frames.add(handle);
158
- try {
159
- const i = sheet.insertRule(`.${token}{}`, sheet.cssRules.length); rule = sheet.cssRules[i];
160
- for (const [k, v] of Object.entries({ position: "absolute", visibility: "hidden", "pointer-events": "none", "z-index": "0", opacity: layer === "front" ? "0.85" : "1", border: "0px", margin: "0px", padding: "0px", "box-sizing": "border-box", "min-width": "0px", "min-height": "0px", "max-width": "none", "max-height": "none", outline: "none", "box-shadow": "none", "background-color": "transparent", animation: "none", transition: "none" })) rule.style.setProperty(k, v, "important");
161
- frame.classList.add(token);
162
- if (host.getComputedStyle(frame).visibility !== "hidden") throw Error("initial local hiding lost");
163
- if (!check(stock)) { remove(); invalidate(failure); return { ok: false }; }
164
- } catch { remove(); invalidate("stage_unavailable"); return { ok: false }; }
165
- return handle;
166
- }
167
- receipts.set(receipt, { identity, project, listeners, invalidate, constrain(fn) { if (dead || frames.size || constraint !== null || typeof fn !== "function") return false; constraint = fn; return true; } }); owners.set(stage, receipt);
168
- try { host.addEventListener("blur", blur); } catch { invalidate("unsupported"); return null; }
169
- return Object.freeze({ receipt, dispose: () => invalidate("stopped"), hide: () => { for (const f of frames) f.hide(); } });
170
- }
@@ -1,40 +0,0 @@
1
- /* #2039: fixed closed-shadow Trial chrome; no inherited owner-CSS typography, parts or slots. */
2
- :host {
3
- all: initial !important;
4
- box-sizing: border-box !important;
5
- display: flex !important;
6
- flex: 0 0 45% !important;
7
- flex-direction: column !important;
8
- align-self: stretch !important;
9
- width: 45% !important;
10
- min-width: 320px !important;
11
- max-width: calc(100% - 368px) !important;
12
- min-height: 0 !important;
13
- height: auto !important;
14
- position: relative !important;
15
- z-index: 1 !important;
16
- overflow: clip !important;
17
- background: #ffffff !important;
18
- color: #1b1b1f !important;
19
- font: 400 16px/1.4 system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", emoji !important;
20
- direction: ltr !important;
21
- unicode-bidi: isolate !important;
22
- text-align: start !important;
23
- visibility: visible !important;
24
- opacity: 1 !important;
25
- }
26
- :host([data-effect-trial-theme="dark"]) { background: #202024 !important; color: #f0f0f4 !important; }
27
- :host::before, :host::after { all: initial !important; content: none !important; display: none !important; }
28
- *, *::before, *::after { box-sizing: border-box; }
29
- [hidden] { display: none !important; }
30
- .effect-trial-head, .effect-trial-controls, .effect-trial-note { position: relative; z-index: 1; padding: 12px; margin: 0; }
31
- .effect-trial-head { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid currentColor; }
32
- .effect-trial-title { flex: 1; min-width: 0; overflow-wrap: anywhere; }
33
- button { appearance: auto; display: inline-block; font: inherit; color: inherit; background: transparent; border: 1px solid currentColor; border-radius: 6px; padding: 8px 12px; cursor: pointer; }
34
- button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
35
- .effect-trial-body { flex: 1; min-height: 0; display: flex; padding: 12px; }
36
- .effect-trial-stage { position: relative; z-index: 0; flex: 1; min-width: 0; min-height: 0; contain: paint; overflow: clip; padding: 0; border: 0; outline: none; box-shadow: none; }
37
- .effect-trial-note { font-size: 14px; }
38
- @media (max-width: 899px) {
39
- :host { position: fixed !important; inset: 0 !important; z-index: 37 !important; width: auto !important; min-width: 0 !important; max-width: none !important; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left) !important; }
40
- }