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