assistant.ts

  1import { text, border, background, foreground, TextStyle } from "./components"
  2import { Interactive, interactive } from "../element"
  3import { tab_bar_button } from "../component/tab_bar_button"
  4import { StyleSets, useTheme } from "../theme"
  5
  6type RoleCycleButton = TextStyle & {
  7    background?: string
  8}
  9// TODO: Replace these with zed types
 10type RemainingTokens = TextStyle & {
 11    background: string
 12    margin: { top: number; right: number }
 13    padding: {
 14        right: number
 15        left: number
 16        top: number
 17        bottom: number
 18    }
 19    corner_radius: number
 20}
 21
 22export default function assistant(): any {
 23    const theme = useTheme()
 24
 25    const interactive_role = (
 26        color: StyleSets
 27    ): Interactive<RoleCycleButton> => {
 28        return interactive({
 29            base: {
 30                ...text(theme.highest, "sans", color, { size: "sm" }),
 31            },
 32            state: {
 33                hovered: {
 34                    ...text(theme.highest, "sans", color, { size: "sm" }),
 35                    background: background(theme.highest, color, "hovered"),
 36                },
 37                clicked: {
 38                    ...text(theme.highest, "sans", color, { size: "sm" }),
 39                    background: background(theme.highest, color, "pressed"),
 40                },
 41            },
 42        })
 43    }
 44
 45    const tokens_remaining = (color: StyleSets): RemainingTokens => {
 46        return {
 47            ...text(theme.highest, "mono", color, { size: "xs" }),
 48            background: background(theme.highest, "on", "default"),
 49            margin: { top: 12, right: 20 },
 50            padding: { right: 4, left: 4, top: 1, bottom: 1 },
 51            corner_radius: 6,
 52        }
 53    }
 54
 55    return {
 56        container: {
 57            background: background(theme.highest),
 58            padding: { left: 12 },
 59        },
 60        message_header: {
 61            margin: { bottom: 4, top: 4 },
 62            background: background(theme.highest),
 63        },
 64        hamburger_button: tab_bar_button(theme, {
 65            icon: "icons/hamburger_15.svg",
 66        }),
 67
 68        split_button: tab_bar_button(theme, {
 69            icon: "icons/split_message_15.svg",
 70        }),
 71        quote_button: tab_bar_button(theme, {
 72            icon: "icons/radix/quote.svg",
 73        }),
 74        assist_button: tab_bar_button(theme, {
 75            icon: "icons/radix/magic-wand.svg",
 76        }),
 77        zoom_in_button: tab_bar_button(theme, {
 78            icon: "icons/radix/maximize.svg",
 79        }),
 80        zoom_out_button: tab_bar_button(theme, {
 81            icon: "icons/radix/minimize.svg",
 82        }),
 83        plus_button: tab_bar_button(theme, {
 84            icon: "icons/radix/plus.svg",
 85        }),
 86        title: {
 87            ...text(theme.highest, "sans", "default", { size: "xs" }),
 88        },
 89        saved_conversation: {
 90            container: interactive({
 91                base: {
 92                    background: background(theme.middle),
 93                    padding: { top: 4, bottom: 4 },
 94                    border: border(theme.middle, "default", {
 95                        top: true,
 96                        overlay: true,
 97                    }),
 98                },
 99                state: {
100                    hovered: {
101                        background: background(theme.middle, "hovered"),
102                    },
103                    clicked: {
104                        background: background(theme.middle, "pressed"),
105                    },
106                },
107            }),
108            saved_at: {
109                margin: { left: 8 },
110                ...text(theme.highest, "sans", "variant", { size: "xs" }),
111            },
112            title: {
113                margin: { left: 12 },
114                ...text(theme.highest, "sans", "default", {
115                    size: "sm",
116                    weight: "bold",
117                }),
118            },
119        },
120        user_sender: interactive_role("base"),
121        assistant_sender: interactive_role("accent"),
122        system_sender: interactive_role("warning"),
123        sent_at: {
124            margin: { top: 2, left: 8 },
125            ...text(theme.highest, "sans", "variant", { size: "2xs" }),
126        },
127        model: interactive({
128            base: {
129                background: background(theme.highest),
130                margin: { left: 12, right: 4, top: 12 },
131                padding: { right: 4, left: 4, top: 1, bottom: 1 },
132                corner_radius: 4,
133                ...text(theme.highest, "sans", "default", { size: "xs" }),
134            },
135            state: {
136                hovered: {
137                    background: background(theme.highest, "on", "hovered"),
138                    border: border(theme.highest, "on", { overlay: true }),
139                },
140            },
141        }),
142        remaining_tokens: tokens_remaining("positive"),
143        low_remaining_tokens: tokens_remaining("warning"),
144        no_remaining_tokens: tokens_remaining("negative"),
145        error_icon: {
146            margin: { left: 8 },
147            color: foreground(theme.highest, "negative"),
148            width: 12,
149        },
150        api_key_editor: {
151            background: background(theme.highest, "on"),
152            corner_radius: 4,
153            text: text(theme.highest, "mono", "on"),
154            placeholder_text: text(theme.highest, "mono", "on", "disabled", {
155                size: "xs",
156            }),
157            selection: theme.players[0],
158            border: border(theme.highest, "on"),
159            padding: {
160                bottom: 4,
161                left: 8,
162                right: 8,
163                top: 4,
164            },
165        },
166        api_key_prompt: {
167            padding: 10,
168            ...text(theme.highest, "sans", "default", { size: "xs" }),
169        },
170    }
171}