summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components/dialog-select-model.tsx
blob: 54783386a67d1c1ffd1b1b192cd3525c20ed6068 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { Component, createMemo, Show } from "solid-js"
import { useLocal } from "@/context/local"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { popularProviders } from "@/hooks/use-providers"
import { Button } from "@opencode-ai/ui/button"
import { Tag } from "@opencode-ai/ui/tag"
import { Dialog } from "@opencode-ai/ui/dialog"
import { List } from "@opencode-ai/ui/list"
import { DialogSelectProvider } from "./dialog-select-provider"
import { DialogManageModels } from "./dialog-manage-models"

export const DialogSelectModel: Component<{ provider?: string }> = (props) => {
  const local = useLocal()
  const dialog = useDialog()

  const models = createMemo(() =>
    local.model
      .list()
      .filter((m) => local.model.visible({ modelID: m.id, providerID: m.provider.id }))
      .filter((m) => (props.provider ? m.provider.id === props.provider : true)),
  )

  return (
    <Dialog
      title="Select model"
      action={
        <Button
          class="h-7 -my-1 text-14-medium"
          icon="plus-small"
          tabIndex={-1}
          onClick={() => dialog.show(() => <DialogSelectProvider />)}
        >
          Connect provider
        </Button>
      }
    >
      <List
        search={{ placeholder: "Search models", autofocus: true }}
        emptyMessage="No model results"
        key={(x) => `${x.provider.id}:${x.id}`}
        items={models}
        current={local.model.current()}
        filterKeys={["provider.name", "name", "id"]}
        sortBy={(a, b) => a.name.localeCompare(b.name)}
        groupBy={(x) => x.provider.name}
        sortGroupsBy={(a, b) => {
          if (a.category === "Recent" && b.category !== "Recent") return -1
          if (b.category === "Recent" && a.category !== "Recent") return 1
          const aProvider = a.items[0].provider.id
          const bProvider = b.items[0].provider.id
          if (popularProviders.includes(aProvider) && !popularProviders.includes(bProvider)) return -1
          if (!popularProviders.includes(aProvider) && popularProviders.includes(bProvider)) return 1
          return popularProviders.indexOf(aProvider) - popularProviders.indexOf(bProvider)
        }}
        onSelect={(x) => {
          local.model.set(x ? { modelID: x.id, providerID: x.provider.id } : undefined, {
            recent: true,
          })
          dialog.close()
        }}
      >
        {(i) => (
          <div class="w-full flex items-center gap-x-3">
            <span>{i.name}</span>
            <Show when={i.provider.id === "opencode" && (!i.cost || i.cost?.input === 0)}>
              <Tag>Free</Tag>
            </Show>
            <Show when={i.latest}>
              <Tag>Latest</Tag>
            </Show>
          </div>
        )}
      </List>
      <Button
        variant="ghost"
        class="ml-3 mt-5 mb-6 text-text-base self-start"
        onClick={() => dialog.show(() => <DialogManageModels />)}
      >
        Manage models
      </Button>
    </Dialog>
  )
}