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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +17 -17
  2. package/src/lib/components/ai-job-links.d.ts +2 -1
  3. package/src/lib/components/ai-job-links.js +8 -2
  4. package/src/lib/components/ai-job-links.js.map +1 -1
  5. package/src/lib/components/assist-edit-canvas.d.ts +12 -6
  6. package/src/lib/components/assist-edit-canvas.js +86 -36
  7. package/src/lib/components/assist-edit-canvas.js.map +1 -1
  8. package/src/lib/components/assist-edit-card.component.js +9 -8
  9. package/src/lib/components/assist-edit-card.component.js.map +1 -1
  10. package/src/lib/components/assist-page-change-card.component.d.ts +1 -1
  11. package/src/lib/components/assist-page-change-card.component.js +2 -2
  12. package/src/lib/components/assist-page-change-card.component.js.map +1 -1
  13. package/src/lib/components/assist-panel.component.js +19 -8
  14. package/src/lib/components/assist-panel.component.js.map +1 -1
  15. package/src/lib/jobs/ai-job-edit-step.d.ts +20 -0
  16. package/src/lib/jobs/ai-job-edit-step.js +39 -3
  17. package/src/lib/jobs/ai-job-edit-step.js.map +1 -1
  18. package/src/lib/model/ai-edit-job.js +1 -1
  19. package/src/lib/model/ai-edit-job.js.map +1 -1
  20. package/src/lib/model/ai-job-notice.js +3 -1
  21. package/src/lib/model/ai-job-notice.js.map +1 -1
  22. package/src/lib/model/assist-edit.d.ts +8 -7
  23. package/src/lib/model/assist-edit.js +4 -4
  24. package/src/lib/model/assist-edit.js.map +1 -1
  25. package/src/lib/model/assist-page-change.d.ts +14 -0
  26. package/src/lib/model/assist-page-change.js +21 -0
  27. package/src/lib/model/assist-page-change.js.map +1 -1
  28. package/src/lib/server/assist-chat.js +5 -1
  29. package/src/lib/server/assist-chat.js.map +1 -1
  30. package/src/lib/server/assist-edit.d.ts +12 -7
  31. package/src/lib/server/assist-edit.js +43 -22
  32. package/src/lib/server/assist-edit.js.map +1 -1
  33. package/src/lib/server/assist-page-change.js +1 -1
  34. package/src/lib/server/assist-page-change.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-edit-canvas.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n screenSeoStageKey,\n type ScreenSeoTextField,\n} from '@aglyn/aglyn/app-utils/screen-seo-fields'\nimport {\n NODE_HIDE_IF_PROP,\n replaceSubtreeWithInstance,\n reusableComponentDefinitionFrom,\n} from '@aglyn/aglyn/app-utils/compose-reusable-components'\nimport { CANVAS_ROOT_ELEMENT_ID } from '@aglyn/aglyn/foundation/constants/canvas'\nimport {\n NODE_MAX_INTERACTIONS,\n upsertNodeInteraction,\n type NodeInteraction,\n} from '@aglyn/aglyn/app-utils/node-interactions'\nimport type {\n ReusableComponentProp,\n ReusableComponentPropValue,\n} from '@aglyn/aglyn/foundation/definitions/platform.types'\nimport {\n stageEditorSessionFields,\n type EditorSession,\n} from '@aglyn/aglyn/plugin-manager/editor-sessions'\nimport {\n ASSIST_EDIT_CONTEXT_MAX_NODES,\n ASSIST_EDIT_CONTEXT_MAX_PROPS,\n ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n ASSIST_EDIT_SELECTED_TEXT_CHARS,\n assistEditOpCounts,\n type AssistEditCanvasContext,\n type AssistEditCanvasNode,\n type AssistEditInsertOp,\n type AssistEditInteractionSummary,\n type AssistEditOp,\n type AssistEditProposal,\n type AssistEditComponentProp,\n type AssistEditSaveAsComponentOp,\n} from '../model/assist-edit'\n\n/**\n * The edit rung's client half (AGL-2906): what the panel tells the server\n * about the open canvas, and how a confirmed proposal lands on it.\n *\n * Applying goes through the canvas's own guarded mutators — the same ones\n * the besigner's panels and the marketing appliers use — inside ONE\n * `batch`, so the whole proposal is one undo step and a guard that refuses\n * part-way leaves nothing behind. Every change is an unsaved edit on the\n * version the editor has open; saving it stays the author's act, with the\n * editor's own control. A version the live site serves is never edited:\n * the check refuses it, and the card offers the editor's own new-version\n * flow instead.\n */\n\n/** A node as the canvas holds it — the fields this module reads. */\nexport interface AssistEditCanvasNodeLike {\n $id?: string\n componentId?: string\n parentId?: string | null\n nodes?: string[]\n name?: string\n props?: unknown\n sx?: unknown\n /** The element's own interactions (AGL-3603), as the canvas holds them. */\n interactions?: unknown\n}\n\n/**\n * The slice of the besigner canvas the edit rung reads and drives. Every\n * member is one `CanvasManager` already has, so the panel hands over the\n * canvas itself and a spec hands over a real one.\n */\nexport interface AssistEditCanvas {\n getNode(id: string): AssistEditCanvasNodeLike | undefined\n batch<T>(mutate: () => T): T\n updateNodeProps(node: any, props: any): void\n updateNodeFields(node: any, patch: any): void\n reparentNode(node: any, parent: any, index?: number): unknown\n deleteNode(node: any): unknown\n addNodeFromNested(nested: any, parent: any, index?: number): unknown\n nodeAcceptsChildren(node: any): boolean\n /** The whole document, which a component save reads its definition out of. */\n toJSON(): { nodes: Record<string, unknown> }\n /** The document after a save: the promoted subtree swapped for an instance. */\n applyNodes(nodes: any): unknown\n}\n\nconst UNDESCRIBED_PROP = /^(html|sx|style|className|dangerouslySetInnerHTML|on[A-Z].*)$/\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * An observable's own keys as a plain object. A canvas node's `props` and\n * `sx` are observable proxies, and a spread of one is how a merge silently\n * copies nothing.\n */\nfunction plain(value: unknown): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!value || typeof value !== 'object') return out\n for (const key in value as Record<string, unknown>) {\n out[key] = (value as Record<string, unknown>)[key]\n }\n return out\n}\n\nfunction describeProps(\n raw: unknown,\n textChars: number,\n): Record<string, string | number | boolean> | undefined {\n const props: Record<string, string | number | boolean> = {}\n let kept = 0\n for (const [name, value] of Object.entries(plain(raw))) {\n if (kept >= ASSIST_EDIT_CONTEXT_MAX_PROPS) break\n if (UNDESCRIBED_PROP.test(name)) continue\n if (typeof value === 'string') {\n if (!value.trim()) continue\n props[name] = value.slice(0, textChars)\n } else if (typeof value === 'number' && Number.isFinite(value)) {\n props[name] = value\n } else if (typeof value === 'boolean') {\n props[name] = value\n } else {\n continue\n }\n kept += 1\n }\n return kept ? props : undefined\n}\n\nfunction describeSx(raw: unknown): Record<string, unknown> | undefined {\n const sx: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(plain(raw))) {\n if (typeof value === 'string' || typeof value === 'number') sx[key] = value\n else if (isRecord(value)) sx[key] = plain(value)\n }\n return Object.keys(sx).length ? sx : undefined\n}\n\n/**\n * The selection's ancestors below the document root, top-level section first\n * and the selection last; null when its parents do not lead to the root,\n * which is not a chain the server can check.\n */\nfunction chainToRoot(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selected: AssistEditCanvasNodeLike,\n): string[] | null {\n const chain: string[] = []\n const walked = new Set<string>()\n let current: AssistEditCanvasNodeLike | undefined = selected\n while (current?.$id && current.$id !== CANVAS_ROOT_ELEMENT_ID && !walked.has(current.$id)) {\n walked.add(current.$id)\n chain.unshift(current.$id)\n current = current.parentId ? canvas.getNode(current.parentId) : undefined\n }\n return current?.$id === CANVAS_ROOT_ELEMENT_ID ? chain : null\n}\n\n/** Elements one shape is taken over at most; a larger subtree is never called alike. */\nconst SHAPE_LIMIT = 200\n\n/**\n * How an element is built: its component and, in order, its children's —\n * what two cards of one row have in common whatever their text. Null past\n * `SHAPE_LIMIT` elements, or for a subtree that loops back on itself.\n */\nfunction shapeOf(canvas: Pick<AssistEditCanvas, 'getNode'>, rootId: string): string | null {\n let budget = SHAPE_LIMIT\n const walked = new Set<string>()\n const walk = (id: string): string | null => {\n const node = canvas.getNode(id)\n if (!node || walked.has(id) || --budget < 0) return null\n walked.add(id)\n const parts: string[] = []\n for (const child of node.nodes ?? []) {\n const part = walk(child)\n if (part === null) return null\n parts.push(part)\n }\n return `${String(node.componentId ?? '')}(${parts.join(',')})`\n }\n return walk(rootId)\n}\n\n/** Elements reachable from the document root through child lists, the root included. */\nfunction countElements(canvas: Pick<AssistEditCanvas, 'getNode'>): number {\n let count = 0\n const reached = new Set<string>([CANVAS_ROOT_ELEMENT_ID])\n const pending = [CANVAS_ROOT_ELEMENT_ID]\n while (pending.length) {\n const node = canvas.getNode(pending.pop() as string)\n if (!node) continue\n count += 1\n for (const child of node.nodes ?? []) {\n if (reached.has(child)) continue\n reached.add(child)\n pending.push(child)\n }\n }\n return count\n}\n\n/**\n * The canvas outline a question carries on the edit rung, in two tiers, until\n * the cap.\n *\n * Described in full, settings and all: the document root, the selection's\n * ancestors and the selection, the document's top-level sections, everything\n * inside the selection — what an edit to it changes — and its siblings.\n *\n * Described briefly, by place alone (`brief`): what surrounds that, so the\n * model knows it exists and asks for it rather than calling it missing —\n *\n * 1. what the selection's siblings hold, level by level (the icons beside a\n * selected link, in the card they share);\n * 2. the siblings of each ancestor below the top-level section, nearest\n * first (the other cards of the row, then what sits beside the row).\n *\n * An element built the same way as the selection, or as the ancestor it sits\n * beside, is marked `like` it and its contents are left out: one card\n * described, and every other card of the row says it holds the same.\n *\n * With nothing selected, it is the root, the top-level sections and one level\n * inside each: enough for a change to the page as a whole, and the prompt asks\n * for a selection before anything more specific.\n *\n * An element is only ever described after its parent, so every ancestor chain\n * the server checks is whole. `total` counts the document, and each element's\n * `childCount` stays its real one, so the server can tell the model what the\n * outline leaves out. The server holds this to its own limits before it quotes\n * a byte of it; null when the canvas has no document root loaded.\n */\nexport function describeAssistEditCanvas(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selectedId: string | null,\n): AssistEditCanvasContext | null {\n const root = canvas.getNode(CANVAS_ROOT_ELEMENT_ID)\n if (!root) return null\n const order: string[] = []\n const seen = new Set<string>()\n const brief = new Set<string>()\n const like = new Map<string, string>()\n const full = (): boolean => order.length >= ASSIST_EDIT_CONTEXT_MAX_NODES\n const add = (id: string | undefined | null, briefly = false): void => {\n if (!id || seen.has(id) || full()) return\n if (!canvas.getNode(id)) return\n seen.add(id)\n order.push(id)\n if (briefly) brief.add(id)\n }\n const childrenOf = (id: string): string[] => canvas.getNode(id)?.nodes ?? []\n const shapes = new Map<string, string | null>()\n const shape = (id: string): string | null => {\n if (!shapes.has(id)) shapes.set(id, shapeOf(canvas, id))\n return shapes.get(id) ?? null\n }\n // Alike only when there are contents to leave out.\n const alike = (id: string, model: string): boolean =>\n childrenOf(id).length > 0 && shape(id) !== null && shape(id) === shape(model)\n\n add(CANVAS_ROOT_ELEMENT_ID)\n const selected =\n selectedId && selectedId !== CANVAS_ROOT_ELEMENT_ID ? canvas.getNode(selectedId) : undefined\n const chain = selected?.$id ? chainToRoot(canvas, selected) : null\n chain?.forEach((id) => add(id))\n if (selected?.$id && chain && seen.has(selected.$id)) {\n for (const id of root.nodes ?? []) add(id)\n const inside = new Set<string>([selected.$id])\n const queue = [...childrenOf(selected.$id)]\n while (queue.length && !full()) {\n const id = queue.shift() as string\n if (inside.has(id)) continue\n inside.add(id)\n add(id)\n queue.push(...childrenOf(id))\n }\n const siblings = selected.parentId\n ? childrenOf(selected.parentId).filter((id) => id !== selected.$id)\n : []\n const held: string[] = []\n for (const id of siblings) {\n add(id)\n // A sibling the cap left out takes its contents with it.\n if (!seen.has(id)) continue\n if (alike(id, selected.$id)) like.set(id, selected.$id)\n else held.push(...childrenOf(id))\n }\n const reached = new Set<string>([...inside, ...siblings, ...held])\n for (let level = held; level.length && !full(); ) {\n const deeper: string[] = []\n for (const id of level) {\n add(id, true)\n for (const child of childrenOf(id)) {\n if (reached.has(child)) continue\n reached.add(child)\n deeper.push(child)\n }\n }\n level = deeper\n }\n // Parent first; the top-level section's own siblings are the sections above.\n for (const ancestor of chain.slice(1, -1).reverse()) {\n const parentId = canvas.getNode(ancestor)?.parentId\n for (const id of parentId ? childrenOf(parentId) : []) {\n if (id === ancestor || seen.has(id)) continue\n add(id, true)\n if (seen.has(id) && alike(id, ancestor)) like.set(id, ancestor)\n }\n }\n } else {\n for (const id of root.nodes ?? []) add(id)\n for (const section of root.nodes ?? []) {\n for (const id of childrenOf(section)) add(id)\n }\n }\n\n const nodes: AssistEditCanvasNode[] = order.map((id) => {\n const node = canvas.getNode(id) as AssistEditCanvasNodeLike\n const isRoot = id === CANVAS_ROOT_ELEMENT_ID\n const parentId = isRoot ? null : (node.parentId ?? null)\n const parent = parentId ? canvas.getNode(parentId) : undefined\n const isSelected = id === selected?.$id\n const isBrief = brief.has(id)\n const props = isBrief\n ? undefined\n : describeProps(\n node.props,\n isSelected ? ASSIST_EDIT_SELECTED_TEXT_CHARS : ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n )\n const sx = isSelected ? describeSx(node.sx) : undefined\n const model = like.get(id)\n return {\n id,\n componentId: String(node.componentId ?? ''),\n parentId,\n index: Math.max(0, parent?.nodes?.indexOf(id) ?? 0),\n childCount: node.nodes?.length ?? 0,\n ...(node.name ? { name: String(node.name) } : {}),\n ...(props ? { props } : {}),\n ...(sx ? { sx } : {}),\n ...(isBrief ? { brief: true } : {}),\n ...(model ? { like: model } : {}),\n ...(isSelected ? summarizeInteractions(node.interactions) : {}),\n }\n })\n return {\n selectedId: selected?.$id && seen.has(selected.$id) ? selected.$id : null,\n total: countElements(canvas),\n nodes,\n }\n}\n\n/**\n * The selected element's interactions as the outline carries them\n * (AGL-3603): name, event and the kinds of its steps — never a selector.\n */\nfunction summarizeInteractions(raw: unknown): { interactions?: AssistEditInteractionSummary[] } {\n if (!Array.isArray(raw) || !raw.length) return {}\n const interactions = raw\n .filter(isRecord)\n .slice(0, NODE_MAX_INTERACTIONS)\n .map((entry) => ({\n name: String(entry['name'] ?? ''),\n event: String(isRecord(entry['trigger']) ? (entry['trigger']['event'] ?? '') : ''),\n steps: (Array.isArray(entry['steps']) ? entry['steps'] : [])\n .filter(isRecord)\n .map((step) => String(step['type'] ?? '')),\n enabled: entry['enabled'] !== false,\n }))\n .filter((entry) => entry.event)\n return interactions.length ? { interactions } : {}\n}\n\n/** Why a proposal cannot land on the open editor as it stands. */\nexport type AssistEditRefusal =\n /** No editor is open. */\n | 'no-editor'\n /** The editor open is not the document the proposal was made for. */\n | 'other-document'\n /** The open version is the one the live site serves. */\n | 'live-version'\n /** An element the proposal names has gone or changed since. */\n | 'stale'\n /** The canvas's own guards refused part of the change. */\n | 'refused'\n\nexport type AssistEditCheck =\n | { ok: true }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\nexport type AssistEditApplyResult =\n | {\n ok: true\n /** Applied ops, counted by kind for the activity row. */\n opCounts: Record<string, number>\n /** Editor fields staged, as the editor keys them. */\n staged: string[]\n }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\n/** Ids of the subtree at `rootId`, the root included, through child lists only. */\nfunction subtreeIds(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n rootId: string,\n): Set<string> {\n const found = new Set<string>([rootId])\n const queue = [...(canvas.getNode(rootId)?.nodes ?? [])]\n while (queue.length) {\n const id = queue.shift() as string\n if (found.has(id) || !canvas.getNode(id)) continue\n found.add(id)\n queue.push(...(canvas.getNode(id)?.nodes ?? []))\n }\n return found\n}\n\nconst STALE: AssistEditCheck = {\n ok: false,\n reason: 'stale',\n message: 'The canvas has changed since this was proposed, so nothing was applied. Ask again.',\n}\n\n/**\n * Whether the proposal can land on the open editor as it stands — checked in\n * full before anything is touched, so a refusal never leaves half an edit.\n */\nexport function checkAssistEdit(\n canvas: Pick<AssistEditCanvas, 'getNode' | 'nodeAcceptsChildren'>,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditCheck {\n if (!session) {\n return {\n ok: false,\n reason: 'no-editor',\n message: 'Open the editor this change was proposed for to apply it.',\n }\n }\n if (\n session.documentKind !== proposal.target.kind ||\n session.documentId !== proposal.target.documentId\n ) {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This change was proposed for a different document than the one open.',\n }\n }\n if (session.isLiveVersion()) {\n return {\n ok: false,\n reason: 'live-version',\n message:\n 'This is the version your live site shows. Make a new version first, then apply the change there.',\n }\n }\n for (const op of proposal.ops) {\n switch (op.op) {\n case 'setSeo': {\n for (const field of Object.keys(op.fields) as ScreenSeoTextField[]) {\n if (typeof session.fields?.[screenSeoStageKey(field)] !== 'function') {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This editor has no search fields to fill in.',\n }\n }\n }\n break\n }\n case 'insertSubtree': {\n const parent = canvas.getNode(op.parentId)\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n if (!canvas.nodeAcceptsChildren(parent)) return STALE\n break\n }\n case 'move': {\n const node = canvas.getNode(op.nodeId)\n const parent = canvas.getNode(op.parentId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n break\n }\n case 'saveAsComponent': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n // The document itself is not a section of itself: promoting the root\n // would leave a document holding one instance of its own contents.\n if (op.nodeId === CANVAS_ROOT_ELEMENT_ID) return STALE\n const inside = subtreeIds(canvas, op.nodeId)\n for (const binding of op.bindings) {\n const bound = canvas.getNode(binding.nodeId)\n if (!bound || bound.componentId !== binding.componentId) return STALE\n // A closed world: a token outside the promoted subtree would bind a\n // property of the new component to an element it does not contain.\n if (!inside.has(binding.nodeId)) return STALE\n }\n break\n }\n case 'addInteraction': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (Array.isArray(node.interactions) && node.interactions.length >= NODE_MAX_INTERACTIONS) {\n return {\n ok: false,\n reason: 'refused',\n message: `That element already does ${NODE_MAX_INTERACTIONS} things, the most one can. Remove one in Interactions first.`,\n }\n }\n // Every element a step acts on is still there, as it was.\n for (const target of op.targets) {\n const live = canvas.getNode(target.nodeId)\n if (!live || live.componentId !== target.componentId) return STALE\n }\n break\n }\n default: {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n }\n }\n }\n return { ok: true }\n}\n\n/**\n * Styles merged one key at a time. A responsive patch over a plain value\n * keeps that value as the base breakpoint, so \"more padding on wide screens\"\n * does not quietly remove the padding everywhere else.\n */\nfunction mergeSx(\n current: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const out = { ...current }\n for (const [key, value] of Object.entries(patch)) {\n const existing = out[key]\n if (isRecord(value) && isRecord(existing)) {\n out[key] = { ...plain(existing), ...value }\n } else if (isRecord(value) && (typeof existing === 'string' || typeof existing === 'number')) {\n out[key] = { xs: existing, ...value }\n } else {\n out[key] = value\n }\n }\n return out\n}\n\n/** A validated flat subtree as the nested shape `addNodeFromNested` takes. */\nfunction nestSubtree(op: AssistEditInsertOp): Record<string, unknown> {\n const visited = new Set<string>()\n const build = (id: string): Record<string, unknown> => {\n visited.add(id)\n const node = op.nodes[id]\n return {\n componentId: node.componentId,\n ...(node.pluginId ? { pluginId: node.pluginId } : {}),\n props: { ...node.props },\n ...(node.sx ? { sx: { ...node.sx } } : {}),\n ...(node.hidden ? { hidden: true } : {}),\n nodes: node.nodes\n .filter((child) => op.nodes[child] && !visited.has(child))\n .map((child) => build(child)),\n }\n }\n return build(op.rootId)\n}\n\nfunction live(canvas: AssistEditCanvas, id: string): AssistEditCanvasNodeLike {\n const node = canvas.getNode(id)\n if (!node) throw new Error(`element ${id} is no longer on the canvas`)\n return node\n}\n\nfunction applyOne(canvas: AssistEditCanvas, op: AssistEditOp): void {\n switch (op.op) {\n case 'updateProps': {\n const node = live(canvas, op.nodeId)\n // Spread the props the element has: `updateNodeProps` REPLACES the bag,\n // and a patch of one setting would otherwise strip every other one.\n const next: Record<string, unknown> = { ...plain(node.props), ...op.props }\n // Rich text renders `html` over `children`; proposed text replaces it.\n if ('children' in op.props) delete next['html']\n canvas.updateNodeProps(node, next)\n return\n }\n case 'updateSx': {\n const node = live(canvas, op.nodeId)\n canvas.updateNodeFields(node, { sx: mergeSx(plain(node.sx), op.sx) })\n return\n }\n case 'move':\n canvas.reparentNode(live(canvas, op.nodeId), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'remove':\n canvas.deleteNode(live(canvas, op.nodeId))\n return\n case 'rename':\n canvas.updateNodeFields(live(canvas, op.nodeId), { name: op.name })\n return\n case 'addInteraction': {\n // Added beside what the element does already, never in place of it:\n // an id the element already uses is re-minted, so nothing is replaced.\n const node = live(canvas, op.nodeId)\n const current = (Array.isArray(node.interactions) ? node.interactions : []) as NodeInteraction[]\n let id = op.interaction.id\n while (current.some((entry) => entry.id === id)) id = `${op.interaction.id}${current.length}x`\n canvas.updateNodeFields(node, {\n interactions: upsertNodeInteraction(current, { ...op.interaction, id }),\n })\n return\n }\n case 'insertSubtree':\n canvas.addNodeFromNested(nestSubtree(op), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'setSeo':\n case 'saveAsComponent':\n // Both are applied outside the canvas batch: search fields are staged\n // into the editor's own form, and a component save mints a document\n // first and then swaps the subtree for an instance of it.\n return\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Save the selection as a reusable component (AGL-2908)\n * ------------------------------------------------------------------ */\n\n/** What the apply needs from the console to create the component. */\nexport interface AssistEditComponentWriter {\n /**\n * Creates the component through `POST /api/hosts/resources`, where the\n * plan's entitlement and the route's field allow-list are enforced, and\n * answers its id. The plugin never writes Firestore from the browser.\n */\n createComponent(input: {\n name: string\n rootId: string\n nodes: Record<string, unknown>\n props: ReusableComponentProp[]\n }): Promise<string>\n}\n\n/**\n * The value a bound field holds on the live canvas right now, which becomes\n * the property's default.\n *\n * `hideIf` is the exception: the part is on the page, so the property that\n * hides it starts at no. Every other field answers with what the author can\n * see, which is what makes the instance render exactly what was there.\n */\nfunction currentValue(\n node: AssistEditCanvasNodeLike,\n field: string,\n): ReusableComponentPropValue | undefined {\n if (field === NODE_HIDE_IF_PROP) return false\n const value = plain(node.props)[field]\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value\n }\n return undefined\n}\n\n/**\n * Whether a default the canvas gave is one the property's own control\n * offers. A Choice whose current value is not among its answers is a\n * selection that has changed since the proposal was made, and applying it\n * would declare a property no page could ever set back.\n */\nfunction defaultFitsProp(prop: AssistEditComponentProp, value: unknown): boolean {\n if (!prop.options?.length) return true\n return prop.options.some((option) => option.value === value)\n}\n\n/**\n * The definition the new component holds: the promoted subtree, with each\n * bound field replaced by its property's token.\n *\n * The defaults are read off the SAME fields a moment before they are\n * replaced, so the instance that takes the subtree's place renders what the\n * author was looking at. Returns null when a default no longer fits its\n * property, which is the stale case.\n */\nfunction componentDefinition(\n canvas: AssistEditCanvas,\n op: AssistEditSaveAsComponentOp,\n): { nodes: Record<string, unknown>; props: ReusableComponentProp[] } | null {\n const nodes = reusableComponentDefinitionFrom(\n canvas.toJSON().nodes as never,\n op.nodeId,\n ) as unknown as Record<string, Record<string, unknown>>\n const defaults = new Map<string, ReusableComponentPropValue | undefined>()\n for (const binding of op.bindings) {\n const live = canvas.getNode(binding.nodeId)\n const stored = nodes[binding.nodeId]\n if (!live || !stored) return null\n if (!defaults.has(binding.prop)) defaults.set(binding.prop, currentValue(live, binding.field))\n stored['props'] = { ...plain(stored['props']), [binding.field]: `{{prop.${binding.prop}}}` }\n }\n const props: ReusableComponentProp[] = []\n for (const declared of op.props) {\n const value = defaults.get(declared.name)\n if (!defaultFitsProp(declared, value)) return null\n props.push({ ...declared, ...(value === undefined ? {} : { defaultValue: value }) })\n }\n return { nodes, props }\n}\n\n/**\n * Lands a confirmed proposal on the open editor: the canvas ops as ONE batch\n * — one undo step, all or nothing — then any search fields staged into the\n * editor's own form. Nothing is saved.\n */\nexport function applyAssistEdit(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditApplyResult {\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n const open = session as EditorSession\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n if (canvasOps.length) {\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message: 'The editor refused part of this change, so none of it was applied.',\n }\n }\n }\n const staged: string[] = []\n for (const op of proposal.ops) {\n if (op.op !== 'setSeo') continue\n const values: Record<string, string> = {}\n for (const [field, value] of Object.entries(op.fields)) {\n values[screenSeoStageKey(field as ScreenSeoTextField)] = String(value)\n }\n staged.push(...stageEditorSessionFields(open, values).staged)\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged }\n}\n\n/**\n * Lands a proposal that saves the selection as a reusable component\n * (AGL-2908) — AGL-2866's recipe, in place, with no clipboard.\n *\n * The order is the manual action's order, and it matters:\n *\n * 1. the definition is read off the live subtree, each bound field replaced\n * by its token and its current value kept as that property's default;\n * 2. the component is created through the host resources route, where the\n * server enforces the plan's entitlement and its own allow-list — so a\n * refusal happens before the open document is touched at all;\n * 3. the subtree is swapped for an instance of what was just created, inside\n * ONE `batch` with the rest of the proposal's canvas ops: one undo step.\n *\n * The only document created is the component, exactly as Save as reusable\n * component creates one. The page change is an unsaved edit on the version\n * the editor has open, which the check has already refused to be a live one.\n * Nothing is published and nothing is saved.\n */\nexport async function applyAssistEditSavingComponent(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n writer: AssistEditComponentWriter,\n): Promise<AssistEditApplyResult> {\n const save = proposal.ops.find(\n (op): op is AssistEditSaveAsComponentOp => op.op === 'saveAsComponent',\n )\n if (!save) return applyAssistEdit(canvas, proposal, session)\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n\n const definition = componentDefinition(canvas, save)\n if (!definition) return STALE as AssistEditApplyResult\n\n let componentId: string\n try {\n componentId = await writer.createComponent({\n name: save.name,\n rootId: save.nodeId,\n nodes: definition.nodes,\n props: definition.props,\n })\n } catch (error) {\n console.error('assist edit could not create the component', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n error instanceof Error && error.message\n ? error.message\n : 'The component could not be saved, so nothing on this page was changed.',\n }\n }\n\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n canvas.applyNodes(\n replaceSubtreeWithInstance(\n canvas.toJSON().nodes as never,\n save.nodeId,\n componentId,\n save.name,\n ),\n )\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n 'The component was saved, but the editor refused to swap this element for it. ' +\n 'Insert it from Your components instead.',\n }\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged: [] }\n}\n"],"names":["screenSeoStageKey","NODE_HIDE_IF_PROP","replaceSubtreeWithInstance","reusableComponentDefinitionFrom","CANVAS_ROOT_ELEMENT_ID","NODE_MAX_INTERACTIONS","upsertNodeInteraction","stageEditorSessionFields","ASSIST_EDIT_CONTEXT_MAX_NODES","ASSIST_EDIT_CONTEXT_MAX_PROPS","ASSIST_EDIT_OUTLINE_TEXT_CHARS","ASSIST_EDIT_SELECTED_TEXT_CHARS","assistEditOpCounts","UNDESCRIBED_PROP","isRecord","value","Array","isArray","plain","out","key","describeProps","raw","textChars","props","kept","name","Object","entries","test","trim","slice","Number","isFinite","undefined","describeSx","sx","keys","length","chainToRoot","canvas","selected","chain","walked","Set","current","$id","has","add","unshift","parentId","getNode","SHAPE_LIMIT","shapeOf","rootId","budget","walk","id","node","parts","child","nodes","part","push","String","componentId","join","countElements","count","reached","pending","pop","describeAssistEditCanvas","selectedId","root","order","seen","brief","like","Map","full","briefly","childrenOf","shapes","shape","set","get","alike","model","forEach","inside","queue","shift","siblings","filter","held","level","deeper","ancestor","reverse","section","map","parent","isRoot","isSelected","isBrief","index","Math","max","indexOf","childCount","summarizeInteractions","interactions","total","entry","event","steps","step","enabled","subtreeIds","found","STALE","ok","reason","message","checkAssistEdit","proposal","session","documentKind","target","kind","documentId","isLiveVersion","op","ops","field","fields","parentComponentId","nodeAcceptsChildren","nodeId","binding","bindings","bound","targets","live","mergeSx","patch","existing","xs","nestSubtree","visited","build","pluginId","hidden","Error","applyOne","next","updateNodeProps","updateNodeFields","reparentNode","NaN","deleteNode","interaction","some","addNodeFromNested","currentValue","defaultFitsProp","prop","options","option","componentDefinition","toJSON","defaults","stored","declared","defaultValue","applyAssistEdit","check","open","canvasOps","batch","error","console","staged","values","opCounts","applyAssistEditSavingComponent","writer","save","find","definition","createComponent","applyNodes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-edit-canvas.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n screenSeoStageKey,\n type ScreenSeoTextField,\n} from '@aglyn/aglyn/app-utils/screen-seo-fields'\nimport {\n NODE_HIDE_IF_PROP,\n replaceSubtreeWithInstance,\n reusableComponentDefinitionFrom,\n} from '@aglyn/aglyn/app-utils/compose-reusable-components'\nimport { CANVAS_ROOT_ELEMENT_ID } from '@aglyn/aglyn/foundation/constants/canvas'\nimport {\n NODE_MAX_INTERACTIONS,\n upsertNodeInteraction,\n type NodeInteraction,\n} from '@aglyn/aglyn/app-utils/node-interactions'\nimport type {\n ReusableComponentProp,\n ReusableComponentPropValue,\n} from '@aglyn/aglyn/foundation/definitions/platform.types'\nimport {\n stageEditorSessionFields,\n type EditorSession,\n} from '@aglyn/aglyn/plugin-manager/editor-sessions'\nimport {\n ASSIST_EDIT_CONTEXT_MAX_NODES,\n ASSIST_EDIT_CONTEXT_MAX_PROPS,\n ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n ASSIST_EDIT_SELECTED_TEXT_CHARS,\n ASSIST_EDIT_WHOLE_MAX_NODES,\n assistEditOpCounts,\n type AssistEditCanvasContext,\n type AssistEditCanvasNode,\n type AssistEditInsertOp,\n type AssistEditInteractionSummary,\n type AssistEditOp,\n type AssistEditProposal,\n type AssistEditComponentProp,\n type AssistEditSaveAsComponentOp,\n} from '../model/assist-edit'\n\n/**\n * The edit rung's client half (AGL-2906): what the panel tells the server\n * about the open canvas, and how a confirmed proposal lands on it.\n *\n * Applying goes through the canvas's own guarded mutators — the same ones\n * the besigner's panels and the marketing appliers use — inside ONE\n * `batch`, so the whole proposal is one undo step and a guard that refuses\n * part-way leaves nothing behind. Every change is an unsaved edit on the\n * version the editor has open; saving it stays the author's act, with the\n * editor's own control. On a version the live site serves, that save writes\n * the page's draft and never the version, so a change lands there too and\n * reaches visitors only when the author publishes (AGL-4116).\n */\n\n/** A node as the canvas holds it — the fields this module reads. */\nexport interface AssistEditCanvasNodeLike {\n $id?: string\n componentId?: string\n parentId?: string | null\n nodes?: string[]\n name?: string\n props?: unknown\n sx?: unknown\n /** The element's own interactions (AGL-3603), as the canvas holds them. */\n interactions?: unknown\n}\n\n/**\n * The slice of the besigner canvas the edit rung reads and drives. Every\n * member is one `CanvasManager` already has, so the panel hands over the\n * canvas itself and a spec hands over a real one.\n */\nexport interface AssistEditCanvas {\n getNode(id: string): AssistEditCanvasNodeLike | undefined\n batch<T>(mutate: () => T): T\n updateNodeProps(node: any, props: any): void\n updateNodeFields(node: any, patch: any): void\n reparentNode(node: any, parent: any, index?: number): unknown\n deleteNode(node: any): unknown\n addNodeFromNested(nested: any, parent: any, index?: number): unknown\n nodeAcceptsChildren(node: any): boolean\n /** The whole document, which a component save reads its definition out of. */\n toJSON(): { nodes: Record<string, unknown> }\n /** The document after a save: the promoted subtree swapped for an instance. */\n applyNodes(nodes: any): unknown\n}\n\nconst UNDESCRIBED_PROP = /^(html|sx|style|className|dangerouslySetInnerHTML|on[A-Z].*)$/\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * An observable's own keys as a plain object. A canvas node's `props` and\n * `sx` are observable proxies, and a spread of one is how a merge silently\n * copies nothing.\n */\nfunction plain(value: unknown): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!value || typeof value !== 'object') return out\n for (const key in value as Record<string, unknown>) {\n out[key] = (value as Record<string, unknown>)[key]\n }\n return out\n}\n\nfunction describeProps(\n raw: unknown,\n textChars: number,\n): Record<string, string | number | boolean> | undefined {\n const props: Record<string, string | number | boolean> = {}\n let kept = 0\n for (const [name, value] of Object.entries(plain(raw))) {\n if (kept >= ASSIST_EDIT_CONTEXT_MAX_PROPS) break\n if (UNDESCRIBED_PROP.test(name)) continue\n if (typeof value === 'string') {\n if (!value.trim()) continue\n props[name] = value.slice(0, textChars)\n } else if (typeof value === 'number' && Number.isFinite(value)) {\n props[name] = value\n } else if (typeof value === 'boolean') {\n props[name] = value\n } else {\n continue\n }\n kept += 1\n }\n return kept ? props : undefined\n}\n\nfunction describeSx(raw: unknown): Record<string, unknown> | undefined {\n const sx: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(plain(raw))) {\n if (typeof value === 'string' || typeof value === 'number') sx[key] = value\n else if (isRecord(value)) sx[key] = plain(value)\n }\n return Object.keys(sx).length ? sx : undefined\n}\n\n/**\n * The selection's ancestors below the document root, top-level section first\n * and the selection last; null when its parents do not lead to the root,\n * which is not a chain the server can check.\n */\nfunction chainToRoot(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selected: AssistEditCanvasNodeLike,\n): string[] | null {\n const chain: string[] = []\n const walked = new Set<string>()\n let current: AssistEditCanvasNodeLike | undefined = selected\n while (current?.$id && current.$id !== CANVAS_ROOT_ELEMENT_ID && !walked.has(current.$id)) {\n walked.add(current.$id)\n chain.unshift(current.$id)\n current = current.parentId ? canvas.getNode(current.parentId) : undefined\n }\n return current?.$id === CANVAS_ROOT_ELEMENT_ID ? chain : null\n}\n\n/** Elements one shape is taken over at most; a larger subtree is never called alike. */\nconst SHAPE_LIMIT = 200\n\n/**\n * How an element is built: its component and, in order, its children's —\n * what two cards of one row have in common whatever their text. Null past\n * `SHAPE_LIMIT` elements, or for a subtree that loops back on itself.\n */\nfunction shapeOf(canvas: Pick<AssistEditCanvas, 'getNode'>, rootId: string): string | null {\n let budget = SHAPE_LIMIT\n const walked = new Set<string>()\n const walk = (id: string): string | null => {\n const node = canvas.getNode(id)\n if (!node || walked.has(id) || --budget < 0) return null\n walked.add(id)\n const parts: string[] = []\n for (const child of node.nodes ?? []) {\n const part = walk(child)\n if (part === null) return null\n parts.push(part)\n }\n return `${String(node.componentId ?? '')}(${parts.join(',')})`\n }\n return walk(rootId)\n}\n\n/** Elements reachable from the document root through child lists, the root included. */\nfunction countElements(canvas: Pick<AssistEditCanvas, 'getNode'>): number {\n let count = 0\n const reached = new Set<string>([CANVAS_ROOT_ELEMENT_ID])\n const pending = [CANVAS_ROOT_ELEMENT_ID]\n while (pending.length) {\n const node = canvas.getNode(pending.pop() as string)\n if (!node) continue\n count += 1\n for (const child of node.nodes ?? []) {\n if (reached.has(child)) continue\n reached.add(child)\n pending.push(child)\n }\n }\n return count\n}\n\n/**\n * The canvas outline a question carries on the edit rung, in two tiers, until\n * the cap.\n *\n * Described in full, settings and all: the document root, the selection's\n * ancestors and the selection, the document's top-level sections, everything\n * inside the selection — what an edit to it changes — and its siblings.\n *\n * Described briefly, by place alone (`brief`): what surrounds that, so the\n * model knows it exists and asks for it rather than calling it missing —\n *\n * 1. what the selection's siblings hold, level by level (the icons beside a\n * selected link, in the card they share);\n * 2. the siblings of each ancestor below the top-level section, nearest\n * first (the other cards of the row, then what sits beside the row).\n *\n * An element built the same way as the selection, or as the ancestor it sits\n * beside, is marked `like` it and its contents are left out: one card\n * described, and every other card of the row says it holds the same.\n *\n * With nothing selected, it is the root, the top-level sections and one level\n * inside each: enough for a change to the page as a whole, and the prompt asks\n * for a selection before anything more specific.\n *\n * With `whole`, it is the whole document instead (AGL-4116), up to\n * `ASSIST_EDIT_WHOLE_MAX_NODES`: every element, in the order it reads on the\n * page, with its settings and its styles. That is what the chat in the\n * Besigner sends, so \"change the Get in touch button\" finds the button with\n * nothing selected. A document past the cap falls back to the two tiers.\n *\n * An element is only ever described after its parent, so every ancestor chain\n * the server checks is whole. `total` counts the document, and each element's\n * `childCount` stays its real one, so the server can tell the model what the\n * outline leaves out. The server holds this to its own limits before it quotes\n * a byte of it; null when the canvas has no document root loaded.\n */\nexport function describeAssistEditCanvas(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selectedId: string | null,\n options: { whole?: boolean } = {},\n): AssistEditCanvasContext | null {\n const root = canvas.getNode(CANVAS_ROOT_ELEMENT_ID)\n if (!root) return null\n const whole = options.whole ? describeWholeCanvas(canvas, selectedId) : null\n if (whole) return whole\n const order: string[] = []\n const seen = new Set<string>()\n const brief = new Set<string>()\n const like = new Map<string, string>()\n const full = (): boolean => order.length >= ASSIST_EDIT_CONTEXT_MAX_NODES\n const add = (id: string | undefined | null, briefly = false): void => {\n if (!id || seen.has(id) || full()) return\n if (!canvas.getNode(id)) return\n seen.add(id)\n order.push(id)\n if (briefly) brief.add(id)\n }\n const childrenOf = (id: string): string[] => canvas.getNode(id)?.nodes ?? []\n const shapes = new Map<string, string | null>()\n const shape = (id: string): string | null => {\n if (!shapes.has(id)) shapes.set(id, shapeOf(canvas, id))\n return shapes.get(id) ?? null\n }\n // Alike only when there are contents to leave out.\n const alike = (id: string, model: string): boolean =>\n childrenOf(id).length > 0 && shape(id) !== null && shape(id) === shape(model)\n\n add(CANVAS_ROOT_ELEMENT_ID)\n const selected =\n selectedId && selectedId !== CANVAS_ROOT_ELEMENT_ID ? canvas.getNode(selectedId) : undefined\n const chain = selected?.$id ? chainToRoot(canvas, selected) : null\n chain?.forEach((id) => add(id))\n if (selected?.$id && chain && seen.has(selected.$id)) {\n for (const id of root.nodes ?? []) add(id)\n const inside = new Set<string>([selected.$id])\n const queue = [...childrenOf(selected.$id)]\n while (queue.length && !full()) {\n const id = queue.shift() as string\n if (inside.has(id)) continue\n inside.add(id)\n add(id)\n queue.push(...childrenOf(id))\n }\n const siblings = selected.parentId\n ? childrenOf(selected.parentId).filter((id) => id !== selected.$id)\n : []\n const held: string[] = []\n for (const id of siblings) {\n add(id)\n // A sibling the cap left out takes its contents with it.\n if (!seen.has(id)) continue\n if (alike(id, selected.$id)) like.set(id, selected.$id)\n else held.push(...childrenOf(id))\n }\n const reached = new Set<string>([...inside, ...siblings, ...held])\n for (let level = held; level.length && !full(); ) {\n const deeper: string[] = []\n for (const id of level) {\n add(id, true)\n for (const child of childrenOf(id)) {\n if (reached.has(child)) continue\n reached.add(child)\n deeper.push(child)\n }\n }\n level = deeper\n }\n // Parent first; the top-level section's own siblings are the sections above.\n for (const ancestor of chain.slice(1, -1).reverse()) {\n const parentId = canvas.getNode(ancestor)?.parentId\n for (const id of parentId ? childrenOf(parentId) : []) {\n if (id === ancestor || seen.has(id)) continue\n add(id, true)\n if (seen.has(id) && alike(id, ancestor)) like.set(id, ancestor)\n }\n }\n } else {\n for (const id of root.nodes ?? []) add(id)\n for (const section of root.nodes ?? []) {\n for (const id of childrenOf(section)) add(id)\n }\n }\n\n const nodes = order.map((id) => {\n const isSelected = id === selected?.$id\n return outlineElement(canvas, id, {\n selected: isSelected,\n brief: brief.has(id),\n like: like.get(id),\n textChars: isSelected ? ASSIST_EDIT_SELECTED_TEXT_CHARS : ASSIST_EDIT_OUTLINE_TEXT_CHARS,\n styles: isSelected,\n })\n })\n return {\n selectedId: selected?.$id && seen.has(selected.$id) ? selected.$id : null,\n total: countElements(canvas),\n nodes,\n }\n}\n\n/** One element as an outline carries it, at the tier it was described in. */\nfunction outlineElement(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n id: string,\n tier: { selected: boolean; brief?: boolean; like?: string; textChars: number; styles: boolean },\n): AssistEditCanvasNode {\n const node = canvas.getNode(id) as AssistEditCanvasNodeLike\n const parentId = id === CANVAS_ROOT_ELEMENT_ID ? null : (node.parentId ?? null)\n const parent = parentId ? canvas.getNode(parentId) : undefined\n const props = tier.brief ? undefined : describeProps(node.props, tier.textChars)\n const sx = tier.styles ? describeSx(node.sx) : undefined\n return {\n id,\n componentId: String(node.componentId ?? ''),\n parentId,\n index: Math.max(0, parent?.nodes?.indexOf(id) ?? 0),\n childCount: node.nodes?.length ?? 0,\n ...(node.name ? { name: String(node.name) } : {}),\n ...(props ? { props } : {}),\n ...(sx ? { sx } : {}),\n ...(tier.brief ? { brief: true } : {}),\n ...(tier.like ? { like: tier.like } : {}),\n ...(tier.selected ? summarizeInteractions(node.interactions) : {}),\n }\n}\n\n/**\n * The whole document as the chat in the Besigner sends it (AGL-4116): every\n * element depth first, children in their stored order, so the outline reads\n * as the page does and each element follows its parent. Null past the cap.\n */\nfunction describeWholeCanvas(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n selectedId: string | null,\n): AssistEditCanvasContext | null {\n const total = countElements(canvas)\n if (total > ASSIST_EDIT_WHOLE_MAX_NODES) return null\n const selected = selectedId !== CANVAS_ROOT_ELEMENT_ID ? selectedId : null\n const nodes: AssistEditCanvasNode[] = []\n const seen = new Set<string>([CANVAS_ROOT_ELEMENT_ID])\n const pending = [CANVAS_ROOT_ELEMENT_ID]\n while (pending.length) {\n const id = pending.pop() as string\n const node = canvas.getNode(id)\n if (!node) continue\n nodes.push(\n outlineElement(canvas, id, {\n selected: id === selected,\n textChars: ASSIST_EDIT_SELECTED_TEXT_CHARS,\n styles: true,\n }),\n )\n const children = node.nodes ?? []\n for (let index = children.length - 1; index >= 0; index -= 1) {\n if (seen.has(children[index])) continue\n seen.add(children[index])\n pending.push(children[index])\n }\n }\n return {\n selectedId: selected && nodes.some((node) => node.id === selected) ? selected : null,\n total,\n nodes,\n whole: true,\n }\n}\n\n/**\n * The selected element's interactions as the outline carries them\n * (AGL-3603): name, event and the kinds of its steps — never a selector.\n */\nfunction summarizeInteractions(raw: unknown): { interactions?: AssistEditInteractionSummary[] } {\n if (!Array.isArray(raw) || !raw.length) return {}\n const interactions = raw\n .filter(isRecord)\n .slice(0, NODE_MAX_INTERACTIONS)\n .map((entry) => ({\n name: String(entry['name'] ?? ''),\n event: String(isRecord(entry['trigger']) ? (entry['trigger']['event'] ?? '') : ''),\n steps: (Array.isArray(entry['steps']) ? entry['steps'] : [])\n .filter(isRecord)\n .map((step) => String(step['type'] ?? '')),\n enabled: entry['enabled'] !== false,\n }))\n .filter((entry) => entry.event)\n return interactions.length ? { interactions } : {}\n}\n\n/** Why a proposal cannot land on the open editor as it stands. */\nexport type AssistEditRefusal =\n /** No editor is open. */\n | 'no-editor'\n /** The editor open is not the document the proposal was made for. */\n | 'other-document'\n /** An element the proposal names has gone or changed since. */\n | 'stale'\n /** The canvas's own guards refused part of the change. */\n | 'refused'\n\nexport type AssistEditCheck =\n | { ok: true }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\nexport type AssistEditApplyResult =\n | {\n ok: true\n /** Applied ops, counted by kind for the activity row. */\n opCounts: Record<string, number>\n /** Editor fields staged, as the editor keys them. */\n staged: string[]\n }\n | { ok: false; reason: AssistEditRefusal; message: string }\n\n/** Ids of the subtree at `rootId`, the root included, through child lists only. */\nfunction subtreeIds(\n canvas: Pick<AssistEditCanvas, 'getNode'>,\n rootId: string,\n): Set<string> {\n const found = new Set<string>([rootId])\n const queue = [...(canvas.getNode(rootId)?.nodes ?? [])]\n while (queue.length) {\n const id = queue.shift() as string\n if (found.has(id) || !canvas.getNode(id)) continue\n found.add(id)\n queue.push(...(canvas.getNode(id)?.nodes ?? []))\n }\n return found\n}\n\nconst STALE: AssistEditCheck = {\n ok: false,\n reason: 'stale',\n message: 'The canvas has changed since this was proposed, so nothing was applied. Ask again.',\n}\n\n/**\n * Whether the proposal can land on the open editor as it stands — checked in\n * full before anything is touched, so a refusal never leaves half an edit.\n */\nexport function checkAssistEdit(\n canvas: Pick<AssistEditCanvas, 'getNode' | 'nodeAcceptsChildren'>,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditCheck {\n if (!session) {\n return {\n ok: false,\n reason: 'no-editor',\n message: 'Open the editor this change was proposed for to apply it.',\n }\n }\n if (\n session.documentKind !== proposal.target.kind ||\n session.documentId !== proposal.target.documentId\n ) {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This change was proposed for a different document than the one open.',\n }\n }\n // The version the live site shows takes the change too (AGL-4116): it lands\n // as unsaved edits on the canvas, exactly as the author's own would, and the\n // Besigner's Save on that version writes the page's draft, never the version\n // visitors see. Publishing stays its own deliberate step.\n for (const op of proposal.ops) {\n switch (op.op) {\n case 'setSeo': {\n for (const field of Object.keys(op.fields) as ScreenSeoTextField[]) {\n if (typeof session.fields?.[screenSeoStageKey(field)] !== 'function') {\n return {\n ok: false,\n reason: 'other-document',\n message: 'This editor has no search fields to fill in.',\n }\n }\n }\n break\n }\n case 'insertSubtree': {\n const parent = canvas.getNode(op.parentId)\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n if (!canvas.nodeAcceptsChildren(parent)) return STALE\n break\n }\n case 'move': {\n const node = canvas.getNode(op.nodeId)\n const parent = canvas.getNode(op.parentId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (!parent || parent.componentId !== op.parentComponentId) return STALE\n break\n }\n case 'saveAsComponent': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n // The document itself is not a section of itself: promoting the root\n // would leave a document holding one instance of its own contents.\n if (op.nodeId === CANVAS_ROOT_ELEMENT_ID) return STALE\n const inside = subtreeIds(canvas, op.nodeId)\n for (const binding of op.bindings) {\n const bound = canvas.getNode(binding.nodeId)\n if (!bound || bound.componentId !== binding.componentId) return STALE\n // A closed world: a token outside the promoted subtree would bind a\n // property of the new component to an element it does not contain.\n if (!inside.has(binding.nodeId)) return STALE\n }\n break\n }\n case 'addInteraction': {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n if (Array.isArray(node.interactions) && node.interactions.length >= NODE_MAX_INTERACTIONS) {\n return {\n ok: false,\n reason: 'refused',\n message: `That element already does ${NODE_MAX_INTERACTIONS} things, the most one can. Remove one in Interactions first.`,\n }\n }\n // Every element a step acts on is still there, as it was.\n for (const target of op.targets) {\n const live = canvas.getNode(target.nodeId)\n if (!live || live.componentId !== target.componentId) return STALE\n }\n break\n }\n default: {\n const node = canvas.getNode(op.nodeId)\n if (!node || node.componentId !== op.componentId) return STALE\n }\n }\n }\n return { ok: true }\n}\n\n/**\n * Styles merged one key at a time. A responsive patch over a plain value\n * keeps that value as the base breakpoint, so \"more padding on wide screens\"\n * does not quietly remove the padding everywhere else.\n */\nfunction mergeSx(\n current: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const out = { ...current }\n for (const [key, value] of Object.entries(patch)) {\n const existing = out[key]\n if (isRecord(value) && isRecord(existing)) {\n out[key] = { ...plain(existing), ...value }\n } else if (isRecord(value) && (typeof existing === 'string' || typeof existing === 'number')) {\n out[key] = { xs: existing, ...value }\n } else {\n out[key] = value\n }\n }\n return out\n}\n\n/** A validated flat subtree as the nested shape `addNodeFromNested` takes. */\nfunction nestSubtree(op: AssistEditInsertOp): Record<string, unknown> {\n const visited = new Set<string>()\n const build = (id: string): Record<string, unknown> => {\n visited.add(id)\n const node = op.nodes[id]\n return {\n componentId: node.componentId,\n ...(node.pluginId ? { pluginId: node.pluginId } : {}),\n props: { ...node.props },\n ...(node.sx ? { sx: { ...node.sx } } : {}),\n ...(node.hidden ? { hidden: true } : {}),\n nodes: node.nodes\n .filter((child) => op.nodes[child] && !visited.has(child))\n .map((child) => build(child)),\n }\n }\n return build(op.rootId)\n}\n\nfunction live(canvas: AssistEditCanvas, id: string): AssistEditCanvasNodeLike {\n const node = canvas.getNode(id)\n if (!node) throw new Error(`element ${id} is no longer on the canvas`)\n return node\n}\n\nfunction applyOne(canvas: AssistEditCanvas, op: AssistEditOp): void {\n switch (op.op) {\n case 'updateProps': {\n const node = live(canvas, op.nodeId)\n // Spread the props the element has: `updateNodeProps` REPLACES the bag,\n // and a patch of one setting would otherwise strip every other one.\n const next: Record<string, unknown> = { ...plain(node.props), ...op.props }\n // Rich text renders `html` over `children`; proposed text replaces it.\n if ('children' in op.props) delete next['html']\n canvas.updateNodeProps(node, next)\n return\n }\n case 'updateSx': {\n const node = live(canvas, op.nodeId)\n canvas.updateNodeFields(node, { sx: mergeSx(plain(node.sx), op.sx) })\n return\n }\n case 'move':\n canvas.reparentNode(live(canvas, op.nodeId), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'remove':\n canvas.deleteNode(live(canvas, op.nodeId))\n return\n case 'rename':\n canvas.updateNodeFields(live(canvas, op.nodeId), { name: op.name })\n return\n case 'addInteraction': {\n // Added beside what the element does already, never in place of it:\n // an id the element already uses is re-minted, so nothing is replaced.\n const node = live(canvas, op.nodeId)\n const current = (Array.isArray(node.interactions) ? node.interactions : []) as NodeInteraction[]\n let id = op.interaction.id\n while (current.some((entry) => entry.id === id)) id = `${op.interaction.id}${current.length}x`\n canvas.updateNodeFields(node, {\n interactions: upsertNodeInteraction(current, { ...op.interaction, id }),\n })\n return\n }\n case 'insertSubtree':\n canvas.addNodeFromNested(nestSubtree(op), live(canvas, op.parentId), op.index ?? NaN)\n return\n case 'setSeo':\n case 'saveAsComponent':\n // Both are applied outside the canvas batch: search fields are staged\n // into the editor's own form, and a component save mints a document\n // first and then swaps the subtree for an instance of it.\n return\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Save the selection as a reusable component (AGL-2908)\n * ------------------------------------------------------------------ */\n\n/** What the apply needs from the console to create the component. */\nexport interface AssistEditComponentWriter {\n /**\n * Creates the component through `POST /api/hosts/resources`, where the\n * plan's entitlement and the route's field allow-list are enforced, and\n * answers its id. The plugin never writes Firestore from the browser.\n */\n createComponent(input: {\n name: string\n rootId: string\n nodes: Record<string, unknown>\n props: ReusableComponentProp[]\n }): Promise<string>\n}\n\n/**\n * The value a bound field holds on the live canvas right now, which becomes\n * the property's default.\n *\n * `hideIf` is the exception: the part is on the page, so the property that\n * hides it starts at no. Every other field answers with what the author can\n * see, which is what makes the instance render exactly what was there.\n */\nfunction currentValue(\n node: AssistEditCanvasNodeLike,\n field: string,\n): ReusableComponentPropValue | undefined {\n if (field === NODE_HIDE_IF_PROP) return false\n const value = plain(node.props)[field]\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return value\n }\n return undefined\n}\n\n/**\n * Whether a default the canvas gave is one the property's own control\n * offers. A Choice whose current value is not among its answers is a\n * selection that has changed since the proposal was made, and applying it\n * would declare a property no page could ever set back.\n */\nfunction defaultFitsProp(prop: AssistEditComponentProp, value: unknown): boolean {\n if (!prop.options?.length) return true\n return prop.options.some((option) => option.value === value)\n}\n\n/**\n * The definition the new component holds: the promoted subtree, with each\n * bound field replaced by its property's token.\n *\n * The defaults are read off the SAME fields a moment before they are\n * replaced, so the instance that takes the subtree's place renders what the\n * author was looking at. Returns null when a default no longer fits its\n * property, which is the stale case.\n */\nfunction componentDefinition(\n canvas: AssistEditCanvas,\n op: AssistEditSaveAsComponentOp,\n): { nodes: Record<string, unknown>; props: ReusableComponentProp[] } | null {\n const nodes = reusableComponentDefinitionFrom(\n canvas.toJSON().nodes as never,\n op.nodeId,\n ) as unknown as Record<string, Record<string, unknown>>\n const defaults = new Map<string, ReusableComponentPropValue | undefined>()\n for (const binding of op.bindings) {\n const live = canvas.getNode(binding.nodeId)\n const stored = nodes[binding.nodeId]\n if (!live || !stored) return null\n if (!defaults.has(binding.prop)) defaults.set(binding.prop, currentValue(live, binding.field))\n stored['props'] = { ...plain(stored['props']), [binding.field]: `{{prop.${binding.prop}}}` }\n }\n const props: ReusableComponentProp[] = []\n for (const declared of op.props) {\n const value = defaults.get(declared.name)\n if (!defaultFitsProp(declared, value)) return null\n props.push({ ...declared, ...(value === undefined ? {} : { defaultValue: value }) })\n }\n return { nodes, props }\n}\n\n/**\n * Lands a confirmed proposal on the open editor: the canvas ops as ONE batch\n * — one undo step, all or nothing — then any search fields staged into the\n * editor's own form. Nothing is saved.\n */\nexport function applyAssistEdit(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n): AssistEditApplyResult {\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n const open = session as EditorSession\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n if (canvasOps.length) {\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message: 'The editor refused part of this change, so none of it was applied.',\n }\n }\n }\n const staged: string[] = []\n for (const op of proposal.ops) {\n if (op.op !== 'setSeo') continue\n const values: Record<string, string> = {}\n for (const [field, value] of Object.entries(op.fields)) {\n values[screenSeoStageKey(field as ScreenSeoTextField)] = String(value)\n }\n staged.push(...stageEditorSessionFields(open, values).staged)\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged }\n}\n\n/**\n * Lands a proposal that saves the selection as a reusable component\n * (AGL-2908) — AGL-2866's recipe, in place, with no clipboard.\n *\n * The order is the manual action's order, and it matters:\n *\n * 1. the definition is read off the live subtree, each bound field replaced\n * by its token and its current value kept as that property's default;\n * 2. the component is created through the host resources route, where the\n * server enforces the plan's entitlement and its own allow-list — so a\n * refusal happens before the open document is touched at all;\n * 3. the subtree is swapped for an instance of what was just created, inside\n * ONE `batch` with the rest of the proposal's canvas ops: one undo step.\n *\n * The only document created is the component, exactly as Save as reusable\n * component creates one. The page change is an unsaved edit on the version\n * the editor has open, which the check has already refused to be a live one.\n * Nothing is published and nothing is saved.\n */\nexport async function applyAssistEditSavingComponent(\n canvas: AssistEditCanvas,\n proposal: AssistEditProposal,\n session: EditorSession | undefined,\n writer: AssistEditComponentWriter,\n): Promise<AssistEditApplyResult> {\n const save = proposal.ops.find(\n (op): op is AssistEditSaveAsComponentOp => op.op === 'saveAsComponent',\n )\n if (!save) return applyAssistEdit(canvas, proposal, session)\n const check = checkAssistEdit(canvas, proposal, session)\n if (check.ok === false) return check\n\n const definition = componentDefinition(canvas, save)\n if (!definition) return STALE as AssistEditApplyResult\n\n let componentId: string\n try {\n componentId = await writer.createComponent({\n name: save.name,\n rootId: save.nodeId,\n nodes: definition.nodes,\n props: definition.props,\n })\n } catch (error) {\n console.error('assist edit could not create the component', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n error instanceof Error && error.message\n ? error.message\n : 'The component could not be saved, so nothing on this page was changed.',\n }\n }\n\n const canvasOps = proposal.ops.filter((op) => op.op !== 'setSeo' && op.op !== 'saveAsComponent')\n try {\n canvas.batch(() => {\n for (const op of canvasOps) applyOne(canvas, op)\n canvas.applyNodes(\n replaceSubtreeWithInstance(\n canvas.toJSON().nodes as never,\n save.nodeId,\n componentId,\n save.name,\n ),\n )\n })\n } catch (error) {\n console.error('assist edit refused by the canvas', error)\n return {\n ok: false,\n reason: 'refused',\n message:\n 'The component was saved, but the editor refused to swap this element for it. ' +\n 'Insert it from Your components instead.',\n }\n }\n return { ok: true, opCounts: assistEditOpCounts(proposal.ops), staged: [] }\n}\n"],"names":["screenSeoStageKey","NODE_HIDE_IF_PROP","replaceSubtreeWithInstance","reusableComponentDefinitionFrom","CANVAS_ROOT_ELEMENT_ID","NODE_MAX_INTERACTIONS","upsertNodeInteraction","stageEditorSessionFields","ASSIST_EDIT_CONTEXT_MAX_NODES","ASSIST_EDIT_CONTEXT_MAX_PROPS","ASSIST_EDIT_OUTLINE_TEXT_CHARS","ASSIST_EDIT_SELECTED_TEXT_CHARS","ASSIST_EDIT_WHOLE_MAX_NODES","assistEditOpCounts","UNDESCRIBED_PROP","isRecord","value","Array","isArray","plain","out","key","describeProps","raw","textChars","props","kept","name","Object","entries","test","trim","slice","Number","isFinite","undefined","describeSx","sx","keys","length","chainToRoot","canvas","selected","chain","walked","Set","current","$id","has","add","unshift","parentId","getNode","SHAPE_LIMIT","shapeOf","rootId","budget","walk","id","node","parts","child","nodes","part","push","String","componentId","join","countElements","count","reached","pending","pop","describeAssistEditCanvas","selectedId","options","root","whole","describeWholeCanvas","order","seen","brief","like","Map","full","briefly","childrenOf","shapes","shape","set","get","alike","model","forEach","inside","queue","shift","siblings","filter","held","level","deeper","ancestor","reverse","section","map","isSelected","outlineElement","styles","total","tier","parent","index","Math","max","indexOf","childCount","summarizeInteractions","interactions","children","some","entry","event","steps","step","enabled","subtreeIds","found","STALE","ok","reason","message","checkAssistEdit","proposal","session","documentKind","target","kind","documentId","op","ops","field","fields","parentComponentId","nodeAcceptsChildren","nodeId","binding","bindings","bound","targets","live","mergeSx","patch","existing","xs","nestSubtree","visited","build","pluginId","hidden","Error","applyOne","next","updateNodeProps","updateNodeFields","reparentNode","NaN","deleteNode","interaction","addNodeFromNested","currentValue","defaultFitsProp","prop","option","componentDefinition","toJSON","defaults","stored","declared","defaultValue","applyAssistEdit","check","open","canvasOps","batch","error","console","staged","values","opCounts","applyAssistEditSavingComponent","writer","save","find","definition","createComponent","applyNodes"],"mappings":"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"}
@@ -26,11 +26,13 @@ import { describeAssistEditDiff } from "../model/assist-edit.js";
26
26
  * It says what would change — the counts, and what validation left out —
27
27
  * and offers exactly one way forward for the editor as it stands:
28
28
  *
29
- * - on the document the proposal was made for, on a version the live site
30
- * does not serve: **Apply as draft**, which the panel carries out through
31
- * the canvas's own mutators as one undoable, unsaved change;
32
- * - on the version the live site serves: **Make a new version**, the
33
- * editor's own flow, after which the same card offers Apply there;
29
+ * - on the document the proposal was made for: **Apply as draft**, which the
30
+ * panel carries out through the canvas's own mutators as one undoable,
31
+ * unsaved change. On the version the live site serves too (AGL-4116): the
32
+ * Besigner saves that version's changes into the page's draft, never the
33
+ * version itself, so the change is as safe there as an edit by hand, and
34
+ * **Make a new version** is offered beside it for an author who wants the
35
+ * change kept apart;
34
36
  * - anywhere else: nothing to press but **No thanks**.
35
37
  *
36
38
  * The card makes no request and holds no write of its own: its buttons call
@@ -137,7 +139,7 @@ export function AssistEditCard(props) {
137
139
  sx: {
138
140
  mt: 1
139
141
  },
140
- children: !onDocument ? `Open this ${noun} in the Besigner to apply the change.` : live ? `This is the version your live site shows. Make a new version first — the change is applied there, and the live ${noun} stays as it is.` : savesComponent ? `${brand} Assist changes nothing until you apply. Applying saves the component to your library, and swaps this element for one that follows it — an unsaved edit on the open canvas that undo takes back. Nothing is published.` : `${brand} Assist changes nothing until you apply. Applying adds these changes to the open canvas as unsaved edits: undo takes them back, and nothing is saved or published until you save.`
142
+ children: !onDocument ? `Open this ${noun} in the Besigner to apply the change.` : live && !savesComponent ? `${brand} Assist changes nothing until you apply. Applying adds these changes to the open canvas as unsaved edits that undo takes back. This is the version your live site shows: Save draft keeps them in this ${noun}’s draft, and visitors see them only when you publish.` : savesComponent ? `${brand} Assist changes nothing until you apply. Applying saves the component to your library, and swaps this element for one that follows it — an unsaved edit on the open canvas that undo takes back. Nothing is published.` : `${brand} Assist changes nothing until you apply. Applying adds these changes to the open canvas as unsaved edits: undo takes them back, and nothing is saved or published until you save.`
141
143
  }),
