@syntrologie/adapt-chatbot 2.8.0-canary.31 → 2.8.0-canary.310

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 (126) hide show
  1. package/dist/AdaptiveChatBar.d.ts +85 -0
  2. package/dist/AdaptiveChatBar.d.ts.map +1 -0
  3. package/dist/AdaptiveChatBar.js +10 -0
  4. package/dist/AdaptiveChatBar.js.map +7 -0
  5. package/dist/AdaptiveChatBarMountable.d.ts +35 -0
  6. package/dist/AdaptiveChatBarMountable.d.ts.map +1 -0
  7. package/dist/AdaptiveChatTrail.d.ts +85 -0
  8. package/dist/AdaptiveChatTrail.d.ts.map +1 -0
  9. package/dist/AdaptiveChatTrail.js +9 -0
  10. package/dist/AdaptiveChatTrail.js.map +7 -0
  11. package/dist/AdaptiveChipsStrip.d.ts +1150 -0
  12. package/dist/AdaptiveChipsStrip.d.ts.map +1 -0
  13. package/dist/AdaptiveChipsStrip.js +11 -0
  14. package/dist/AdaptiveChipsStrip.js.map +7 -0
  15. package/dist/AdaptiveChipsStripMountable.d.ts +24 -0
  16. package/dist/AdaptiveChipsStripMountable.d.ts.map +1 -0
  17. package/dist/ChatAssistantLit.d.ts +60 -0
  18. package/dist/ChatAssistantLit.d.ts.map +1 -0
  19. package/dist/ChatAssistantLit.js +12 -0
  20. package/dist/ChatAssistantLit.js.map +7 -0
  21. package/dist/ChatSession.d.ts +178 -0
  22. package/dist/ChatSession.d.ts.map +1 -0
  23. package/dist/ChatTransport.d.ts +283 -0
  24. package/dist/ChatTransport.d.ts.map +1 -0
  25. package/dist/NavLinkMountable.d.ts +25 -0
  26. package/dist/NavLinkMountable.d.ts.map +1 -0
  27. package/dist/NavLinkMountable.test.d.ts +2 -0
  28. package/dist/NavLinkMountable.test.d.ts.map +1 -0
  29. package/dist/TextAnswerMountable.d.ts +17 -0
  30. package/dist/TextAnswerMountable.d.ts.map +1 -0
  31. package/dist/Turnstile.d.ts +83 -0
  32. package/dist/Turnstile.d.ts.map +1 -0
  33. package/dist/cdn.d.ts +2 -6
  34. package/dist/cdn.d.ts.map +1 -1
  35. package/dist/chunk-2ZUJ7DZI.js +8770 -0
  36. package/dist/chunk-2ZUJ7DZI.js.map +7 -0
  37. package/dist/chunk-BNN5YLN3.js +417 -0
  38. package/dist/chunk-BNN5YLN3.js.map +7 -0
  39. package/dist/chunk-FVNSOP7B.js +634 -0
  40. package/dist/chunk-FVNSOP7B.js.map +7 -0
  41. package/dist/chunk-ONGGPQER.js +3722 -0
  42. package/dist/chunk-ONGGPQER.js.map +7 -0
  43. package/dist/chunk-SCVTTLFJ.js +334 -0
  44. package/dist/chunk-SCVTTLFJ.js.map +7 -0
  45. package/dist/chunk-UVKRO5ER.js +13 -0
  46. package/dist/chunk-UVKRO5ER.js.map +7 -0
  47. package/dist/chunk-VLJ3WOEX.js +231 -0
  48. package/dist/chunk-VLJ3WOEX.js.map +7 -0
  49. package/dist/editor-lit.d.ts +37 -0
  50. package/dist/editor-lit.d.ts.map +1 -0
  51. package/dist/editor-lit.js +134 -0
  52. package/dist/editor-lit.js.map +7 -0
  53. package/dist/elements/ActionHandler.d.ts +34 -0
  54. package/dist/elements/ActionHandler.d.ts.map +1 -0
  55. package/dist/elements/ElementInstanceStore.d.ts +155 -0
  56. package/dist/elements/ElementInstanceStore.d.ts.map +1 -0
  57. package/dist/elements/ElementInstanceStore.test.d.ts +2 -0
  58. package/dist/elements/ElementInstanceStore.test.d.ts.map +1 -0
  59. package/dist/elements/ElementTypeHandler.d.ts +77 -0
  60. package/dist/elements/ElementTypeHandler.d.ts.map +1 -0
  61. package/dist/elements/ItemHandler.d.ts +60 -0
  62. package/dist/elements/ItemHandler.d.ts.map +1 -0
  63. package/dist/elements/ItemHandler.test.d.ts +2 -0
  64. package/dist/elements/ItemHandler.test.d.ts.map +1 -0
  65. package/dist/elements/TileHandler.d.ts +52 -0
  66. package/dist/elements/TileHandler.d.ts.map +1 -0
  67. package/dist/elements/blockRenderer.d.ts +46 -0
  68. package/dist/elements/blockRenderer.d.ts.map +1 -0
  69. package/dist/elements/blockRenderer.test.d.ts +13 -0
  70. package/dist/elements/blockRenderer.test.d.ts.map +1 -0
  71. package/dist/elements/blocks.d.ts +58 -0
  72. package/dist/elements/blocks.d.ts.map +1 -0
  73. package/dist/elements/envelope.d.ts +24 -0
  74. package/dist/elements/envelope.d.ts.map +1 -0
  75. package/dist/elements/fetcher.d.ts +40 -0
  76. package/dist/elements/fetcher.d.ts.map +1 -0
  77. package/dist/elements/index.d.ts +32 -0
  78. package/dist/elements/index.d.ts.map +1 -0
  79. package/dist/elements/types.d.ts +106 -0
  80. package/dist/elements/types.d.ts.map +1 -0
  81. package/dist/observer/__tests__/allowlist.test.d.ts +9 -0
  82. package/dist/observer/__tests__/allowlist.test.d.ts.map +1 -0
  83. package/dist/observer/__tests__/observer-isolation.test.d.ts +13 -0
  84. package/dist/observer/__tests__/observer-isolation.test.d.ts.map +1 -0
  85. package/dist/observer/__tests__/queue.test.d.ts +2 -0
  86. package/dist/observer/__tests__/queue.test.d.ts.map +1 -0
  87. package/dist/observer/__tests__/transport.test.d.ts +2 -0
  88. package/dist/observer/__tests__/transport.test.d.ts.map +1 -0
  89. package/dist/observer/allowlist.d.ts +32 -0
  90. package/dist/observer/allowlist.d.ts.map +1 -0
  91. package/dist/observer/index.d.ts +35 -0
  92. package/dist/observer/index.d.ts.map +1 -0
  93. package/dist/observer/queue.d.ts +57 -0
  94. package/dist/observer/queue.d.ts.map +1 -0
  95. package/dist/observer/transport.d.ts +26 -0
  96. package/dist/observer/transport.d.ts.map +1 -0
  97. package/dist/runtime-lit.d.ts +8 -0
  98. package/dist/runtime-lit.d.ts.map +1 -0
  99. package/dist/runtime.d.ts +8 -3
  100. package/dist/runtime.d.ts.map +1 -1
  101. package/dist/runtime.js +1649 -29
  102. package/dist/runtime.js.map +7 -0
  103. package/dist/schema.d.ts +3298 -11
  104. package/dist/schema.d.ts.map +1 -1
  105. package/dist/schema.js +126 -31
  106. package/dist/schema.js.map +7 -0
  107. package/dist/types.d.ts +47 -31
  108. package/dist/types.d.ts.map +1 -1
  109. package/package.json +50 -19
  110. package/dist/ChatAssistant.d.ts +0 -18
  111. package/dist/ChatAssistant.d.ts.map +0 -1
  112. package/dist/ChatAssistant.js +0 -178
  113. package/dist/actionParser.d.ts +0 -15
  114. package/dist/actionParser.d.ts.map +0 -1
  115. package/dist/actionParser.js +0 -52
  116. package/dist/apiClient.d.ts +0 -23
  117. package/dist/apiClient.d.ts.map +0 -1
  118. package/dist/apiClient.js +0 -51
  119. package/dist/cdn.js +0 -37
  120. package/dist/editor.d.ts +0 -17
  121. package/dist/editor.d.ts.map +0 -1
  122. package/dist/editor.js +0 -36
  123. package/dist/types.js +0 -6
  124. package/dist/useChat.d.ts +0 -25
  125. package/dist/useChat.d.ts.map +0 -1
  126. package/dist/useChat.js +0 -106
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../sdk-contracts/dist/mount-plumbing.js", "../../../sdk-contracts/dist/schemas.js", "../../../../node_modules/@lit/context/src/lib/create-context.ts", "../../../sdk-contracts/dist/canvas-context.js", "../../../sdk-contracts/dist/routes.js", "../../../sdk-contracts/dist/tile-lifecycle.js"],
4
+ "sourcesContent": ["/**\n * Mount contract types and helper for adaptive widget mountables.\n *\n * The `WidgetRegistry` in `@syntrologie/runtime-sdk` delivers props to each\n * mountable as `{ ...tile.props, instanceId, runtime, tileId? }` spread flat\n * (see `MountableContract.test.ts` in runtime-sdk for the end-to-end lockdown).\n *\n * Adaptives that strip plumbing manually maintain private blacklists that\n * silently drift when the contract grows (PR #2234 and #2238 documented this).\n * `stripMountPlumbing` centralizes the list so adding a new plumbing key in\n * the future is a one-line change here that every adaptive picks up automatically.\n *\n * Adaptives whose widget schemas use Zod `.strict()` MUST call this before\n * validating, or strict-mode will reject the runtime-injected keys and the\n * widget will silently render its empty/error state.\n */\nexport const MOUNT_PLUMBING_KEYS = ['instanceId', 'runtime', 'tileId'];\nexport function stripMountPlumbing(config) {\n if (!config || typeof config !== 'object') {\n return {};\n }\n const out = { ...config };\n for (const key of MOUNT_PLUMBING_KEYS) {\n delete out[key];\n }\n return out;\n}\n", "/**\n * Shared Zod schemas for decision strategies, conditions, and event scoping.\n *\n * These are the canonical definitions \u2014 runtime-sdk and all adaptive packages\n * should import from here instead of duplicating.\n */\nimport { z } from 'zod';\n// =============================================================================\n// ANCHOR ID SCHEMA\n// =============================================================================\nexport const AnchorIdZ = z\n .object({\n selector: z.string(),\n route: z.union([z.string(), z.array(z.string())]),\n})\n .strict();\n// =============================================================================\n// AUTHORING FIELDS \u2014 id / title / description / validation\n//\n// Shared fields every action carries. `id` is the action identifier the\n// runtime uses to dispatch, dedupe, and drop/replace actions \u2014 it is NOT\n// stripped before serving. `title` / `description` / `validation` are\n// authoring-only metadata stripped server-side in `to_runtime_config`\n// (platform/backend/app/domains/experiments/helpers.py).\n//\n// They all appear in the JSON Schema (and therefore in the tactician's\n// prompt) because the LLM needs to know they are valid action properties \u2014\n// otherwise schema validation would reject what the prompt commands.\n//\n// Each action variant should `.extend(AuthoringFieldsZ)` alongside any\n// triggerWhen/condition extensions.\n// =============================================================================\nexport const AuthoringFieldsZ = {\n id: z.string().optional().describe('Stable action identifier (e.g. \"act_3db6a14d2ab0\").'),\n title: z\n .string()\n .max(200)\n .optional()\n .describe('Authoring-only: short label shown on the action plan dashboard. Stripped before serving to the runtime SDK.'),\n description: z\n .string()\n .max(1000)\n .optional()\n .describe('Authoring-only: one-sentence explanation of what this action does and why. Stripped before serving to the runtime SDK.'),\n validation: z\n .array(z.string().max(500))\n .max(10)\n .optional()\n .describe('Authoring-only: ordered steps a reviewer can follow to trigger this action and visually confirm it works. Each entry is one step. Stripped before serving to the runtime SDK.'),\n};\n// =============================================================================\n// TRIGGER VOCABULARY \u2014 canonical lists of valid event names, metric keys, etc.\n// These flow through to the JSON schema as enums and are used by the LLM prompt.\n// =============================================================================\n/** Events that can be counted in event_count conditions.\n *\n * Every value here must be an event the runtime actually emits \u2014 either a\n * PostHog-autocapture normalization (ui.click/scroll/input/change/submit) or\n * an event-processor detector (ui.hover/idle/scroll_thrash/focus_bounce/\n * hesitate/rage_click). Do not add aspirational names; a trigger counting an\n * event nothing emits never fires.\n */\nexport const COUNTABLE_EVENTS = [\n // User interactions (from PostHog autocapture normalization)\n 'ui.click',\n 'ui.scroll',\n 'ui.input',\n 'ui.change',\n 'ui.submit',\n // Behavioral detectors (from event-processor)\n 'ui.hover',\n 'ui.idle',\n 'ui.scroll_thrash',\n 'ui.focus_bounce',\n 'ui.hesitate',\n 'ui.rage_click',\n // Navigation\n 'nav.page_view',\n 'nav.page_leave',\n];\nexport const CountableEventZ = z\n .enum(COUNTABLE_EVENTS)\n .describe('Event name to count. ui.* = user interactions and behavioral detectors (hesitate, rage_click, scroll_thrash, focus_bounce, idle, hover); nav.* = page navigation.');\n/** Valid session metric keys. */\nexport const SESSION_METRIC_KEYS = ['time_on_page', 'page_views', 'scroll_depth'];\nexport const SessionMetricKeyZ = z\n .enum(SESSION_METRIC_KEYS)\n .describe('Session metric key. time_on_page = seconds on current page, page_views = pages visited this session, scroll_depth = 0-100 percentage.');\n/** Element chain match field prefixes for counter filters. */\nexport const ELEMENT_MATCH_FIELDS = ['tag_name', '$el_text'];\n// Note: attr__* is a dynamic prefix (attr__data-id, attr__class, attr__href, etc.)\n// and cannot be enumerated. The match key is either one of ELEMENT_MATCH_FIELDS\n// or starts with \"attr__\".\n// =============================================================================\n// CONDITION SCHEMAS\n// =============================================================================\nexport const PageUrlConditionZ = z\n .object({\n type: z.literal('page_url'),\n url: z.string().describe('URL path to match (e.g. \"/pricing\", \"/dashboard\")'),\n})\n .describe('Fires when the current page URL matches. Use for page-specific actions. ' +\n 'Example: {\"type\": \"page_url\", \"url\": \"/pricing\"}');\nexport const RouteConditionZ = z\n .object({\n type: z.literal('route'),\n routeId: z.string().describe('Named route ID from the route filter'),\n})\n .describe('Fires when the current route matches a named route ID.');\nexport const AnchorVisibleConditionZ = z\n .object({\n type: z.literal('anchor_visible'),\n anchorId: z.string().describe('CSS selector of the anchor element'),\n state: z\n .enum(['visible', 'present', 'absent'])\n .describe('\"visible\" = in viewport, \"present\" = in DOM, \"absent\" = not in DOM'),\n})\n .describe(\"Fires based on a DOM element's visibility state. \" +\n 'Example: {\"type\": \"anchor_visible\", \"anchorId\": \"#cta-button\", \"state\": \"visible\"}');\nexport const EventOccurredConditionZ = z\n .object({\n type: z.literal('event_occurred'),\n eventName: z.string().describe('Event name (e.g. \"ui.click\", \"$pageview\")'),\n withinMs: z.number().optional().describe('Time window in ms. Omit = any time this session.'),\n})\n .describe('Fires when a specific event has occurred during this session. ' +\n 'Example: {\"type\": \"event_occurred\", \"eventName\": \"ui.click\", \"withinMs\": 5000}');\nexport const StateEqualsConditionZ = z\n .object({\n type: z.literal('state_equals'),\n key: z\n .string()\n .describe('Key in the SDK persistent state store (localStorage). Only valid for keys the host app explicitly sets via syntro.state.set().'),\n value: z.unknown().describe('Expected value to match against'),\n})\n .describe('Checks the SDK persistent state store (localStorage). ONLY for host-app state set via syntro.state.set() \u2014 ' +\n 'NOT for user attributes like region, device, or UTM params (those are handled by segment targeting). ' +\n 'Do NOT use this for targeting. If you do not know the valid state keys, do not use this condition type.');\nexport const ViewportConditionZ = z\n .object({\n type: z.literal('viewport'),\n minWidth: z.number().optional().describe('Minimum viewport width in pixels'),\n maxWidth: z.number().optional().describe('Maximum viewport width in pixels'),\n minHeight: z.number().optional().describe('Minimum viewport height in pixels'),\n maxHeight: z.number().optional().describe('Maximum viewport height in pixels'),\n})\n .describe('Fires based on viewport (screen) size. Use for responsive behavior. ' +\n 'Example: {\"type\": \"viewport\", \"minWidth\": 768} \u2014 fires on tablet and larger.');\nexport const SessionMetricConditionZ = z\n .object({\n type: z.literal('session_metric'),\n key: SessionMetricKeyZ,\n operator: z.enum(['gte', 'lte', 'eq', 'gt', 'lt']),\n threshold: z.number().describe('Numeric threshold to compare against'),\n})\n .describe('Fires when a session metric crosses a threshold. Valid keys: \"time_on_page\" (seconds), ' +\n '\"page_views\" (count), \"scroll_depth\" (0-100). ' +\n 'Example: {\"type\": \"session_metric\", \"key\": \"time_on_page\", \"operator\": \"gte\", \"threshold\": 30}');\nexport const DismissedConditionZ = z\n .object({\n type: z.literal('dismissed'),\n key: z.string().describe('Dismissal key (usually a tile or action ID)'),\n inverted: z\n .boolean()\n .optional()\n .describe('When true, fires if NOT dismissed (default behavior)'),\n})\n .describe('Checks if an item has been dismissed by the user. Use with inverted: true to show only if not dismissed.');\nexport const CooldownActiveConditionZ = z\n .object({\n type: z.literal('cooldown_active'),\n key: z.string().describe('Cooldown key'),\n inverted: z.boolean().optional().describe('When true, fires if cooldown is NOT active'),\n})\n .describe('Checks if a cooldown timer is currently active. Use to prevent showing the same intervention too frequently.');\nexport const FrequencyLimitConditionZ = z\n .object({\n type: z.literal('frequency_limit'),\n key: z.string().describe('Frequency counter key'),\n limit: z.number().describe('Maximum allowed count'),\n inverted: z.boolean().optional().describe('When true, fires if limit NOT reached'),\n})\n .describe('Checks if a frequency limit has been reached. Use to cap how many times an action fires per session.');\nexport const MatchOpZ = z\n .object({\n equals: z.union([z.string(), z.number(), z.boolean()]).optional(),\n contains: z.string().optional(),\n})\n .describe('Match operator for counter filters. Exactly one of equals or contains must be specified.');\nexport const CounterDefZ = z\n .object({\n events: z\n .array(CountableEventZ)\n .min(1)\n .describe('Event names to count. Use values from the countable events enum.'),\n match: z\n .record(z.string(), MatchOpZ)\n .optional()\n .describe('Property filters. Keys are event prop names or element-chain fields ' +\n '(tag_name, $el_text, attr__*). All entries AND together.'),\n})\n .describe('Defines what events to count. Registered as an accumulator predicate at config-load time.');\nexport const EventCountConditionZ = z\n .object({\n type: z.literal('event_count'),\n key: z.string().describe('Unique key for this counter (used for accumulator registration)'),\n operator: z.enum(['gte', 'lte', 'eq', 'gt', 'lt']),\n count: z.number().int().min(0).describe('Target count threshold'),\n withinMs: z\n .number()\n .positive()\n .optional()\n .describe('Time window in ms. Omit = count across entire session.'),\n counter: CounterDefZ.optional().describe('Inline counter definition. Defines what events to count.'),\n})\n .describe('Fires when accumulated event count crosses a threshold. Most powerful trigger type. ' +\n 'Example: {\"type\": \"event_count\", \"key\": \"pricing-clicks\", \"operator\": \"gte\", \"count\": 3, ' +\n '\"counter\": {\"events\": [\"ui.click\"], \"match\": {\"attr__data-cta\": {\"contains\": \"pricing\"}}}}');\nexport const ConditionZ = z.discriminatedUnion('type', [\n PageUrlConditionZ,\n RouteConditionZ,\n AnchorVisibleConditionZ,\n EventOccurredConditionZ,\n StateEqualsConditionZ,\n ViewportConditionZ,\n SessionMetricConditionZ,\n DismissedConditionZ,\n CooldownActiveConditionZ,\n FrequencyLimitConditionZ,\n EventCountConditionZ,\n]);\n// =============================================================================\n// STRATEGY SCHEMAS\n// =============================================================================\nexport const RuleZ = z\n .object({\n conditions: z\n .array(ConditionZ)\n .describe('Array of conditions \u2014 ALL must match (AND logic) for this rule to fire.'),\n value: z\n .unknown()\n .describe('Value returned when all conditions match. For triggerWhen: true = fire the action.'),\n})\n .describe('A single rule. ALL conditions must match (AND logic). Rules in a strategy are evaluated ' +\n 'top-to-bottom \u2014 first rule where all conditions match wins and returns its value.');\nexport const RuleStrategyZ = z\n .object({\n type: z.literal('rules'),\n rules: z\n .array(RuleZ)\n .describe('Ordered list of rules. Evaluated top-to-bottom \u2014 first match wins.'),\n default: z\n .unknown()\n .describe('Fallback value when no rule matches. For triggerWhen: false = do not fire by default.'),\n})\n .describe('Rule-based strategy. Evaluates rules top-to-bottom. First rule where ALL conditions match ' +\n 'returns its value. If no rule matches, returns default. ' +\n 'For triggerWhen: set value=true on matching rules, default=false.');\nexport const ScoreStrategyZ = z\n .object({\n type: z.literal('score'),\n field: z.string(),\n threshold: z.number(),\n above: z.unknown(),\n below: z.unknown(),\n})\n .describe('Score-based strategy. Compares a field value against a threshold.');\nexport const ModelStrategyZ = z\n .object({\n type: z.literal('model'),\n modelId: z.string(),\n inputs: z.array(z.string()),\n outputMapping: z.record(z.string(), z.unknown()),\n default: z.unknown(),\n})\n .describe('ML model strategy. Sends inputs to a model and maps outputs.');\nexport const ExternalStrategyZ = z\n .object({\n type: z.literal('external'),\n endpoint: z.string(),\n method: z.enum(['GET', 'POST']).optional(),\n default: z.unknown(),\n timeoutMs: z.number().optional(),\n})\n .describe('External API strategy. Calls an endpoint to determine the value.');\nexport const DecisionStrategyZ = z.discriminatedUnion('type', [\n RuleStrategyZ,\n ScoreStrategyZ,\n ModelStrategyZ,\n ExternalStrategyZ,\n]);\n/** Canonical Zod schema for the optional triggerWhen field on actions and adaptive items. */\nexport const TriggerWhenZ = DecisionStrategyZ.nullable().optional();\n// =============================================================================\n// TRIGGER DOCUMENTATION \u2014 examples and match field docs\n// Exported as constants so the schema generator can inject them into the\n// JSON schema. The Python prompt builder reads them from the schema.\n// =============================================================================\n/** Complete triggerWhen examples showing the full rules wrapper structure. */\nexport const TRIGGER_EXAMPLES = [\n {\n name: 'Click count on a specific element',\n description: 'Fire when user clicks an element with data-id=\"hero-cta\" 2+ times',\n triggerWhen: {\n type: 'rules',\n rules: [\n {\n conditions: [\n {\n type: 'event_count',\n key: 'cta-clicks',\n operator: 'gte',\n count: 2,\n counter: {\n events: ['ui.click'],\n match: { 'attr__data-id': { equals: 'hero-cta' } },\n },\n },\n ],\n value: true,\n },\n ],\n default: false,\n },\n },\n {\n name: 'Time on page threshold',\n description: 'Fire after user spends 30+ seconds on the page',\n triggerWhen: {\n type: 'rules',\n rules: [\n {\n conditions: [\n {\n type: 'session_metric',\n key: 'time_on_page',\n operator: 'gte',\n threshold: 30,\n },\n ],\n value: true,\n },\n ],\n default: false,\n },\n },\n {\n name: 'Element visible in viewport',\n description: 'Fire when a DOM element becomes visible',\n triggerWhen: {\n type: 'rules',\n rules: [\n {\n conditions: [\n {\n type: 'anchor_visible',\n anchorId: '#pricing-section',\n state: 'visible',\n },\n ],\n value: true,\n },\n ],\n default: false,\n },\n },\n {\n name: 'No trigger (fire immediately)',\n description: 'Action fires as soon as the segment matches \u2014 no in-session condition needed',\n triggerWhen: null,\n },\n];\n/** Documentation for counter.match field keys. */\nexport const MATCH_FIELD_DOCS = {\n tag_name: 'HTML tag name (e.g. \"button\", \"a\", \"input\")',\n $el_text: 'Visible text content of the element',\n 'attr__*': 'HTML attribute prefixed with attr__. Example: attr__data-id matches the data-id attribute, ' +\n 'attr__class matches the class attribute, attr__href matches the href attribute.',\n};\n// =============================================================================\n// EVENT SCOPE SCHEMA\n// =============================================================================\n/** Scopes a widget to specific events/URLs. */\nexport const EventScopeZ = z.object({\n events: z.array(z.string()),\n urlContains: z.string().optional(),\n props: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(),\n});\n// =============================================================================\n// NOTIFY SCHEMA\n// =============================================================================\n/** Toast notification config for triggerWhen transitions. */\nexport const NotifyZ = z\n .object({\n title: z.string().optional(),\n body: z.string().optional(),\n icon: z.string().optional(),\n})\n .nullable()\n .optional();\n", "/**\n * @license\n * Copyright 2021 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * The Context type defines a type brand to associate a key value with the context value type\n */\nexport type Context<KeyType, ValueType> = KeyType & {__context__: ValueType};\n\n/**\n * @deprecated use Context instead\n */\nexport type ContextKey<KeyType, ValueType> = Context<KeyType, ValueType>;\n\n/**\n * A helper type which can extract a Context value type from a Context type\n */\nexport type ContextType<Key extends Context<unknown, unknown>> =\n Key extends Context<unknown, infer ValueType> ? ValueType : never;\n\n/**\n * Creates a typed Context.\n *\n * Contexts are compared with strict equality.\n *\n * If you want two separate `createContext()` calls to referer to the same\n * context, then use a key that will by equal under strict equality like a\n * string for `Symbol.for()`:\n *\n * ```ts\n * // true\n * createContext('my-context') === createContext('my-context')\n * // true\n * createContext(Symbol.for('my-context')) === createContext(Symbol.for('my-context'))\n * ```\n *\n * If you want a context to be unique so that it's guaranteed to not collide\n * with other contexts, use a key that's unique under strict equality, like\n * a `Symbol()` or object.:\n *\n * ```\n * // false\n * createContext({}) === createContext({})\n * // false\n * createContext(Symbol('my-context')) === createContext(Symbol('my-context'))\n * ```\n *\n * @param key a context key value\n * @template ValueType the type of value that can be provided by this context.\n * @returns the context key value cast to `Context<K, ValueType>`\n */\nexport function createContext<ValueType, K = unknown>(key: K) {\n return key as Context<K, ValueType>;\n}\n", "/**\n * Canvas runtime context \u2014 the shared @lit/context symbol both\n * runtime-sdk (the provider) and canvas-sdk / canvas authors (the\n * consumers) use to thread a narrow runtime handle through the canvas\n * element tree.\n *\n * Living here keeps the symbol identity stable across both packages.\n * If canvas-sdk created its own symbol with `createContext(...)`, it\n * would never match the one runtime-sdk publishes, and `<sc-mount>`\n * would silently see `undefined` instead of the widget registry.\n *\n * The shape declared here is a NARROW VIEW of `SmartCanvasRuntime`.\n * Canvas-side code reads only this subset. The runtime-sdk's\n * `SmartCanvasRuntime` type is a structural superset.\n */\nimport { createContext } from '@lit/context';\n/**\n * The @lit/context symbol. Both runtime-sdk's ContextProvider and\n * canvas-sdk's ContextConsumer must import THIS exact symbol \u2014 not a\n * symbol with the same string name \u2014 for context propagation to work.\n */\nexport const canvasRuntimeContext = createContext('syntrologie:canvas-runtime');\n", "/**\n * Canonical route normalization. See `routes.md` for rules and\n * `normalize-route.cases.json` for the parity corpus shared with the\n * Python implementation in syntrologie_common/sdk/routing.py.\n *\n * Two exports \u2014 `normalizeRoute` for literal paths, `normalizeRoutePattern`\n * for activation patterns containing `*`, `**`, `:param`. Today they share\n * an implementation because the rules happen to be wildcard-safe (no\n * lowercase, unreserved-only decode, slash collapse preserves `**`).\n * The seam is preserved as separate exports so the API can diverge\n * without consumer churn if rules change.\n */\n// RFC 3986 reserved characters (gen-delims + sub-delims). When a `%XX`\n// sequence decodes to one of these bytes, we keep the percent-encoded\n// form \u2014 decoding would re-segment the path or change its meaning.\nconst RESERVED_BYTES = new Set([\n 0x21, // !\n 0x23, // #\n 0x24, // $\n 0x26, // &\n 0x27, // '\n 0x28, // (\n 0x29, // )\n 0x2a, // *\n 0x2b, // +\n 0x2c, // ,\n 0x2f, // /\n 0x3a, // :\n 0x3b, // ;\n 0x3d, // =\n 0x3f, // ?\n 0x40, // @\n 0x5b, // [\n 0x5d, // ]\n]);\nconst utf8Decoder = new TextDecoder('utf-8', { fatal: false });\n/** Decode `%XX` sequences for unreserved bytes only. Collapses\n * adjacent `%XX` runs into a UTF-8 decode so `%C3%A9` \u2192 `\u00E9`. */\nfunction decodeUnreservedOnly(input) {\n let out = '';\n let pending = [];\n const flushPending = () => {\n if (pending.length === 0)\n return;\n const bytes = new Uint8Array(pending);\n out += utf8Decoder.decode(bytes);\n pending = [];\n };\n let i = 0;\n while (i < input.length) {\n const ch = input[i];\n if (ch === '%' && i + 2 < input.length && isHex(input[i + 1]) && isHex(input[i + 2])) {\n const byte = parseInt(input.slice(i + 1, i + 3), 16);\n if (RESERVED_BYTES.has(byte)) {\n flushPending();\n // Keep raw, but normalize hex case to uppercase so the\n // canonical form is stable across input casing.\n out += `%${input.slice(i + 1, i + 3).toUpperCase()}`;\n i += 3;\n }\n else {\n pending.push(byte);\n i += 3;\n }\n }\n else {\n flushPending();\n out += ch;\n i += 1;\n }\n }\n flushPending();\n return out;\n}\nfunction isHex(c) {\n return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');\n}\n/** Strip query string and hash fragment. */\nfunction stripQueryAndHash(s) {\n const q = s.indexOf('?');\n if (q !== -1)\n s = s.slice(0, q);\n const h = s.indexOf('#');\n if (h !== -1)\n s = s.slice(0, h);\n return s;\n}\n/**\n * Normalize a literal path (e.g. `window.location.pathname`, an\n * action's `route` field, a wiki route key).\n *\n * Throws `TypeError` if the input is not an absolute path. Callers\n * that want a soft API should use {@link normalizeRouteWithChange}.\n */\nexport function normalizeRoute(path) {\n if (typeof path !== 'string' || path.length === 0) {\n throw new TypeError('normalizeRoute: input must be a non-empty string');\n }\n if (!path.startsWith('/')) {\n throw new TypeError(`normalizeRoute: input must be absolute (start with '/'); got ${JSON.stringify(path)}`);\n }\n let s = stripQueryAndHash(path);\n s = decodeUnreservedOnly(s);\n s = s.replace(/\\/+/g, '/');\n if (s.length > 1 && s.endsWith('/'))\n s = s.slice(0, -1);\n return s;\n}\n/**\n * Normalize an activation route pattern. Preserves `*`, `**`,\n * `:param` exactly. Today equivalent to {@link normalizeRoute} \u2014 kept\n * as a separate export so rules can diverge later without API churn.\n */\nexport function normalizeRoutePattern(pattern) {\n return normalizeRoute(pattern);\n}\n/**\n * Normalize a route and report whether the input was already\n * canonical. Used by authoring tools to decide whether to emit a\n * warning to the LLM.\n */\nexport function normalizeRouteWithChange(path) {\n const canonical = normalizeRoute(path);\n return { canonical, changed: canonical !== path };\n}\n/** Pattern-side counterpart of {@link normalizeRouteWithChange}. */\nexport function normalizeRoutePatternWithChange(pattern) {\n const canonical = normalizeRoutePattern(pattern);\n return { canonical, changed: canonical !== pattern };\n}\n/**\n * Case-insensitive comparison of two already-canonical paths. Use\n * this anywhere two routes are compared for equality (wiki lookups,\n * non-pattern action route gates) \u2014 preserves casing in the inputs\n * while honoring case-insensitive routing on the customer's site.\n */\nexport function routesMatch(a, b) {\n return a.toLowerCase() === b.toLowerCase();\n}\n", "/**\n * Shared event contract for LLM-mounted tile lifecycle.\n *\n * Producer: `adaptive-chatbot`'s `TileHandler` publishes one of three\n * events whenever the LLM mounts/patches/unmounts a tile.\n *\n * Consumer: `runtime-sdk`'s `SmartCanvasElementLit` subscribes and\n * merges the resulting tiles into its slot-routing pipeline.\n *\n * Replay: `runtime-sdk` publishes `TILE_REPLAY_REQUEST_EVENT` whenever\n * it (re)subscribes; `adaptive-chatbot`'s ElementInstanceStore catches\n * that and re-publishes `TILE_MOUNTED_EVENT` for every active tile.\n *\n * This module is the single source of truth for the event names AND\n * the payload shapes. Both packages import the constants and the\n * `parseTile{Mounted,Patched,Unmounted}EventProps` helpers. Renaming a\n * field here is a TypeScript error on both sides \u2014 no silent drift.\n */\nexport const TILE_MOUNTED_EVENT = 'element.tile_mounted';\nexport const TILE_PATCHED_EVENT = 'element.tile_patched';\nexport const TILE_UNMOUNTED_EVENT = 'element.tile_unmounted';\nexport const TILE_REPLAY_REQUEST_EVENT = 'element.tile_replay_request';\n/**\n * Defensive parser for the event payload. Returns null on missing /\n * malformed fields rather than throwing. Subscribers MUST run the\n * incoming `event.props` through this so a contract drift surfaces as\n * a no-op log line, not a render crash.\n */\nexport function parseTileMountedEventProps(raw) {\n if (!raw || typeof raw !== 'object')\n return null;\n const r = raw;\n const slot = typeof r.slot === 'string' ? r.slot : '';\n const instance_id = typeof r.instance_id === 'string' ? r.instance_id : '';\n const widget = typeof r.widget === 'string' ? r.widget : '';\n if (!slot || !instance_id || !widget)\n return null;\n const props = r.props && typeof r.props === 'object' ? r.props : {};\n return { slot, instance_id, widget, props };\n}\nexport function parseTileUnmountedEventProps(raw) {\n if (!raw || typeof raw !== 'object')\n return null;\n const r = raw;\n const slot = typeof r.slot === 'string' ? r.slot : '';\n const instance_id = typeof r.instance_id === 'string' ? r.instance_id : '';\n if (!instance_id)\n return null;\n return { slot, instance_id };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["createContext", "key"]
7
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Adaptive Chatbot — Editor (Lit web component).
3
+ *
4
+ * Custom element: <se-chatbot-editor>
5
+ *
6
+ * Lit port of editor.tsx. Form-based: edits backendUrl, mlflowRunId,
7
+ * greeting, maxHistory and emits change events. No sub-items, no list view.
8
+ *
9
+ * Properties:
10
+ * - `config: ChatbotConfig | undefined` — current chatbot tile props
11
+ * - `onChange: (updatedAppConfig) => void` — callback fired when a field changes
12
+ *
13
+ * Events (bubbling, composed):
14
+ * - `navigate-home` — back button
15
+ * - `dirty-change` (detail: { dirty: boolean }) — emit dirty=true on first edit
16
+ */
17
+ import { LitElement } from 'lit';
18
+ type AppConfig = Record<string, unknown>;
19
+ export declare class ChatbotEditorLit extends LitElement {
20
+ static properties: {
21
+ config: {
22
+ attribute: boolean;
23
+ };
24
+ onChange: {
25
+ attribute: boolean;
26
+ };
27
+ };
28
+ config: AppConfig | undefined;
29
+ onChange: ((updated: AppConfig) => void) | undefined;
30
+ private _emittedDirty;
31
+ createRenderRoot(): this;
32
+ private _handleField;
33
+ private _navigateHome;
34
+ render(): import("lit-html").TemplateResult<1>;
35
+ }
36
+ export {};
37
+ //# sourceMappingURL=editor-lit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-lit.d.ts","sourceRoot":"","sources":["../src/editor-lit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAIvC,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzC,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,OAAgB,UAAU;;;;;;;MAGxB;IAEF,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAErD,OAAO,CAAC,aAAa,CAAS;IAErB,gBAAgB;IAIzB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,aAAa;IAIZ,MAAM;CAkGhB"}
@@ -0,0 +1,134 @@
1
+ import "./chunk-UVKRO5ER.js";
2
+
3
+ // src/editor-lit.ts
4
+ import { html, LitElement } from "lit";
5
+ var ChatbotEditorLit = class extends LitElement {
6
+ constructor() {
7
+ super(...arguments);
8
+ this._emittedDirty = false;
9
+ }
10
+ createRenderRoot() {
11
+ return this;
12
+ }
13
+ _handleField(field, value) {
14
+ if (!this.config) return;
15
+ const next = { ...this.config, [field]: value };
16
+ this.onChange?.(next);
17
+ if (!this._emittedDirty) {
18
+ this._emittedDirty = true;
19
+ this.dispatchEvent(
20
+ new CustomEvent("dirty-change", {
21
+ detail: { dirty: true },
22
+ bubbles: true,
23
+ composed: true
24
+ })
25
+ );
26
+ }
27
+ }
28
+ _navigateHome() {
29
+ this.dispatchEvent(new CustomEvent("navigate-home", { bubbles: true, composed: true }));
30
+ }
31
+ render() {
32
+ const cfg = this.config ?? {};
33
+ return html`
34
+ <div class="se-flex se-flex-col se-h-full se-font-sans">
35
+ <!-- Header -->
36
+ <div class="se-px-4 se-pt-3 se-pb-1 se-flex se-items-center se-gap-3">
37
+ <button
38
+ type="button"
39
+ @click=${() => this._navigateHome()}
40
+ class="se-py-1.5 se-px-3 se-rounded-md se-border-none se-bg-card-bg se-text-text-primary se-text-sm se-cursor-pointer"
41
+ >← Back</button>
42
+ <div class="se-flex se-flex-col">
43
+ <h2 class="se-m-0 se-text-base se-font-semibold se-text-text-primary">Chat Assistant</h2>
44
+ <p class="se-mt-0.5 se-mb-0 se-text-xs se-text-text-secondary">
45
+ Configure AI chat assistant
46
+ </p>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="se-flex-1 se-overflow-auto se-px-4 se-py-3">
51
+ <!-- API Configuration -->
52
+ <div class="se-mb-6">
53
+ <div
54
+ class="se-text-xs se-font-semibold se-text-text-secondary se-uppercase se-tracking-wide se-mb-3"
55
+ >
56
+ API Configuration
57
+ </div>
58
+
59
+ <label class="se-block se-mb-3">
60
+ <span class="se-block se-text-xs se-text-text-secondary se-mb-1">Backend URL</span>
61
+ <input
62
+ type="text"
63
+ .value=${cfg.backendUrl ?? ""}
64
+ placeholder="/api/chat/message"
65
+ class="se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm focus:se-outline-none focus:se-border-input-field-border-selected"
66
+ @input=${(e) => this._handleField("backendUrl", e.target.value)}
67
+ />
68
+ </label>
69
+
70
+ <label class="se-block se-mb-3">
71
+ <span class="se-block se-text-xs se-text-text-secondary se-mb-1">
72
+ MLflow Run ID (optional)
73
+ </span>
74
+ <input
75
+ type="text"
76
+ .value=${cfg.mlflowRunId ?? ""}
77
+ placeholder="e.g., abc123"
78
+ class="se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm focus:se-outline-none focus:se-border-input-field-border-selected"
79
+ @input=${(e) => this._handleField("mlflowRunId", e.target.value)}
80
+ />
81
+ </label>
82
+ </div>
83
+
84
+ <!-- Chat Settings -->
85
+ <div class="se-mb-6">
86
+ <div
87
+ class="se-text-xs se-font-semibold se-text-text-secondary se-uppercase se-tracking-wide se-mb-3"
88
+ >
89
+ Chat Settings
90
+ </div>
91
+
92
+ <label class="se-block se-mb-3">
93
+ <span class="se-block se-text-xs se-text-text-secondary se-mb-1">Greeting Message</span>
94
+ <textarea
95
+ aria-label="Greeting Message"
96
+ .value=${cfg.greeting ?? ""}
97
+ placeholder="Hi! How can I help?"
98
+ rows="2"
99
+ class="se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm se-resize-none focus:se-outline-none focus:se-border-input-field-border-selected"
100
+ @input=${(e) => this._handleField("greeting", e.target.value)}
101
+ ></textarea>
102
+ </label>
103
+
104
+ <label class="se-block se-mb-3">
105
+ <span class="se-block se-text-xs se-text-text-secondary se-mb-1">
106
+ Max History (messages sent to backend)
107
+ </span>
108
+ <input
109
+ type="number"
110
+ .value=${String(cfg.maxHistory ?? 20)}
111
+ min="1"
112
+ max="100"
113
+ class="se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm focus:se-outline-none focus:se-border-input-field-border-selected"
114
+ @input=${(e) => {
115
+ const n = parseInt(e.target.value, 10);
116
+ if (!Number.isNaN(n)) this._handleField("maxHistory", n);
117
+ }}
118
+ />
119
+ </label>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ `;
124
+ }
125
+ };
126
+ ChatbotEditorLit.properties = {
127
+ config: { attribute: false },
128
+ onChange: { attribute: false }
129
+ };
130
+ customElements.define("se-chatbot-editor", ChatbotEditorLit);
131
+ export {
132
+ ChatbotEditorLit
133
+ };
134
+ //# sourceMappingURL=editor-lit.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/editor-lit.ts"],
4
+ "sourcesContent": ["/**\n * Adaptive Chatbot \u2014 Editor (Lit web component).\n *\n * Custom element: <se-chatbot-editor>\n *\n * Lit port of editor.tsx. Form-based: edits backendUrl, mlflowRunId,\n * greeting, maxHistory and emits change events. No sub-items, no list view.\n *\n * Properties:\n * - `config: ChatbotConfig | undefined` \u2014 current chatbot tile props\n * - `onChange: (updatedAppConfig) => void` \u2014 callback fired when a field changes\n *\n * Events (bubbling, composed):\n * - `navigate-home` \u2014 back button\n * - `dirty-change` (detail: { dirty: boolean }) \u2014 emit dirty=true on first edit\n */\n\nimport { html, LitElement } from 'lit';\n\nimport type { ChatbotConfig } from './types';\n\ntype AppConfig = Record<string, unknown>;\n\nexport class ChatbotEditorLit extends LitElement {\n static override properties = {\n config: { attribute: false },\n onChange: { attribute: false },\n };\n\n config: AppConfig | undefined;\n onChange: ((updated: AppConfig) => void) | undefined;\n\n private _emittedDirty = false;\n\n override createRenderRoot() {\n return this;\n }\n\n private _handleField(field: keyof ChatbotConfig, value: string | number) {\n if (!this.config) return;\n const next = { ...(this.config as Partial<ChatbotConfig>), [field]: value };\n this.onChange?.(next as AppConfig);\n\n if (!this._emittedDirty) {\n this._emittedDirty = true;\n this.dispatchEvent(\n new CustomEvent('dirty-change', {\n detail: { dirty: true },\n bubbles: true,\n composed: true,\n })\n );\n }\n }\n\n private _navigateHome() {\n this.dispatchEvent(new CustomEvent('navigate-home', { bubbles: true, composed: true }));\n }\n\n override render() {\n const cfg = (this.config ?? {}) as Partial<ChatbotConfig>;\n\n return html`\n <div class=\"se-flex se-flex-col se-h-full se-font-sans\">\n <!-- Header -->\n <div class=\"se-px-4 se-pt-3 se-pb-1 se-flex se-items-center se-gap-3\">\n <button\n type=\"button\"\n @click=${() => this._navigateHome()}\n class=\"se-py-1.5 se-px-3 se-rounded-md se-border-none se-bg-card-bg se-text-text-primary se-text-sm se-cursor-pointer\"\n >\u2190 Back</button>\n <div class=\"se-flex se-flex-col\">\n <h2 class=\"se-m-0 se-text-base se-font-semibold se-text-text-primary\">Chat Assistant</h2>\n <p class=\"se-mt-0.5 se-mb-0 se-text-xs se-text-text-secondary\">\n Configure AI chat assistant\n </p>\n </div>\n </div>\n\n <div class=\"se-flex-1 se-overflow-auto se-px-4 se-py-3\">\n <!-- API Configuration -->\n <div class=\"se-mb-6\">\n <div\n class=\"se-text-xs se-font-semibold se-text-text-secondary se-uppercase se-tracking-wide se-mb-3\"\n >\n API Configuration\n </div>\n\n <label class=\"se-block se-mb-3\">\n <span class=\"se-block se-text-xs se-text-text-secondary se-mb-1\">Backend URL</span>\n <input\n type=\"text\"\n .value=${cfg.backendUrl ?? ''}\n placeholder=\"/api/chat/message\"\n class=\"se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm focus:se-outline-none focus:se-border-input-field-border-selected\"\n @input=${(e: Event) =>\n this._handleField('backendUrl', (e.target as HTMLInputElement).value)}\n />\n </label>\n\n <label class=\"se-block se-mb-3\">\n <span class=\"se-block se-text-xs se-text-text-secondary se-mb-1\">\n MLflow Run ID (optional)\n </span>\n <input\n type=\"text\"\n .value=${cfg.mlflowRunId ?? ''}\n placeholder=\"e.g., abc123\"\n class=\"se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm focus:se-outline-none focus:se-border-input-field-border-selected\"\n @input=${(e: Event) =>\n this._handleField('mlflowRunId', (e.target as HTMLInputElement).value)}\n />\n </label>\n </div>\n\n <!-- Chat Settings -->\n <div class=\"se-mb-6\">\n <div\n class=\"se-text-xs se-font-semibold se-text-text-secondary se-uppercase se-tracking-wide se-mb-3\"\n >\n Chat Settings\n </div>\n\n <label class=\"se-block se-mb-3\">\n <span class=\"se-block se-text-xs se-text-text-secondary se-mb-1\">Greeting Message</span>\n <textarea\n aria-label=\"Greeting Message\"\n .value=${cfg.greeting ?? ''}\n placeholder=\"Hi! How can I help?\"\n rows=\"2\"\n class=\"se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm se-resize-none focus:se-outline-none focus:se-border-input-field-border-selected\"\n @input=${(e: Event) =>\n this._handleField('greeting', (e.target as HTMLTextAreaElement).value)}\n ></textarea>\n </label>\n\n <label class=\"se-block se-mb-3\">\n <span class=\"se-block se-text-xs se-text-text-secondary se-mb-1\">\n Max History (messages sent to backend)\n </span>\n <input\n type=\"number\"\n .value=${String(cfg.maxHistory ?? 20)}\n min=\"1\"\n max=\"100\"\n class=\"se-w-full se-py-2 se-px-3 se-rounded-md se-border se-border-input-field-border se-bg-input-field-bg se-text-text-primary se-text-sm focus:se-outline-none focus:se-border-input-field-border-selected\"\n @input=${(e: Event) => {\n const n = parseInt((e.target as HTMLInputElement).value, 10);\n if (!Number.isNaN(n)) this._handleField('maxHistory', n);\n }}\n />\n </label>\n </div>\n </div>\n </div>\n `;\n }\n}\n\ncustomElements.define('se-chatbot-editor', ChatbotEditorLit);\n"],
5
+ "mappings": ";;;AAiBA,SAAS,MAAM,kBAAkB;AAM1B,IAAM,mBAAN,cAA+B,WAAW;AAAA,EAA1C;AAAA;AASL,SAAQ,gBAAgB;AAAA;AAAA,EAEf,mBAAmB;AAC1B,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,OAA4B,OAAwB;AACvE,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,OAAO,EAAE,GAAI,KAAK,QAAmC,CAAC,KAAK,GAAG,MAAM;AAC1E,SAAK,WAAW,IAAiB;AAEjC,QAAI,CAAC,KAAK,eAAe;AACvB,WAAK,gBAAgB;AACrB,WAAK;AAAA,QACH,IAAI,YAAY,gBAAgB;AAAA,UAC9B,QAAQ,EAAE,OAAO,KAAK;AAAA,UACtB,SAAS;AAAA,UACT,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB;AACtB,SAAK,cAAc,IAAI,YAAY,iBAAiB,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AAAA,EACxF;AAAA,EAES,SAAS;AAChB,UAAM,MAAO,KAAK,UAAU,CAAC;AAE7B,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMU,MAAM,KAAK,cAAc,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAwBtB,IAAI,cAAc,EAAE;AAAA;AAAA;AAAA,yBAGpB,CAAC,MACR,KAAK,aAAa,cAAe,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAU9D,IAAI,eAAe,EAAE;AAAA;AAAA;AAAA,yBAGrB,CAAC,MACR,KAAK,aAAa,eAAgB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAiB/D,IAAI,YAAY,EAAE;AAAA;AAAA;AAAA;AAAA,yBAIlB,CAAC,MACR,KAAK,aAAa,YAAa,EAAE,OAA+B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAU/D,OAAO,IAAI,cAAc,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA,yBAI5B,CAAC,MAAa;AACrB,YAAM,IAAI,SAAU,EAAE,OAA4B,OAAO,EAAE;AAC3D,UAAI,CAAC,OAAO,MAAM,CAAC,EAAG,MAAK,aAAa,cAAc,CAAC;AAAA,IACzD,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOf;AACF;AAtIa,iBACK,aAAa;AAAA,EAC3B,QAAQ,EAAE,WAAW,MAAM;AAAA,EAC3B,UAAU,EAAE,WAAW,MAAM;AAC/B;AAoIF,eAAe,OAAO,qBAAqB,gBAAgB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Action element handler — dispatches an ActionStep through
3
+ * `ActionEngine.applyBatch`.
4
+ *
5
+ * The `content` field of an action `MountedElement` carries the action's
6
+ * params; the executor `kind` comes from the template (which the SDK
7
+ * doesn't have locally yet — for v1 the template's `kind` is encoded
8
+ * into `content.__kind`, set by the backend tool). When proper
9
+ * template loading lands on the SDK side, this handler resolves the
10
+ * kind from the loaded template instead.
11
+ *
12
+ * **Imperative actions never re-fire on boot.** The `lifecycle` field
13
+ * here is `imperative` — `ElementInstanceStore` skips boot rehydrate
14
+ * for imperative instances with `state === 'applied'`. The backend
15
+ * record exists for audit; replaying a scroll/navigate on every page
16
+ * load would be visibly wrong.
17
+ *
18
+ * Stateful actions (e.g. `content:insertHtml`, `content:setText`,
19
+ * `content:addClass` once Phase 7's renderer lands) ARE re-applied on
20
+ * boot. v1 supports the imperative shape; stateful action handling
21
+ * waits on the Portable Text renderer.
22
+ */
23
+ import type { ElementHandlerContext, ElementTypeHandler, ValidateResult } from './ElementTypeHandler';
24
+ import type { MountedElement } from './types';
25
+ export declare class ActionHandler implements ElementTypeHandler {
26
+ readonly typeName: "action";
27
+ readonly lifecycle: "imperative";
28
+ validate(instance: MountedElement, _ctx: ElementHandlerContext): ValidateResult;
29
+ mount(instance: MountedElement, ctx: ElementHandlerContext): Promise<void>;
30
+ patch(instance: MountedElement, ctx: ElementHandlerContext): Promise<void>;
31
+ unmount(_instance: MountedElement, _ctx: ElementHandlerContext): Promise<void>;
32
+ private _actionFromInstance;
33
+ }
34
+ //# sourceMappingURL=ActionHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionHandler.d.ts","sourceRoot":"","sources":["../../src/elements/ActionHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EACV,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,qBAAa,aAAc,YAAW,kBAAkB;IACtD,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAGtC,QAAQ,CAAC,SAAS,EAAG,YAAY,CAAU;IAE3C,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,qBAAqB,GAAG,cAAc;IAWzE,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1E,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1E,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpF,OAAO,CAAC,mBAAmB;CAiC5B"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Type-neutral store for LLM-authored UI element instances — Phase 6.
3
+ *
4
+ * On SDK boot:
5
+ * 1. Caller fetches `/api/adaptive/mounted_elements` (see `fetcher.ts`).
6
+ * 2. Calls `store.hydrate(response.mounted_elements)`.
7
+ * 3. The store iterates each instance, looks up its handler, and
8
+ * either mounts (stateful) or skips (imperative already-applied).
9
+ *
10
+ * During chat turns:
11
+ * - AGUI `syntro.element.mutation` envelopes arrive via
12
+ * `AgUiTransport.onA2UIEvent`. The transport caller decodes the
13
+ * envelope and invokes `store.apply(envelope.mutations)`.
14
+ *
15
+ * Concurrency / dedup:
16
+ * - Per-instance `version` is the dedup key. A mutation whose version
17
+ * is `<= currentVersion` is treated as already-applied and silently
18
+ * dropped — handles the SSE-during-boot-fetch race per the design
19
+ * doc (the live mutation might arrive before the boot snapshot does,
20
+ * and the snapshot is then a no-op).
21
+ * - The store is single-threaded by Node/browser convention; no
22
+ * cross-tab sync in v1.
23
+ *
24
+ * The store delegates all DOM work to per-type handlers
25
+ * (`ElementTypeHandler`). It owns the registry, the in-memory state,
26
+ * and the dispatch logic.
27
+ */
28
+ import type { ActionEngine } from '../types';
29
+ import type { ElementTypeHandler } from './ElementTypeHandler';
30
+ import type { ElementMutation, MountedElement } from './types';
31
+ export interface ElementInstanceStoreOptions {
32
+ actions: ActionEngine;
33
+ /** Runtime's event bus. ItemHandler publishes
34
+ * `element.compositional_append` events here so container widgets
35
+ * (chips strip, FAQ accordion, nav tips) can subscribe and inject
36
+ * LLM-authored items into their compositional-actions lists.
37
+ *
38
+ * When `subscribe` is also provided, the store listens for
39
+ * `element.compositional_replay_request` events. A container widget
40
+ * publishes this event with its `tile_id` whenever it subscribes
41
+ * (e.g. on first mount AND on SPA-navigation remount); the store
42
+ * responds by re-publishing `element.compositional_append` for every
43
+ * matching item still in its in-memory map. This is what makes
44
+ * LLM-authored items persist across navigations within the page
45
+ * session — the store survives chat-bar unmount/remount, container
46
+ * widgets re-pull on each fresh mount.
47
+ */
48
+ events?: {
49
+ publish: (name: string, props?: Record<string, unknown>) => void;
50
+ /**
51
+ * Overloaded to match the runtime SDK's `EventBus.subscribe`:
52
+ * pass `{names:[...]}` to filter, or a callback to receive every
53
+ * event. The store uses the filtered form so it doesn't fan
54
+ * unrelated traffic (PostHog autocapture, every action lifecycle
55
+ * event) into a string-compare on each delivery.
56
+ */
57
+ subscribe?: {
58
+ (filter: {
59
+ names?: string[];
60
+ }, handler: (event: {
61
+ name: string;
62
+ props?: Record<string, unknown>;
63
+ }) => void): () => void;
64
+ (handler: (event: {
65
+ name: string;
66
+ props?: Record<string, unknown>;
67
+ }) => void): () => void;
68
+ };
69
+ };
70
+ handlers?: ElementTypeHandler[];
71
+ /** Override the logger — used by tests to capture log output. */
72
+ logger?: Pick<Console, 'info' | 'warn' | 'error'>;
73
+ /**
74
+ * Optional template→widget resolver used by the rehydrate replay.
75
+ * Without this, replayed tile mounts emit ``widget: template_id``,
76
+ * which only works when the admin's template ids match the widget
77
+ * registry (e.g. ``adaptive-faq:accordion``). When an admin uses a
78
+ * friendly id like ``product-card`` mapping to widget
79
+ * ``adaptive-product:card``, the rehydrate path needs the resolver
80
+ * to match the live mount path.
81
+ *
82
+ * Same shape as ``TileHandler``'s resolver — pass the same function
83
+ * to both so live mounts and replays agree on the widget id.
84
+ */
85
+ resolveTileWidget?: (templateId: string) => string | undefined;
86
+ }
87
+ export declare class ElementInstanceStore {
88
+ private readonly _actions;
89
+ private readonly _events;
90
+ private readonly _handlers;
91
+ private readonly _instances;
92
+ private readonly _logger;
93
+ private readonly _resolveTileWidget?;
94
+ /** Active TTL timeout — replaced on each call to `scheduleClientTtl`. */
95
+ private _ttlTimer;
96
+ constructor(options: ElementInstanceStoreOptions);
97
+ /**
98
+ * Listen for `element.compositional_replay_request` from container
99
+ * widgets and re-publish `element.compositional_append` for every
100
+ * matching item still tracked in `_instances`. This keeps LLM-authored
101
+ * items visible across SPA navigations: the store is a module-level
102
+ * singleton that survives chat-bar unmount/remount, so when a fresh
103
+ * chips-strip mounts and subscribes, asking for a replay re-populates
104
+ * its chip array.
105
+ */
106
+ private _subscribeReplayRequests;
107
+ private _replayItems;
108
+ private _replayTiles;
109
+ registerHandler(handler: ElementTypeHandler): void;
110
+ /**
111
+ * Apply the server-provided boot snapshot. For each instance:
112
+ * - stateful: validated + mounted via the type handler;
113
+ * - imperative + already-applied: recorded only (no DOM action);
114
+ * - any: tracked in the in-memory map for future patches.
115
+ *
116
+ * Safe to call once on SDK init. Calling again would re-mount
117
+ * stateful instances; callers should not.
118
+ */
119
+ hydrate(snapshot: MountedElement[]): Promise<void>;
120
+ /**
121
+ * Re-publish `element.tile_mounted` / `element.compositional_append`
122
+ * for every active LLM-authored instance in the store. Idempotent —
123
+ * receivers key by `instance_id` (tiles) or by widget identity
124
+ * (items via tile_id filter).
125
+ */
126
+ private _broadcastActive;
127
+ /**
128
+ * Apply a batch of mutations, atomically per-batch. Each mutation is
129
+ * version-checked (mount: must not conflict with existing instance;
130
+ * patch: resulting_version must be > current; unmount: idempotent).
131
+ */
132
+ apply(mutations: ElementMutation[]): Promise<void>;
133
+ /** Read-only snapshot of currently-known instances. */
134
+ getInstances(): MountedElement[];
135
+ getInstance(instance_id: string): MountedElement | undefined;
136
+ /**
137
+ * Schedule a client-side TTL that unmounts every active stateful
138
+ * instance when the server-side session expires. Replaces any
139
+ * previously-scheduled TTL.
140
+ *
141
+ * Avoids the orphan-window where session-expired tiles linger on the
142
+ * page until manual refresh — the server forgets at the 4h mark and
143
+ * the SDK tears down concurrently. Re-schedule on each boot fetch /
144
+ * mutation event that carries a refreshed `session_expires_at`.
145
+ *
146
+ * Pass `null` to clear the existing timer without scheduling a new one.
147
+ * Pass a past timestamp to trigger cleanup immediately.
148
+ */
149
+ scheduleClientTtl(session_expires_at: string | null): void;
150
+ private _handleSessionExpiry;
151
+ private _applyOne;
152
+ private _mount;
153
+ private _ctx;
154
+ }
155
+ //# sourceMappingURL=ElementInstanceStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElementInstanceStore.d.ts","sourceRoot":"","sources":["../../src/elements/ElementInstanceStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAyB,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK/D,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,YAAY,CAAC;IACtB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;QACjE;;;;;;WAMG;QACH,SAAS,CAAC,EAAE;YACV,CACE,MAAM,EAAE;gBAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;aAAE,EAC5B,OAAO,EAAE,CAAC,KAAK,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,KAAK,IAAI,GAC1E,MAAM,IAAI,CAAC;YACd,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;SAC3F,CAAC;KACH,CAAC;IACF,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAChC,iEAAiE;IACjE,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAClD;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAChE;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;IACnE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAA6C;IACjF,yEAAyE;IACzE,OAAO,CAAC,SAAS,CAA8C;gBAEnD,OAAO,EAAE,2BAA2B;IAYhD;;;;;;;;OAQG;IACH,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,YAAY;IAepB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAIlD;;;;;;;;OAQG;IACG,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CxD;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAiBxB;;;;OAIG;IACG,KAAK,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxD,uDAAuD;IACvD,YAAY,IAAI,cAAc,EAAE;IAIhC,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI5D;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;YAuB5C,oBAAoB;YAkBpB,SAAS;YAsGT,MAAM;IAyBpB,OAAO,CAAC,IAAI;CAGb"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ElementInstanceStore.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElementInstanceStore.test.d.ts","sourceRoot":"","sources":["../../src/elements/ElementInstanceStore.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Per-type handler interface for `ElementInstanceStore`.
3
+ *
4
+ * Adding a future element type (overlay / tour / form) is one new
5
+ * `ElementTypeHandler` implementation registered in the store —
6
+ * `ElementInstanceStore` itself stays type-neutral.
7
+ *
8
+ * Handlers own their per-type lifecycle. They receive the current
9
+ * `MountedElement` snapshot and the runtime's `ActionEngine` and either
10
+ * call `applyBatch` to drive DOM changes or hold on to returned
11
+ * `ActionHandle`s for later cleanup.
12
+ *
13
+ * Design choices the handlers MUST honor:
14
+ *
15
+ * - **Imperative actions never re-fire on boot.** When the store
16
+ * hydrates an element with `lifecycle === 'imperative'` and `state ===
17
+ * 'applied'`, the handler's `mount()` is NOT called. The backend
18
+ * records the prior invocation for audit but the SDK does not replay
19
+ * it (would re-scroll, re-navigate, etc.).
20
+ * - **Defense-in-depth content validation.** `validate()` is called
21
+ * before every mount/patch. The backend already validated, but the
22
+ * handler should refuse malformed content so a buggy server can't
23
+ * crash the runtime.
24
+ */
25
+ import type { ActionEngine } from '../types';
26
+ import type { ElementMutation, MountedElement } from './types';
27
+ /** Lifecycle classification used to decide whether to apply on boot rehydrate. */
28
+ export type ElementLifecycle = 'stateful' | 'imperative' | 'ephemeral';
29
+ export interface ElementHandlerContext {
30
+ /** Runtime's ActionEngine — handlers use `applyBatch` to drive DOM
31
+ * changes via existing executors (`core:mountWidget`, etc.). */
32
+ actions: ActionEngine;
33
+ /** Runtime's event bus — handlers publish typed events that container
34
+ * widgets subscribe to. Used by `ItemHandler` to broadcast
35
+ * `element.compositional_append` so chip-strip / FAQ / nav-tips
36
+ * containers can insert LLM-authored items.
37
+ * Optional so test fixtures that exercise only DOM action handlers
38
+ * don't need to stub the bus.
39
+ */
40
+ events?: {
41
+ publish: (name: string, props?: Record<string, unknown>) => void;
42
+ };
43
+ }
44
+ export type ValidateResult = {
45
+ accepted: true;
46
+ } | {
47
+ accepted: false;
48
+ reason: string;
49
+ detail?: string;
50
+ };
51
+ export interface ElementTypeHandler {
52
+ readonly typeName: 'tile' | 'action' | 'item';
53
+ /** Whether the handler's elements survive a boot rehydrate. Imperative
54
+ * handlers (action handler in v1) DO NOT replay applied instances. */
55
+ readonly lifecycle: ElementLifecycle;
56
+ /** Defense-in-depth — refuse malformed content/placement before the
57
+ * handler touches the DOM. The store calls this before `mount` and
58
+ * `patch`; a rejection is logged but does not throw — the store
59
+ * records the rejection on the instance and skips the apply. */
60
+ validate(instance: MountedElement, ctx: ElementHandlerContext): ValidateResult;
61
+ /** Apply a new mount to the DOM. Called once per mount; the store
62
+ * passes the instance object so the handler can read `placement`,
63
+ * `content`, `template_id`, etc. */
64
+ mount(instance: MountedElement, ctx: ElementHandlerContext): Promise<void>;
65
+ /** Apply a patch — typically by re-mounting the widget with merged
66
+ * content. v1 has no fine-grained reactivity; full re-mount is
67
+ * expected. */
68
+ patch(instance: MountedElement, ctx: ElementHandlerContext): Promise<void>;
69
+ /** Remove the element from the DOM. Idempotent — called for both
70
+ * user-initiated unmounts and TTL-triggered cleanup. */
71
+ unmount(instance: MountedElement, ctx: ElementHandlerContext): Promise<void>;
72
+ }
73
+ export interface ElementMutationContext extends ElementHandlerContext {
74
+ /** Op being processed — handler-side telemetry / debug surface. */
75
+ mutation: ElementMutation;
76
+ }
77
+ //# sourceMappingURL=ElementTypeHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElementTypeHandler.d.ts","sourceRoot":"","sources":["../../src/elements/ElementTypeHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/D,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,qBAAqB;IACpC;qEACiE;IACjE,OAAO,EAAE,YAAY,CAAC;IACtB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KAClE,CAAC;CACH;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAClB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IAE9C;2EACuE;IACvE,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IAErC;;;qEAGiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,cAAc,CAAC;IAE/E;;yCAEqC;IACrC,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;;oBAEgB;IAChB,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3E;6DACyD;IACzD,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,MAAM,WAAW,sBAAuB,SAAQ,qBAAqB;IACnE,mEAAmE;IACnE,QAAQ,EAAE,eAAe,CAAC;CAC3B"}