@mgamadeus/ddd-agents 0.1.0-alpha.21 → 0.1.0-alpha.23

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 (143) hide show
  1. package/README.md +3 -2
  2. package/dist/chat.js +22 -72
  3. package/dist/chat.js.map +1 -1
  4. package/dist/chunks/{ConversationMarkdown-W7NHglmL.js → ConversationMarkdown-CJhAnuVa.js} +110 -8
  5. package/dist/chunks/ConversationMarkdown-CJhAnuVa.js.map +1 -0
  6. package/dist/chunks/{WebSearchResultsConversationWidget-BvnLWHyi.js → WebSearchResultsConversationWidget-DRBQvycE.js} +140 -1125
  7. package/dist/chunks/WebSearchResultsConversationWidget-DRBQvycE.js.map +1 -0
  8. package/dist/chunks/{canvasBodies-9SuF6NAB.js → canvasBodies-DLjDkviP.js} +9 -6
  9. package/dist/chunks/canvasBodies-DLjDkviP.js.map +1 -0
  10. package/dist/chunks/{canvas-behaviours-BRFR1ALE.js → decide-canvas-open-DBWoWtAC.js} +18 -2
  11. package/dist/chunks/decide-canvas-open-DBWoWtAC.js.map +1 -0
  12. package/dist/chunks/entity-detail-name-3A82gDAp.js +15 -0
  13. package/dist/chunks/entity-detail-name-3A82gDAp.js.map +1 -0
  14. package/dist/chunks/icon-names-Di6c4zLo.js +86 -0
  15. package/dist/chunks/icon-names-Di6c4zLo.js.map +1 -0
  16. package/dist/chunks/index-7Qc_3GbG.js +1046 -0
  17. package/dist/chunks/index-7Qc_3GbG.js.map +1 -0
  18. package/dist/chunks/{widget-image-readiness-signal-DeOuL89j.js → widget-image-readiness-signal-D3ci53xr.js} +2 -2
  19. package/dist/chunks/{widget-image-readiness-signal-DeOuL89j.js.map → widget-image-readiness-signal-D3ci53xr.js.map} +1 -1
  20. package/dist/chunks/{widget-name-resolver-DyIY6Zu4.js → widget-name-resolver-C8SfpiR5.js} +48 -116
  21. package/dist/chunks/widget-name-resolver-C8SfpiR5.js.map +1 -0
  22. package/dist/client-testing.js +68 -1
  23. package/dist/client-testing.js.map +1 -1
  24. package/dist/files/chat/Conversation.module.scss +268 -0
  25. package/dist/files/chat/ConversationViewBody/ConversationViewBody.module.scss +336 -0
  26. package/dist/files/chat/_conversation-tokens.scss +37 -0
  27. package/dist/files/image-render/WidgetImageRender.module.scss +22 -0
  28. package/dist/files/kit/ComposedViewConversationWidget.md +59 -0
  29. package/dist/files/kit/components/data/data.preview-fixtures.json +3298 -0
  30. package/dist/files/kit/components/embedding/widget.preview-fixtures.json +147 -0
  31. package/dist/files/kit/components/entity/entity-link.preview-fixtures.json +340 -0
  32. package/dist/files/kit/components/form/form.preview-fixtures.json +319 -0
  33. package/dist/files/kit/components/inputs/button.preview-fixtures.json +301 -0
  34. package/dist/files/kit/components/inputs/checkbox.preview-fixtures.json +35 -0
  35. package/dist/files/kit/components/inputs/date-picker.preview-fixtures.json +36 -0
  36. package/dist/files/kit/components/inputs/input.preview-fixtures.json +55 -0
  37. package/dist/files/kit/components/inputs/radio-group.preview-fixtures.json +76 -0
  38. package/dist/files/kit/components/inputs/select.preview-fixtures.json +314 -0
  39. package/dist/files/kit/components/inputs/slider.preview-fixtures.json +178 -0
  40. package/dist/files/kit/components/inputs/tabs.preview-fixtures.json +304 -0
  41. package/dist/files/kit/components/inputs/textarea.preview-fixtures.json +37 -0
  42. package/dist/files/kit/components/layout/layout.preview-fixtures.json +892 -0
  43. package/dist/files/kit/components/map/map.preview-fixtures.json +339 -0
  44. package/dist/files/kit/components/media/image-group.preview-fixtures.json +228 -0
  45. package/dist/files/kit/components/media/image.preview-fixtures.json +61 -0
  46. package/dist/files/kit/components/media/video-card/video-card.preview-fixtures.json +121 -0
  47. package/dist/files/kit/components/media/video.preview-fixtures.json +68 -0
  48. package/dist/files/kit/components/rich/code.preview-fixtures.json +105 -0
  49. package/dist/files/kit/components/rich/diagram.preview-fixtures.json +89 -0
  50. package/dist/files/kit/components/rich/math.preview-fixtures.json +152 -0
  51. package/dist/files/kit/components/rich/svg.preview-fixtures.json +243 -0
  52. package/dist/files/kit/components/text/badge.preview-fixtures.json +44 -0
  53. package/dist/files/kit/components/text/caption.preview-fixtures.json +31 -0
  54. package/dist/files/kit/components/text/favicon.preview-fixtures.json +69 -0
  55. package/dist/files/kit/components/text/label.preview-fixtures.json +48 -0
  56. package/dist/files/kit/components/text/link.preview-fixtures.json +103 -0
  57. package/dist/files/kit/components/text/markdown.preview-fixtures.json +29 -0
  58. package/dist/files/kit/components/text/source-ref.preview-fixtures.json +51 -0
  59. package/dist/files/kit/components/text/text.preview-fixtures.json +106 -0
  60. package/dist/files/kit/components/text/title.preview-fixtures.json +172 -0
  61. package/dist/files/kit/composed-view-widget-contract.json +88 -0
  62. package/dist/files/kit/composed-view.preview-fixtures.json +376 -0
  63. package/dist/files/renderer/conversation-widget-layout.module.scss +47 -0
  64. package/dist/files/renderer/widget-tree/composed-node-schema.json +3428 -0
  65. package/dist/files/styles/_conversation-widget-container.scss +6 -0
  66. package/dist/files/styles/_media.scss +50 -0
  67. package/dist/files/styles/_spacings.scss +23 -0
  68. package/dist/files/styles/_surfaces.scss +28 -0
  69. package/dist/files/widgets/ClockConversationWidget/ClockConversationWidget.md +53 -0
  70. package/dist/files/widgets/ClockConversationWidget/clock.preview-fixtures.json +76 -0
  71. package/dist/files/widgets/ConceptExplainerConversationWidget/ConceptExplainerConversationWidget.md +86 -0
  72. package/dist/files/widgets/ConceptExplainerConversationWidget/concept-explainer.preview-fixtures.json +23 -0
  73. package/dist/files/widgets/ConversationSearchResultsConversationWidget/ConversationSearchResultsConversationWidget.md +59 -0
  74. package/dist/files/widgets/ConversationSearchResultsConversationWidget/conversation-search-results.preview-fixtures.json +85 -0
  75. package/dist/files/widgets/CurrencyConverterConversationWidget/CurrencyConverterConversationWidget.md +51 -0
  76. package/dist/files/widgets/CurrencyConverterConversationWidget/currency-converter.preview-fixtures.json +73 -0
  77. package/dist/files/widgets/CustomVisualizationConversationWidget/CustomVisualizationConversationWidget.md +83 -0
  78. package/dist/files/widgets/CustomVisualizationConversationWidget/custom-visualization.preview-fixtures.json +227 -0
  79. package/dist/files/widgets/CustomVisualizationConversationWidget/sandbox-frame/custom-visualization-frame.html +188 -0
  80. package/dist/files/widgets/EntityMentionConversationWidget/EntityMentionConversationWidget.md +55 -0
  81. package/dist/files/widgets/EntityMentionConversationWidget/entity-mention.preview-fixtures.json +55 -0
  82. package/dist/files/widgets/MultiChoiceConversationWidget/MultiChoiceConversationWidget.md +61 -0
  83. package/dist/files/widgets/MultiChoiceConversationWidget/multi-choice-widget-contract.json +43 -0
  84. package/dist/files/widgets/MultiChoiceConversationWidget/multi-choice.preview-fixtures.json +103 -0
  85. package/dist/files/widgets/QuickRepliesConversationWidget/QuickRepliesConversationWidget.md +65 -0
  86. package/dist/files/widgets/QuickRepliesConversationWidget/quick-replies-widget-contract.json +43 -0
  87. package/dist/files/widgets/QuickRepliesConversationWidget/quick-replies.preview-fixtures.json +45 -0
  88. package/dist/files/widgets/SuggestedActions/SuggestedActions.md +60 -0
  89. package/dist/files/widgets/SuggestedActions/suggested-actions.preview-fixtures.json +19 -0
  90. package/dist/files/widgets/ToolTraceConversationWidget/ToolTraceConversationWidget.md +48 -0
  91. package/dist/files/widgets/ToolTraceConversationWidget/tool-trace.preview-fixtures.json +32 -0
  92. package/dist/files/widgets/WebSearchResultsConversationWidget/WebSearchResultsConversationWidget.md +49 -0
  93. package/dist/files/widgets/WebSearchResultsConversationWidget/web-search-results.preview-fixtures.json +57 -0
  94. package/dist/files/widgets/WritingDraftConversationWidget/WritingDraftConversationWidget.md +66 -0
  95. package/dist/files/widgets/WritingDraftConversationWidget/writing-draft.preview-fixtures.json +129 -0
  96. package/dist/image-render.js +11 -10
  97. package/dist/image-render.js.map +1 -1
  98. package/dist/index.js +32 -28
  99. package/dist/index.js.map +1 -1
  100. package/dist/kit.js +11 -2
  101. package/dist/kit.js.map +1 -1
  102. package/dist/preview.js +7 -6
  103. package/dist/provider.js +71 -0
  104. package/dist/provider.js.map +1 -0
  105. package/dist/renderer.js +138 -63
  106. package/dist/renderer.js.map +1 -1
  107. package/dist/styles.css +32 -17
  108. package/dist/types/client/testing/test-conversation-widgets.d.ts +25 -0
  109. package/dist/types/client/testing/widget-hydration-stand-ins.d.ts +33 -0
  110. package/dist/types/entries/chat.d.ts +10 -0
  111. package/dist/types/entries/client-testing.d.ts +2 -0
  112. package/dist/types/entries/index.d.ts +4 -3
  113. package/dist/types/entries/kit.d.ts +7 -0
  114. package/dist/types/entries/preview.d.ts +1 -0
  115. package/dist/types/entries/provider.d.ts +1 -0
  116. package/dist/types/entries/renderer.d.ts +16 -0
  117. package/dist/types/entries/widgets.d.ts +13 -0
  118. package/dist/types/kit/components/data/apex-chart-component.d.ts +3 -0
  119. package/dist/types/kit/components/data/chart-model.d.ts +164 -0
  120. package/dist/types/kit/components/data/data-value-format.d.ts +44 -0
  121. package/dist/types/kit/components/data/use-chart-palette.d.ts +9 -0
  122. package/dist/types/kit/components/data/use-number-locale.d.ts +5 -0
  123. package/dist/types/provider/index.d.ts +1 -0
  124. package/dist/types/renderer/_access/ConversationWidgetGateSkeleton.d.ts +6 -0
  125. package/dist/types/renderer/_agent-space/use-conversation-widget-agent-space-fallback.d.ts +16 -0
  126. package/dist/types/renderer/canvas/use-anchor-widget-agent-space-key.d.ts +17 -0
  127. package/dist/types/renderer/conversationWidgetRegistry.d.ts +6 -0
  128. package/dist/types/renderer/read-conversation-widget-variant.d.ts +22 -0
  129. package/dist/types/widgets/_shared/CardFooter.d.ts +6 -0
  130. package/dist/types/widgets/_shared/WidgetLabel.d.ts +8 -0
  131. package/dist/types/widgets/_shared/entity-update-channel.d.ts +17 -0
  132. package/dist/types/widgets/_shared/use-element-visible.d.ts +6 -0
  133. package/dist/widgets.js +120 -27
  134. package/dist/widgets.js.map +1 -1
  135. package/package.json +74 -1
  136. package/public-api.json +761 -0
  137. package/dist/chunks/ConversationMarkdown-W7NHglmL.js.map +0 -1
  138. package/dist/chunks/WebSearchResultsConversationWidget-BvnLWHyi.js.map +0 -1
  139. package/dist/chunks/canvas-behaviours-BRFR1ALE.js.map +0 -1
  140. package/dist/chunks/canvasBodies-9SuF6NAB.js.map +0 -1
  141. package/dist/chunks/decide-canvas-open-Ct-wnNEJ.js +0 -20
  142. package/dist/chunks/decide-canvas-open-Ct-wnNEJ.js.map +0 -1
  143. package/dist/chunks/widget-name-resolver-DyIY6Zu4.js.map +0 -1
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: MultiChoice
3
+ emitter: none
4
+ status: Not implemented — nothing emits it yet; analysis of whether implementing it is worthwhile pending, possibly useful
5
+ summary: Generic multi-select picker with "Select all" and "Confirm N selections".
6
+ description: Generic multi-select picker. Renders a labelled list of options with checkboxes plus a "Select all" toggle and a "Confirm N selections" button. Emits a follow-up chat message with the chosen labels.
7
+ ---
8
+
9
+ # MultiChoiceConversationWidget
10
+
11
+ ## Description
12
+ Generic, payload-driven multi-select directive. Used wherever the assistant needs the user to pick one or more items from a finite list and confirm — e.g. business attributes, opening-hour days, GBP service flags, social-channel picks.
13
+
14
+ Visual: heading (optional title + subtitle), then a vertical stack of clickable rows each carrying a label, optional sublabel and a checkbox. A footer holds "Select all" / "Clear all" + a primary "Confirm {count} selections" button. Once confirmed the directive locks (no further toggling) and emits the configured chat message.
15
+
16
+ ## Data structure
17
+ JSON payload:
18
+ ```ts
19
+ {
20
+ title?: string,
21
+ subtitle?: string,
22
+ options: Array<{
23
+ label: string, // visible label
24
+ sublabel?: string, // small caption under the label
25
+ value: string, // unique id, used in confirm action
26
+ selected?: boolean, // pre-checked when true
27
+ }>,
28
+ selectAllLabel?: string, // default: "Select all"
29
+ confirmLabelTemplate?: string, // default: "Confirm {count} selection" (one key, plural via its MANY value:
30
+ // "Confirm 1 selection" / "Confirm 2 selections") — {count} is replaced; a custom
31
+ // template has no plural form, so word it count-neutral ("Selected: {count}")
32
+ confirmAction?: string, // default: "Confirmed: {values}" — {values}/{count} replaced before send
33
+ }
34
+ ```
35
+
36
+ Markdown shape:
37
+ ```md
38
+ ::MultiChoice{payload='{"title":"…","options":[{"label":"…","value":"…"}]}'}
39
+ ```
40
+
41
+ ## When to use
42
+ - User needs to pick one or more items from a known, finite set and explicitly confirm.
43
+ - Skip for single-pick prompts (use a single-select directive) and for free-text answers.
44
+ - Skip when each pick should fire its own action immediately — `MultiChoiceConversationWidget` defers until confirm.
45
+
46
+ ## ASCII layout (inline)
47
+ ```
48
+ Title (optional)
49
+ Subtitle (optional)
50
+
51
+ ┌────────────────────────────────────────────┐
52
+ │ Label A [✓] │
53
+ │ Currently not added │
54
+ └────────────────────────────────────────────┘
55
+ ┌────────────────────────────────────────────┐
56
+ │ Label B [ ] │
57
+ └────────────────────────────────────────────┘
58
+ …
59
+
60
+ [ Select all ] [ Confirm N selections ]
61
+ ```
@@ -0,0 +1,43 @@
1
+ {
2
+ "wireName": "MultiChoice",
3
+ "description": "The owner's answer on the multi-choice widget of an owner question. The confirm posts confirmAction as the owner's TEXT (sendMessageToChat): '{values}' becomes the picked options' labels in option order joined by ', ', '{count}' their number (default confirmAction 'Confirmed: {values}'; askOwner writes '{values}'), with the suffix the app declares appended when the widget belongs to another agent space than the active one (its agentSpaceId; the package default appends none, anotherAgentSpaceSuffixTemplate is empty). The backend reader is MultiChoiceConversationWidget (OwnerQuestionConversationWidget::readAnswer() / readPickFromFirstOwnerText()): the app's suffix is stripped when it names the widget's own agent space, the whole text is matched against one label first (a label may carry ', '), and only then split at ', ' with every part a label. Any owner text answers the widget; a text that matches no way is an answer without labels — so is a confirm under the default 'Confirmed: ' prefix today. The widget has no decline control. A stored contract: the confirm wording never changes without the readers accepting both.",
4
+ "anotherAgentSpaceSuffixTemplate": "",
5
+ "exampleBlocks": [
6
+ "```widget\n{\"type\":\"MultiChoice\",\"question\":\"Which channels should we post on?\",\"options\":[{\"label\":\"Instagram\",\"value\":\"Instagram\"},{\"label\":\"Facebook\",\"value\":\"Facebook\",\"sublabel\":\"Your page with 1,200 followers\"},{\"label\":\"TikTok\",\"value\":\"TikTok\"}],\"confirmAction\":\"{values}\",\"emittedBy\":\"tool:askOwner\"}\n```",
7
+ "```widget\n{\"type\":\"MultiChoice\",\"agentSpaceId\":412553,\"title\":\"What do you sell?\",\"options\":[{\"label\":\"Bread, rolls and cakes\",\"value\":\"bakery\"},{\"label\":\"Coffee\",\"value\":\"coffee\"}],\"confirmAction\":\"{values}\"}\n```"
8
+ ],
9
+ "exampleReactions": [
10
+ {
11
+ "exampleBlock": 0,
12
+ "messageType": "TEXT",
13
+ "confirmedValues": ["Instagram", "TikTok"],
14
+ "clickedOnWidgetOfAnotherAgentSpace": false,
15
+ "text": "Instagram, TikTok",
16
+ "expectsAnswer": true,
17
+ "expectsDecline": false,
18
+ "expectedLabels": ["Instagram", "TikTok"],
19
+ "expectedMeanings": []
20
+ },
21
+ {
22
+ "exampleBlock": 1,
23
+ "messageType": "TEXT",
24
+ "confirmedValues": ["bakery"],
25
+ "clickedOnWidgetOfAnotherAgentSpace": true,
26
+ "text": "Bread, rolls and cakes",
27
+ "expectsAnswer": true,
28
+ "expectsDecline": false,
29
+ "expectedLabels": ["Bread, rolls and cakes"],
30
+ "expectedMeanings": [],
31
+ "expectedAnotherAgentSpaceKey": 412553
32
+ },
33
+ {
34
+ "exampleBlock": 0,
35
+ "messageType": "TEXT",
36
+ "text": "Only Instagram for now, maybe TikTok later",
37
+ "expectsAnswer": true,
38
+ "expectsDecline": false,
39
+ "expectedLabels": [],
40
+ "expectedMeanings": []
41
+ }
42
+ ]
43
+ }
@@ -0,0 +1,103 @@
1
+ {
2
+ "wireName": "MultiChoice",
3
+ "fixtures": [
4
+ {
5
+ "name": "default",
6
+ "description": "Choice pills with a confirm — the reservation time pills of the ChatGPT reference.",
7
+ "payload": {
8
+ "question": "Which channels should we post on?",
9
+ "options": [
10
+ {
11
+ "label": "Instagram",
12
+ "value": "Instagram"
13
+ },
14
+ {
15
+ "label": "Facebook",
16
+ "value": "Facebook",
17
+ "sublabel": "Your page with 1,200 followers"
18
+ },
19
+ {
20
+ "label": "TikTok",
21
+ "value": "TikTok"
22
+ }
23
+ ],
24
+ "confirmAction": "{values}"
25
+ },
26
+ "expectedState": "data",
27
+ "width": 528,
28
+ "interactions": [
29
+ {
30
+ "name": "pick Instagram",
31
+ "click": {
32
+ "text": "Instagram"
33
+ }
34
+ },
35
+ {
36
+ "name": "pick Facebook",
37
+ "click": {
38
+ "text": "Facebook"
39
+ }
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ "name": "render-report-error",
45
+ "description": "A payload without an options list reports failed INVALID_PROP.",
46
+ "payload": {
47
+ "question": "Which channels?"
48
+ },
49
+ "expectedState": "error",
50
+ "width": 528
51
+ },
52
+ {
53
+ "name": "kassel-dental-services",
54
+ "description": "Which services the November posts of the practice should feature — several may be picked, the confirm sends them.",
55
+ "dataSet": "kassel-dental-practice",
56
+ "payload": {
57
+ "question": "Welche Leistungen sollen die November-Posts zeigen?",
58
+ "options": [
59
+ {
60
+ "label": "Prophylaxe / professionelle Zahnreinigung",
61
+ "value": "Prophylaxe",
62
+ "sublabel": "Passt zu den Prophylaxe-Wochen"
63
+ },
64
+ {
65
+ "label": "Implantologie",
66
+ "value": "Implantologie"
67
+ },
68
+ {
69
+ "label": "Bleaching",
70
+ "value": "Bleaching"
71
+ },
72
+ {
73
+ "label": "Kinderzahnheilkunde",
74
+ "value": "Kinderzahnheilkunde"
75
+ },
76
+ {
77
+ "label": "Angstpatienten-Behandlung",
78
+ "value": "Angstpatienten-Behandlung"
79
+ }
80
+ ],
81
+ "confirmAction": "{values}"
82
+ },
83
+ "agentSpaceId": 7,
84
+ "locale": "de",
85
+ "expectedState": "data",
86
+ "width": 528,
87
+ "interactions": [
88
+ {
89
+ "name": "pick Prophylaxe",
90
+ "click": {
91
+ "text": "Prophylaxe / professionelle Zahnreinigung"
92
+ }
93
+ },
94
+ {
95
+ "name": "pick Bleaching",
96
+ "click": {
97
+ "text": "Bleaching"
98
+ }
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ }
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: QuickReplies
3
+ emitter: agent
4
+ summary: Short answer pills under a closed question — one click sends that option's text as the owner's message.
5
+ description: The pill answers to a closed question (a backend hard rule) — two to five SHORT options in the owner's language, each a complete answer the owner could also type. A click posts the option's text as the owner's own message; the card locks once the send is confirmed, and goes inert once a newer owner message exists (the conversation moved past the question).
6
+ ---
7
+
8
+ # QuickRepliesConversationWidget
9
+
10
+ ## Description
11
+ The agent asks a CLOSED question in prose, then offers the answers as pills instead of leaving the owner to type one. Renders a row of short buttons under the question; a click sends that button's exact text as the owner's chat message — a shortcut for typing the same words, never a separate action channel.
12
+
13
+ Single pick only (compare `MultiChoiceConversationWidget`, which defers to an explicit multi-select confirm). Locks after the click is confirmed sent; a rejected send (closed conversation, an in-flight start) leaves the pills clickable again. Once a NEWER owner message exists in the conversation — the owner typed past it, or answered a later question — the card goes inert (rendered disabled) so a stale pick can never answer the wrong question.
14
+
15
+ Every option MUST be a complete answer the owner could send verbatim — never a template with a blank (e.g. "Yes, we deliver to these areas: …"). The widget enforces this as a backstop: an option containing an ellipsis (`…`/`...`), a bracketed or underscore blank (`[...]`, `[…]`, `___`), or ending in a colon is a "placeholder option" — clicking it never sends; instead the stripped text is placed in the composer (with a trailing space) and focused, so the owner types the missing part themselves.
16
+
17
+ ## Data structure
18
+ JSON payload:
19
+ ```ts
20
+ {
21
+ options: string[], // 2 to 5 entries, each trimmed, non-empty, unique case-insensitively
22
+ }
23
+ ```
24
+
25
+ Validation (an invalid payload renders nothing):
26
+ - `options` must be an array.
27
+ - 2 to 5 entries.
28
+ - Each entry a non-empty string after trimming.
29
+ - No two entries equal case-insensitively (not silently deduplicated — a payload that violates this is dropped).
30
+ - An entry longer than 60 characters is shown truncated with an ellipsis; the click still sends the FULL text.
31
+
32
+ Markdown shape (the fence form):
33
+ ```widget
34
+ { "type": "QuickReplies", "options": ["Ja, veröffentlichen", "Jetzt nicht"] }
35
+ ```
36
+
37
+ ## When to use
38
+ - Right under a closed (yes/no/either-or) question, so the owner can answer with one click instead of typing.
39
+ - Each option must be a short, complete answer the owner could also type verbatim — not a label for a longer action.
40
+ - Skip for an open-ended question (free text is the only sensible answer) and for multi-select (`MultiChoiceConversationWidget`).
41
+
42
+ ## ASCII layout (inline)
43
+ ```
44
+ Möchtest du die Änderungen jetzt veröffentlichen?
45
+
46
+ [ Ja, veröffentlichen ] [ Jetzt nicht ]
47
+ ```
48
+
49
+ After a confirmed click, every pill disables and the chosen one stays highlighted:
50
+ ```
51
+ Möchtest du die Änderungen jetzt veröffentlichen?
52
+
53
+ [ Ja, veröffentlichen ]■ [ Jetzt nicht ] (■ = chosen, both disabled)
54
+ ```
55
+
56
+
57
+ ## Platform-written widgets (`askOwner`)
58
+
59
+ The backend's `askOwner` meta-tool renders the model's own closed question as a QuickReplies tool widget under the
60
+ final text. Its fence carries extra flat fields the widget ignores and the platform reads back: `question` (the
61
+ model's question text), `questionKey` (a catalogue key such as `serveModel`, `draftApproval`), `optionMeanings`
62
+ (one catalogue meaning per option, same order) and `descriptions` (one optional explanation per option, `null`
63
+ where none). The click still posts the option label as the owner's message — that label is the platform's read-back
64
+ key. A multi-select question renders as `MultiChoice` with `confirmAction: "{values}"` (the picked labels joined by
65
+ ", ").
@@ -0,0 +1,43 @@
1
+ {
2
+ "wireName": "QuickReplies",
3
+ "description": "The owner's answer on the single-choice pills of an owner question. A click posts the option's label as the owner's TEXT (sendMessageToChat), with the suffix the app declares appended when the widget belongs to another agent space than the active one (its agentSpaceId; the package default appends none, anotherAgentSpaceSuffixTemplate is empty). A placeholder option (an ellipsis, a bracketed or underscore blank, a trailing colon) never posts: it fills the composer instead. The backend reader is QuickRepliesConversationWidget (OwnerQuestionConversationWidget::readAnswer() / readPickFromFirstOwnerText()): the app's suffix is stripped when it names the widget's own agent space, then the whole text is matched against the labels (case-insensitive, trailing ' .!' ignored). Any owner text answers the widget; a text that matches no label is an answer without labels. The pills have no decline control. A stored contract: the click wording never changes without the readers accepting both.",
4
+ "anotherAgentSpaceSuffixTemplate": "",
5
+ "exampleBlocks": [
6
+ "```widget\n{\"type\":\"QuickReplies\",\"question\":\"Wie erreichen dich deine Kunden?\",\"options\":[\"Kunden kommen zu uns\",\"Wir fahren zu den Kunden\",\"Beides\"],\"questionKey\":\"serveModel\",\"optionMeanings\":[\"walkIn\",\"mobile\",\"hybrid\"],\"emittedBy\":\"tool:askOwner\"}\n```",
7
+ "```widget\n{\"type\":\"QuickReplies\",\"agentSpaceId\":412553,\"options\":[\"Yes, publish it\",\"Not yet\"]}\n```"
8
+ ],
9
+ "exampleReactions": [
10
+ {
11
+ "exampleBlock": 0,
12
+ "messageType": "TEXT",
13
+ "clickedOption": "Wir fahren zu den Kunden",
14
+ "clickedOnWidgetOfAnotherAgentSpace": false,
15
+ "text": "Wir fahren zu den Kunden",
16
+ "expectsAnswer": true,
17
+ "expectsDecline": false,
18
+ "expectedLabels": ["Wir fahren zu den Kunden"],
19
+ "expectedMeanings": ["mobile"]
20
+ },
21
+ {
22
+ "exampleBlock": 0,
23
+ "messageType": "TEXT",
24
+ "text": "Beides, aber hauptsächlich fahren wir raus",
25
+ "expectsAnswer": true,
26
+ "expectsDecline": false,
27
+ "expectedLabels": [],
28
+ "expectedMeanings": []
29
+ },
30
+ {
31
+ "exampleBlock": 1,
32
+ "messageType": "TEXT",
33
+ "clickedOption": "Yes, publish it",
34
+ "clickedOnWidgetOfAnotherAgentSpace": true,
35
+ "text": "Yes, publish it",
36
+ "expectsAnswer": true,
37
+ "expectsDecline": false,
38
+ "expectedLabels": ["Yes, publish it"],
39
+ "expectedMeanings": [],
40
+ "expectedAnotherAgentSpaceKey": 412553
41
+ }
42
+ ]
43
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "wireName": "QuickReplies",
3
+ "fixtures": [
4
+ {
5
+ "name": "default",
6
+ "description": "An owner question with three answer pills — the follow-up suggestions of the ChatGPT reference as one tap each.",
7
+ "payload": {
8
+ "question": "What should we look at next?",
9
+ "options": ["Compare with last month", "Show the top keywords", "Which competitor grew most?"]
10
+ },
11
+ "expectedState": "data",
12
+ "width": 528,
13
+ "interactions": [{ "name": "pick the second answer", "click": { "text": "Show the top keywords" } }]
14
+ },
15
+ {
16
+ "name": "render-report-error",
17
+ "description": "Two options that differ only by case drop the card, reported failed INVALID_PROP.",
18
+ "payload": {
19
+ "options": [
20
+ "Yes",
21
+ "yes"
22
+ ]
23
+ },
24
+ "expectedState": "error",
25
+ "width": 528
26
+ },
27
+ {
28
+ "name": "kassel-dental-next-step",
29
+ "description": "After the review summary the assistant asks the practice owner what to look at next — three answer pills the model wrote.",
30
+ "dataSet": "kassel-dental-practice",
31
+ "payload": {
32
+ "question": "Womit sollen wir weitermachen?",
33
+ "options": [
34
+ "Auf die 2-Sterne-Bewertung antworten",
35
+ "Bewertungen mit Dentalzentrum Kassel-West vergleichen",
36
+ "Bewertungsanfragen an Prophylaxe-Patienten senden"
37
+ ]
38
+ },
39
+ "agentSpaceId": 7,
40
+ "locale": "de",
41
+ "expectedState": "data",
42
+ "width": 528
43
+ }
44
+ ]
45
+ }
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: SuggestedActions
3
+ emitter: frontend
4
+ summary: Quick-reply pill buttons under an AI message; click sends a predefined prompt.
5
+ description: Inline row of muted pill buttons rendered under an AI message. Each pill is a quick-reply — clicking it sends the predefined `userAction` text back into the chat as if the user typed it. Lightweight quick-reply pattern; no icons, no descriptions, no flags.
6
+ ---
7
+
8
+ # SuggestedActions
9
+
10
+ ## Description
11
+ Quick-reply pills shown under an assistant turn. Parses `options` (JSON array of `{displayText, userAction}`), renders muted component-library `Button`s in a single horizontal flex row. Click → `sendMessageToChat(userAction)` → the chat behaves as if the user typed `userAction`. Returns `null` on parse / shape failure (warns to console).
12
+
13
+ Visual contract:
14
+ - Single horizontal row, compact muted buttons.
15
+ - `displayText` is the **short** label the user sees on the pill (verb-led, ~1–4 words).
16
+ - `userAction` is the **full** message that gets injected into the chat on click — phrase it as something a real user would naturally type, can be a complete sentence.
17
+ - No icons, no subtitles, no recommended / destructive variants.
18
+
19
+ ## Data structure
20
+ Single prop `options` — a non-empty array of `{displayText, userAction}` objects.
21
+ ```ts
22
+ interface SuggestedActionsProps {
23
+ options: {
24
+ displayText: string; // required, short pill label (~1–4 words, verb-led)
25
+ userAction: string; // required, full user message sent to chat on click
26
+ }[]; // required, non-empty
27
+ }
28
+ ```
29
+ The renderer JSON-stringifies prop objects automatically, so mock / backend authors supply a plain array — no double-encoding needed.
30
+
31
+ Concrete `options` value:
32
+ ```json
33
+ [
34
+ { "displayText": "Reply now", "userAction": "Help me reply to my recent reviews" },
35
+ { "displayText": "Draft it", "userAction": "Draft a weekend promo post for Google" },
36
+ { "displayText": "Skip for now","userAction": "Skip these for now" }
37
+ ]
38
+ ```
39
+
40
+ Markdown shape:
41
+ ```md
42
+ ::SuggestedActions{options='[{"displayText":"Reply now","userAction":"Help me reply to my recent reviews"}]'}
43
+ ```
44
+
45
+ ## When to use
46
+ - AI ends a turn with 2–6 obvious conversational follow-ups the user is likely to tap instead of typing.
47
+ - Each option must be **a message the user would say**, not an action that opens a UI / mounts a widget / triggers a side effect.
48
+ - `displayText` reads like a chat-reply chip ("Show me how", "Draft it for me", "Not now").
49
+ - `userAction` reads like a complete user turn — specific enough that the assistant can act on it without follow-up clarification.
50
+ - Options that would need descriptions, titles, icons or a recommended flag are written as prose — there is no card-stack widget.
51
+ - Skip when an option must open a canvas, mount a widget, or run a side effect → pick the matching dedicated widget.
52
+ - Skip when there is exactly one obvious next step — just ask the user directly.
53
+
54
+ ## ASCII layout (inline)
55
+ ```
56
+ ... AI message text above ...
57
+
58
+ [ Reply now ] [ Draft it ] [ Add photos ] [ Sync hours ] [ Skip for now ]
59
+ muted muted muted muted muted
60
+ ```
@@ -0,0 +1,19 @@
1
+ {
2
+ "wireName": "SuggestedActions",
3
+ "fixtures": [
4
+ {
5
+ "name": "render-report-error",
6
+ "description": "A fence carries no options attribute, so the widget reports failed INVALID_PROP and renders nothing.",
7
+ "payload": {
8
+ "options": [
9
+ {
10
+ "displayText": "Yes",
11
+ "userAction": "Yes"
12
+ }
13
+ ]
14
+ },
15
+ "expectedState": "error",
16
+ "width": 528
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: ToolTrace
3
+ emitter: frontend
4
+ summary: Collapsible trace of the tool calls behind an answer (debug/transparency).
5
+ description: Muted, italic single-line trace of a `tool_use` assistant part (e.g. `→ Opened Example Tasks`). Payload-only, renders on both live delivery and history replay, and never executes the tool.
6
+ ---
7
+
8
+ # ToolTraceConversationWidget
9
+
10
+ ## Description
11
+
12
+ Renders a muted single-line label for a `tool_use` part so the user can see which tool
13
+ the agent invoked, without re-running it. Renders identically on live delivery and on
14
+ history replay — it is purely presentational.
15
+
16
+ ## Payload
17
+
18
+ ```json
19
+ {
20
+ "name": "Navigate",
21
+ "input": { "destination": "APP.NAV.EXAMPLE.TASKS" }
22
+ }
23
+ ```
24
+
25
+ | Field | Type | Required | Notes |
26
+ |---|---|---|---|
27
+ | `name` | string | no | Tool name. Falls back to `"Tool"` when missing/non-string. |
28
+ | `input` | object | no | Tool input. Only read when `name === "Navigate"`. |
29
+
30
+ ## Label resolution
31
+
32
+ - `name === "Navigate"` **and** `input.destination` is a non-empty string → the last
33
+ dot-segment of the destination is humanized: `APP.NAV.EXAMPLE.TASKS` → `Example Tasks`.
34
+ - Otherwise → the raw `name` (or `"Tool"`).
35
+
36
+ Output is `→ Opened <label>`.
37
+
38
+ ## States
39
+
40
+ - Non-JSON / non-object payload, or unresolvable label → renders nothing (`null`).
41
+
42
+ ## Layout
43
+
44
+ ```
45
+ → Opened Example Tasks
46
+ ```
47
+
48
+ Single inline `<span>`, 12px, italic, subtle text color.
@@ -0,0 +1,32 @@
1
+ {
2
+ "wireName": "ToolTrace",
3
+ "fixtures": [
4
+ {
5
+ "name": "render-report-mounted",
6
+ "description": "A readable trace mounts (a fence always carries an object, so the unreadable path is spec-only).",
7
+ "payload": {
8
+ "name": "Navigate",
9
+ "input": {
10
+ "destination": "APP.NAV.EXAMPLE.TASKS"
11
+ }
12
+ },
13
+ "expectedState": "data",
14
+ "width": 528
15
+ },
16
+ {
17
+ "name": "default",
18
+ "description": "The muted trace line of a navigation the assistant made for the practice owner: it opened the reviews page of the app.",
19
+ "dataSet": "kassel-dental-practice",
20
+ "payload": {
21
+ "name": "Navigate",
22
+ "input": {
23
+ "destination": "APP.NAV.EXAMPLE.REVIEWS"
24
+ }
25
+ },
26
+ "agentSpaceId": 7,
27
+ "locale": "de",
28
+ "expectedState": "data",
29
+ "width": 528
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: WebSearchResults
3
+ emitter: agent
4
+ canvas: webSearchResults
5
+ summary: References of the agent's own web research answer — the pages it used as link chips with site icons, placed under its prose answer. DATA-COMPLETE.
6
+ description: Renders the references of a web research answer the agent wrote itself — one link chip per page it used (the site's favicon and name, the page title on hover). The agent writes the answer as prose ABOVE the widget; the widget carries only `query` and `sources`. Legacy messages with an `answer` field render the former answer card.
7
+ ---
8
+
9
+ # WebSearchResultsConversationWidget
10
+
11
+ ## Description
12
+ The references of a web research answer. The agent writes its answer as prose in the message and puts this
13
+ widget on its own line UNDER it, carrying the pages it actually used. Each page renders as a link chip: the site's
14
+ favicon, the site name, the full page title on hover; a click opens the page in a new tab.
15
+
16
+ ## Data structure — DATA-COMPLETE (no re-fetch)
17
+ **This widget does NOT fetch anything.** It renders entirely from the payload. The `sources` are copied character for
18
+ character from the `searchTheWeb` / `extractInformationFromWebPagesWithFastLLM` tool results.
19
+ ```ts
20
+ interface WebSearchResultsPayload {
21
+ query: string; // what was researched
22
+ provider?: string; // PERPLEXITY
23
+ sources: { url: string; title?: string }[]; // the pages the answer used, in order
24
+ // legacy (older stored messages): title, display, answer — a payload with `answer` renders the answer card
25
+ }
26
+ ```
27
+ Concrete payload example:
28
+ ```json
29
+ {
30
+ "query": "BMW iX M60 vs iX M70 chassis and acceleration",
31
+ "provider": "PERPLEXITY",
32
+ "sources": [
33
+ { "url": "https://www.press.bmwgroup.com/deutschland/article/detail/T0447680DE/der-neue-bmw-ix", "title": "Der neue BMW iX" },
34
+ { "url": "https://fastestlaps.com/models/bmw-ix-m60", "title": "BMW iX M60 specs, 0-60, quarter mile" }
35
+ ]
36
+ }
37
+ ```
38
+
39
+ ## When to use
40
+ - After a web research answer on a screen: the answer as prose first, then this widget on its own line with the pages
41
+ the answer used. Never the answer inside the widget, never a page the tools did not return.
42
+
43
+ ## ASCII layout
44
+ ```
45
+ <the agent's answer, prose, tables>
46
+
47
+ Sources
48
+ (🌐 press.bmwgroup.com) (🌐 fastestlaps.com) (🌐 autobild.de)
49
+ ```
@@ -0,0 +1,57 @@
1
+ {
2
+ "wireName": "WebSearchResults",
3
+ "fixtures": [
4
+ {
5
+ "name": "default",
6
+ "description": "The sources of a web research answer — the source cards of the ChatGPT news feed reference.",
7
+ "payload": {
8
+ "query": "Münster bakery opening hours on public holidays",
9
+ "provider": "PERPLEXITY",
10
+ "sources": [
11
+ { "url": "https://www.muenster.de/feiertage.html", "title": "Feiertage in Münster" },
12
+ { "url": "https://www.ihk.de/nordwestfalen/ladenoeffnung", "title": "Ladenöffnung an Feiertagen" },
13
+ { "url": "https://www.bäckerhandwerk.de/oeffnungszeiten", "title": "Öffnungszeiten im Bäckerhandwerk" }
14
+ ]
15
+ },
16
+ "expectedState": "data",
17
+ "width": 528
18
+ },
19
+ {
20
+ "name": "render-report-empty",
21
+ "description": "No answer and no source with a url reports empty NO_DATA.",
22
+ "payload": {
23
+ "query": "opening hours",
24
+ "sources": []
25
+ },
26
+ "expectedState": "empty",
27
+ "width": 528
28
+ },
29
+ {
30
+ "name": "kassel-dental-emergency-service",
31
+ "description": "The owner asked how the dental emergency service in Kassel is organised at weekends (for the practice's Notfallsprechstunde page); the widget carries the three pages the answer used.",
32
+ "dataSet": "kassel-dental-practice",
33
+ "payload": {
34
+ "query": "zahnärztlicher Notdienst Kassel Wochenende",
35
+ "provider": "PERPLEXITY",
36
+ "sources": [
37
+ {
38
+ "url": "https://www.lzkh.de/patienten/zahnaerztlicher-notdienst",
39
+ "title": "Zahnärztlicher Notdienst in Hessen – Landeszahnärztekammer Hessen"
40
+ },
41
+ {
42
+ "url": "https://www.kzvh.de/patienten/notdienst",
43
+ "title": "Notdienstsuche – Kassenzahnärztliche Vereinigung Hessen"
44
+ },
45
+ {
46
+ "url": "https://www.kassel.de/buerger/gesundheit/notdienste.php",
47
+ "title": "Notdienste und Bereitschaftsdienste – Stadt Kassel"
48
+ }
49
+ ]
50
+ },
51
+ "agentSpaceId": 7,
52
+ "locale": "de",
53
+ "expectedState": "data",
54
+ "width": 528
55
+ }
56
+ ]
57
+ }