Explorar o código

Revert "tui: remove prompt model/thinking/permissions selectors on dev so the composer stays simple"

This reverts commit ae25c1e7b75c17d799f7a245f03ca0cd8bef1eab.
David Hill hai 1 mes
pai
achega
09388c98f3
Modificáronse 1 ficheiros con 148 adicións e 1 borrados
  1. 148 1
      packages/app/src/components/prompt-input.tsx

+ 148 - 1
packages/app/src/components/prompt-input.tsx

@@ -23,11 +23,15 @@ import { useComments } from "@/context/comments"
 import { Button } from "@opencode-ai/ui/button"
 import { DockShellForm, DockTray } from "@opencode-ai/ui/dock-surface"
 import { Icon } from "@opencode-ai/ui/icon"
+import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
 import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
 import { IconButton } from "@opencode-ai/ui/icon-button"
 import { Select } from "@opencode-ai/ui/select"
 import { RadioGroup } from "@opencode-ai/ui/radio-group"
 import { useDialog } from "@opencode-ai/ui/context/dialog"
+import { ModelSelectorPopover } from "@/components/dialog-select-model"
+import { DialogSelectModelUnpaid } from "@/components/dialog-select-model-unpaid"
+import { useProviders } from "@/hooks/use-providers"
 import { useCommand } from "@/context/command"
 import { Persist, persisted } from "@/utils/persist"
 import { usePermission } from "@/context/permission"
@@ -100,6 +104,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
   const comments = useComments()
   const params = useParams()
   const dialog = useDialog()
+  const providers = useProviders()
   const command = useCommand()
   const permission = usePermission()
   const language = useLanguage()
@@ -945,12 +950,21 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
     readClipboardImage: platform.readClipboardImage,
   })
 
+  const variants = createMemo(() => ["default", ...local.model.variant.list()])
   const accepting = createMemo(() => {
     const id = params.id
     if (!id) return permission.isAutoAcceptingDirectory(sdk.directory)
     return permission.isAutoAccepting(id, sdk.directory)
   })
 
