@consciousclouds/operator-shell 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +80 -31
- package/dist/chief/ChiefDrawer.d.ts +34 -2
- package/dist/chief/ChiefDrawer.d.ts.map +1 -1
- package/dist/chief/ChiefDrawer.js +43 -30
- package/dist/chief/ChiefDrawer.js.map +1 -1
- package/dist/chief/ChiefHeaderBar.d.ts +19 -0
- package/dist/chief/ChiefHeaderBar.d.ts.map +1 -0
- package/dist/chief/ChiefHeaderBar.js +7 -0
- package/dist/chief/ChiefHeaderBar.js.map +1 -0
- package/dist/chief/ChiefMarkdown.d.ts +12 -0
- package/dist/chief/ChiefMarkdown.d.ts.map +1 -0
- package/dist/chief/ChiefMarkdown.js +95 -0
- package/dist/chief/ChiefMarkdown.js.map +1 -0
- package/dist/chief/ChiefPanel.d.ts +44 -1
- package/dist/chief/ChiefPanel.d.ts.map +1 -1
- package/dist/chief/ChiefPanel.js +79 -29
- package/dist/chief/ChiefPanel.js.map +1 -1
- package/dist/chief/ChiefRegion.d.ts +44 -1
- package/dist/chief/ChiefRegion.d.ts.map +1 -1
- package/dist/chief/ChiefRegion.js +63 -27
- package/dist/chief/ChiefRegion.js.map +1 -1
- package/dist/chief/ChiefSession.d.ts +46 -10
- package/dist/chief/ChiefSession.d.ts.map +1 -1
- package/dist/chief/ChiefSession.js +252 -6
- package/dist/chief/ChiefSession.js.map +1 -1
- package/dist/chief/ChiefTrigger.d.ts +26 -0
- package/dist/chief/ChiefTrigger.d.ts.map +1 -0
- package/dist/chief/ChiefTrigger.js +21 -0
- package/dist/chief/ChiefTrigger.js.map +1 -0
- package/dist/chief/conversation-adapter.d.ts +70 -0
- package/dist/chief/conversation-adapter.d.ts.map +1 -0
- package/dist/chief/conversation-adapter.js +26 -0
- package/dist/chief/conversation-adapter.js.map +1 -0
- package/dist/chief/conversation-identity.d.ts +48 -0
- package/dist/chief/conversation-identity.d.ts.map +1 -0
- package/dist/chief/conversation-identity.js +100 -0
- package/dist/chief/conversation-identity.js.map +1 -0
- package/dist/chief/personality-display.d.ts +56 -0
- package/dist/chief/personality-display.d.ts.map +1 -0
- package/dist/chief/personality-display.js +52 -0
- package/dist/chief/personality-display.js.map +1 -0
- package/dist/chief/turn-adapter.d.ts +45 -0
- package/dist/chief/turn-adapter.d.ts.map +1 -1
- package/dist/chief/use-chief-turn.d.ts +127 -14
- package/dist/chief/use-chief-turn.d.ts.map +1 -1
- package/dist/chief/use-chief-turn.js +284 -28
- package/dist/chief/use-chief-turn.js.map +1 -1
- package/dist/chief/use-controlled-open.d.ts +2 -0
- package/dist/chief/use-controlled-open.d.ts.map +1 -0
- package/dist/chief/use-controlled-open.js +27 -0
- package/dist/chief/use-controlled-open.js.map +1 -0
- package/dist/chief/use-smooth-stream.d.ts +8 -0
- package/dist/chief/use-smooth-stream.d.ts.map +1 -0
- package/dist/chief/use-smooth-stream.js +128 -0
- package/dist/chief/use-smooth-stream.js.map +1 -0
- package/dist/flavor/types.d.ts +36 -21
- package/dist/flavor/types.d.ts.map +1 -1
- package/dist/frame/ComposedWorkspace.d.ts +39 -0
- package/dist/frame/ComposedWorkspace.d.ts.map +1 -0
- package/dist/frame/ComposedWorkspace.js +94 -0
- package/dist/frame/ComposedWorkspace.js.map +1 -0
- package/dist/frame/OperatorShell.d.ts +115 -13
- package/dist/frame/OperatorShell.d.ts.map +1 -1
- package/dist/frame/OperatorShell.js +200 -12
- package/dist/frame/OperatorShell.js.map +1 -1
- package/dist/guard/permissions.d.ts +2 -2
- package/dist/guard/permissions.js +2 -2
- package/dist/header/OperatorHeader.d.ts +15 -2
- package/dist/header/OperatorHeader.d.ts.map +1 -1
- package/dist/header/OperatorHeader.js +3 -3
- package/dist/header/OperatorHeader.js.map +1 -1
- package/dist/icons/registry.d.ts +7 -1
- package/dist/icons/registry.d.ts.map +1 -1
- package/dist/icons/registry.js +31 -2
- package/dist/icons/registry.js.map +1 -1
- package/dist/index.d.ts +24 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -17
- package/dist/index.js.map +1 -1
- package/dist/sidebar/OperatorSidebar.d.ts +16 -1
- package/dist/sidebar/OperatorSidebar.d.ts.map +1 -1
- package/dist/sidebar/OperatorSidebar.js +13 -10
- package/dist/sidebar/OperatorSidebar.js.map +1 -1
- package/dist/workspace/FormWorkspace.d.ts +2 -3
- package/dist/workspace/FormWorkspace.d.ts.map +1 -1
- package/dist/workspace/FormWorkspace.js.map +1 -1
- package/dist/workspace/session-adapter.d.ts +95 -0
- package/dist/workspace/session-adapter.d.ts.map +1 -0
- package/dist/workspace/session-adapter.js +29 -0
- package/dist/workspace/session-adapter.js.map +1 -0
- package/package.json +10 -5
- package/styles/source.css +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,72 @@
|
|
|
2
2
|
|
|
3
3
|
Versioned on the independent frontend-SDK lifecycle (NOT `contract_version`).
|
|
4
4
|
|
|
5
|
+
## [0.2.0] — 2026-07-05
|
|
6
|
+
|
|
7
|
+
The first post-publish polish of the AI Region — the Chief window rebuilt to
|
|
8
|
+
the reference operator surface's proven quality. Behavior parity throughout:
|
|
9
|
+
turn lifecycle, routed-directive handling, the in-console guard, ⌘J, and the
|
|
10
|
+
TurnAdapter contract are IDENTICAL — only chrome/UX changed.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Chrome config** (`OperatorShellProps.chrome`) — layout philosophy as
|
|
15
|
+
DEFAULTS-AND-OVERRIDES (a composition concern, deliberately not Flavor
|
|
16
|
+
data): `chiefBehavior: 'push' | 'overlay' | 'rail'` (default `push`),
|
|
17
|
+
`chiefWidth` (default 420), `workspaceChrome: 'framed' | 'edge-to-edge'`
|
|
18
|
+
(default `framed` — the workspace floats as a rounded container, a sibling
|
|
19
|
+
card beside the Chief panel, the layout gap animating with the panel).
|
|
20
|
+
- **Push behavior (new default)** — the responsive hybrid, one component:
|
|
21
|
+
overlay drawer below `lg` (fixed `inset-y-4 right-4`, clickable scrim,
|
|
22
|
+
300ms translate+opacity), in-flow push panel at `lg+` animating
|
|
23
|
+
`w-0 → w-(--chief-width)` so the workspace visibly reflows. Closed by
|
|
24
|
+
default; summoned by the new header **ChiefTrigger** or ⌘J; a
|
|
25
|
+
dismissible, non-modal peer surface (Esc + outside-click close, composer
|
|
26
|
+
focused on open, focus returned to the trigger on close — the full
|
|
27
|
+
assistant-surface option set). `rail` preserves the previous
|
|
28
|
+
always-visible posture; `overlay` floats at every width.
|
|
29
|
+
- **Suggestion chips** — inert `flavor.chief.suggestions?: string[]`
|
|
30
|
+
(Declarative-Flavor law); a chip submits its text through the SAME
|
|
31
|
+
`submitPrompt` the composer uses.
|
|
32
|
+
- **Markdown answers** — `ChiefMarkdown` over react-markdown + remark-gfm
|
|
33
|
+
(MIT), token-class styled, **sanitized by default** (no raw HTML); pulse
|
|
34
|
+
cursor ▍ rides the stream; separate color-coded metadata bar; pill
|
|
35
|
+
composer; `h-12` header bar with icon · title · close ✕.
|
|
36
|
+
- **Personality-display seam (D-Q2)** — `personalityDisplay?:
|
|
37
|
+
{ displayName, iconRef?, accentRef? }` threaded OperatorShell → Chief
|
|
38
|
+
region: the seam the Factory personality record feeds after the D-Q7
|
|
39
|
+
split. Precedence `personalityDisplay.displayName > flavor.chief.title >
|
|
40
|
+
"Chief"` (`resolveChiefTitle`); `iconRef` via the icon registry,
|
|
41
|
+
`accentRef` via token ROLE names (`resolvePersonalityAccent`) —
|
|
42
|
+
references only, fail-closed, never raw values.
|
|
43
|
+
- **Notifications slot** — `OperatorShellProps.notifications?:
|
|
44
|
+
React.ReactNode` (threaded to the header): the product injects its own
|
|
45
|
+
notifications affordance; absent ⇒ nothing renders. Replaces the previous
|
|
46
|
+
built-in inert bell button — a missing affordance beats a fake one.
|
|
47
|
+
- **Icon vocabulary grown** — the built-in operator registry now ships the
|
|
48
|
+
common operator-console nouns (`settings` · `users` · `database` ·
|
|
49
|
+
`server` · `shield` · `key` · `globe` · `folder` · `file-text` · `search`
|
|
50
|
+
· `bell` · `layers` · `terminal` · `cpu` · `cloud` · `package` ·
|
|
51
|
+
`git-branch` · `workflow` · `book` · `chart-line`) alongside the original
|
|
52
|
+
nine. Unknown names still fail soft to the neutral placeholder; product
|
|
53
|
+
extensions still override.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- `flavor.chief.placement` is **deprecated** (honored as a hint: `rail` →
|
|
58
|
+
`rail`, `drawer` → `overlay`; the chrome config wins) — layout philosophy
|
|
59
|
+
moved to the composition root.
|
|
60
|
+
- `ChiefDrawer` is now the floating overlay card (previously the sheet
|
|
61
|
+
primitive); it keeps a floating corner trigger only when mounted
|
|
62
|
+
standalone without an external trigger.
|
|
63
|
+
- Default panel width 340 → 420.
|
|
64
|
+
- The header's built-in bell button is REMOVED in favor of the
|
|
65
|
+
`notifications` slot (it was inert chrome — no notification source ships
|
|
66
|
+
in the shell).
|
|
67
|
+
- Dependencies: `@consciousclouds/assistant-surface`,
|
|
68
|
+
`@consciousclouds/canvas-sdk`, `@consciousclouds/canvas-runtime` pinned to
|
|
69
|
+
`^0.2.1` (published as caret ranges via the workspace protocol).
|
|
70
|
+
|
|
5
71
|
## [0.1.0] — 2026-07-04
|
|
6
72
|
|
|
7
73
|
### Added
|
package/README.md
CHANGED
|
@@ -8,13 +8,16 @@ shadcn/ui registry** (sidebar-16's header-above-sidebar geometry, sidebar-07's
|
|
|
8
8
|
icon-collapsible rail) over `@consciousclouds/ui` primitives:
|
|
9
9
|
|
|
10
10
|
- **Frame** — `OperatorShell`: sticky full-width header, icon-collapsible
|
|
11
|
-
left sidebar (⌘B, mobile sheet),
|
|
12
|
-
(Chief —
|
|
11
|
+
left sidebar (⌘B, mobile sheet), the workspace (framed or edge-to-edge —
|
|
12
|
+
the `chrome` config), and the AI Region (Chief — summoned by the header
|
|
13
|
+
trigger or **⌘J/Ctrl+J**, the palette's ⌘K twin; closed-by-default push
|
|
14
|
+
panel unless the chrome says otherwise).
|
|
13
15
|
- **Header** — brand slot (rendered through the Brand Platform's
|
|
14
16
|
`BrandLogo` + `useBrand`; the shell never bakes an image or a mark string),
|
|
15
|
-
the search button that opens the command palette, notifications
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
the search button that opens the command palette, a **notifications
|
|
18
|
+
slot** (`notifications` shell prop — the product injects its own
|
|
19
|
+
affordance; absent ⇒ nothing renders), theme toggle (the Token System's
|
|
20
|
+
`useTheme`), and a **profile slot** with a neutral default menu.
|
|
18
21
|
- **Command palette** — `CommandPalette` (mounted by the frame; ⌘K/Ctrl+K
|
|
19
22
|
and the header search button open the one instance; Chief's invocation
|
|
20
23
|
binding sits next to it — **⌘J/Ctrl+J**, see the Chief region) over the registry
|
|
@@ -52,8 +55,12 @@ icon-collapsible rail) over `@consciousclouds/ui` primitives:
|
|
|
52
55
|
- **Icon Platform** — the string-name → icon resolution seam. The Flavor
|
|
53
56
|
declares **inert string names** (`icon: "home"` — never a component,
|
|
54
57
|
Declarative-Flavor law); the shell ships the built-in operator vocabulary
|
|
55
|
-
(`OPERATOR_ICONS`:
|
|
56
|
-
`
|
|
58
|
+
(`OPERATOR_ICONS`: the common operator-console nouns — `home`, `bot`,
|
|
59
|
+
`plug`, `wrench`, `boxes`, `activity`, `bar-chart-3`, `route`,
|
|
60
|
+
`waypoints`, `settings`, `users`, `database`, `server`, `shield`, `key`,
|
|
61
|
+
`globe`, `folder`, `file-text`, `search`, `bell`, `layers`, `terminal`,
|
|
62
|
+
`cpu`, `cloud`, `package`, `git-branch`, `workflow`, `book`,
|
|
63
|
+
`chart-line`) and the product **extends** it through the `icons` shell prop
|
|
57
64
|
(`IconRegistry`: string name → Lucide component; extensions may
|
|
58
65
|
deliberately override built-ins). Unknown names **fail closed** to the
|
|
59
66
|
exported `UNKNOWN_ICON` — one deterministic neutral glyph for every
|
|
@@ -90,10 +97,9 @@ icon-collapsible rail) over `@consciousclouds/ui` primitives:
|
|
|
90
97
|
and honest: no provider ⇒ no chrome; ONE configured environment ⇒ a
|
|
91
98
|
single-entry **indicator** (not a pretend menu); two or more named targets
|
|
92
99
|
⇒ a dropdown switcher.
|
|
93
|
-
- **Workspace-switcher seam** — typed + documented, **INERT until
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
workspace existing at all): the Flavor may declare
|
|
100
|
+
- **Workspace-switcher seam** — typed + documented, **INERT** until the
|
|
101
|
+
platform's control plane keys enrollment per (project, environment) — the
|
|
102
|
+
prerequisite for a second workspace existing at all: the Flavor may declare
|
|
97
103
|
`workspaces?: OperatorFlavorWorkspace[]` (labels/refs only) and the shell
|
|
98
104
|
ships the `workspaceSwitcher` slot on `OperatorShellProps` (rendered in
|
|
99
105
|
the sidebar header). Products inject nothing today, the shell renders
|
|
@@ -137,26 +143,68 @@ icon-collapsible rail) over `@consciousclouds/ui` primitives:
|
|
|
137
143
|
vocabulary · `displayName` · optional `icon` by NAME · `Component`
|
|
138
144
|
receiving `WorkspaceComponentProps<TInput>`) and include it in your
|
|
139
145
|
`createWorkspaceRegistry` composition alongside the built-ins.
|
|
140
|
-
- **Chief region** — the AI Region. `ChiefRegion` resolves
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
146
|
+
- **Chief region** — the AI Region. `ChiefRegion` resolves a layout
|
|
147
|
+
**behavior** to a presentation; EVERY behavior runs the identical turn
|
|
148
|
+
flow (`useChiefTurn` over the injected TurnAdapter) and body
|
|
149
|
+
(`ChiefSession`), mounted through the headless
|
|
144
150
|
`@consciousclouds/assistant-surface` hook. Turn lifecycle,
|
|
145
151
|
routed-directive handling (directive → href validated against routes
|
|
146
|
-
**derived from `flavor.nav`**), and streaming/routed/error states.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
**derived from `flavor.nav`**), and streaming/routed/error states.
|
|
153
|
+
Behavior moves the panel and NOTHING else — it can never widen Chief's
|
|
154
|
+
reach.
|
|
155
|
+
- **Behaviors** (`chrome.chiefBehavior` on `OperatorShell` — layout
|
|
156
|
+
philosophy is a COMPOSITION concern, deliberately a prop and not Flavor
|
|
157
|
+
data; the SDK ships the defaults, the app overrides at its composition
|
|
158
|
+
root): **`push`** (default) — the responsive hybrid, one component:
|
|
159
|
+
below `lg` a fixed overlay drawer sliding from the right over a
|
|
160
|
+
clickable scrim; at `lg+` an in-flow peer panel animating `w-0 →
|
|
161
|
+
w-(--chief-width)` (300ms) so the workspace visibly reflows. Closed by
|
|
162
|
+
default; summoned by the header **ChiefTrigger** (icon + display name)
|
|
163
|
+
or ⌘J. A dismissible, non-modal peer surface: Esc + outside-click
|
|
164
|
+
close, composer focused on open, focus returned to the trigger on
|
|
165
|
+
close. **`overlay`** — the floating drawer at every width. **`rail`** —
|
|
166
|
+
the always-visible inflow rail at xl+ (the previous default posture; the
|
|
167
|
+
overlay below xl keeps Chief reachable). `chrome.chiefWidth` sets the
|
|
168
|
+
panel width (default 420). The legacy `flavor.chief.placement` is
|
|
169
|
+
honored as a hint when the chrome declares nothing (`rail` → `rail`,
|
|
170
|
+
`drawer` → `overlay`); `resolveChiefBehavior` is the pure rule.
|
|
171
|
+
- **Session body** — the empty state renders the Flavor's hint card plus
|
|
172
|
+
**suggestion chips** from inert `flavor.chief.suggestions` (strings
|
|
173
|
+
only, Declarative-Flavor law; a chip submits its text through the SAME
|
|
174
|
+
`submitPrompt` the composer uses). Streamed answers render as
|
|
175
|
+
**markdown** (`ChiefMarkdown`: react-markdown + remark-gfm, both MIT;
|
|
176
|
+
token-class styling; **sanitized by default — raw HTML never renders**)
|
|
177
|
+
with a pulse cursor ▍ riding the stream; a separate color-coded
|
|
178
|
+
metadata bar carries routed (`routed → /path · 0 tokens`) /
|
|
179
|
+
off-console / error outcomes; the composer is a pill input.
|
|
180
|
+
- **Personality display (the D-Q2 seam)** — `personalityDisplay?:
|
|
181
|
+
{ displayName, iconRef?, accentRef? }` on `OperatorShell`, threaded to
|
|
182
|
+
the Chief region: the seam the **Factory personality record** will feed
|
|
183
|
+
after the D-Q7 personality split (the shell renders "the current
|
|
184
|
+
personality" and never knows which). `displayName` is literal —
|
|
185
|
+
precedence **`personalityDisplay.displayName` > `flavor.chief.title` >
|
|
186
|
+
`"Chief"`** (`resolveChiefTitle` is the pure rule). `iconRef` resolves
|
|
187
|
+
through the **icon registry** (product extensions apply; unknown ⇒ the
|
|
188
|
+
deterministic fallback) and `accentRef` through the **Token System's
|
|
189
|
+
role names** (`resolvePersonalityAccent`; unknown role ⇒ the default
|
|
190
|
+
token classes stand) — **REFERENCES ONLY, never raw assets or hex
|
|
191
|
+
values**: Brand stays the single owner of appearance.
|
|
150
192
|
**Invocation parity — ⌘J/Ctrl+J** (the palette's ⌘K twin, shell-owned,
|
|
151
193
|
wired where the mounted presentation lives just as ⌘K lives with the
|
|
152
|
-
palette): on the **rail** it focuses the composer; on
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
194
|
+
palette): on the **rail** it focuses the composer; on **push/overlay** it
|
|
195
|
+
summons/dismisses through the one open state the trigger, Esc,
|
|
196
|
+
outside-click, and the scrim all drive. Exactly one presentation mounts
|
|
197
|
+
at a time (single-surface rule), so exactly one listener is ever
|
|
156
198
|
attached. Shift/alt refuse the match — ⌘⇧J stays the browser's downloads
|
|
157
|
-
chord
|
|
158
|
-
decoration). `isChiefShortcut` is the exported pure match rule;
|
|
199
|
+
chord. `isChiefShortcut` is the exported pure match rule;
|
|
159
200
|
`CHIEF_SHORTCUT_LABEL` carries the display copy.
|
|
201
|
+
- **Workspace chrome** — `chrome.workspaceChrome` on `OperatorShell`:
|
|
202
|
+
**`framed`** (default) renders the workspace inside a rounded floating
|
|
203
|
+
container (breathing room; a sibling card beside the Chief panel, with
|
|
204
|
+
the layout gap animating alongside the panel's width) — a generalized
|
|
205
|
+
mechanism, proven by a product surface that needed it; **`edge-to-edge`**
|
|
206
|
+
is the flat layout. Future shells (Business / Consumer / Mobile) choose
|
|
207
|
+
their own defaults over the same mechanism.
|
|
160
208
|
|
|
161
209
|
**The shell owns the panel; the product owns the wire.** Transport is injected
|
|
162
210
|
via a **TurnAdapter** typed against the published turn vocabulary
|
|
@@ -194,8 +242,9 @@ data and mount `BrandProvider`. See `@consciousclouds/brand`'s README.
|
|
|
194
242
|
**4. Flavor.** Write ONE inert `OperatorFlavor` per surface: the product
|
|
195
243
|
block, nav groups (route strings + icon NAMES + optional permission
|
|
196
244
|
references), `defaultLanding`, optional palette `commands` (references),
|
|
197
|
-
`inspector.entityKinds` (references), and Chief decoration (
|
|
198
|
-
an inert personality reference — never an endpoint
|
|
245
|
+
`inspector.entityKinds` (references), and Chief decoration (copy +
|
|
246
|
+
`suggestions` strings + an inert personality reference — never an endpoint;
|
|
247
|
+
layout behavior belongs to the shell's `chrome` prop, not the Flavor).
|
|
199
248
|
|
|
200
249
|
**5. The four injections.** Mount the shell from a **client component**
|
|
201
250
|
(adapters/resolvers are functions — they cannot be serialized from a server
|
|
@@ -280,9 +329,8 @@ An `inspect` action needs its entity kind declared in
|
|
|
280
329
|
your environment targets to light up the environment switcher; wire a
|
|
281
330
|
favicon from your Brand's `favicon` role.
|
|
282
331
|
|
|
283
|
-
The reference implementation of every step is
|
|
284
|
-
|
|
285
|
-
`lib/{brand,flavor,turn-adapter,workspaces,search-sources}.ts`).
|
|
332
|
+
The reference implementation of every step is the platform's own admin
|
|
333
|
+
console — the proving ground every mechanism here graduated from.
|
|
286
334
|
|
|
287
335
|
## The membrane gates — what may never enter this package
|
|
288
336
|
|
|
@@ -311,7 +359,8 @@ Runtime: `ui` · `brand` · `assistant-surface` · `conductor-sdk` /
|
|
|
311
359
|
`conductor-react` (types + directive handling) · `frontend-runtime`
|
|
312
360
|
(environment context — consumed, never rebuilt) · `canvas-runtime` /
|
|
313
361
|
`canvas-sdk` (the canvas workspace type — consumed, never rebuilt) ·
|
|
314
|
-
`lucide-react
|
|
362
|
+
`lucide-react` · `react-markdown` + `remark-gfm` (MIT — Chief's streamed
|
|
363
|
+
answers; sanitized by default, no raw-HTML plugin). Peers: `react`, `next` (>=15 <17), and
|
|
315
364
|
`@consciousclouds/tokens` — tokens is a peer (not a bundled dep) because
|
|
316
365
|
theme state is token machinery: the app mounts tokens' `ThemeProvider`; the
|
|
317
366
|
shell's theme toggle reads the same single instance through tokens'
|
|
@@ -1,11 +1,43 @@
|
|
|
1
|
+
import type { CanvasDefinition } from "@consciousclouds/canvas-sdk";
|
|
1
2
|
import type { OperatorFlavor } from "../flavor/types.js";
|
|
3
|
+
import type { IconRegistry } from "../icons/registry.js";
|
|
4
|
+
import { type ChiefWorkspacesRegion } from "./ChiefSession.js";
|
|
5
|
+
import type { ConversationAdapter } from "./conversation-adapter.js";
|
|
6
|
+
import { type PersonalityDisplay } from "./personality-display.js";
|
|
2
7
|
import type { TurnAdapter } from "./turn-adapter.js";
|
|
8
|
+
import { type ComposedMeta } from "./use-chief-turn.js";
|
|
3
9
|
export interface ChiefDrawerProps {
|
|
4
10
|
flavor: OperatorFlavor;
|
|
5
11
|
/** The product's transport (P1-1). The shell owns the panel, never the wire. */
|
|
6
12
|
adapter: TurnAdapter;
|
|
7
|
-
/**
|
|
13
|
+
/** Drawer width in px (default 420; never wider than the viewport − 2rem). */
|
|
14
|
+
width?: number;
|
|
15
|
+
/** Controlled open state. Omit for uncontrolled (closed by default). */
|
|
16
|
+
open?: boolean;
|
|
17
|
+
/** Open-state observer/setter — fires for every open/close, however caused. */
|
|
18
|
+
onOpenChange?: (open: boolean) => void;
|
|
19
|
+
/**
|
|
20
|
+
* External trigger (e.g. the shell header's ChiefTrigger): excluded from
|
|
21
|
+
* outside-click dismissal; receives focus back on close. When provided,
|
|
22
|
+
* the floating fallback trigger does not render.
|
|
23
|
+
*/
|
|
24
|
+
getTriggerElement?: () => HTMLElement | null;
|
|
25
|
+
/** Display identity from the Factory personality record (D-Q2 seam). */
|
|
26
|
+
personalityDisplay?: PersonalityDisplay;
|
|
27
|
+
/** Icon-registry extensions for `personalityDisplay.iconRef` resolution. */
|
|
28
|
+
icons?: IconRegistry;
|
|
29
|
+
/** Brand icon family (read-and-defaulted by the registry). */
|
|
30
|
+
iconFamily?: string;
|
|
31
|
+
/** The compose→center seam — forwarded verbatim to useChiefTurn (see ChiefRegion). */
|
|
32
|
+
onComposed?: (canvas: CanvasDefinition, meta: ComposedMeta) => void;
|
|
33
|
+
/** Composition activity (real tool events) — forwarded verbatim to useChiefTurn. */
|
|
34
|
+
onComposeActivity?: (phase: "composing" | "idle") => void;
|
|
35
|
+
/** The transcript transport — forwarded verbatim to useChiefTurn (fail-closed slot). */
|
|
36
|
+
conversationAdapter?: ConversationAdapter;
|
|
37
|
+
/** Kept workspaces for the drawer's Workspaces tab (fail-closed slot). */
|
|
38
|
+
workspaces?: ChiefWorkspacesRegion;
|
|
39
|
+
/** Extra classes on the floating fallback trigger button. */
|
|
8
40
|
triggerClassName?: string;
|
|
9
41
|
}
|
|
10
|
-
export declare function ChiefDrawer({ flavor, adapter, triggerClassName }: ChiefDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export declare function ChiefDrawer({ flavor, adapter, width, open: openProp, onOpenChange, getTriggerElement, personalityDisplay, icons, iconFamily, onComposed, onComposeActivity, conversationAdapter, workspaces, triggerClassName, }: ChiefDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
11
43
|
//# sourceMappingURL=ChiefDrawer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChiefDrawer.d.ts","sourceRoot":"","sources":["../../src/chief/ChiefDrawer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChiefDrawer.d.ts","sourceRoot":"","sources":["../../src/chief/ChiefDrawer.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAGpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAgB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGtE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,gFAAgF;IAChF,OAAO,EAAE,WAAW,CAAC;IACrB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAC7C,wEAAwE;IACxE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACpE,oFAAoF;IACpF,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,KAAK,IAAI,CAAC;IAC1D,wFAAwF;IACxF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,0EAA0E;IAC1E,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,OAAO,EACP,KAAW,EACX,IAAI,EAAE,QAAQ,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,EACL,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,gBAAgB,GACjB,EAAE,gBAAgB,2CAgFlB"}
|
|
@@ -1,49 +1,62 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* ChiefDrawer — the AI Region's
|
|
5
|
-
* (useChiefTurn + ChiefSession, shared verbatim with the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* ChiefDrawer — the AI Region's OVERLAY placement: the same Chief content
|
|
5
|
+
* (useChiefTurn + ChiefSession, shared verbatim with the inflow panel) as a
|
|
6
|
+
* floating drawer card — `fixed inset-y-4 right-4`, rounded, shadowed,
|
|
7
|
+
* sliding in from the right (300ms translate + opacity) over a clickable
|
|
8
|
+
* backdrop scrim — at EVERY viewport width. It is both the standalone
|
|
9
|
+
* `overlay` behavior and the below-breakpoint fallback of the rail.
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* trigger
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* every dismissal back through the same onOpenChange. The hook stays
|
|
15
|
-
* non-modal/non-dismissible so neither layer duplicates the other's job.
|
|
11
|
+
* A dismissible, non-modal peer surface via assistant-surface's full option
|
|
12
|
+
* set: Esc + outside-click close, composer focused on open, focus returned
|
|
13
|
+
* to the trigger on close. When no external trigger is supplied (standalone
|
|
14
|
+
* mounts outside OperatorShell), a floating corner trigger renders as the
|
|
15
|
+
* fallback so the drawer stays reachable.
|
|
16
16
|
*
|
|
17
|
-
* The turn state lives OUTSIDE the
|
|
18
|
-
* closing and reopening
|
|
19
|
-
*
|
|
20
|
-
* never owns the wire (P1-1).
|
|
17
|
+
* The turn state lives OUTSIDE the animated chrome (in this component), so
|
|
18
|
+
* closing and reopening keeps the thread. Transport is the injected
|
|
19
|
+
* TurnAdapter's — the shell never owns the wire (P1-1).
|
|
21
20
|
*/
|
|
22
21
|
import * as React from "react";
|
|
23
|
-
import { Sparkles } from "lucide-react";
|
|
24
22
|
import { useAssistantSurface } from "@consciousclouds/assistant-surface";
|
|
25
|
-
import { Button,
|
|
23
|
+
import { Button, cn } from "@consciousclouds/ui";
|
|
24
|
+
import { ChiefHeaderBar } from "./ChiefHeaderBar.js";
|
|
26
25
|
import { ChiefSession } from "./ChiefSession.js";
|
|
26
|
+
import { resolvePersonalityAccent, resolvePersonalityIcon, } from "./personality-display.js";
|
|
27
27
|
import { useChiefShortcut } from "./use-chief-shortcut.js";
|
|
28
28
|
import { useChiefTurn } from "./use-chief-turn.js";
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
//
|
|
29
|
+
import { useControlledOpen } from "./use-controlled-open.js";
|
|
30
|
+
export function ChiefDrawer({ flavor, adapter, width = 420, open: openProp, onOpenChange, getTriggerElement, personalityDisplay, icons, iconFamily, onComposed, onComposeActivity, conversationAdapter, workspaces, triggerClassName, }) {
|
|
31
|
+
const [open, setOpen] = useControlledOpen(openProp, onOpenChange);
|
|
32
|
+
const session = useChiefTurn({ flavor, adapter, personalityDisplay, onComposed, onComposeActivity, conversationAdapter });
|
|
33
|
+
const composerRef = React.useRef(null);
|
|
34
|
+
const Icon = resolvePersonalityIcon(personalityDisplay, icons, iconFamily);
|
|
35
|
+
const accentColor = resolvePersonalityAccent(personalityDisplay?.accentRef);
|
|
36
|
+
// The shell-owned Chief keybinding (⌘J / Ctrl+J): summon/dismiss through
|
|
37
|
+
// the SAME setOpen the trigger, Esc, outside-click, and the scrim drive —
|
|
38
|
+
// one open state, whoever moves it.
|
|
39
|
+
useChiefShortcut(() => setOpen(!open));
|
|
40
|
+
// Assistant-surface lifecycle (same surface id in every placement — one AI
|
|
41
|
+
// Region per application): the full dismissible peer-panel option set —
|
|
42
|
+
// non-modal (no trap, no scroll lock), Esc + outside-click close, composer
|
|
43
|
+
// focus on open, focus back to the trigger on close.
|
|
41
44
|
const surface = useAssistantSurface({
|
|
42
45
|
open,
|
|
43
46
|
onOpenChange: setOpen,
|
|
44
47
|
surfaceId: "operator-shell-chief",
|
|
45
48
|
"aria-label": session.title,
|
|
49
|
+
modal: false,
|
|
50
|
+
dismissible: true,
|
|
51
|
+
// EXPLICIT-CLOSE (owner): only ✕ / trigger / Esc — never an outside click.
|
|
52
|
+
closeOnOutsideClick: false,
|
|
53
|
+
focusOnOpen: () => composerRef.current,
|
|
54
|
+
getTriggerElement,
|
|
46
55
|
});
|
|
47
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", ref: surface.triggerRef, ...surface.triggerProps, className: cn("fixed right-4 bottom-4 z-40 gap-2 rounded-full shadow-lg", triggerClassName), "aria-label": `Open ${session.title}`, children: [_jsx(
|
|
56
|
+
return (_jsxs(_Fragment, { children: [!getTriggerElement && (_jsxs(Button, { type: "button", ref: surface.triggerRef, ...surface.triggerProps, className: cn("fixed right-4 bottom-4 z-40 gap-2 rounded-full shadow-lg", triggerClassName), "aria-label": `Open ${session.title}`, children: [_jsx(Icon, { className: "size-4" }), session.title] })), _jsx("div", { "aria-hidden": true,
|
|
57
|
+
// No click-to-close: explicit-close only (✕ / trigger / Esc).
|
|
58
|
+
className: cn("fixed inset-0 z-40 bg-black/30 transition-opacity duration-(--motion-duration-base)", open ? "opacity-100" : "pointer-events-none opacity-0") }), _jsxs("aside", { ref: surface.surfaceRef, ...surface.surfaceProps, role: "dialog", style: { "--chief-width": `${width}px` }, className: cn("fixed inset-y-4 right-4 z-50 flex w-[min(var(--chief-width),calc(100vw-2rem))] flex-col overflow-hidden rounded-xl bg-muted/50 shadow-2xl backdrop-blur-xl", "transition-all duration-(--motion-duration-base) ease-(--motion-ease-standard)", open
|
|
59
|
+
? "translate-x-0 opacity-100"
|
|
60
|
+
: "pointer-events-none invisible translate-x-[calc(100%+1.5rem)] opacity-0"), children: [_jsx(ChiefHeaderBar, { title: session.title, icon: Icon, accentColor: accentColor, onClose: () => setOpen(false) }), _jsx(ChiefSession, { session: session, composerRef: composerRef, accentColor: accentColor, workspaces: workspaces })] })] }));
|
|
48
61
|
}
|
|
49
62
|
//# sourceMappingURL=ChiefDrawer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChiefDrawer.js","sourceRoot":"","sources":["../../src/chief/ChiefDrawer.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb
|
|
1
|
+
{"version":3,"file":"ChiefDrawer.js","sourceRoot":"","sources":["../../src/chief/ChiefDrawer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChiefHeaderBar — the AI Region's shared header chrome: personality icon +
|
|
3
|
+
* title on the left, an optional close ✕ on the right (`h-12 px-4` over a
|
|
4
|
+
* soft `border-border/50` rule). Rendered identically by every placement;
|
|
5
|
+
* the rail simply passes no `onClose` (always-visible mode has nothing to
|
|
6
|
+
* close). Icon and accent arrive RESOLVED (registry component + token-role
|
|
7
|
+
* color) — references were resolved upstream, raw values never enter here.
|
|
8
|
+
*/
|
|
9
|
+
import type { LucideIcon } from "lucide-react";
|
|
10
|
+
export interface ChiefHeaderBarProps {
|
|
11
|
+
title: string;
|
|
12
|
+
icon: LucideIcon;
|
|
13
|
+
/** Composable CSS color from a token ROLE (resolvePersonalityAccent). */
|
|
14
|
+
accentColor?: string;
|
|
15
|
+
/** Close handler; omitted on the always-visible rail. */
|
|
16
|
+
onClose?: () => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function ChiefHeaderBar({ title, icon: Icon, accentColor, onClose }: ChiefHeaderBarProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=ChiefHeaderBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChiefHeaderBar.d.ts","sourceRoot":"","sources":["../../src/chief/ChiefHeaderBar.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;IACjB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,mBAAmB,2CAuB9F"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { X } from "lucide-react";
|
|
4
|
+
export function ChiefHeaderBar({ title, icon: Icon, accentColor, onClose }) {
|
|
5
|
+
return (_jsxs("div", { className: "flex h-12 shrink-0 items-center justify-between border-b border-border/50 px-4", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(Icon, { "aria-hidden": true, className: "size-4 shrink-0 text-primary", style: accentColor ? { color: accentColor } : undefined }), _jsx("span", { className: "truncate text-sm font-semibold tracking-tight", children: title })] }), onClose && (_jsx("button", { type: "button", onClick: onClose, "aria-label": `Close ${title}`, className: "flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-background/60 hover:text-foreground", children: _jsx(X, { className: "size-4" }) }))] }));
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ChiefHeaderBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChiefHeaderBar.js","sourceRoot":"","sources":["../../src/chief/ChiefHeaderBar.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAYb,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAWjC,MAAM,UAAU,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAuB;IAC7F,OAAO,CACL,eAAK,SAAS,EAAC,gFAAgF,aAC7F,eAAK,SAAS,EAAC,iCAAiC,aAC9C,KAAC,IAAI,yBAEH,SAAS,EAAC,8BAA8B,EACxC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,GACvD,EACF,eAAM,SAAS,EAAC,+CAA+C,YAAE,KAAK,GAAQ,IAC1E,EACL,OAAO,IAAI,CACV,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,gBACJ,SAAS,KAAK,EAAE,EAC5B,SAAS,EAAC,kJAAkJ,YAE5J,KAAC,CAAC,IAAC,SAAS,EAAC,QAAQ,GAAG,GACjB,CACV,IACG,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ChiefMarkdownProps {
|
|
2
|
+
/** The (possibly still-streaming) markdown source. */
|
|
3
|
+
children: string;
|
|
4
|
+
/** A turn is in flight — show the pulse cursor at the stream's tail. */
|
|
5
|
+
streaming?: boolean;
|
|
6
|
+
/** Fade each newly-revealed word in (the "materializing" edge). Pass while the
|
|
7
|
+
* answer is actively revealing; ignored under reduced-motion. Off → plain markdown. */
|
|
8
|
+
wordFade?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function ChiefMarkdown({ children, streaming, wordFade, className, }: ChiefMarkdownProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=ChiefMarkdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChiefMarkdown.d.ts","sourceRoot":"","sources":["../../src/chief/ChiefMarkdown.tsx"],"names":[],"mappings":"AAqKA,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;4FACwF;IACxF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAiB,EACjB,QAAgB,EAChB,SAAS,GACV,EAAE,kBAAkB,2CA2BpB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import Markdown from "react-markdown";
|
|
4
|
+
import remarkGfm from "remark-gfm";
|
|
5
|
+
import { motion } from "motion/react";
|
|
6
|
+
import { motionTokens } from "@consciousclouds/tokens";
|
|
7
|
+
import { cn, useReducedMotion } from "@consciousclouds/ui";
|
|
8
|
+
const remarkPlugins = [remarkGfm];
|
|
9
|
+
/** The per-word fade (the "materializing" edge). A rehype plugin wraps each word
|
|
10
|
+
* of the answer in a `<span class="cc-stream-word">`, and the span component
|
|
11
|
+
* below fades it in ONCE on mount — so as the paced reveal lands a new word, it
|
|
12
|
+
* breathes in instead of snapping. Skips code/pre (monospace + whitespace stay
|
|
13
|
+
* intact). Enabled only while streaming/revealing (and never on reduced-motion),
|
|
14
|
+
* so a settled answer renders as plain, un-wrapped markdown. */
|
|
15
|
+
const CC_STREAM_WORD = "cc-stream-word";
|
|
16
|
+
function rehypeWordFade() {
|
|
17
|
+
const walk = (node) => {
|
|
18
|
+
if (!Array.isArray(node.children))
|
|
19
|
+
return;
|
|
20
|
+
if (node.type === "element" && (node.tagName === "code" || node.tagName === "pre"))
|
|
21
|
+
return;
|
|
22
|
+
const next = [];
|
|
23
|
+
for (const raw of node.children) {
|
|
24
|
+
const child = raw;
|
|
25
|
+
if (child.type === "text" && typeof child.value === "string") {
|
|
26
|
+
const parts = child.value.match(/\S+|\s+/g);
|
|
27
|
+
if (!parts) {
|
|
28
|
+
next.push(child);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
for (const part of parts) {
|
|
32
|
+
if (/\S/.test(part)) {
|
|
33
|
+
next.push({
|
|
34
|
+
type: "element",
|
|
35
|
+
tagName: "span",
|
|
36
|
+
properties: { className: [CC_STREAM_WORD] },
|
|
37
|
+
children: [{ type: "text", value: part }],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
next.push({ type: "text", value: part });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
walk(child);
|
|
47
|
+
next.push(child);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
node.children = next;
|
|
51
|
+
};
|
|
52
|
+
return (tree) => walk(tree);
|
|
53
|
+
}
|
|
54
|
+
const wordTransition = { duration: motionTokens.duration.base, ease: motionTokens.easing.standard };
|
|
55
|
+
/** Renders a react-markdown `span`. A word wrapped by rehypeWordFade fades in
|
|
56
|
+
* once on mount; any other span renders plain. framer-motion's `initial` runs
|
|
57
|
+
* only on mount, so already-revealed words never re-fade as the answer grows. */
|
|
58
|
+
function StreamSpan({ node: _n, className, ...props }) {
|
|
59
|
+
if (typeof className === "string" && className.includes(CC_STREAM_WORD)) {
|
|
60
|
+
return (_jsx(motion.span, { initial: { opacity: 0 }, animate: { opacity: 1 }, transition: wordTransition, className: className, ...props }));
|
|
61
|
+
}
|
|
62
|
+
return _jsx("span", { className: className, ...props });
|
|
63
|
+
}
|
|
64
|
+
/** Token-class styling for every element the answer stream may produce. */
|
|
65
|
+
const components = {
|
|
66
|
+
h1: ({ node: _n, className, ...props }) => (_jsx("h3", { className: cn("mt-3 mb-1 text-sm font-semibold first:mt-0", className), ...props })),
|
|
67
|
+
h2: ({ node: _n, className, ...props }) => (_jsx("h4", { className: cn("mt-3 mb-1 text-sm font-semibold first:mt-0", className), ...props })),
|
|
68
|
+
h3: ({ node: _n, className, ...props }) => (_jsx("h5", { className: cn("mt-2.5 mb-1 text-[13px] font-semibold first:mt-0", className), ...props })),
|
|
69
|
+
h4: ({ node: _n, className, ...props }) => (_jsx("h6", { className: cn("mt-2.5 mb-1 text-[13px] font-semibold first:mt-0", className), ...props })),
|
|
70
|
+
p: ({ node: _n, className, ...props }) => (_jsx("p", { className: cn("my-1.5 first:mt-0 last:mb-0", className), ...props })),
|
|
71
|
+
a: ({ node: _n, className, ...props }) => (_jsx("a", { className: cn("font-medium text-primary underline underline-offset-2", className), rel: "noreferrer", ...props })),
|
|
72
|
+
ul: ({ node: _n, className, ...props }) => (_jsx("ul", { className: cn("my-1.5 list-disc space-y-0.5 pl-4", className), ...props })),
|
|
73
|
+
ol: ({ node: _n, className, ...props }) => (_jsx("ol", { className: cn("my-1.5 list-decimal space-y-0.5 pl-4", className), ...props })),
|
|
74
|
+
blockquote: ({ node: _n, className, ...props }) => (_jsx("blockquote", { className: cn("my-1.5 border-l-2 border-border pl-3 text-muted-foreground", className), ...props })),
|
|
75
|
+
// Block code gets the readable panel; the inner <code> chrome resets so
|
|
76
|
+
// the inline-code styling below never doubles up inside a block.
|
|
77
|
+
pre: ({ node: _n, className, ...props }) => (_jsx("pre", { className: cn("my-2 overflow-x-auto rounded-md border border-border/60 bg-background/60 p-2.5 font-mono text-xs leading-relaxed", "[&_code]:rounded-none [&_code]:bg-transparent [&_code]:p-0 [&_code]:font-mono [&_code]:text-xs", className), ...props })),
|
|
78
|
+
code: ({ node: _n, className, ...props }) => (_jsx("code", { className: cn("rounded bg-background/80 px-1 py-0.5 font-mono text-[0.85em]", className), ...props })),
|
|
79
|
+
hr: ({ node: _n, className, ...props }) => (_jsx("hr", { className: cn("my-2 border-border/60", className), ...props })),
|
|
80
|
+
// GFM tables scroll inside the bubble instead of blowing the panel width.
|
|
81
|
+
table: ({ node: _n, className, ...props }) => (_jsx("div", { className: "my-2 overflow-x-auto", children: _jsx("table", { className: cn("w-full border-collapse text-xs", className), ...props }) })),
|
|
82
|
+
th: ({ node: _n, className, ...props }) => (_jsx("th", { className: cn("border border-border/60 px-2 py-1 text-left font-semibold", className), ...props })),
|
|
83
|
+
td: ({ node: _n, className, ...props }) => (_jsx("td", { className: cn("border border-border/60 px-2 py-1 align-top", className), ...props })),
|
|
84
|
+
};
|
|
85
|
+
/** The base styling map plus the fading word-span, used while the answer reveals. */
|
|
86
|
+
const fadeComponents = { ...components, span: StreamSpan };
|
|
87
|
+
export function ChiefMarkdown({ children, streaming = false, wordFade = false, className, }) {
|
|
88
|
+
const reduced = useReducedMotion();
|
|
89
|
+
const fade = wordFade && !reduced;
|
|
90
|
+
return (_jsxs("div", { className: cn("min-w-0 [word-break:break-word]",
|
|
91
|
+
// While streaming, the last paragraph flows inline so the cursor
|
|
92
|
+
// sits on the tail of the text instead of a line of its own.
|
|
93
|
+
streaming && "[&>p:last-child]:inline", className), children: [_jsx(Markdown, { remarkPlugins: remarkPlugins, rehypePlugins: fade ? [rehypeWordFade] : undefined, components: fade ? fadeComponents : components, children: children }), streaming && (_jsx("span", { "aria-hidden": true, className: "ml-0.5 inline-block animate-pulse select-none", children: "\u258D" }))] }));
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ChiefMarkdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChiefMarkdown.js","sourceRoot":"","sources":["../../src/chief/ChiefMarkdown.tsx"],"names":[],"mappings":"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"}
|