diff --git a/bun.lock b/bun.lock index 2c91b45ed6..ba18f4635a 100644 --- a/bun.lock +++ b/bun.lock @@ -72,6 +72,7 @@ "shiki": "catalog:", "solid-js": "catalog:", "solid-list": "catalog:", + "solid-presence": "0.2.0", "tailwindcss": "catalog:", }, "devDependencies": { @@ -5103,7 +5104,7 @@ "solid-list": ["solid-list@0.3.0", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-t4hx/F/l8Vmq+ib9HtZYl7Z9F1eKxq3eKJTXlvcm7P7yI4Z8O7QSOOEVHb/K6DD7M0RxzVRobK/BS5aSfLRwKg=="], - "solid-presence": ["solid-presence@0.1.8", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA=="], + "solid-presence": ["solid-presence@0.2.0", "", { "dependencies": { "@corvu/utils": "~0.4.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-YM92o+jvpzX3XGaD4rLYmq/Kc2ZVh47GSCLEufHBFQQIurvZTs8SoGJxO8BJGNDxBKdcS8F3dYhW1SDXp4BNjA=="], "solid-prevent-scroll": ["solid-prevent-scroll@0.1.10", "", { "dependencies": { "@corvu/utils": "~0.4.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw=="], @@ -5921,6 +5922,8 @@ "@jsx-email/doiuse-email/htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="], + "@kobalte/core/solid-presence": ["solid-presence@0.1.8", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA=="], + "@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "@mdx-js/mdx/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], diff --git a/packages/app/package.json b/packages/app/package.json index 7430a614bf..704c7401f2 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -88,6 +88,7 @@ "shiki": "catalog:", "solid-js": "catalog:", "solid-list": "catalog:", + "solid-presence": "0.2.0", "tailwindcss": "catalog:" } } diff --git a/packages/app/src/components/settings-dialog.tsx b/packages/app/src/components/settings-dialog.tsx index d2cc85c04e..46dd89ade8 100644 --- a/packages/app/src/components/settings-dialog.tsx +++ b/packages/app/src/components/settings-dialog.tsx @@ -4,7 +4,7 @@ import { useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { useDialog } from "@opencode-ai/ui/context/dialog" -export function useSettingsDialog() { +export function useSettingsDialog(defaultValue?: string) { const dialog = useDialog() const params = useParams<{ id?: string }>() let run = 0 @@ -19,7 +19,7 @@ export function useSettingsDialog() { const sessionID = params.id void import("@/components/settings-v2").then((module) => { if (dead || run !== current) return - void dialog.show(() => ) + void dialog.show(() => ) }) } } diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index c60920d107..b343d1a929 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -548,6 +548,7 @@ export const dict = { "home.sessions.group.today": "اليوم", "home.sessions.group.yesterday": "أمس", "home.sessions.group.older": "الأقدم", + "home.providerTip": "اتصل بأكثر من 75 مزودًا لاستخدام نماذج أخرى، بما فيها Claude وGPT وGemini وغيرها", "session.tab.session": "جلسة", "session.tab.review": "مراجعة", "session.tab.context": "سياق", diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts index 12911744e2..0d164cd03a 100644 --- a/packages/app/src/i18n/br.ts +++ b/packages/app/src/i18n/br.ts @@ -552,6 +552,7 @@ export const dict = { "home.sessions.group.today": "Hoje", "home.sessions.group.yesterday": "Ontem", "home.sessions.group.older": "Mais antigas", + "home.providerTip": "Conecte-se a mais de 75 provedores para usar outros modelos, incluindo Claude, GPT, Gemini e muito mais", "session.tab.session": "Sessão", "session.tab.review": "Revisão", "session.tab.context": "Contexto", diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts index 086ecc1b4c..04b6474a78 100644 --- a/packages/app/src/i18n/bs.ts +++ b/packages/app/src/i18n/bs.ts @@ -603,6 +603,7 @@ export const dict = { "home.sessions.group.today": "Danas", "home.sessions.group.yesterday": "Jučer", "home.sessions.group.older": "Starije", + "home.providerTip": "Povežite se s više od 75 pružalaca usluga kako biste koristili druge modele, uključujući Claude, GPT, Gemini i druge", "session.tab.session": "Sesija", "session.tab.review": "Pregled", diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts index 859bea230b..35cee17aef 100644 --- a/packages/app/src/i18n/da.ts +++ b/packages/app/src/i18n/da.ts @@ -600,6 +600,7 @@ export const dict = { "home.sessions.group.today": "I dag", "home.sessions.group.yesterday": "I går", "home.sessions.group.older": "Ældre", + "home.providerTip": "Opret forbindelse til mere end 75 udbydere for at bruge andre modeller, herunder Claude, GPT, Gemini og flere", "session.tab.session": "Session", "session.tab.review": "Gennemgang", diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index c96dc232a5..afd176c580 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -560,6 +560,7 @@ export const dict = { "home.sessions.group.today": "Heute", "home.sessions.group.yesterday": "Gestern", "home.sessions.group.older": "Älter", + "home.providerTip": "Verbinde dich mit über 75 Anbietern, um weitere Modelle wie Claude, GPT, Gemini und andere zu nutzen", "session.tab.session": "Sitzung", "session.tab.review": "Überprüfung", "session.tab.context": "Kontext", diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 3da8183bb7..a281968d65 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -622,6 +622,7 @@ export const dict = { "home.sessions.group.today": "Today", "home.sessions.group.yesterday": "Yesterday", "home.sessions.group.older": "Older", + "home.providerTip": "Connect to 75+ providers to use other models, including Claude, GPT, Gemini, etc", "session.tab.session": "Session", "session.tab.review": "Review", diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index 5ef7862cd6..77011732c8 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -604,6 +604,7 @@ export const dict = { "home.sessions.group.today": "Hoy", "home.sessions.group.yesterday": "Ayer", "home.sessions.group.older": "Anteriores", + "home.providerTip": "Conéctate a más de 75 proveedores para usar otros modelos, como Claude, GPT, Gemini y muchos más", "session.tab.session": "Sesión", "session.tab.review": "Revisión", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index 77a543180d..fa6262ec75 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -557,6 +557,7 @@ export const dict = { "home.sessions.group.today": "Aujourd'hui", "home.sessions.group.yesterday": "Hier", "home.sessions.group.older": "Plus anciennes", + "home.providerTip": "Connectez-vous à plus de 75 fournisseurs pour utiliser d’autres modèles, notamment Claude, GPT, Gemini, etc.", "session.tab.session": "Session", "session.tab.review": "Revue", "session.tab.context": "Contexte", diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts index 24d1a29e8a..87f0ebebe7 100644 --- a/packages/app/src/i18n/ja.ts +++ b/packages/app/src/i18n/ja.ts @@ -550,6 +550,7 @@ export const dict = { "home.sessions.group.today": "今日", "home.sessions.group.yesterday": "昨日", "home.sessions.group.older": "それ以前", + "home.providerTip": "75以上のプロバイダーに接続して、Claude、GPT、Geminiなどの他のモデルを利用できます", "session.tab.session": "セッション", "session.tab.review": "レビュー", "session.tab.context": "コンテキスト", diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index cf789f5644..de3a61a9f9 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -950,6 +950,7 @@ export const dict = { "home.sessions.group.today": "오늘", "home.sessions.group.yesterday": "어제", "home.sessions.group.older": "이전", + "home.providerTip": "75개 이상의 제공업체에 연결하여 Claude, GPT, Gemini 등의 다른 모델을 사용하세요", "session.tab.unknown": "알 수 없는 세션", "session.error.notFound": "이 세션을 찾을 수 없습니다", diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts index f3faa31382..36c64e683d 100644 --- a/packages/app/src/i18n/no.ts +++ b/packages/app/src/i18n/no.ts @@ -1043,6 +1043,7 @@ export const dict = { "home.sessions.group.today": "I dag", "home.sessions.group.yesterday": "I går", "home.sessions.group.older": "Eldre", + "home.providerTip": "Koble til over 75 leverandører for å bruke andre modeller, inkludert Claude, GPT, Gemini og flere", "session.tab.unknown": "Ukjent sesjon", "session.error.notFound": "Denne sesjonen finnes ikke", diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts index 295d8e615a..2a087909b4 100644 --- a/packages/app/src/i18n/pl.ts +++ b/packages/app/src/i18n/pl.ts @@ -553,6 +553,7 @@ export const dict = { "home.sessions.group.today": "Dzisiaj", "home.sessions.group.yesterday": "Wczoraj", "home.sessions.group.older": "Starsze", + "home.providerTip": "Połącz się z ponad 75 dostawcami, aby korzystać z innych modeli, w tym Claude, GPT, Gemini i innych", "session.tab.session": "Sesja", "session.tab.review": "Przegląd", "session.tab.context": "Kontekst", diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts index 7ef78bb480..6079004d6f 100644 --- a/packages/app/src/i18n/ru.ts +++ b/packages/app/src/i18n/ru.ts @@ -604,6 +604,7 @@ export const dict = { "home.sessions.group.today": "Сегодня", "home.sessions.group.yesterday": "Вчера", "home.sessions.group.older": "Ранее", + "home.providerTip": "Подключитесь к более чем 75 провайдерам, чтобы использовать другие модели, включая Claude, GPT, Gemini и другие", "session.tab.session": "Сессия", "session.tab.review": "Обзор", diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts index 686db7407c..5b245d55e2 100644 --- a/packages/app/src/i18n/th.ts +++ b/packages/app/src/i18n/th.ts @@ -599,6 +599,7 @@ export const dict = { "home.sessions.group.today": "วันนี้", "home.sessions.group.yesterday": "เมื่อวาน", "home.sessions.group.older": "ก่อนหน้านี้", + "home.providerTip": "เชื่อมต่อกับผู้ให้บริการกว่า 75 รายเพื่อใช้โมเดลอื่นๆ รวมถึง Claude, GPT, Gemini และอีกมากมาย", "session.tab.session": "เซสชัน", "session.tab.review": "ตรวจสอบ", diff --git a/packages/app/src/i18n/tr.ts b/packages/app/src/i18n/tr.ts index b578f89cca..f0472d325e 100644 --- a/packages/app/src/i18n/tr.ts +++ b/packages/app/src/i18n/tr.ts @@ -608,6 +608,7 @@ export const dict = { "home.sessions.group.today": "Bugün", "home.sessions.group.yesterday": "Dün", "home.sessions.group.older": "Daha eski", + "home.providerTip": "Claude, GPT, Gemini ve diğer modelleri kullanmak için 75'ten fazla sağlayıcıya bağlanın", "session.tab.session": "Oturum", "session.tab.review": "İnceleme", diff --git a/packages/app/src/i18n/uk.ts b/packages/app/src/i18n/uk.ts index ff18c8e342..afac52b0e2 100644 --- a/packages/app/src/i18n/uk.ts +++ b/packages/app/src/i18n/uk.ts @@ -626,6 +626,7 @@ export const dict = { "home.sessions.group.today": "Сьогодні", "home.sessions.group.yesterday": "Учора", "home.sessions.group.older": "Раніше", + "home.providerTip": "Підключіться до понад 75 провайдерів, щоб використовувати інші моделі, зокрема Claude, GPT, Gemini та інші", "session.tab.session": "Сесія", "session.tab.review": "Огляд", diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index 3cccc0c82d..a1325d9067 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -600,6 +600,7 @@ export const dict = { "home.sessions.group.today": "今天", "home.sessions.group.yesterday": "昨天", "home.sessions.group.older": "更早", + "home.providerTip": "连接 75 个以上的提供商,使用 Claude、GPT、Gemini 等其他模型", "session.tab.session": "会话", "session.tab.review": "审查", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index afe285f6e5..436e2b60d8 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -595,6 +595,7 @@ export const dict = { "home.sessions.group.today": "今天", "home.sessions.group.yesterday": "昨天", "home.sessions.group.older": "更早", + "home.providerTip": "連接 75 個以上的供應商,使用 Claude、GPT、Gemini 等其他模型", "session.tab.session": "工作階段", "session.tab.review": "審查", diff --git a/packages/app/src/pages/new-session.tsx b/packages/app/src/pages/new-session.tsx index 7831ed8514..7a8e44c5ab 100644 --- a/packages/app/src/pages/new-session.tsx +++ b/packages/app/src/pages/new-session.tsx @@ -1,8 +1,10 @@ -import { Show, createEffect, createMemo, createResource, untrack } from "solid-js" +import { Show, createEffect, createMemo, createResource, createSignal, onCleanup, untrack } from "solid-js" import { createStore } from "solid-js/store" import { Portal } from "solid-js/web" import { useSearchParams } from "@solidjs/router" import { Tooltip } from "@opencode-ai/ui/tooltip" +import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon" +import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2" import { NewSessionDesignView } from "@/components/session" import { PromptInput } from "@/components/prompt-input" import { StatusPopoverV2 } from "@/components/status-popover" @@ -24,8 +26,14 @@ import { useComposerCommands } from "@/pages/session/use-composer-commands" import { NEW_SESSION_CONTENT_WIDTH } from "@/pages/session/new-session-layout" import { PromptWorkspaceSelector } from "@/components/prompt-workspace-selector" import { useTitlebarRightMount } from "@/components/titlebar" +import { useProviders } from "@/hooks/use-providers" +import { useSettingsDialog } from "@/components/settings-dialog" +import { Persist, persisted } from "@/utils/persist" +import createPresence from "solid-presence" const workspaceBarEnabled = import.meta.env.VITE_OPENCODE_CHANNEL !== "prod" +const providerTipDismissalDuration = 30 * 24 * 60 * 60 * 1000 +const providerTipExitDuration = 250 /** * The `/new-session` draft page. Unlike `session.tsx`, this only renders the prompt @@ -40,6 +48,8 @@ export default function NewSessionPage() { const comments = useComments() const language = useLanguage() const settings = useSettings() + const providers = useProviders(() => sdk().directory) + const openProviderSettings = useSettingsDialog("providers") const route = useSessionKey() const [searchParams, setSearchParams] = useSearchParams<{ draftId?: string; prompt?: string }>() @@ -174,9 +184,81 @@ export default function NewSessionPage() { + serverSync().child(sdk().directory)[0].provider_ready} + connected={() => providers.paid().length > 0} + openProviders={openProviderSettings} + /> ) } + +function ProviderTip(props: { ready: () => boolean; connected: () => boolean; openProviders: () => void }) { + const language = useLanguage() + const [persistedState, setPersistedState, , persistedReady] = persisted( + Persist.global("new-session.provider-tip"), + createStore({ dismissedAt: 0 }), + ) + const visible = createMemo( + () => + props.ready() && + persistedReady() && + !props.connected() && + Date.now() - persistedState.dismissedAt >= providerTipDismissalDuration, + ) + + function dismiss() { + setPersistedState("dismissedAt", Date.now()) + } + + const [ref, setRef] = createSignal() + const presence = createPresence({ + show: () => visible(), + element: () => ref() ?? null, + }) + + return ( + +
+
+ + + + +
+
+
+ ) +}