+  const flip = () => {
+    if (!params.id) {
+      permission.toggleAutoAcceptDirectory(sdk.directory)
+      return
+    }
+    permission.toggleAutoAccept(params.id, sdk.directory)
+  }
+
   const { abort, handleSubmit } = createPromptSubmit({
     info,
     imageAttachments,
@@ -1176,7 +1190,11 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
           onMouseDown={(e) => {
             const target = e.target
             if (!(target instanceof HTMLElement)) return
-            if (target.closest('[data-action="prompt-attach"], [data-action="prompt-submit"]')) {
+            if (
+              target.closest(
+                '[data-action="prompt-attach"], [data-action="prompt-submit"], [data-action="prompt-permissions"]',
+              )
+            ) {
               return
             }
             editorRef?.focus()
@@ -1310,6 +1328,99 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
                   <Icon name="plus" class="size-4.5" />
                 </Button>
               </TooltipKeybind>
+
+              <Show
+                when={providers.paid().length > 0}
+                fallback={
+                  <TooltipKeybind
+                    placement="top"
+                    gutter={8}
+                    title={language.t("command.model.choose")}
+                    keybind={command.keybind("model.choose")}
+                  >
+                    <Button
+                      as="div"
+                      variant="ghost"
+                      size="small"
+                      class="min-w-0 max-w-[240px] text-13-regular text-text-base group"
+                      style={{
+                        opacity: buttonsSpring(),
+                        transform: `scale(${0.95 + buttonsSpring() * 0.05})`,
+                        filter: `blur(${(1 - buttonsSpring()) * 2}px)`,
+                      }}
+                      onClick={() => dialog.show(() => <DialogSelectModelUnpaid />)}
+                    >
+                      <Show when={local.model.current()?.provider?.id}>
+                        <ProviderIcon
+                          id={local.model.current()!.provider.id}
+                          class="size-4 shrink-0 opacity-40 group-hover:opacity-100 transition-opacity duration-150"
+                          style={{ "will-change": "opacity", transform: "translateZ(0)" }}
+                        />
+                      </Show>
+                      <span class="truncate">
+                        {local.model.current()?.name ?? language.t("dialog.model.select.title")}
+                      </span>
+                      <Icon name="chevron-down" size="small" class="shrink-0" />
+                    </Button>
+                  </TooltipKeybind>
+                }
+              >
+                <TooltipKeybind
+                  placement="top"
+                  gutter={8}
+                  title={language.t("command.model.choose")}
+                  keybind={command.keybind("model.choose")}
+                >
+                  <ModelSelectorPopover
+                    triggerAs={Button}
+                    triggerProps={{
+                      variant: "ghost",
+                      size: "small",
+                      style: {
+                        opacity: buttonsSpring(),
+                        transform: `scale(${0.95 + buttonsSpring() * 0.05})`,
+                        filter: `blur(${(1 - buttonsSpring()) * 2}px)`,
+                      },
+                      class: "min-w-0 max-w-[240px] text-13-regular text-text-base group",
+                    }}
+                  >
+                    <Show when={local.model.current()?.provider?.id}>
+                      <ProviderIcon
+                        id={local.model.current()!.provider.id}
+                        class="size-4 shrink-0 opacity-40 group-hover:opacity-100 transition-opacity duration-150"
+                        style={{ "will-change": "opacity", transform: "translateZ(0)" }}
+                      />
+                    </Show>
+                    <span class="truncate">
+                      {local.model.current()?.name ?? language.t("dialog.model.select.title")}
+                    </span>
+                    <Icon name="chevron-down" size="small" class="shrink-0" />
+                  </ModelSelectorPopover>
+                </TooltipKeybind>
+              </Show>
+
+              <TooltipKeybind
+                placement="top"
+                gutter={8}
+                title={language.t("command.model.variant.cycle")}
+                keybind={command.keybind("model.variant.cycle")}
+              >
+                <Select
+                  size="small"
+                  options={variants()}
+                  current={local.model.variant.current() ?? "default"}
+                  label={(x) => (x === "default" ? language.t("common.default") : x)}
+                  onSelect={(x) => local.model.variant.set(x === "default" ? undefined : x)}
+                  class="capitalize max-w-[160px]"
+                  valueClass="truncate text-13-regular text-text-base"
+                  triggerStyle={{
+                    opacity: buttonsSpring(),
+                    transform: `scale(${0.95 + buttonsSpring() * 0.05})`,
+                    filter: `blur(${(1 - buttonsSpring()) * 2}px)`,
+                  }}
+                  variant="ghost"
+                />
+              </TooltipKeybind>
             </div>
           </div>
         </div>
@@ -1355,6 +1466,42 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
                     variant="ghost"
                   />
                 </TooltipKeybind>
+
+                <TooltipKeybind
+                  placement="top"
+                  gutter={4}
+                  title={language.t(
+                    accepting() ? "command.permissions.autoaccept.disable" : "command.permissions.autoaccept.enable",
+                  )}
+                  keybind={command.keybind("permissions.autoaccept")}
+                >
+                  <Select
+                    size="normal"
+                    options={["default", "autoaccept"] as const}
+                    current={accepting() ? "autoaccept" : "default"}
+                    label={(x) =>
+                      x === "autoaccept"
+                        ? language.t("command.permissions.autoaccept.enable")
+                        : `${language.t("common.default")} ${language.t("command.category.permissions")}`
+                    }
+                    onSelect={(x) => {
+                      if (!x) return
+                      if (x === "autoaccept" && accepting()) return
+                      if (x === "default" && !accepting()) return
+                      flip()
+                    }}
+                    class="max-w-[220px]"
+                    valueClass="truncate text-13-regular text-text-base"
+                    triggerStyle={{
+                      height: "28px",
+                      opacity: buttonsSpring(),
+                      transform: `scale(${0.95 + buttonsSpring() * 0.05})`,
+                      filter: `blur(${(1 - buttonsSpring()) * 2}px)`,
+                      "pointer-events": buttonsSpring() > 0.5 ? "auto" : "none",
+                    }}
+                    variant="ghost"
+                  />
+                </TooltipKeybind>
               </div>
             </div>
             <div class="shrink-0">