@unoverse-platform/studio 0.1.68 → 0.1.69
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.
- package/local/{sample-template/chat/states/conversation.yaml → sample-component/text-chat/layouts/chat-active.yaml} +0 -1
- package/local/{sample-template/chat/states/welcome.yaml → sample-component/text-chat/layouts/chat-welcome.yaml} +0 -1
- package/local/sample-component/text-chat/layouts/chat.yaml +77 -0
- package/local/sample-component/text-chat/manifest.yaml +10 -0
- package/local/sample-component/text-chat/text-chat.yaml +59 -0
- package/local/sample-template/chat/components/chat-region.yaml +10 -0
- package/local/sample-template/chat/components/core-focus.yaml +3 -31
- package/local/sample-template/chat/components/core.yaml +1 -28
- package/local/sample-template/chat/manifest.yaml +7 -12
- package/local/scaffold.mjs +8 -3
- package/package.json +1 -1
- package/screens/ComponentsView.tsx +8 -1
- package/vendor/sdk/appEngine.tsx +1 -1
- package/vendor/skills/unoverse-create/references/brand.md +1 -1
- package/vendor/skills/unoverse-create/references/component.md +21 -1
- package/vendor/skills/unoverse-create/references/template.md +1 -1
- /package/local/{sample-template/chat → sample-component/text-chat}/components/assistant-turn.yaml +0 -0
- /package/local/{sample-template/chat → sample-component/text-chat}/components/header.yaml +0 -0
- /package/local/{sample-template/chat → sample-component/text-chat}/components/suggestions.yaml +0 -0
- /package/local/{sample-template/chat → sample-component/text-chat}/components/thinking-dots.yaml +0 -0
- /package/local/{sample-template/chat → sample-component/text-chat}/components/user-turn.yaml +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# THE SHELL of the one public state: the FULL chat CX — the header, the mood region
|
|
2
|
+
# (welcome hero / live timeline), the suggestion chips over its foot, and the composer.
|
|
3
|
+
# The steps switch on chatState (the declared axis): Studio writes it when you step
|
|
4
|
+
# Welcome/Active. Live, nothing writes it, so the Switch falls to its default case,
|
|
5
|
+
# where the projected conversation facts pick the mood.
|
|
6
|
+
type: Box
|
|
7
|
+
style:
|
|
8
|
+
direction: column
|
|
9
|
+
# `flex: 1` fills a flex column (the template's core); `height: full` fills a block
|
|
10
|
+
# parent with a real height (the standalone preview).
|
|
11
|
+
flex: 1
|
|
12
|
+
height: full
|
|
13
|
+
minHeight: "0"
|
|
14
|
+
children:
|
|
15
|
+
- $include: components/header
|
|
16
|
+
- type: Box
|
|
17
|
+
style:
|
|
18
|
+
direction: column
|
|
19
|
+
flex: 1
|
|
20
|
+
minHeight: "0"
|
|
21
|
+
position: relative
|
|
22
|
+
when:
|
|
23
|
+
- field: hasMessages
|
|
24
|
+
eq: true
|
|
25
|
+
apply:
|
|
26
|
+
background: surface.base
|
|
27
|
+
radiusTopLeft: 2xl
|
|
28
|
+
overflow: hidden
|
|
29
|
+
- field: chatState
|
|
30
|
+
eq: active
|
|
31
|
+
apply:
|
|
32
|
+
background: surface.base
|
|
33
|
+
radiusTopLeft: 2xl
|
|
34
|
+
overflow: hidden
|
|
35
|
+
# chatState is only ever set by Studio's stepper, so this height is
|
|
36
|
+
# preview-only: live, the template's flex sizes the region.
|
|
37
|
+
minHeight: "120"
|
|
38
|
+
children:
|
|
39
|
+
- type: Switch
|
|
40
|
+
on: chatState
|
|
41
|
+
cases:
|
|
42
|
+
welcome: { $include: layouts/chat-welcome }
|
|
43
|
+
active: { $include: layouts/chat-active }
|
|
44
|
+
default:
|
|
45
|
+
type: Box
|
|
46
|
+
style:
|
|
47
|
+
direction: column
|
|
48
|
+
flex: 1
|
|
49
|
+
minHeight: "0"
|
|
50
|
+
children:
|
|
51
|
+
- type: Box
|
|
52
|
+
visibleWhen: isEmpty
|
|
53
|
+
style:
|
|
54
|
+
direction: column
|
|
55
|
+
flex: 1
|
|
56
|
+
minHeight: "0"
|
|
57
|
+
children:
|
|
58
|
+
- $include: layouts/chat-welcome
|
|
59
|
+
- type: Box
|
|
60
|
+
visibleWhen: hasMessages
|
|
61
|
+
style:
|
|
62
|
+
direction: column
|
|
63
|
+
flex: 1
|
|
64
|
+
minHeight: "0"
|
|
65
|
+
children:
|
|
66
|
+
- $include: layouts/chat-active
|
|
67
|
+
- type: Box
|
|
68
|
+
style:
|
|
69
|
+
position: absolute
|
|
70
|
+
bottom: "0"
|
|
71
|
+
left: "0"
|
|
72
|
+
right: "0"
|
|
73
|
+
direction: column
|
|
74
|
+
children:
|
|
75
|
+
- $include: components/suggestions
|
|
76
|
+
- type: Ref
|
|
77
|
+
ref: composer-bar
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
title: Text Chat
|
|
2
|
+
description: The conversation surface, a welcome hero on an empty chat and the live message timeline once it begins.
|
|
3
|
+
whenToUse: Start talking to the assistant and see the conversation itself, the welcome screen to begin from, then the running exchange of messages once the chat is underway. Not for typing a message and not a page or card of its own, it is the chat surface inside your own apps.
|
|
4
|
+
category: Communication
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
|
|
7
|
+
# The app-level LOAD MODE: absent, a component app would load in `focus`. Arrival
|
|
8
|
+
# inside a template is the tree's first declared state (chat); this key keeps the app
|
|
9
|
+
# load honest to it.
|
|
10
|
+
defaultState: chat
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# THE CHAT SURFACE — a worked example component, shipped with Studio so the chat CX
|
|
2
|
+
# lives in ONE place your apps can share. It is yours: rename it, restyle it (it uses
|
|
3
|
+
# only foundation tokens, so your project's theme restyles it whole), or delete it.
|
|
4
|
+
# Guide: https://docs.unoverse.ai/design/components.md
|
|
5
|
+
unoverse: "1.0"
|
|
6
|
+
kind: component
|
|
7
|
+
name: text-chat
|
|
8
|
+
category: Communication
|
|
9
|
+
nodeSize:
|
|
10
|
+
width: 480
|
|
11
|
+
height: 400
|
|
12
|
+
props:
|
|
13
|
+
# `input: false` on all three — no workflow fills them, so none of them join the
|
|
14
|
+
# node's config contract. They exist so the preview has something to draw.
|
|
15
|
+
#
|
|
16
|
+
# chatState is THE PREVIEW AXIS: Studio writes it when you step Welcome/Active. The
|
|
17
|
+
# default is EMPTY on purpose — live, nothing writes it, the Switch falls to its
|
|
18
|
+
# default case and the conversation facts pick the mood. A non-empty default would
|
|
19
|
+
# pin the mood forever.
|
|
20
|
+
chatState:
|
|
21
|
+
type: string
|
|
22
|
+
input: false
|
|
23
|
+
default: ""
|
|
24
|
+
enum: ["", welcome, active]
|
|
25
|
+
# Preview defaults for the live fallback's guards (the conversation facts the
|
|
26
|
+
# platform projects for real).
|
|
27
|
+
isEmpty:
|
|
28
|
+
type: boolean
|
|
29
|
+
input: false
|
|
30
|
+
default: true
|
|
31
|
+
hasMessages:
|
|
32
|
+
type: boolean
|
|
33
|
+
input: false
|
|
34
|
+
default: false
|
|
35
|
+
# THE STATE TREE (State Model v2): ONE public state — the single-state permanent
|
|
36
|
+
# component: it lives in a template's core and templates never rearrange around it.
|
|
37
|
+
# The chat's two moods NEST beneath it as PRIVATE substates (the rearrange rule: the
|
|
38
|
+
# template wouldn't move, so they nest), which is also what makes them steppable in
|
|
39
|
+
# Studio. The mood is DERIVED from the conversation, so the shell's default case keeps
|
|
40
|
+
# its own conditions. The template has the state; this component just reacts.
|
|
41
|
+
state:
|
|
42
|
+
view:
|
|
43
|
+
states:
|
|
44
|
+
chat:
|
|
45
|
+
on: chatState
|
|
46
|
+
states:
|
|
47
|
+
welcome:
|
|
48
|
+
layout: chat-welcome
|
|
49
|
+
active:
|
|
50
|
+
layout: chat-active
|
|
51
|
+
root:
|
|
52
|
+
type: Switch
|
|
53
|
+
on: view
|
|
54
|
+
cases:
|
|
55
|
+
chat: { $include: layouts/chat }
|
|
56
|
+
# Ref placement: embedded in a template's core the component has no spawned
|
|
57
|
+
# instance slice, so `view` is absent from scope — the chat is still the one
|
|
58
|
+
# thing to draw.
|
|
59
|
+
default: { $include: layouts/chat }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# THE CHAT REGION — one shared component (text-chat) owns the whole chat CX: the
|
|
2
|
+
# welcome hero on an empty chat, the live timeline once messages exist, the suggestion
|
|
3
|
+
# chips and the composer. The switching rides the projected conversation facts inside
|
|
4
|
+
# the component; nothing is wired here. Shared by core and core-focus.
|
|
5
|
+
#
|
|
6
|
+
# A BARE ref resolves your own project's component: a ref inside a project's tree
|
|
7
|
+
# matches that project first. Qualify it (`<project>/text-chat`) only if you ship two
|
|
8
|
+
# projects that both carry the name.
|
|
9
|
+
type: Ref
|
|
10
|
+
ref: text-chat
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# THE CHAT COLUMN WITH A FOCUSED COMPONENT OVER IT — core, plus the focus surface
|
|
2
|
-
# laid over
|
|
3
|
-
#
|
|
4
|
-
# overlay slot.
|
|
2
|
+
# laid over it. A core VARIANT, not a copy: chat-region is the same shared file
|
|
3
|
+
# core.yaml includes; the only difference is the overlay slot.
|
|
5
4
|
type: Box
|
|
6
5
|
appWidth: chat
|
|
7
6
|
style:
|
|
@@ -15,32 +14,5 @@ children:
|
|
|
15
14
|
minHeight: "0"
|
|
16
15
|
position: relative
|
|
17
16
|
children:
|
|
18
|
-
- $include: components/
|
|
19
|
-
- type: Box
|
|
20
|
-
style:
|
|
21
|
-
direction: column
|
|
22
|
-
flex: 1
|
|
23
|
-
minHeight: "0"
|
|
24
|
-
position: relative
|
|
25
|
-
when:
|
|
26
|
-
- field: hasMessages
|
|
27
|
-
eq: true
|
|
28
|
-
apply:
|
|
29
|
-
background: surface.base
|
|
30
|
-
radiusTopLeft: 2xl
|
|
31
|
-
overflow: hidden
|
|
32
|
-
children:
|
|
33
|
-
- $include: states/welcome
|
|
34
|
-
- $include: states/conversation
|
|
35
|
-
- type: Box
|
|
36
|
-
style:
|
|
37
|
-
position: absolute
|
|
38
|
-
bottom: "0"
|
|
39
|
-
left: "0"
|
|
40
|
-
right: "0"
|
|
41
|
-
direction: column
|
|
42
|
-
children:
|
|
43
|
-
- $include: components/suggestions
|
|
17
|
+
- $include: components/chat-region
|
|
44
18
|
- $include: components/focus-overlay
|
|
45
|
-
- type: Ref
|
|
46
|
-
ref: composer-bar
|
|
@@ -11,31 +11,4 @@ children:
|
|
|
11
11
|
minHeight: "0"
|
|
12
12
|
position: relative
|
|
13
13
|
children:
|
|
14
|
-
- $include: components/
|
|
15
|
-
- type: Box
|
|
16
|
-
style:
|
|
17
|
-
direction: column
|
|
18
|
-
flex: 1
|
|
19
|
-
minHeight: "0"
|
|
20
|
-
position: relative
|
|
21
|
-
when:
|
|
22
|
-
- field: hasMessages
|
|
23
|
-
eq: true
|
|
24
|
-
apply:
|
|
25
|
-
background: surface.base
|
|
26
|
-
radiusTopLeft: 2xl
|
|
27
|
-
overflow: hidden
|
|
28
|
-
children:
|
|
29
|
-
- $include: states/welcome
|
|
30
|
-
- $include: states/conversation
|
|
31
|
-
- type: Box
|
|
32
|
-
style:
|
|
33
|
-
position: absolute
|
|
34
|
-
bottom: "0"
|
|
35
|
-
left: "0"
|
|
36
|
-
right: "0"
|
|
37
|
-
direction: column
|
|
38
|
-
children:
|
|
39
|
-
- $include: components/suggestions
|
|
40
|
-
- type: Ref
|
|
41
|
-
ref: composer-bar
|
|
14
|
+
- $include: components/chat-region
|
|
@@ -16,22 +16,17 @@ inputSchema:
|
|
|
16
16
|
description: The user's request
|
|
17
17
|
|
|
18
18
|
# THE TEMPLATE TREE (State Model v2): one declaration, everything follows.
|
|
19
|
-
# Top-level order IS the priority ladder (base first, then reaction states).
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
# and legitimately drawn under the focus overlay too. Declaring it would contain it to
|
|
26
|
-
# standard and empty the chat column in every reaction state.
|
|
19
|
+
# Top-level order IS the priority ladder (base first, then reaction states). No
|
|
20
|
+
# stateOrder, no hand-written guards.
|
|
21
|
+
# NOTE: the chat itself is not a state here. Its two moods (welcome hero / live
|
|
22
|
+
# timeline) live inside the text-chat component, which both cores draw via
|
|
23
|
+
# components/chat-region. The component defaults to welcome on an empty conversation
|
|
24
|
+
# and hands over to the timeline the moment messages exist.
|
|
27
25
|
states:
|
|
28
|
-
standard:
|
|
29
|
-
states:
|
|
30
|
-
welcome: {}
|
|
26
|
+
standard: {}
|
|
31
27
|
focused: {}
|
|
32
28
|
|
|
33
29
|
preview:
|
|
34
|
-
conversation: [ markdown-renderer ]
|
|
35
30
|
focused: [ card ]
|
|
36
31
|
|
|
37
32
|
autoTrigger: false
|
package/local/scaffold.mjs
CHANGED
|
@@ -86,13 +86,18 @@ export function createProject(home, name) {
|
|
|
86
86
|
cpSync(sampleStyles, join(root, "styles"), { recursive: true });
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
// A worked example TEMPLATE (a generic chat:
|
|
90
|
-
//
|
|
91
|
-
// templates/ is never an empty folder and the first app is a rename away. Same
|
|
89
|
+
// A worked example TEMPLATE (a generic chat: focus overlay + the chat region),
|
|
90
|
+
// so templates/ is never an empty folder and the first app is a rename away. Same
|
|
92
91
|
// rule as the styles: copied only into an empty folder, then the developer's.
|
|
93
92
|
const sampleTemplate = join(dirname(fileURLToPath(import.meta.url)), "sample-template/chat");
|
|
94
93
|
if (existsSync(sampleTemplate) && readdirSync(join(root, "templates")).length === 0) {
|
|
95
94
|
cpSync(sampleTemplate, join(root, "templates/chat"), { recursive: true });
|
|
95
|
+
// Its other half: the chat CX itself (welcome hero, timeline, suggestions,
|
|
96
|
+
// composer) is a COMPONENT the template draws via `Ref`, so the surface lives once
|
|
97
|
+
// and every app of this project shares it. Copied with the template, never without
|
|
98
|
+
// it — a template whose chat-region resolves nothing renders an empty column.
|
|
99
|
+
const sampleComponent = join(dirname(fileURLToPath(import.meta.url)), "sample-component/text-chat");
|
|
100
|
+
if (existsSync(sampleComponent)) cpSync(sampleComponent, join(root, "components/text-chat"), { recursive: true });
|
|
96
101
|
}
|
|
97
102
|
return root;
|
|
98
103
|
}
|
package/package.json
CHANGED
|
@@ -715,9 +715,16 @@ export function ComponentsView({ theme, org = "all" }: { theme: ResolvedTheme; o
|
|
|
715
715
|
</>
|
|
716
716
|
)}
|
|
717
717
|
<div className={isFocused ? "min-h-0 flex-1 overflow-auto" : "min-w-0 flex-1 overflow-auto p-10"}>
|
|
718
|
+
{/* THE STAGE OFFERS ITS HEIGHT; the component decides whether to take it.
|
|
719
|
+
A single-row GRID, not a flex column: the SDK's shadow host is
|
|
720
|
+
`display: contents`, so `.uno-isolate-root` is the item here, and a grid
|
|
721
|
+
item stretches on BOTH axes by default — a flex item only stretches
|
|
722
|
+
across. That gives the isolate root a real height to resolve against,
|
|
723
|
+
so a full surface (chat, voice) fills and a card still sizes to its
|
|
724
|
+
content. */}
|
|
718
725
|
<div
|
|
719
726
|
key={`${masterState}:${previewNonce}`}
|
|
720
|
-
className={`mx-auto max-w-full ${isFocused ? "h-full" : "transition-[width] duration-200"}`}
|
|
727
|
+
className={`mx-auto max-w-full ${isFocused ? "h-full" : "grid h-full grid-rows-1 transition-[width] duration-200"}`}
|
|
721
728
|
style={{ width: sourceOpen ? "100%" : (stageWidth ?? "100%"), ...(isFocused ? { animation: "wb-focusFadeIn 0.2s ease-out" } : {}) }}
|
|
722
729
|
>
|
|
723
730
|
{selected && <UnoverseComponent client={client} store={store} chatId={CHAT_ID} nodeId={selected} theme={theme} onAction={(a) => setLastAction(typeof a === "string" ? a : a?.type ?? null)} />}
|
package/vendor/sdk/appEngine.tsx
CHANGED
|
@@ -151,7 +151,7 @@ export function AppEngine(cfg: AppConfig) {
|
|
|
151
151
|
// the ordinary case (one org, one `chat` size), and the incoming app then reported
|
|
152
152
|
// nothing: its frame sat at the host default (100%) while its core panel held its
|
|
153
153
|
// declared width, leaving a dead band beside it (observed live 2026-08-13,
|
|
154
|
-
// bpp-voice
|
|
154
|
+
// bpp-voice). Clearing the guard here makes the first report after an app
|
|
155
155
|
// switch unconditional; the guard still suppresses repeats within one app.
|
|
156
156
|
lastWidthRef.current = undefined;
|
|
157
157
|
const report = () => {
|
|
@@ -133,7 +133,7 @@ place. Work through them in order.
|
|
|
133
133
|
|
|
134
134
|
1. **Copy the folder.** `design/<source>/` → `design/<neworg>/`, keeping `styles/`, `components/`,
|
|
135
135
|
`templates/`.
|
|
136
|
-
2. **Rename the templates.** Folder AND the id inside the manifest. `bpp-chat
|
|
136
|
+
2. **Rename the templates.** Folder AND the id inside the manifest. `bpp-chat`
|
|
137
137
|
becomes `lyceum-chat-layout` in both places. Template ids are org-qualified and they
|
|
138
138
|
are referenced by string.
|
|
139
139
|
3. **Component names stay as copied.** Names are unique per org, not across orgs, so a
|
|
@@ -88,7 +88,9 @@ The rules, in the order they bite:
|
|
|
88
88
|
- **Each state owns its layout(s).** `layout:` is OPTIONAL: a state with no declaration
|
|
89
89
|
draws the layout of its own name, and `{}` is a complete state. Write `layout:` only
|
|
90
90
|
when the filename differs. A layout is never addressable on its own; only its owning
|
|
91
|
-
state selects it. Name states for what they MEAN (`detail`), never for their drawing.
|
|
91
|
+
state selects it. Name states for what they MEAN (`detail`), never for their drawing. **Substate drawings are axis-prefixed**: a step's file carries its axis key
|
|
92
|
+
(`step-register`, `callState-idle`) and is declared via `layout:`; unprefixed
|
|
93
|
+
files are arrangements (exemplars: `course-application`, `voice-chat`).
|
|
92
94
|
- **Shell vs steps.** A state's own layout is its SHELL, always on while the state is
|
|
93
95
|
active. Its nested substates are the STEPS, the only choices inside it, addressed by
|
|
94
96
|
state names (layout filenames are plumbing).
|
|
@@ -120,6 +122,24 @@ The rules, in the order they bite:
|
|
|
120
122
|
static → hardcode);
|
|
121
123
|
- workflow-fed data → **`props` with `input: true`** (the `default` is the preview mock).
|
|
122
124
|
Usually empty.
|
|
125
|
+
- **Projected-field preview rule:** any LOCKED/projected field a
|
|
126
|
+
component branches on (`callState`, `isEmpty`, `hasMessages`) must ALSO be declared as
|
|
127
|
+
a prop with a preview default: Studio's bare component preview supplies ONLY prop
|
|
128
|
+
defaults, so an undeclared projected read renders NOTHING there; live, the projected
|
|
129
|
+
value wins and the default never applies. A Ref-embedded component's root Switch
|
|
130
|
+
likewise needs a `default:` case (`view` is absent without a spawned slice).
|
|
131
|
+
- **Who owns a mood: the DRIVER decides.** Ask what WRITES the discriminant:
|
|
132
|
+
(1) the component's own buttons (`setValue`) → component substates on a private axis,
|
|
133
|
+
names from the design (`course-application`); (2) a service projecting a NAMED value
|
|
134
|
+
(`callState`) → component substates named for those values + a preview prop
|
|
135
|
+
(`voice-chat`); (3) DERIVED from conversation facts (`isEmpty`/`hasMessages`) → the
|
|
136
|
+
TEMPLATE tier owns it: a condition-guarded mood, or guarded drawings inside an
|
|
137
|
+
embedded component reacting to the same facts — the template has the state,
|
|
138
|
+
components just react. NEVER model a derived mood as component named substates, and
|
|
139
|
+
never borrow another field's values (`lifecycle`) as state names (bpp `text-chat`). Declare the axis as a prop with enum + default
|
|
140
|
+
(preview only; live the projection wins), give the root Switch a `default:` case for
|
|
141
|
+
Ref placement, and prefix the step drawings with the axis (`callState-idle`,
|
|
142
|
+
`lifecycle-active`). Exemplars: `voice-chat`, bpp `text-chat`.
|
|
123
143
|
- **Prop names = the data contract. Never invent them.** Source data hydrates props
|
|
124
144
|
BY NAME (as-is, no mapping); a name the source doesn't carry silently renders the
|
|
125
145
|
preview default (tell: title streams, image stays mock). Content-attached cards use
|
|
@@ -9,7 +9,7 @@ Everything in the component playbook (closed vocabulary, tokens, scale steps) ap
|
|
|
9
9
|
here too. **Study an exemplar before writing**: templates are always a project's own
|
|
10
10
|
(none ship in the base set), so your references are the canonical manifest tree inlined
|
|
11
11
|
below, [design/templates](https://docs.unoverse.ai/design/templates.md), and any template
|
|
12
|
-
already in the workspace. (Monorepo: `design/sab/templates/sab-chat
|
|
12
|
+
already in the workspace. (Monorepo: `design/sab/templates/sab-chat`.)
|
|
13
13
|
|
|
14
14
|
## THE model: the component drives; the template reacts by name
|
|
15
15
|
|
/package/local/{sample-template/chat → sample-component/text-chat}/components/assistant-turn.yaml
RENAMED
|
File without changes
|
|
File without changes
|
/package/local/{sample-template/chat → sample-component/text-chat}/components/suggestions.yaml
RENAMED
|
File without changes
|
/package/local/{sample-template/chat → sample-component/text-chat}/components/thinking-dots.yaml
RENAMED
|
File without changes
|
/package/local/{sample-template/chat → sample-component/text-chat}/components/user-turn.yaml
RENAMED
|
File without changes
|