KQ-1341 · AI/WORKSPACE
AI Workspace
A whole assistant screen built from thread-view, prompt-dock and pin-press: a dated, searchable conversation sidebar, a thread whose replies stream in word by word while Send folds into Stop, and an artifact the reply writes line by line in a pane that slides in beside the thread on glide, its column and the thread's edge one motion value, each new line rising 4px on glide; split, overlay and canvas set how the pane arrives, a split divider follows the pointer 1:1 and settles on glide, and pinned conversations glide to the top. Below 640px it becomes a stack of conversations, thread and artifact pushed on glide with the screen beneath shifting and dimming. The sidebar is a roving list (arrows, Home, End), the divider a separator the arrow keys move, Preview and Source a tablist, and Escape closes the pane or goes back.
Payout cut-off policy
Fernworks Model 3
payout cut-off policy · 7 conversations
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/ai-workspace
Props
- density
- "compact" | "cozy" | "roomy"
- default "cozy"
- How tightly the thread and the sidebar are set: passed to the thread, and the sidebar's rows follow.
- pane
- "split" | "overlay" | "canvas"
- default "split"
- How the artifact arrives: a column sharing the stage with the thread (with a draggable divider, the sidebar folding when the three cannot fit), a sheet sliding over the thread's edge, or a canvas that gives the artifact the stage.
- theme
- "page" | "light" | "dark"
- default "page"
- Wear the page's theme, or force light or dark inside the workspace.
- conversations / defaultConversations
- AiConversation[]
- default defaultAiConversations
- Every conversation: a title, its thread-view messages, whether it is pinned, and the latest artifact it produced. Controlled or uncontrolled.
- onConversationsChange
- (conversations: AiConversation[]) => void
- default —
- Fires from the send, stream, pin, edit or reaction that changed them, with all of them. A streamed reply is reported whole when it starts and again when it finishes.
- conversation / defaultConversation
- string
- default the first conversation
- The open conversation's id. Controlled or uncontrolled.
- onConversationChange
- (id: string) => void
- default —
- Fires from the row, New chat or key that opened another conversation.
- artifactOpen / defaultArtifactOpen
- boolean
- default false
- Whether the artifact pane is open. Controlled or uncontrolled.
- onArtifactOpenChange
- (open: boolean) => void
- default —
- Fires from the strip, the Artifact button, Close, Escape, or a reply that started writing an artifact.
- respond
- (prompt: string, conversation: AiConversation) => AiReply | Promise<AiReply>
- default defaultAiRespond
- Answers a prompt with text and, optionally, an artifact. A promise shows the reply thinking until it settles; a rejection shows it failed, with Retry.
- onSend
- (text: string, conversationId: string) => void
- default —
- A prompt was sent, from the dock or by editing a sent turn.
- onStop
- (conversationId: string) => void
- default —
- Stop, or Escape in the dock, cut a reply short where it stood.
- onCopy
- (text: string, artifact: AiArtifact) => void
- default —
- The artifact was copied.
- models
- DockModel[]
- default defaultModels
- The models the dock's pill switches between.
- model
- string
- default the first model
- The selected model's id; its name signs replies and heads the thread.
- onModelChange
- (id: string) => void
- default —
- The visitor switched models in the dock.
- user
- { name: string; plan?: string }
- default { name: "Rae Okafor", plan: "Team plan" }
- Who is signed in, at the foot of the sidebar; prompts are sent under this name.
- workspace
- string
- default "Fieldline"
- The workspace's name, at the head of the sidebar.
- now
- Date | number
- default defaultAiNow
- The moment the sidebar's groups (Today, Yesterday, Previous 7 days) and times count from, so server and browser agree.
- stream
- number
- default 240
- How fast a reply streams in, in characters a second.
- status
- "ready" | "loading" | "error"
- default "ready"
- Whether the conversations have arrived: loading draws placeholders, error offers Try again.
- onRetry
- () => void
- default —
- Try again was pressed after the conversations failed to load.
- label
- string
- default "Assistant"
- The screen's accessible name.
- sound
- boolean
- default false
- Play the ticks and the pane's swish, only for the visitor's own actions. The composed pieces play theirs too.
- disabled
- boolean
- default false
- Read only: nothing can be sent, pinned or opened.
- className
- string
- default —
- Classes for the root. It is 560px tall by default; pass a height class to change it.
| Prop | Type | Default | Description |
|---|---|---|---|
| density | "compact" | "cozy" | "roomy" | "cozy" | How tightly the thread and the sidebar are set: passed to the thread, and the sidebar's rows follow. |
| pane | "split" | "overlay" | "canvas" | "split" | How the artifact arrives: a column sharing the stage with the thread (with a draggable divider, the sidebar folding when the three cannot fit), a sheet sliding over the thread's edge, or a canvas that gives the artifact the stage. |
| theme | "page" | "light" | "dark" | "page" | Wear the page's theme, or force light or dark inside the workspace. |
| conversations / defaultConversations | AiConversation[] | defaultAiConversations | Every conversation: a title, its thread-view messages, whether it is pinned, and the latest artifact it produced. Controlled or uncontrolled. |
| onConversationsChange | (conversations: AiConversation[]) => void | — | Fires from the send, stream, pin, edit or reaction that changed them, with all of them. A streamed reply is reported whole when it starts and again when it finishes. |
| conversation / defaultConversation | string | the first conversation | The open conversation's id. Controlled or uncontrolled. |
| onConversationChange | (id: string) => void | — | Fires from the row, New chat or key that opened another conversation. |
| artifactOpen / defaultArtifactOpen | boolean | false | Whether the artifact pane is open. Controlled or uncontrolled. |
| onArtifactOpenChange | (open: boolean) => void | — | Fires from the strip, the Artifact button, Close, Escape, or a reply that started writing an artifact. |
| respond | (prompt: string, conversation: AiConversation) => AiReply | Promise<AiReply> | defaultAiRespond | Answers a prompt with text and, optionally, an artifact. A promise shows the reply thinking until it settles; a rejection shows it failed, with Retry. |
| onSend | (text: string, conversationId: string) => void | — | A prompt was sent, from the dock or by editing a sent turn. |
| onStop | (conversationId: string) => void | — | Stop, or Escape in the dock, cut a reply short where it stood. |
| onCopy | (text: string, artifact: AiArtifact) => void | — | The artifact was copied. |
| models | DockModel[] | defaultModels | The models the dock's pill switches between. |
| model | string | the first model | The selected model's id; its name signs replies and heads the thread. |
| onModelChange | (id: string) => void | — | The visitor switched models in the dock. |
| user | { name: string; plan?: string } | { name: "Rae Okafor", plan: "Team plan" } | Who is signed in, at the foot of the sidebar; prompts are sent under this name. |
| workspace | string | "Fieldline" | The workspace's name, at the head of the sidebar. |
| now | Date | number | defaultAiNow | The moment the sidebar's groups (Today, Yesterday, Previous 7 days) and times count from, so server and browser agree. |
| stream | number | 240 | How fast a reply streams in, in characters a second. |
| status | "ready" | "loading" | "error" | "ready" | Whether the conversations have arrived: loading draws placeholders, error offers Try again. |
| onRetry | () => void | — | Try again was pressed after the conversations failed to load. |
| label | string | "Assistant" | The screen's accessible name. |
| sound | boolean | false | Play the ticks and the pane's swish, only for the visitor's own actions. The composed pieces play theirs too. |
| disabled | boolean | false | Read only: nothing can be sent, pinned or opened. |
| className | string | — | Classes for the root. It is 560px tall by default; pass a height class to change it. |