142
144
  failure ? /*#__PURE__*/ _jsx(Alert, {
143
145
  severity: "warning",
@@ -153,14 +155,13 @@ export function AssistEditCard(props) {
153
155
  mt: 1.5
154
156
  },
155
157
  children: [
156
- onDocument && !live ? /*#__PURE__*/ _jsx(Button, {
158
+ onDocument ? /*#__PURE__*/ _jsx(Button, {
157
159
  variant: "contained",
158
160
  size: "small",
159
161
  onClick: onApply,
160
162
  children: "Apply as draft"
161
163
  }) : null,
162
164
  onDocument && live && (session == null ? void 0 : session.createVersion) ? /*#__PURE__*/ _jsx(Button, {
163
- variant: "contained",
164
165
  size: "small",
165
166
  onClick: onCreateVersion,
166
167
  children: "Make a new version"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-edit-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport type { EditorSession } from '@aglyn/aglyn/plugin-manager/editor-sessions'\nimport { mdiChevronDown, mdiChevronUp } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport {\n Alert,\n Box,\n Button,\n Collapse,\n Link,\n Paper,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useState } from 'react'\nimport {\n describeAssistEditDiff,\n type AssistEditDocumentKind,\n type AssistEditProposal,\n} from '../model/assist-edit'\n\n/**\n * The edit card (AGL-2906): a level-3 proposal as the author decides on it.\n *\n * It says what would change — the counts, and what validation left out —\n * and offers exactly one way forward for the editor as it stands:\n *\n * - on the document the proposal was made for, on a version the live site\n * does not serve: **Apply as draft**, which the panel carries out through\n * the canvas's own mutators as one undoable, unsaved change;\n * - on the version the live site serves: **Make a new version**, the\n * editor's own flow, after which the same card offers Apply there;\n * - anywhere else: nothing to press but **No thanks**.\n *\n * The card makes no request and holds no write of its own: its buttons call\n * back into the panel, which applies through the canvas and reports nothing\n * but the counts.\n */\n\nconst DOCUMENT_NOUNS: Readonly<Record<AssistEditDocumentKind, string>> = {\n screen: 'page',\n component: 'component',\n layout: 'layout',\n}\n\nexport interface AssistEditCardProps {\n proposal: AssistEditProposal\n /** The product's name as this org reads it. */\n brand: string\n /** The open editor, or `undefined` when none is open. */\n session: EditorSession | undefined\n /** Why the last attempt to apply was refused, when it was. */\n failure?: string | null\n onApply: () => void\n onCreateVersion: () => void\n onDismiss: () => void\n}\n\nexport function AssistEditCard(props: AssistEditCardProps) {\n const { proposal, brand, session, failure, onApply, onCreateVersion, onDismiss } = props\n const [showDropped, setShowDropped] = useState(false)\n const noun = DOCUMENT_NOUNS[proposal.target.kind] ?? 'document'\n const onDocument = Boolean(\n session &&\n session.documentKind === proposal.target.kind &&\n session.documentId === proposal.target.documentId,\n )\n const live = onDocument && Boolean(session?.isLiveVersion())\n const changes = describeAssistEditDiff(proposal.diff)\n // A component save creates one document (AGL-2908), which is the one thing\n // on this card that outlives an undo. The copy says so before Apply.\n const savesComponent = proposal.ops.some((op) => op.op === 'saveAsComponent')\n\n return (\n <Paper\n variant=\"outlined\"\n sx={{ mt: 1, p: 1.5, borderRadius: 2, bgcolor: 'background.paper' }}\n >\n <Typography variant=\"subtitle2\">Proposed change</Typography>\n {proposal.summary ? (\n <Typography variant=\"body2\" sx={{ mt: 0.5 }}>\n {proposal.summary}\n </Typography>\n ) : null}\n {changes.length > 0 && (\n <Stack component=\"ul\" sx={{ m: 0, mt: 1, pl: 2.5 }}>\n {changes.map((line) => (\n <Typography key={line} component=\"li\" variant=\"caption\">\n {line}\n </Typography>\n ))}\n </Stack>\n )}\n {proposal.dropped.length > 0 && (\n <Box sx={{ mt: 0.5 }}>\n <Link\n component=\"button\"\n type=\"button\"\n variant=\"caption\"\n underline=\"hover\"\n onClick={() => setShowDropped((prior) => !prior)}\n sx={{ display: 'inline-flex', alignItems: 'center', gap: 0.25 }}\n >\n {`Left out (${proposal.dropped.length})`}\n <MdiIcon\n path={showDropped ? mdiChevronUp.path : mdiChevronDown.path}\n sx={{ fontSize: 14 }}\n />\n </Link>\n <Collapse in={showDropped} unmountOnExit>\n <Stack component=\"ul\" sx={{ m: 0, pl: 2.5 }}>\n {proposal.dropped.map((reason, index) => (\n <Typography\n key={index}\n component=\"li\"\n variant=\"caption\"\n color=\"text.secondary\"\n >\n {reason}\n </Typography>\n ))}\n </Stack>\n </Collapse>\n </Box>\n )}\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n component=\"div\"\n sx={{ mt: 1 }}\n >\n {!onDocument\n ? `Open this ${noun} in the Besigner to apply the change.`\n : live\n ? `This is the version your live site shows. Make a new version first — the change is applied there, and the live ${noun} stays as it is.`\n : savesComponent\n ? `${brand} Assist changes nothing until you apply. Applying saves the component to your library, and swaps this element for one that follows it — an unsaved edit on the open canvas that undo takes back. Nothing is published.`\n : `${brand} Assist changes nothing until you apply. Applying adds these changes to the open canvas as unsaved edits: undo takes them back, and nothing is saved or published until you save.`}\n </Typography>\n {failure ? (\n <Alert severity=\"warning\" sx={{ mt: 1 }}>\n {failure}\n </Alert>\n ) : null}\n <Stack direction=\"row\" spacing={1} sx={{ mt: 1.5 }}>\n {onDocument && !live ? (\n <Button variant=\"contained\" size=\"small\" onClick={onApply}>\n Apply as draft\n </Button>\n ) : null}\n {onDocument && live && session?.createVersion ? (\n <Button variant=\"contained\" size=\"small\" onClick={onCreateVersion}>\n Make a new version\n </Button>\n ) : null}\n <Button size=\"small\" color=\"inherit\" onClick={onDismiss}>\n No thanks\n </Button>\n </Stack>\n </Paper>\n )\n}\n\nexport default AssistEditCard\n"],"names":["mdiChevronDown","mdiChevronUp","MdiIcon","Alert","Box","Button","Collapse","Link","Paper","Stack","Typography","useState","describeAssistEditDiff","DOCUMENT_NOUNS","screen","component","layout","AssistEditCard","props","proposal","brand","session","failure","onApply","onCreateVersion","onDismiss","showDropped","setShowDropped","noun","target","kind","onDocument","Boolean","documentKind","documentId","live","isLiveVersion","changes","diff","savesComponent","ops","some","op","variant","sx","mt","p","borderRadius","bgcolor","summary","length","m","pl","map","line","dropped","type","underline","onClick","prior","display","alignItems","gap","path","fontSize","in","unmountOnExit","reason","index","color","severity","direction","spacing","size","createVersion"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-edit-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport type { EditorSession } from '@aglyn/aglyn/plugin-manager/editor-sessions'\nimport { mdiChevronDown, mdiChevronUp } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport {\n Alert,\n Box,\n Button,\n Collapse,\n Link,\n Paper,\n Stack,\n Typography,\n} from '@mui/material'\nimport { useState } from 'react'\nimport {\n describeAssistEditDiff,\n type AssistEditDocumentKind,\n type AssistEditProposal,\n} from '../model/assist-edit'\n\n/**\n * The edit card (AGL-2906): a level-3 proposal as the author decides on it.\n *\n * It says what would change — the counts, and what validation left out —\n * and offers exactly one way forward for the editor as it stands:\n *\n * - on the document the proposal was made for: **Apply as draft**, which the\n * panel carries out through the canvas's own mutators as one undoable,\n * unsaved change. On the version the live site serves too (AGL-4116): the\n * Besigner saves that version's changes into the page's draft, never the\n * version itself, so the change is as safe there as an edit by hand, and\n * **Make a new version** is offered beside it for an author who wants the\n * change kept apart;\n * - anywhere else: nothing to press but **No thanks**.\n *\n * The card makes no request and holds no write of its own: its buttons call\n * back into the panel, which applies through the canvas and reports nothing\n * but the counts.\n */\n\nconst DOCUMENT_NOUNS: Readonly<Record<AssistEditDocumentKind, string>> = {\n screen: 'page',\n component: 'component',\n layout: 'layout',\n}\n\nexport interface AssistEditCardProps {\n proposal: AssistEditProposal\n /** The product's name as this org reads it. */\n brand: string\n /** The open editor, or `undefined` when none is open. */\n session: EditorSession | undefined\n /** Why the last attempt to apply was refused, when it was. */\n failure?: string | null\n onApply: () => void\n onCreateVersion: () => void\n onDismiss: () => void\n}\n\nexport function AssistEditCard(props: AssistEditCardProps) {\n const { proposal, brand, session, failure, onApply, onCreateVersion, onDismiss } = props\n const [showDropped, setShowDropped] = useState(false)\n const noun = DOCUMENT_NOUNS[proposal.target.kind] ?? 'document'\n const onDocument = Boolean(\n session &&\n session.documentKind === proposal.target.kind &&\n session.documentId === proposal.target.documentId,\n )\n const live = onDocument && Boolean(session?.isLiveVersion())\n const changes = describeAssistEditDiff(proposal.diff)\n // A component save creates one document (AGL-2908), which is the one thing\n // on this card that outlives an undo. The copy says so before Apply.\n const savesComponent = proposal.ops.some((op) => op.op === 'saveAsComponent')\n\n return (\n <Paper\n variant=\"outlined\"\n sx={{ mt: 1, p: 1.5, borderRadius: 2, bgcolor: 'background.paper' }}\n >\n <Typography variant=\"subtitle2\">Proposed change</Typography>\n {proposal.summary ? (\n <Typography variant=\"body2\" sx={{ mt: 0.5 }}>\n {proposal.summary}\n </Typography>\n ) : null}\n {changes.length > 0 && (\n <Stack component=\"ul\" sx={{ m: 0, mt: 1, pl: 2.5 }}>\n {changes.map((line) => (\n <Typography key={line} component=\"li\" variant=\"caption\">\n {line}\n </Typography>\n ))}\n </Stack>\n )}\n {proposal.dropped.length > 0 && (\n <Box sx={{ mt: 0.5 }}>\n <Link\n component=\"button\"\n type=\"button\"\n variant=\"caption\"\n underline=\"hover\"\n onClick={() => setShowDropped((prior) => !prior)}\n sx={{ display: 'inline-flex', alignItems: 'center', gap: 0.25 }}\n >\n {`Left out (${proposal.dropped.length})`}\n <MdiIcon\n path={showDropped ? mdiChevronUp.path : mdiChevronDown.path}\n sx={{ fontSize: 14 }}\n />\n </Link>\n <Collapse in={showDropped} unmountOnExit>\n <Stack component=\"ul\" sx={{ m: 0, pl: 2.5 }}>\n {proposal.dropped.map((reason, index) => (\n <Typography\n key={index}\n component=\"li\"\n variant=\"caption\"\n color=\"text.secondary\"\n >\n {reason}\n </Typography>\n ))}\n </Stack>\n </Collapse>\n </Box>\n )}\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n component=\"div\"\n sx={{ mt: 1 }}\n >\n {!onDocument\n ? `Open this ${noun} in the Besigner to apply the change.`\n : live && !savesComponent\n ? `${brand} Assist changes nothing until you apply. Applying adds these changes to the open canvas as unsaved edits that undo takes back. This is the version your live site shows: Save draft keeps them in this ${noun}’s draft, and visitors see them only when you publish.`\n : savesComponent\n ? `${brand} Assist changes nothing until you apply. Applying saves the component to your library, and swaps this element for one that follows it — an unsaved edit on the open canvas that undo takes back. Nothing is published.`\n : `${brand} Assist changes nothing until you apply. Applying adds these changes to the open canvas as unsaved edits: undo takes them back, and nothing is saved or published until you save.`}\n </Typography>\n {failure ? (\n <Alert severity=\"warning\" sx={{ mt: 1 }}>\n {failure}\n </Alert>\n ) : null}\n <Stack direction=\"row\" spacing={1} sx={{ mt: 1.5 }}>\n {onDocument ? (\n <Button variant=\"contained\" size=\"small\" onClick={onApply}>\n Apply as draft\n </Button>\n ) : null}\n {onDocument && live && session?.createVersion ? (\n <Button size=\"small\" onClick={onCreateVersion}>\n Make a new version\n </Button>\n ) : null}\n <Button size=\"small\" color=\"inherit\" onClick={onDismiss}>\n No thanks\n </Button>\n </Stack>\n </Paper>\n )\n}\n\nexport default AssistEditCard\n"],"names":["mdiChevronDown","mdiChevronUp","MdiIcon","Alert","Box","Button","Collapse","Link","Paper","Stack","Typography","useState","describeAssistEditDiff","DOCUMENT_NOUNS","screen","component","layout","AssistEditCard","props","proposal","brand","session","failure","onApply","onCreateVersion","onDismiss","showDropped","setShowDropped","noun","target","kind","onDocument","Boolean","documentKind","documentId","live","isLiveVersion","changes","diff","savesComponent","ops","some","op","variant","sx","mt","p","borderRadius","bgcolor","summary","length","m","pl","map","line","dropped","type","underline","onClick","prior","display","alignItems","gap","path","fontSize","in","unmountOnExit","reason","index","color","severity","direction","spacing","size","createVersion"],"mappings":"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"}
@@ -20,7 +20,7 @@ import { type AssistPageChangeProposal } from '../model/assist-page-change';
20
20
  /**
21
21
  * A change to a page the site already has, asked in the chat (AGL-4116):
22
22
  * the edit job making it, then the page's draft it wrote, opened in the
23
- * Besigner with Open draft, where the person checks it and publishes it. No
23
+ * Besigner on that draft, where the person checks it and publishes it. No
24
24
  * plan, no AI jobs page. On every plan: a new version is made only when one
25
25
  * was asked for, and the job's note says which it was.
26
26
  */
@@ -26,13 +26,13 @@ import { followAiJobEvents } from "./ai-job-events.js";
26
26
  import { aiJobOutputHref } from "./ai-job-links.js";
27
27
  const ASSIST_PAGE_CHANGE_HELP = pluginDocsHelp('aiAssistBuilds', {
28
28
  anchor: '#change-a-page',
29
- excerpt: 'The change is saved into the page’s draft. Open the page in the Besigner and choose Open draft to check it, then publish it; until then visitors see the page as it is.'
29
+ excerpt: 'The change is saved into the page’s draft. Open it in the Besigner to check it, then publish it; until then visitors see the page as it is.'
30
30
  });
31
31
  export function assistPageChangeMakingCopy(pageName) {
32
32
  return `Making the change as a draft of ${pageName}…`;
33
33
  }
34
34
  export function assistPageChangeReadyCopy(pageName) {
35
- return `Your draft of ${pageName} is ready. Open it in the Besigner and choose Open draft to check it. Visitors see the page as it is until you publish.`;
35
+ return `Your draft of ${pageName} is ready. Open it in the Besigner to check it. Visitors see the page as it is until you publish.`;
36
36
  }
37
37
  export function AssistPageChangeCard({ proposal, job, notice, orgId, orgSlug, user, onJob, onRetry, busy = false }) {
38
38
  var _ref, _ref1, _ref2, _ref3;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-page-change-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport type { MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { AppLink, HelpTip } from '@aglyn/shared-ui-jsx'\nimport { Button, CircularProgress, Paper, Stack, Typography } from '@mui/material'\nimport { useEffect, useRef } from 'react'\nimport { AI_JOB_TERMINAL_STATUSES, type AiJobSummary } from '../model/ai-jobs.types'\nimport { assistPageChangeOutput, type AssistPageChangeProposal } from '../model/assist-page-change'\nimport { followAiJobEvents } from './ai-job-events'\nimport { aiJobOutputHref } from './ai-job-links'\n\n/**\n * A change to a page the site already has, asked in the chat (AGL-4116):\n * the edit job making it, then the page's draft it wrote, opened in the\n * Besigner with Open draft, where the person checks it and publishes it. No\n * plan, no AI jobs page. On every plan: a new version is made only when one\n * was asked for, and the job's note says which it was.\n */\n\nexport interface AssistPageChangeCardProps {\n proposal: AssistPageChangeProposal\n /** The edit job, as last seen; `null` while it is being created. */\n job: AiJobSummary | null\n /** Why the job could not be started, when it could not. */\n notice: string | null\n orgId: string\n orgSlug: string\n user: MaybeTokenSource\n /** The job as it moved, for the thread to keep. */\n onJob: (job: AiJobSummary) => void\n /** Starts the same change again, after it failed. */\n onRetry: () => void\n busy?: boolean\n}\n\nconst ASSIST_PAGE_CHANGE_HELP = pluginDocsHelp('aiAssistBuilds', {\n anchor: '#change-a-page',\n excerpt:\n 'The change is saved into the page’s draft. Open the page in the Besigner and choose Open draft to check it, then publish it; until then visitors see the page as it is.',\n})\n\nexport function assistPageChangeMakingCopy(pageName: string): string {\n return `Making the change as a draft of ${pageName}…`\n}\n\nexport function assistPageChangeReadyCopy(pageName: string): string {\n return `Your draft of ${pageName} is ready. Open it in the Besigner and choose Open draft to check it. Visitors see the page as it is until you publish.`\n}\n\nexport function AssistPageChangeCard({\n proposal,\n job,\n notice,\n orgId,\n orgSlug,\n user,\n onJob,\n onRetry,\n busy = false,\n}: AssistPageChangeCardProps): JSX.Element {\n const userRef = useRef(user)\n userRef.current = user\n const onJobRef = useRef(onJob)\n onJobRef.current = onJob\n\n // Follow the job until it settles; one waiting on the person has nothing\n // more to say on the stream.\n const following = Boolean(\n job && !AI_JOB_TERMINAL_STATUSES.includes(job.status) && job.status !== 'needs_review' && job.status !== 'needs_input',\n )\n const jobId = job?.id ?? null\n useEffect(() => {\n if (!following || !jobId) return\n const controller = new AbortController()\n void followAiJobEvents(() => userRef.current, orgId, jobId, controller.signal, (next) => onJobRef.current(next))\n return () => controller.abort()\n }, [following, jobId, orgId])\n\n const output = assistPageChangeOutput(job)\n const href = output ? aiJobOutputHref(output, orgSlug) : null\n const stopped = Boolean(job && (job.status === 'failed' || job.status === 'canceled'))\n const waiting = Boolean(job && (job.status === 'needs_review' || job.status === 'needs_input'))\n\n return (\n <Paper variant=\"outlined\" sx={{ mt: 1, p: 1.5 }} aria-label=\"Page change\">\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle2\">{proposal.summary}</Typography>\n <HelpTip {...ASSIST_PAGE_CHANGE_HELP} />\n </Stack>\n {(!job && !notice) || following ? (\n <Stack direction=\"row\" spacing={1} sx={{ mt: 0.5, alignItems: 'center' }}>\n <CircularProgress size={14} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {assistPageChangeMakingCopy(proposal.pageName)}\n </Typography>\n </Stack>\n ) : null}\n {notice && (\n <Typography variant=\"body2\" color=\"error\" sx={{ mt: 0.5 }} role=\"alert\">\n {notice}\n </Typography>\n )}\n {output && (\n <>\n <Typography variant=\"body2\" sx={{ mt: 0.5 }}>\n {/* The job's own note says where the change went — the draft or a\n new version — and what it left out. */}\n {output.note || assistPageChangeReadyCopy(proposal.pageName)}\n </Typography>\n {href && (\n <Button size=\"small\" variant=\"contained\" component={AppLink} href={href} sx={{ mt: 1 }}>\n {'Open in the Besigner'}\n </Button>\n )}\n </>\n )}\n {waiting && (\n <Typography variant=\"body2\" sx={{ mt: 0.5 }} role=\"alert\">\n {job?.review?.message ?? job?.error ?? 'The change is waiting on you.'}\n </Typography>\n )}\n {stopped && (\n <>\n <Typography variant=\"body2\" color=\"error\" sx={{ mt: 0.5 }} role=\"alert\">\n {job?.error ?? 'The change could not be made.'}\n </Typography>\n <Button size=\"small\" sx={{ mt: 1 }} disabled={busy} onClick={onRetry}>\n {'Try again'}\n </Button>\n </>\n )}\n </Paper>\n )\n}\n"],"names":["pluginDocsHelp","AppLink","HelpTip","Button","CircularProgress","Paper","Stack","Typography","useEffect","useRef","AI_JOB_TERMINAL_STATUSES","assistPageChangeOutput","followAiJobEvents","aiJobOutputHref","ASSIST_PAGE_CHANGE_HELP","anchor","excerpt","assistPageChangeMakingCopy","pageName","assistPageChangeReadyCopy","AssistPageChangeCard","proposal","job","notice","orgId","orgSlug","user","onJob","onRetry","busy","userRef","current","onJobRef","following","Boolean","includes","status","jobId","id","controller","AbortController","signal","next","abort","output","href","stopped","waiting","variant","sx","mt","p","aria-label","direction","spacing","alignItems","summary","size","color","role","note","component","review","message","error","disabled","onClick"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/assist-page-change-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport type { MaybeTokenSource } from '@aglyn/shared-util-http/authorized-token'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { AppLink, HelpTip } from '@aglyn/shared-ui-jsx'\nimport { Button, CircularProgress, Paper, Stack, Typography } from '@mui/material'\nimport { useEffect, useRef } from 'react'\nimport { AI_JOB_TERMINAL_STATUSES, type AiJobSummary } from '../model/ai-jobs.types'\nimport { assistPageChangeOutput, type AssistPageChangeProposal } from '../model/assist-page-change'\nimport { followAiJobEvents } from './ai-job-events'\nimport { aiJobOutputHref } from './ai-job-links'\n\n/**\n * A change to a page the site already has, asked in the chat (AGL-4116):\n * the edit job making it, then the page's draft it wrote, opened in the\n * Besigner on that draft, where the person checks it and publishes it. No\n * plan, no AI jobs page. On every plan: a new version is made only when one\n * was asked for, and the job's note says which it was.\n */\n\nexport interface AssistPageChangeCardProps {\n proposal: AssistPageChangeProposal\n /** The edit job, as last seen; `null` while it is being created. */\n job: AiJobSummary | null\n /** Why the job could not be started, when it could not. */\n notice: string | null\n orgId: string\n orgSlug: string\n user: MaybeTokenSource\n /** The job as it moved, for the thread to keep. */\n onJob: (job: AiJobSummary) => void\n /** Starts the same change again, after it failed. */\n onRetry: () => void\n busy?: boolean\n}\n\nconst ASSIST_PAGE_CHANGE_HELP = pluginDocsHelp('aiAssistBuilds', {\n anchor: '#change-a-page',\n excerpt:\n 'The change is saved into the page’s draft. Open it in the Besigner to check it, then publish it; until then visitors see the page as it is.',\n})\n\nexport function assistPageChangeMakingCopy(pageName: string): string {\n return `Making the change as a draft of ${pageName}…`\n}\n\nexport function assistPageChangeReadyCopy(pageName: string): string {\n return `Your draft of ${pageName} is ready. Open it in the Besigner to check it. Visitors see the page as it is until you publish.`\n}\n\nexport function AssistPageChangeCard({\n proposal,\n job,\n notice,\n orgId,\n orgSlug,\n user,\n onJob,\n onRetry,\n busy = false,\n}: AssistPageChangeCardProps): JSX.Element {\n const userRef = useRef(user)\n userRef.current = user\n const onJobRef = useRef(onJob)\n onJobRef.current = onJob\n\n // Follow the job until it settles; one waiting on the person has nothing\n // more to say on the stream.\n const following = Boolean(\n job && !AI_JOB_TERMINAL_STATUSES.includes(job.status) && job.status !== 'needs_review' && job.status !== 'needs_input',\n )\n const jobId = job?.id ?? null\n useEffect(() => {\n if (!following || !jobId) return\n const controller = new AbortController()\n void followAiJobEvents(() => userRef.current, orgId, jobId, controller.signal, (next) => onJobRef.current(next))\n return () => controller.abort()\n }, [following, jobId, orgId])\n\n const output = assistPageChangeOutput(job)\n const href = output ? aiJobOutputHref(output, orgSlug) : null\n const stopped = Boolean(job && (job.status === 'failed' || job.status === 'canceled'))\n const waiting = Boolean(job && (job.status === 'needs_review' || job.status === 'needs_input'))\n\n return (\n <Paper variant=\"outlined\" sx={{ mt: 1, p: 1.5 }} aria-label=\"Page change\">\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Typography variant=\"subtitle2\">{proposal.summary}</Typography>\n <HelpTip {...ASSIST_PAGE_CHANGE_HELP} />\n </Stack>\n {(!job && !notice) || following ? (\n <Stack direction=\"row\" spacing={1} sx={{ mt: 0.5, alignItems: 'center' }}>\n <CircularProgress size={14} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {assistPageChangeMakingCopy(proposal.pageName)}\n </Typography>\n </Stack>\n ) : null}\n {notice && (\n <Typography variant=\"body2\" color=\"error\" sx={{ mt: 0.5 }} role=\"alert\">\n {notice}\n </Typography>\n )}\n {output && (\n <>\n <Typography variant=\"body2\" sx={{ mt: 0.5 }}>\n {/* The job's own note says where the change went — the draft or a\n new version — and what it left out. */}\n {output.note || assistPageChangeReadyCopy(proposal.pageName)}\n </Typography>\n {href && (\n <Button size=\"small\" variant=\"contained\" component={AppLink} href={href} sx={{ mt: 1 }}>\n {'Open in the Besigner'}\n </Button>\n )}\n </>\n )}\n {waiting && (\n <Typography variant=\"body2\" sx={{ mt: 0.5 }} role=\"alert\">\n {job?.review?.message ?? job?.error ?? 'The change is waiting on you.'}\n </Typography>\n )}\n {stopped && (\n <>\n <Typography variant=\"body2\" color=\"error\" sx={{ mt: 0.5 }} role=\"alert\">\n {job?.error ?? 'The change could not be made.'}\n </Typography>\n <Button size=\"small\" sx={{ mt: 1 }} disabled={busy} onClick={onRetry}>\n {'Try again'}\n </Button>\n </>\n )}\n </Paper>\n )\n}\n"],"names":["pluginDocsHelp","AppLink","HelpTip","Button","CircularProgress","Paper","Stack","Typography","useEffect","useRef","AI_JOB_TERMINAL_STATUSES","assistPageChangeOutput","followAiJobEvents","aiJobOutputHref","ASSIST_PAGE_CHANGE_HELP","anchor","excerpt","assistPageChangeMakingCopy","pageName","assistPageChangeReadyCopy","AssistPageChangeCard","proposal","job","notice","orgId","orgSlug","user","onJob","onRetry","busy","userRef","current","onJobRef","following","Boolean","includes","status","jobId","id","controller","AbortController","signal","next","abort","output","href","stopped","waiting","variant","sx","mt","p","aria-label","direction","spacing","alignItems","summary","size","color","role","note","component","review","message","error","disabled","onClick"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;AAGA,SAASA,cAAc,QAAQ,mCAAkC;AACjE,SAASC,OAAO,EAAEC,OAAO,QAAQ,uBAAsB;AACvD,SAASC,MAAM,EAAEC,gBAAgB,EAAEC,KAAK,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AAClF,SAASC,SAAS,EAAEC,MAAM,QAAQ,QAAO;AACzC,SAASC,wBAAwB,QAA2B,4BAAwB;AACpF,SAASC,sBAAsB,QAAuC,iCAA6B;AACnG,SAASC,iBAAiB,QAAQ,qBAAiB;AACnD,SAASC,eAAe,QAAQ,oBAAgB;AA0BhD,MAAMC,0BAA0Bd,eAAe,kBAAkB;IAC/De,QAAQ;IACRC,SACE;AACJ;AAEA,OAAO,SAASC,2BAA2BC,QAAgB;IACzD,OAAO,CAAC,gCAAgC,EAAEA,SAAS,CAAC,CAAC;AACvD;AAEA,OAAO,SAASC,0BAA0BD,QAAgB;IACxD,OAAO,CAAC,cAAc,EAAEA,SAAS,iGAAiG,CAAC;AACrI;AAEA,OAAO,SAASE,qBAAqB,EACnCC,QAAQ,EACRC,GAAG,EACHC,MAAM,EACNC,KAAK,EACLC,OAAO,EACPC,IAAI,EACJC,KAAK,EACLC,OAAO,EACPC,OAAO,KAAK,EACc;cA2DjBP;QAAAA;IA1DT,MAAMQ,UAAUrB,OAAOiB;IACvBI,QAAQC,OAAO,GAAGL;IAClB,MAAMM,WAAWvB,OAAOkB;IACxBK,SAASD,OAAO,GAAGJ;IAEnB,yEAAyE;IACzE,6BAA6B;IAC7B,MAAMM,YAAYC,QAChBZ,OAAO,CAACZ,yBAAyByB,QAAQ,CAACb,IAAIc,MAAM,KAAKd,IAAIc,MAAM,KAAK,kBAAkBd,IAAIc,MAAM,KAAK;IAE3G,MAAMC,gBAAQf,uBAAAA,IAAKgB,EAAE,mBAAI;IACzB9B,UAAU;QACR,IAAI,CAACyB,aAAa,CAACI,OAAO;QAC1B,MAAME,aAAa,IAAIC;QACvB,KAAK5B,kBAAkB,IAAMkB,QAAQC,OAAO,EAAEP,OAAOa,OAAOE,WAAWE,MAAM,EAAE,CAACC,OAASV,SAASD,OAAO,CAACW;QAC1G,OAAO,IAAMH,WAAWI,KAAK;IAC/B,GAAG;QAACV;QAAWI;QAAOb;KAAM;IAE5B,MAAMoB,SAASjC,uBAAuBW;IACtC,MAAMuB,OAAOD,SAAS/B,gBAAgB+B,QAAQnB,WAAW;IACzD,MAAMqB,UAAUZ,QAAQZ,OAAQA,CAAAA,IAAIc,MAAM,KAAK,YAAYd,IAAIc,MAAM,KAAK,UAAS;IACnF,MAAMW,UAAUb,QAAQZ,OAAQA,CAAAA,IAAIc,MAAM,KAAK,kBAAkBd,IAAIc,MAAM,KAAK,aAAY;IAE5F,qBACE,MAAC/B;QAAM2C,SAAQ;QAAWC,IAAI;YAAEC,IAAI;YAAGC,GAAG;QAAI;QAAGC,cAAW;;0BAC1D,MAAC9C;gBAAM+C,WAAU;gBAAMC,SAAS;gBAAKL,IAAI;oBAAEM,YAAY;gBAAS;;kCAC9D,KAAChD;wBAAWyC,SAAQ;kCAAa3B,SAASmC,OAAO;;kCACjD,KAACtD,sBAAYY;;;YAEb,CAACQ,OAAO,CAACC,UAAWU,0BACpB,MAAC3B;gBAAM+C,WAAU;gBAAMC,SAAS;gBAAGL,IAAI;oBAAEC,IAAI;oBAAKK,YAAY;gBAAS;;kCACrE,KAACnD;wBAAiBqD,MAAM;;kCACxB,KAAClD;wBAAWyC,SAAQ;wBAAQU,OAAM;kCAC/BzC,2BAA2BI,SAASH,QAAQ;;;iBAG/C;YACHK,wBACC,KAAChB;gBAAWyC,SAAQ;gBAAQU,OAAM;gBAAQT,IAAI;oBAAEC,IAAI;gBAAI;gBAAGS,MAAK;0BAC7DpC;;YAGJqB,wBACC;;kCACE,KAACrC;wBAAWyC,SAAQ;wBAAQC,IAAI;4BAAEC,IAAI;wBAAI;kCAGvCN,OAAOgB,IAAI,IAAIzC,0BAA0BE,SAASH,QAAQ;;oBAE5D2B,sBACC,KAAC1C;wBAAOsD,MAAK;wBAAQT,SAAQ;wBAAYa,WAAW5D;wBAAS4C,MAAMA;wBAAMI,IAAI;4BAAEC,IAAI;wBAAE;kCAClF;;;;YAKRH,yBACC,KAACxC;gBAAWyC,SAAQ;gBAAQC,IAAI;oBAAEC,IAAI;gBAAI;gBAAGS,MAAK;2BAC/CrC,iBAAAA,wBAAAA,cAAAA,IAAKwC,MAAM,qBAAXxC,YAAayC,OAAO,oBAAIzC,uBAAAA,IAAK0C,KAAK,YAAlC1C,QAAsC;;YAG1CwB,yBACC;;kCACE,KAACvC;wBAAWyC,SAAQ;wBAAQU,OAAM;wBAAQT,IAAI;4BAAEC,IAAI;wBAAI;wBAAGS,MAAK;2CAC7DrC,uBAAAA,IAAK0C,KAAK,oBAAI;;kCAEjB,KAAC7D;wBAAOsD,MAAK;wBAAQR,IAAI;4BAAEC,IAAI;wBAAE;wBAAGe,UAAUpC;wBAAMqC,SAAStC;kCAC1D;;;;;;AAMb"}
@@ -36,7 +36,7 @@ import { AssistBuildCard } from "./assist-build-card.component.js";
36
36
  import { isAssistBuildProposal } from "../model/assist-build.js";
37
37
  import { assistBuildDraftLinks, isAssistFollowUpDue, isLiveAssistFollowUp } from "../model/assist-follow-up.js";
38
38
  import { cancelAiJobRequest, startAssistBuildRequest, startAssistPageChangeRequest } from "./ai-job-requests.js";
39
- import { assistPageChangeDraftVersion, isAssistPageChangeProposal } from "../model/assist-page-change.js";
39
+ import { assistPageChangeDraftVersion, assistPageChangeHistoryNote, isAssistPageChangeProposal } from "../model/assist-page-change.js";
40
40
  import { AssistPageChangeCard } from "./assist-page-change-card.component.js";
41
41
  import { aiInsightSurfaceForPath } from "../model/ai-insight.js";
42
42
  import { AssistJobsDrawer } from "./assist-jobs-drawer.component.js";
@@ -50,6 +50,15 @@ import { followAiJobsForUsageMeter, refreshAiUsageMeterFree } from "./ai-usage-m
50
50
  import { readAiUsageMeter, usePublishAiUsageMeter } from "./use-ai-usage-meter.js";
51
51
  import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
52
52
  import { HelpTip } from "@aglyn/shared-ui-jsx";
53
+ /**
54
+ * A turn as the next question's history carries it (AGL-4116): its words, and
55
+ * what became of the change it made, which the words alone never say.
56
+ */ function assistHistoryText(message) {
57
+ var _assistPageChangeHistoryNote;
58
+ var _message_editOutcome;
59
+ const note = (_assistPageChangeHistoryNote = assistPageChangeHistoryNote(message)) != null ? _assistPageChangeHistoryNote : message.edit && ((_message_editOutcome = message.editOutcome) == null ? void 0 : _message_editOutcome.kind) === 'applied' ? `(Applied to the open canvas as an unsaved change: ${message.edit.summary})` : null;
60
+ return note ? `${message.text}\n\n${note}` : message.text;
61
+ }
53
62
  /** The key a follow-up waiting for its canvas is kept under, per org (AGL-3616). */ const followUpKey = (orgId)=>`aglyn-assist-follow-up:${orgId}`;
54
63
  function loadFollowUp(orgId) {
55
64
  if (!orgId || typeof sessionStorage === 'undefined') return null;
@@ -713,9 +722,9 @@ export function AssistPanelComponent(props) {
713
722
  const draftLinks = hostId ? assistThreadDraftLinks(messages, orgSlug) : [];
714
723
  // Only this site's turns ride the question (AGL-4116), and the answer
715
724
  // lands in the thread it was asked in.
716
- const history = messages.slice(-HISTORY_TURNS_SENT).map(({ role, text })=>({
717
- role,
718
- text
725
+ const history = messages.slice(-HISTORY_TURNS_SENT).map((message)=>({
726
+ role: message.role,
727
+ text: assistHistoryText(message)
719
728
  }));
720
729
  const askedIn = threadKey;
721
730
  updateThread(askedIn, (prior)=>[
@@ -753,12 +762,14 @@ export function AssistPanelComponent(props) {
753
762
  try {
754
763
  var _ref;
755
764
  // The canvas outline rides along from the besigner document the open
756
- // editor holds — ids, component ids and short values, never the stored
757
- // document — and only while that editor is on the version the route
758
- // names, so the outline and the selection are the ones on screen.
765
+ // editor holds, every element with its settings and styles (AGL-4116),
766
+ // and only while that editor is on the version the route names, so the
767
+ // outline and the selection are the ones on screen.
759
768
  const editDocument = editRungHint ? assistEditDocumentOf(pathname != null ? pathname : '') : null;
760
769
  const session = editDocument ? openEditorSession() : undefined;
761
- const canvasOutline = editDocument && session && session.documentKind === editDocument.kind && session.documentId === editDocument.documentId && session.versionId === editDocument.versionId ? describeAssistEditCanvas(canvas, (_ref = session.selectedNodeId == null ? void 0 : session.selectedNodeId.call(session)) != null ? _ref : null) : null;
770
+ const canvasOutline = editDocument && session && session.documentKind === editDocument.kind && session.documentId === editDocument.documentId && session.versionId === editDocument.versionId ? describeAssistEditCanvas(canvas, (_ref = session.selectedNodeId == null ? void 0 : session.selectedNodeId.call(session)) != null ? _ref : null, {
771
+ whole: true
772
+ }) : null;
762
773
  const response = await authorizedFetch(user, '/api/assist/chat', {
763
774
  method: 'POST',
764
775
  headers: {