225 lines
7.5 KiB
Plaintext
225 lines
7.5 KiB
Plaintext
-- allium: 1
|
|
-- bDS Chat Panel
|
|
-- Scope: UI content area — AI chat surface
|
|
-- Distilled from: ChatPanel.tsx
|
|
|
|
-- Describes the layout and behaviour of the chat panel.
|
|
|
|
use "./i18n.allium" as i18n
|
|
|
|
-- ─── Chat panel ───────────────────────────────────────────────
|
|
|
|
value ChatPanelView {
|
|
conversation_id: String?
|
|
needs_api_key: Boolean
|
|
title: String -- conversation title or "New Chat"
|
|
selected_model_id: String?
|
|
messages: List<ChatMessage>
|
|
is_streaming: Boolean
|
|
input_text: String
|
|
}
|
|
|
|
value ChatMessage {
|
|
role: String -- user | assistant | system
|
|
content: String -- user: plain text; assistant: GFM markdown
|
|
tool_markers: List<ToolMarker>
|
|
inline_surfaces: List<InlineSurface>
|
|
is_streaming: Boolean -- true while accumulating
|
|
}
|
|
|
|
value InlineSurface {
|
|
id: String
|
|
type: "card" | "chart" | "form" | "list" | "metric" | "mindmap" | "table" | "tabs" | "text" | "json"
|
|
title: String?
|
|
subtitle: String? -- card only
|
|
body: String? -- card, text
|
|
actions: List<SurfaceAction> -- card only
|
|
columns: List<String> -- table
|
|
rows: List<List<String>> -- table
|
|
chart_type: String? -- chart: bar/pie/line
|
|
series: List<ChartSeries> -- chart
|
|
max_value: Integer? -- chart
|
|
label: String? -- metric
|
|
value: String? -- metric
|
|
items: List<String> -- list
|
|
nodes: List<MindmapNode> -- mindmap
|
|
fields: List<FormField> -- form
|
|
submit_label: String? -- form
|
|
submit_action: String? -- form
|
|
tabs: List<TabPanel> -- tabs
|
|
selected_index: Integer? -- tabs
|
|
raw: Map? -- json catch-all
|
|
}
|
|
|
|
value SurfaceAction {
|
|
label: String
|
|
action: String
|
|
payload: Map
|
|
}
|
|
|
|
value ChartSeries {
|
|
label: String
|
|
value: Integer
|
|
segments: List
|
|
}
|
|
|
|
value MindmapNode {
|
|
id: String?
|
|
label: String
|
|
children: List<String>
|
|
}
|
|
|
|
value FormField {
|
|
key: String
|
|
label: String
|
|
input_type: String
|
|
placeholder: String?
|
|
value: String?
|
|
options: List<FieldOption>
|
|
required: Boolean
|
|
}
|
|
|
|
value FieldOption {
|
|
label: String
|
|
value: String
|
|
}
|
|
|
|
value TabPanel {
|
|
label: String
|
|
content: List<InlineSurface> -- nested surfaces or text
|
|
}
|
|
|
|
value ToolMarker {
|
|
tool_name: String
|
|
args_preview: String -- string args truncated to config.chat_tool_args_max_length
|
|
is_complete: Boolean -- checkmark when done, dot when in-progress
|
|
}
|
|
|
|
value ModelSelectorDropdown {
|
|
groups: List<ModelProviderGroup>
|
|
selected_model_id: String?
|
|
}
|
|
|
|
surface ModelSelectorDropdownSurface {
|
|
context dropdown: ModelSelectorDropdown
|
|
|
|
exposes:
|
|
dropdown.selected_model_id when dropdown.selected_model_id != null
|
|
for group in dropdown.groups:
|
|
group.provider_name
|
|
for model in group.models:
|
|
model.model_id
|
|
model.display_name
|
|
model.context_window
|
|
model.max_output_tokens
|
|
}
|
|
|
|
value ModelProviderGroup {
|
|
provider_name: String -- e.g. "OpenAI", "Ollama", "LM Studio"
|
|
models: List<ModelEntry>
|
|
}
|
|
|
|
value ModelEntry {
|
|
model_id: String
|
|
display_name: String
|
|
context_window: Integer
|
|
max_output_tokens: Integer
|
|
}
|
|
|
|
config {
|
|
chat_tool_args_max_length: Integer = 30
|
|
chat_input_max_height: Integer = 200
|
|
surface_form_debounce_ms: Integer = 500
|
|
}
|
|
|
|
surface ChatPanelSurface {
|
|
context panel: ChatPanelView
|
|
|
|
exposes:
|
|
panel.needs_api_key
|
|
panel.title
|
|
panel.selected_model_id
|
|
panel.is_streaming
|
|
panel.input_text
|
|
for msg in panel.messages:
|
|
msg.role
|
|
msg.content
|
|
msg.is_streaming
|
|
for tm in msg.tool_markers:
|
|
tm.tool_name
|
|
tm.args_preview
|
|
tm.is_complete
|
|
for sfc in msg.inline_surfaces:
|
|
sfc.type
|
|
sfc.id
|
|
|
|
provides:
|
|
ChatSendMessage(panel.conversation_id, panel.input_text)
|
|
when panel.input_text != "" and not panel.is_streaming
|
|
ChatAbortStreaming(panel.conversation_id)
|
|
when panel.is_streaming
|
|
ChatSelectModel(panel.conversation_id, model_id)
|
|
ChatOpenSettings()
|
|
when panel.needs_api_key
|
|
|
|
@guarantee ApiKeyRequiredScreen
|
|
-- Shown when needs_api_key is true.
|
|
-- Key icon, title, description text, "Open Settings" button.
|
|
-- No chat functionality available until API key is set.
|
|
|
|
@guarantee HeaderLayout
|
|
-- Left: conversation title (or "New Chat"), CSS ellipsis on overflow.
|
|
-- Right: model selector button opening dropdown.
|
|
|
|
@guarantee ModelSelectorDropdown
|
|
-- Dropdown groups models by provider (section headers).
|
|
-- Each entry: model display name.
|
|
-- Expandable details: context window, max output tokens.
|
|
-- Selection is per-conversation override, persisted with conversation.
|
|
-- Changing model mid-conversation applies to subsequent messages only.
|
|
|
|
@guarantee WelcomeScreen
|
|
-- Shown when no messages and not streaming.
|
|
-- Robot icon, title, description, 5 tip bullet points.
|
|
|
|
@guarantee MessageRendering
|
|
-- User messages: plain text.
|
|
-- Assistant messages: rendered as GFM Markdown.
|
|
-- External images blocked (CSP), shown as links.
|
|
-- Tool markers: checkmark (done) or dot (in-progress) icon,
|
|
-- tool name, args truncated to config.chat_tool_args_max_length for strings.
|
|
-- Streaming: accumulating markdown + tool markers, thinking dots animation.
|
|
|
|
@guarantee AutoScroll
|
|
-- Message area auto-scrolls to bottom on new messages.
|
|
|
|
@guarantee InputArea
|
|
-- Abort/Stop button: square stop icon, visible only during streaming.
|
|
-- Auto-growing textarea: max config.chat_input_max_height px.
|
|
-- Enter sends message. Shift+Enter inserts newline.
|
|
-- Send button: up-arrow icon, disabled when input is empty or streaming.
|
|
|
|
@guarantee AssistantActionDispatch
|
|
-- Assistant tool calls can trigger navigation actions:
|
|
-- open_post(id), open_media(id), open_settings(), etc.
|
|
-- Actions dispatched through store, same as user clicks.
|
|
-- Navigation actions open tabs with pin intent.
|
|
|
|
@guarantee InlineSurfaceRendering
|
|
-- Assistant render-tool calls produce structured inline surfaces
|
|
-- rendered between message content and tool markers.
|
|
-- 9 surface types: card, chart, form, list, metric, mindmap, table, tabs, text, json.
|
|
-- Render tool names: render_card, render_chart, render_form, render_list,
|
|
-- render_metric, render_mindmap, render_table, render_tabs.
|
|
-- Unrecognized render names render as json (raw dump).
|
|
-- Tab content nests any surface type including plain text.
|
|
-- Form surfaces persist field values in conversation surface_state.
|
|
-- Tab surfaces track selected_index in conversation surface_state.
|
|
-- Surfaces can be dismissed, persisted in conversation surface_state.
|
|
-- Form debounce: config.surface_form_debounce_ms.
|
|
|
|
@guarantee TokenTracking
|
|
-- Token usage tracked per conversation.
|
|
-- Displayed in status bar, not in the chat panel itself.
|
|
}
|