mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-12 20:49:53 +08:00
refactor(settings): remove wrapper layers, dead props and unused dictionary keys
- components/model-selector.tsx uses Dialog, Command and Tooltip directly; delete components/ai-elements/model-selector.tsx and components/button-with-tooltip.tsx; one renderGroups for both lists; no "Server · " prefix round trip - components/ui: drop CommandDialog, CommandShortcut and six unused shadcn exports - model-config-dialog: no type-to-confirm on provider delete; provider-credentials-fields: drop footer and bedrockApiKey - hooks/use-model-config.ts and lib/types/model-config.ts: remove the 2025-12 single-provider migration, resetConfig, selectedModel and fields nothing reads - components/chat/TemplateFormDialog.tsx replaces the create and edit dialogs; TemplatePanel drops the setInput fallback, the templatesChanged listener, dictionary fallbacks and formatLastUsed; lib/template-storage.ts drops getTemplate, clickCount and indexes - reasoning.tsx becomes one component; shimmer uses a CSS keyframe (motion and @radix-ui/react-use-controllable-state removed) - error-toast.tsx deleted in favour of toast.error; ValidationCard drops the idle status; dev-xml-simulator uses English literals - admin: no enum setting type, shared types from lib/admin (AdminProviderInput stays exported for that), ENABLE_HISTORY_XML_REPLACE entry removed - app/globals.css: drop check-pop, --ease-spring, --duration-normal and the shadow aliases - dictionaries: 81 unused keys removed from all four languages
This commit is contained in:
@@ -56,7 +56,7 @@ const StoredAdminProviderSchema = AdminProviderSchema.extend({
|
||||
vertexApiKey: z.string().optional(),
|
||||
})
|
||||
|
||||
type AdminProviderInput = z.infer<typeof AdminProviderSchema>
|
||||
export type AdminProviderInput = z.infer<typeof AdminProviderSchema>
|
||||
|
||||
// Stored form: secrets are plain strings
|
||||
export interface StoredAdminProvider {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// - ADMIN_PASSWORD / SETTINGS_FILE: bootstrap values, env-only to avoid lockout
|
||||
// - Per-provider reasoning/thinking tuning vars: env-only (see env.example)
|
||||
|
||||
export type SettingType = "string" | "secret" | "number" | "boolean" | "enum"
|
||||
export type SettingType = "string" | "secret" | "number" | "boolean"
|
||||
|
||||
export interface SettingDef {
|
||||
key: string
|
||||
@@ -18,7 +18,6 @@ export interface SettingDef {
|
||||
type: SettingType
|
||||
label: string
|
||||
description?: string
|
||||
options?: string[]
|
||||
min?: number
|
||||
max?: number
|
||||
placeholder?: string
|
||||
@@ -123,13 +122,6 @@ export const SETTINGS_REGISTRY: SettingDef[] = [
|
||||
label: "Validation Timeout (ms)",
|
||||
min: 1000,
|
||||
},
|
||||
{
|
||||
key: "ENABLE_HISTORY_XML_REPLACE",
|
||||
group: "features",
|
||||
type: "boolean",
|
||||
label: "History XML Compression",
|
||||
description: "Replace old diagram XML in history with placeholders.",
|
||||
},
|
||||
{
|
||||
key: "ALLOW_PRIVATE_URLS",
|
||||
group: "features",
|
||||
|
||||
@@ -3,48 +3,25 @@
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"close": "Close",
|
||||
"clear": "Clear",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"loading": "Loading.."
|
||||
},
|
||||
"nav": {
|
||||
"editor": "Editor",
|
||||
"newChat": "New diagram",
|
||||
"github": "GitHub",
|
||||
"settings": "Settings",
|
||||
"hidePanel": "Hide chat panel",
|
||||
"showPanel": "Show chat panel",
|
||||
"aiChat": "AI chat"
|
||||
},
|
||||
"providers": {
|
||||
"useServerDefault": "Use Server Default",
|
||||
"openai": "OpenAI",
|
||||
"anthropic": "Anthropic",
|
||||
"google": "Google",
|
||||
"azure": "Azure OpenAI",
|
||||
"openrouter": "OpenRouter",
|
||||
"deepseek": "DeepSeek",
|
||||
"siliconflow": "SiliconFlow",
|
||||
"modelscope": "ModelScope",
|
||||
"minimax": "MiniMax",
|
||||
"glm": "GLM",
|
||||
"qwen": "Qwen",
|
||||
"kimi": "Kimi",
|
||||
"qiniu": "Qiniu",
|
||||
"mimo": "MiMo (Xiaomi)"
|
||||
},
|
||||
"chat": {
|
||||
"placeholder": "Describe your diagram or upload a file...",
|
||||
"inputLabel": "Chat input",
|
||||
"send": "Send",
|
||||
"stopGeneration": "Stop generation",
|
||||
"sendMessage": "Send message",
|
||||
"clearConversation": "Clear conversation",
|
||||
"uploadFile": "Upload file (image, PDF, text)",
|
||||
"minimalStyle": "Minimal",
|
||||
"styledMode": "Styled",
|
||||
"minimalTooltip": "Use minimal for faster generation (no colors)",
|
||||
"regenerate": "Regenerate response",
|
||||
"copyResponse": "Copy response",
|
||||
"copied": "Copied!",
|
||||
@@ -82,17 +59,6 @@
|
||||
"accessCode": "Access code",
|
||||
"accessCodePlaceholder": "Enter access code",
|
||||
"accessCodeDescription": "Required to use this application.",
|
||||
"aiProvider": "AI Provider Settings",
|
||||
"aiProviderDescription": "Use your own API key to bypass usage limits. Your key is stored locally in your browser and is never stored on the server.",
|
||||
"provider": "Provider",
|
||||
"modelId": "Model ID",
|
||||
"apiKey": "API Key",
|
||||
"apiKeyPlaceholder": "Your API key",
|
||||
"baseUrl": "Base URL (optional)",
|
||||
"customEndpoint": "Custom endpoint URL",
|
||||
"overrides": "Overrides",
|
||||
"clearSettings": "Clear Settings",
|
||||
"useServerDefault": "Use Server Default",
|
||||
"language": "Language",
|
||||
"languageDescription": "Choose your interface language.",
|
||||
"theme": "Theme",
|
||||
@@ -103,10 +69,6 @@
|
||||
"sendShortcutDescription": "Choose how to send messages.",
|
||||
"enterToSend": "Enter to send",
|
||||
"ctrlEnterToSend": "Cmd/Ctrl+Enter to send",
|
||||
"diagramActions": "Diagram Actions",
|
||||
"diagramActionsDescription": "Manage diagram history and exports",
|
||||
"history": "History",
|
||||
"download": "Download",
|
||||
"proxy": "Proxy settings",
|
||||
"proxyDescription": "Configure HTTP/HTTPS proxy for API requests (Desktop only)",
|
||||
"httpProxy": "HTTP proxy",
|
||||
@@ -170,13 +132,9 @@
|
||||
"retryLimit": "Auto-retry limit reached ({max}). Please try again manually.",
|
||||
"continuationRetryLimit": "Continuation retry limit reached ({max}). The diagram may be too complex.",
|
||||
"sessionCorrupted": "Session data was corrupted. Starting fresh.",
|
||||
"failedToSave": "Failed to save messages to localStorage",
|
||||
"failedToRestore": "Failed to restore from localStorage",
|
||||
"failedToPersist": "Failed to persist state before unload",
|
||||
"failedToExport": "Error fetching chart data",
|
||||
"failedToLoadExample": "Error loading example image",
|
||||
"failedToRecordFeedback": "Failed to record your feedback. Please try again.",
|
||||
"storageUpdateFailed": "Chat cleared but browser storage could not be updated",
|
||||
"sessionSaveFailed": "Could not save this chat. Browser storage may be full: delete old chats from history and try again.",
|
||||
"sessionSaveFailedLeave": "Could not save this chat. Browser storage may be full. You can go on without saving it, then delete old chats from the list in the new chat.",
|
||||
"continueWithoutSaving": "Continue without saving",
|
||||
@@ -208,8 +166,6 @@
|
||||
"quota": {
|
||||
"dailyLimit": "Daily Quota Reached",
|
||||
"tokenLimit": "Daily Token Limit Reached",
|
||||
"tpmLimit": "Rate Limit",
|
||||
"tpmMessage": "Too many requests. Please wait a moment.",
|
||||
"tpmMessageDetailed": "Rate limit reached ({limit} tokens/min). Please wait {seconds} seconds before sending another request.",
|
||||
"messageApi": "Looks like you've reached today's demo limit. We're glad you're enjoying it; the limit keeps the demo fair for everyone.",
|
||||
"messageApiSelfHosted": null,
|
||||
@@ -221,7 +177,6 @@
|
||||
"configModel": "Use Your API Key",
|
||||
"selfHost": "Self-host",
|
||||
"sponsor": "Sponsor",
|
||||
"learnMore": "Learn more →",
|
||||
"usedOf": "{used}/{limit}"
|
||||
},
|
||||
"tools": {
|
||||
@@ -248,37 +203,8 @@
|
||||
"thoughtForOne": "Thought for 1 second",
|
||||
"thoughtBrief": "Thought for a few seconds"
|
||||
},
|
||||
"dev": {
|
||||
"title": "Dev: XML Streaming Simulator",
|
||||
"preset": "Preset:",
|
||||
"selectPreset": "Select a preset...",
|
||||
"clear": "Clear",
|
||||
"placeholder": "Paste mxCell XML here or select a preset...",
|
||||
"interval": "Interval:",
|
||||
"chars": "Chars:",
|
||||
"streaming": "Streaming...",
|
||||
"simulate": "Simulate",
|
||||
"stop": "Stop",
|
||||
"testQuotaToast": "Test Quota Toast",
|
||||
"simulatingMessage": "[Dev] Simulating XML streaming",
|
||||
"successMessage": "Successfully displayed the diagram."
|
||||
},
|
||||
"about": {
|
||||
"modelChange": "Model Change & Usage Limits",
|
||||
"walletCrying": "(Or: Why My Wallet is Crying)",
|
||||
"seekingSponsorship": "Call for Sponsorship",
|
||||
"contactMe": "Contact Me",
|
||||
"usageNotice": "Due to high usage, I have changed the model from Claude to minimax-m2 and added some usage limits. See About page for details."
|
||||
},
|
||||
"sessionHistory": {
|
||||
"tooltip": "Chat History",
|
||||
"newChat": "New Chat",
|
||||
"empty": "No diagrams yet",
|
||||
"emptyHint": "Start a conversation to begin",
|
||||
"today": "Today",
|
||||
"yesterday": "Yesterday",
|
||||
"thisWeek": "This Week",
|
||||
"earlier": "Earlier",
|
||||
"deleteTitle": "Delete this diagram?",
|
||||
"deleteDescription": "The diagram and its conversation are deleted for good.",
|
||||
"justNow": "Just now",
|
||||
@@ -351,20 +277,13 @@
|
||||
"regenerateWithFeedback": "Regenerate the diagram using the validation feedback"
|
||||
},
|
||||
"modelConfig": {
|
||||
"configure": "Configure",
|
||||
"addProvider": "Add provider",
|
||||
"addModel": "Add Model",
|
||||
"modelId": "Model ID",
|
||||
"modelLabel": "Display Label",
|
||||
"streaming": "Enable Streaming",
|
||||
"deleteProvider": "Delete provider",
|
||||
"deleteModel": "Delete Model",
|
||||
"noModels": "No models configured. Add a model to get started.",
|
||||
"validationError": "The test failed",
|
||||
"addModelFirst": "Add a model first.",
|
||||
"displayName": "Display Name",
|
||||
"bedrockApiKey": "Bedrock API key",
|
||||
"bedrockApiKeyHint": "With an API key, the access keys below are not needed.",
|
||||
"awsAccessKeyId": "AWS Access Key ID",
|
||||
"awsSecretAccessKey": "AWS Secret Access Key",
|
||||
"awsRegion": "AWS Region",
|
||||
@@ -372,7 +291,6 @@
|
||||
"apiKey": "API key",
|
||||
"enterApiKey": "Enter your API key",
|
||||
"enterSecretKey": "Enter your secret access key",
|
||||
"baseUrl": "Base URL",
|
||||
"optional": "(optional)",
|
||||
"getApiKey": "Get API key",
|
||||
"noTools": "no tool calls",
|
||||
@@ -388,8 +306,6 @@
|
||||
"modelIdEmpty": "Model ID cannot be empty",
|
||||
"modelIdExists": "This model ID already exists",
|
||||
"deleteConfirmDesc": "Are you sure you want to delete {name}? This will remove all configured models and cannot be undone.",
|
||||
"typeToConfirm": "Type \"{name}\" to confirm",
|
||||
"typeProviderName": "Type the provider name...",
|
||||
"requestFailed": "Request failed ({status})",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete",
|
||||
@@ -583,10 +499,6 @@
|
||||
"VALIDATION_TIMEOUT": {
|
||||
"label": "Check Timeout (ms)"
|
||||
},
|
||||
"ENABLE_HISTORY_XML_REPLACE": {
|
||||
"label": "Trim Old Diagrams",
|
||||
"description": "Old diagrams in the chat history are kept as a short marker"
|
||||
},
|
||||
"ALLOW_PRIVATE_URLS": {
|
||||
"label": "Allow Private URLs",
|
||||
"description": "When off, custom model URLs can't point to private networks; safer"
|
||||
@@ -697,7 +609,6 @@
|
||||
"lede": "Describe a diagram or upload a screenshot or PDF. You get a draw.io diagram you can keep editing and export.",
|
||||
"placeholder": "For example: a login sequence diagram with SMS codes and retries",
|
||||
"recent": "Recent diagrams",
|
||||
"drawYourself": "Start with a blank canvas",
|
||||
"openFileHint": "Keep working on a diagram you have"
|
||||
"drawYourself": "Start with a blank canvas"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,48 +3,25 @@
|
||||
"save": "保存",
|
||||
"cancel": "キャンセル",
|
||||
"close": "閉じる",
|
||||
"clear": "クリア",
|
||||
"edit": "編集",
|
||||
"delete": "削除",
|
||||
"loading": "読み込み中.."
|
||||
},
|
||||
"nav": {
|
||||
"editor": "エディタ",
|
||||
"newChat": "新しい図",
|
||||
"github": "GitHub",
|
||||
"settings": "設定",
|
||||
"hidePanel": "チャットパネルを非表示",
|
||||
"showPanel": "チャットパネルを表示",
|
||||
"aiChat": "AI チャット"
|
||||
},
|
||||
"providers": {
|
||||
"useServerDefault": "サーバーデフォルトを使用",
|
||||
"openai": "OpenAI",
|
||||
"anthropic": "Anthropic",
|
||||
"google": "Google",
|
||||
"azure": "Azure OpenAI",
|
||||
"openrouter": "OpenRouter",
|
||||
"deepseek": "DeepSeek",
|
||||
"siliconflow": "SiliconFlow",
|
||||
"modelscope": "ModelScope",
|
||||
"minimax": "MiniMax",
|
||||
"glm": "GLM",
|
||||
"qwen": "Qwen",
|
||||
"kimi": "Kimi",
|
||||
"qiniu": "Qiniu",
|
||||
"mimo": "MiMo (Xiaomi)"
|
||||
},
|
||||
"chat": {
|
||||
"placeholder": "ダイアグラムを説明するか、ファイルをアップロード...",
|
||||
"inputLabel": "チャット入力",
|
||||
"send": "送信",
|
||||
"stopGeneration": "生成を停止",
|
||||
"sendMessage": "メッセージを送信",
|
||||
"clearConversation": "会話をクリア",
|
||||
"uploadFile": "ファイルをアップロード(画像、PDF、テキスト)",
|
||||
"minimalStyle": "ミニマル",
|
||||
"styledMode": "スタイル付き",
|
||||
"minimalTooltip": "高速生成のためミニマルを使用(色なし)",
|
||||
"regenerate": "応答を再生成",
|
||||
"copyResponse": "応答をコピー",
|
||||
"copied": "コピーしました!",
|
||||
@@ -82,17 +59,6 @@
|
||||
"accessCode": "アクセスコード",
|
||||
"accessCodePlaceholder": "アクセスコードを入力",
|
||||
"accessCodeDescription": "このアプリケーションを使用するために必要です。",
|
||||
"aiProvider": "AI プロバイダー設定",
|
||||
"aiProviderDescription": "独自の API キーを使用して使用制限を回避できます。キーはブラウザのローカルに保存され、サーバーには保存されません。",
|
||||
"provider": "プロバイダー",
|
||||
"modelId": "モデル ID",
|
||||
"apiKey": "API キー",
|
||||
"apiKeyPlaceholder": "あなたの API キー",
|
||||
"baseUrl": "ベース URL(オプション)",
|
||||
"customEndpoint": "カスタムエンドポイント URL",
|
||||
"overrides": "上書き",
|
||||
"clearSettings": "設定をクリア",
|
||||
"useServerDefault": "サーバーデフォルトを使用",
|
||||
"language": "言語",
|
||||
"languageDescription": "インターフェース言語を選択します。",
|
||||
"theme": "テーマ",
|
||||
@@ -103,10 +69,6 @@
|
||||
"sendShortcutDescription": "メッセージの送信方法を選択します。",
|
||||
"enterToSend": "Enterで送信",
|
||||
"ctrlEnterToSend": "Cmd/Ctrl+Enterで送信",
|
||||
"diagramActions": "ダイアグラム操作",
|
||||
"diagramActionsDescription": "ダイアグラムの履歴とエクスポートを管理",
|
||||
"history": "履歴",
|
||||
"download": "ダウンロード",
|
||||
"proxy": "プロキシ設定",
|
||||
"proxyDescription": "API リクエスト用の HTTP/HTTPS プロキシを設定(デスクトップ版のみ)",
|
||||
"httpProxy": "HTTP プロキシ",
|
||||
@@ -170,13 +132,9 @@
|
||||
"retryLimit": "自動再試行制限に達しました({max})。手動で再試行してください。",
|
||||
"continuationRetryLimit": "継続再試行制限に達しました({max})。ダイアグラムが複雑すぎる可能性があります。",
|
||||
"sessionCorrupted": "セッションデータが破損しました。最初からやり直します。",
|
||||
"failedToSave": "localStorage へのメッセージの保存に失敗しました",
|
||||
"failedToRestore": "localStorage からの復元に失敗しました",
|
||||
"failedToPersist": "アンロード前の状態の永続化に失敗しました",
|
||||
"failedToExport": "チャートデータの取得エラー",
|
||||
"failedToLoadExample": "例の画像の読み込みエラー",
|
||||
"failedToRecordFeedback": "フィードバックの記録に失敗しました。もう一度お試しください。",
|
||||
"storageUpdateFailed": "チャットはクリアされましたが、ブラウザストレージを更新できませんでした",
|
||||
"sessionSaveFailed": "このチャットを保存できませんでした。ブラウザのストレージがいっぱいの可能性があります。履歴から古いチャットを削除して、もう一度お試しください。",
|
||||
"sessionSaveFailedLeave": "このチャットを保存できませんでした。ブラウザのストレージがいっぱいの可能性があります。保存せずに続けて、新しいチャットの一覧から古いチャットを削除できます。",
|
||||
"continueWithoutSaving": "保存せずに続ける",
|
||||
@@ -208,8 +166,6 @@
|
||||
"quota": {
|
||||
"dailyLimit": "1日の割当量に達しました",
|
||||
"tokenLimit": "1日のトークン制限に達しました",
|
||||
"tpmLimit": "レート制限",
|
||||
"tpmMessage": "リクエストが多すぎます。しばらくお待ちください。",
|
||||
"tpmMessageDetailed": "レート制限に達しました({limit}トークン/分)。{seconds}秒待ってからもう一度リクエストしてください。",
|
||||
"messageApi": "今日のデモ利用上限に達したようです。楽しんでいただけて嬉しいです。皆様に公平にご利用いただくため、利用量に上限を設けています。",
|
||||
"messageApiSelfHosted": null,
|
||||
@@ -221,7 +177,6 @@
|
||||
"configModel": "APIキーを使用",
|
||||
"selfHost": "セルフホスト",
|
||||
"sponsor": "スポンサー",
|
||||
"learnMore": "詳細 →",
|
||||
"usedOf": "{used}/{limit}"
|
||||
},
|
||||
"tools": {
|
||||
@@ -248,37 +203,8 @@
|
||||
"thoughtForOne": "1 秒考えました",
|
||||
"thoughtBrief": "数秒考えました"
|
||||
},
|
||||
"dev": {
|
||||
"title": "開発:XMLストリーミングシミュレーター",
|
||||
"preset": "プリセット:",
|
||||
"selectPreset": "プリセットを選択...",
|
||||
"clear": "クリア",
|
||||
"placeholder": "ここに mxCell XML を貼り付けるか、プリセットを選択...",
|
||||
"interval": "間隔:",
|
||||
"chars": "文字:",
|
||||
"streaming": "ストリーミング中...",
|
||||
"simulate": "シミュレート",
|
||||
"stop": "停止",
|
||||
"testQuotaToast": "クォータトーストをテスト",
|
||||
"simulatingMessage": "[開発] XMLストリーミングをシミュレート中",
|
||||
"successMessage": "ダイアグラムの表示に成功しました。"
|
||||
},
|
||||
"about": {
|
||||
"modelChange": "モデル変更と利用制限について",
|
||||
"walletCrying": "(別名:お財布が悲鳴を上げています)",
|
||||
"seekingSponsorship": "スポンサー募集",
|
||||
"contactMe": "お問い合わせ",
|
||||
"usageNotice": "利用量の増加に伴い、コスト削減のためモデルを Claude から minimax-m2 に変更し、いくつかの利用制限を設けました。詳細は概要ページをご覧ください。"
|
||||
},
|
||||
"sessionHistory": {
|
||||
"tooltip": "チャット履歴",
|
||||
"newChat": "新しいチャット",
|
||||
"empty": "まだ図はありません",
|
||||
"emptyHint": "会話を始めてください",
|
||||
"today": "今日",
|
||||
"yesterday": "昨日",
|
||||
"thisWeek": "今週",
|
||||
"earlier": "それ以前",
|
||||
"deleteTitle": "この図を削除しますか?",
|
||||
"deleteDescription": "図とその会話は完全に削除されます。",
|
||||
"justNow": "たった今",
|
||||
@@ -306,20 +232,13 @@
|
||||
"regenerateWithFeedback": "検証フィードバックを使用してダイアグラムを再生成"
|
||||
},
|
||||
"modelConfig": {
|
||||
"configure": "設定",
|
||||
"addProvider": "プロバイダーを追加",
|
||||
"addModel": "モデルを追加",
|
||||
"modelId": "モデルID",
|
||||
"modelLabel": "表示名",
|
||||
"streaming": "ストリーミングを有効",
|
||||
"deleteProvider": "プロバイダーを削除",
|
||||
"deleteModel": "モデルを削除",
|
||||
"noModels": "モデルが設定されていません。モデルを追加してください。",
|
||||
"validationError": "テストに失敗しました",
|
||||
"addModelFirst": "先にモデルを追加してください。",
|
||||
"displayName": "表示名",
|
||||
"bedrockApiKey": "Bedrock API キー",
|
||||
"bedrockApiKeyHint": "API キーを入力すれば、下のアクセスキーは不要です。",
|
||||
"awsAccessKeyId": "AWS アクセスキー ID",
|
||||
"awsSecretAccessKey": "AWS シークレットアクセスキー",
|
||||
"awsRegion": "AWS リージョン",
|
||||
@@ -327,7 +246,6 @@
|
||||
"apiKey": "API キー",
|
||||
"enterApiKey": "API キーを入力",
|
||||
"enterSecretKey": "シークレットアクセスキーを入力",
|
||||
"baseUrl": "ベース URL",
|
||||
"optional": "(オプション)",
|
||||
"getApiKey": "API キーを取得",
|
||||
"noTools": "ツール呼び出し非対応",
|
||||
@@ -343,8 +261,6 @@
|
||||
"modelIdEmpty": "モデル ID は空にできません",
|
||||
"modelIdExists": "このモデル ID は既に存在します",
|
||||
"deleteConfirmDesc": "{name} を削除してもよろしいですか?設定されたすべてのモデルが削除され、元に戻せません。",
|
||||
"typeToConfirm": "確認のため「{name}」と入力",
|
||||
"typeProviderName": "プロバイダー名を入力...",
|
||||
"requestFailed": "リクエストに失敗しました({status})",
|
||||
"cancel": "キャンセル",
|
||||
"delete": "削除",
|
||||
@@ -583,10 +499,6 @@
|
||||
"VALIDATION_TIMEOUT": {
|
||||
"label": "チェックのタイムアウト(ms)"
|
||||
},
|
||||
"ENABLE_HISTORY_XML_REPLACE": {
|
||||
"label": "古い図を省略",
|
||||
"description": "会話履歴の古い図は短い印だけ残します"
|
||||
},
|
||||
"ALLOW_PRIVATE_URLS": {
|
||||
"label": "内部ネットワークへのアクセス",
|
||||
"description": "オフにすると、ユーザーが指定するモデルの URL に内部アドレスを使えなくなり、安全です"
|
||||
@@ -697,7 +609,6 @@
|
||||
"lede": "図を説明するか、スクリーンショットや PDF をアップロードしてください。できあがるのは編集もエクスポートもできる draw.io の図です。",
|
||||
"placeholder": "例:SMS 認証とリトライを含むログインのシーケンス図",
|
||||
"recent": "最近の図",
|
||||
"drawYourself": "白紙のキャンバスから始める",
|
||||
"openFileHint": "手元の図の続きを編集"
|
||||
"drawYourself": "白紙のキャンバスから始める"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,48 +3,25 @@
|
||||
"save": "儲存",
|
||||
"cancel": "取消",
|
||||
"close": "關閉",
|
||||
"clear": "清除",
|
||||
"edit": "編輯",
|
||||
"delete": "刪除",
|
||||
"loading": "載入中..."
|
||||
},
|
||||
"nav": {
|
||||
"editor": "編輯器",
|
||||
"newChat": "新增圖紙",
|
||||
"github": "GitHub",
|
||||
"settings": "設定",
|
||||
"hidePanel": "隱藏聊天面板",
|
||||
"showPanel": "顯示聊天面板",
|
||||
"aiChat": "AI 對話"
|
||||
},
|
||||
"providers": {
|
||||
"useServerDefault": "使用伺服器預設值",
|
||||
"openai": "OpenAI",
|
||||
"anthropic": "Anthropic",
|
||||
"google": "Google",
|
||||
"azure": "Azure OpenAI",
|
||||
"openrouter": "OpenRouter",
|
||||
"deepseek": "DeepSeek",
|
||||
"siliconflow": "SiliconFlow",
|
||||
"modelscope": "ModelScope",
|
||||
"minimax": "MiniMax",
|
||||
"glm": "GLM",
|
||||
"qwen": "Qwen",
|
||||
"kimi": "Kimi",
|
||||
"qiniu": "Qiniu",
|
||||
"mimo": "MiMo (小米)"
|
||||
},
|
||||
"chat": {
|
||||
"placeholder": "描述您的圖表或上傳檔案...",
|
||||
"inputLabel": "聊天輸入框",
|
||||
"send": "傳送",
|
||||
"stopGeneration": "停止產生",
|
||||
"sendMessage": "傳送訊息",
|
||||
"clearConversation": "清除對話",
|
||||
"uploadFile": "上傳檔案(圖片、PDF、文字)",
|
||||
"minimalStyle": "簡約",
|
||||
"styledMode": "精緻",
|
||||
"minimalTooltip": "使用簡約模式以加快產生速度(無顏色)",
|
||||
"regenerate": "重新產生回應",
|
||||
"copyResponse": "複製回應",
|
||||
"copied": "已複製!",
|
||||
@@ -82,17 +59,6 @@
|
||||
"accessCode": "存取碼",
|
||||
"accessCodePlaceholder": "輸入存取碼",
|
||||
"accessCodeDescription": "使用此應用程式需要存取碼。",
|
||||
"aiProvider": "AI 服務商設定",
|
||||
"aiProviderDescription": "使用您自己的 API 金鑰來繞過使用限制。您的金鑰僅儲存在瀏覽器本機,不會儲存在伺服器上。",
|
||||
"provider": "服務商",
|
||||
"modelId": "模型 ID",
|
||||
"apiKey": "API 金鑰",
|
||||
"apiKeyPlaceholder": "您的 API 金鑰",
|
||||
"baseUrl": "基礎 URL(可選)",
|
||||
"customEndpoint": "自訂端點 URL",
|
||||
"overrides": "覆寫",
|
||||
"clearSettings": "清除設定",
|
||||
"useServerDefault": "使用伺服器預設值",
|
||||
"language": "語言",
|
||||
"languageDescription": "選擇介面語言。",
|
||||
"theme": "主題",
|
||||
@@ -103,10 +69,6 @@
|
||||
"sendShortcutDescription": "選擇傳送訊息的方式。",
|
||||
"enterToSend": "Enter 傳送",
|
||||
"ctrlEnterToSend": "Cmd/Ctrl+Enter 傳送",
|
||||
"diagramActions": "圖表操作",
|
||||
"diagramActionsDescription": "管理圖表歷史紀錄和匯出",
|
||||
"history": "歷史紀錄",
|
||||
"download": "下載",
|
||||
"proxy": "代理設定",
|
||||
"proxyDescription": "配置 API 請求的 HTTP/HTTPS 代理(僅桌面版)",
|
||||
"httpProxy": "HTTP 代理",
|
||||
@@ -170,13 +132,9 @@
|
||||
"retryLimit": "已達自動重試限制({max})。請手動重試。",
|
||||
"continuationRetryLimit": "已達繼續重試限制({max})。圖表可能過於複雜。",
|
||||
"sessionCorrupted": "工作階段資料已損壞。重新開始。",
|
||||
"failedToSave": "無法儲存訊息到 localStorage",
|
||||
"failedToRestore": "無法從 localStorage 還原",
|
||||
"failedToPersist": "卸載前無法持久化狀態",
|
||||
"failedToExport": "取得圖表資料時出錯",
|
||||
"failedToLoadExample": "載入範例圖片時出錯",
|
||||
"failedToRecordFeedback": "記錄您的回饋失敗。請重試。",
|
||||
"storageUpdateFailed": "聊天已清除,但無法更新瀏覽器儲存空間",
|
||||
"sessionSaveFailed": "無法儲存這個對話。瀏覽器儲存空間可能已滿,請在歷史紀錄裡刪除舊對話後重試。",
|
||||
"sessionSaveFailedLeave": "無法儲存這個對話,瀏覽器儲存空間可能已滿。可以不儲存它、直接繼續,再在新對話的列表裡刪除舊對話。",
|
||||
"continueWithoutSaving": "不儲存,繼續",
|
||||
@@ -208,8 +166,6 @@
|
||||
"quota": {
|
||||
"dailyLimit": "已達每日配額",
|
||||
"tokenLimit": "已達每日 token 上限",
|
||||
"tpmLimit": "速率限制",
|
||||
"tpmMessage": "請求過多。請稍等片刻。",
|
||||
"tpmMessageDetailed": "達到速率限制(每分鐘 {limit} token)。請等待 {seconds} 秒後再傳送請求。",
|
||||
"messageApi": "看來您今天的體驗次數已達上限。很高興您玩得開心;為了讓大家都能公平使用,示範站對用量做了限制。",
|
||||
"messageApiSelfHosted": null,
|
||||
@@ -221,7 +177,6 @@
|
||||
"configModel": "使用自己的 API Key",
|
||||
"selfHost": "自行託管",
|
||||
"sponsor": "贊助",
|
||||
"learnMore": "了解更多 →",
|
||||
"usedOf": "{used}/{limit}"
|
||||
},
|
||||
"tools": {
|
||||
@@ -248,37 +203,8 @@
|
||||
"thoughtForOne": "思考了 1 秒",
|
||||
"thoughtBrief": "思考了幾秒鐘"
|
||||
},
|
||||
"dev": {
|
||||
"title": "開發:XML 串流模擬器",
|
||||
"preset": "預設:",
|
||||
"selectPreset": "選擇預設...",
|
||||
"clear": "清除",
|
||||
"placeholder": "在此貼上 mxCell XML 或選擇預設...",
|
||||
"interval": "間隔:",
|
||||
"chars": "字元:",
|
||||
"streaming": "串流傳輸中...",
|
||||
"simulate": "模擬",
|
||||
"stop": "停止",
|
||||
"testQuotaToast": "測試配額提示",
|
||||
"simulatingMessage": "[開發] 模擬 XML 串流傳輸",
|
||||
"successMessage": "成功顯示圖表。"
|
||||
},
|
||||
"about": {
|
||||
"modelChange": "模型變更與用量限制",
|
||||
"walletCrying": "(別名:我的錢包頂不住了)",
|
||||
"seekingSponsorship": "尋求贊助(求大佬撈一把)",
|
||||
"contactMe": "聯絡我",
|
||||
"usageNotice": "由於使用量過高,我已將模型從 Claude 更換為 minimax-m2,並設定了一些用量限制。詳情請查看關於頁面。"
|
||||
},
|
||||
"sessionHistory": {
|
||||
"tooltip": "聊天歷史",
|
||||
"newChat": "新對話",
|
||||
"empty": "還沒有圖紙",
|
||||
"emptyHint": "開始對話吧",
|
||||
"today": "今天",
|
||||
"yesterday": "昨天",
|
||||
"thisWeek": "本週",
|
||||
"earlier": "更早",
|
||||
"deleteTitle": "刪除這張圖紙?",
|
||||
"deleteDescription": "圖紙和它的對話會被永久刪除。",
|
||||
"justNow": "剛剛",
|
||||
@@ -351,20 +277,13 @@
|
||||
"regenerateWithFeedback": "使用驗證回饋重新產生圖表"
|
||||
},
|
||||
"modelConfig": {
|
||||
"configure": "配置",
|
||||
"addProvider": "新增服務商",
|
||||
"addModel": "新增模型",
|
||||
"modelId": "模型 ID",
|
||||
"modelLabel": "顯示名稱",
|
||||
"streaming": "啟用串流輸出",
|
||||
"deleteProvider": "刪除服務商",
|
||||
"deleteModel": "刪除模型",
|
||||
"noModels": "尚未配置模型。新增模型以開始使用。",
|
||||
"validationError": "測試沒通過",
|
||||
"addModelFirst": "先新增一個模型。",
|
||||
"displayName": "顯示名稱",
|
||||
"bedrockApiKey": "Bedrock API Key",
|
||||
"bedrockApiKeyHint": "填了 API 金鑰,下面的存取金鑰就不用填。",
|
||||
"awsAccessKeyId": "AWS 存取金鑰 ID",
|
||||
"awsSecretAccessKey": "AWS Secret Access Key",
|
||||
"awsRegion": "AWS 區域",
|
||||
@@ -372,7 +291,6 @@
|
||||
"apiKey": "API Key",
|
||||
"enterApiKey": "輸入 API Key",
|
||||
"enterSecretKey": "輸入 Secret Access Key",
|
||||
"baseUrl": "基礎 URL",
|
||||
"optional": "(可選)",
|
||||
"getApiKey": "取得 API Key",
|
||||
"noTools": "不支援工具呼叫",
|
||||
@@ -388,8 +306,6 @@
|
||||
"modelIdEmpty": "模型 ID 不能為空",
|
||||
"modelIdExists": "此模型 ID 已存在",
|
||||
"deleteConfirmDesc": "確定要刪除 {name} 嗎?這將移除所有配置的模型且無法復原。",
|
||||
"typeToConfirm": "輸入「{name}」以確認",
|
||||
"typeProviderName": "輸入服務商名稱...",
|
||||
"requestFailed": "請求失敗({status})",
|
||||
"cancel": "取消",
|
||||
"delete": "刪除",
|
||||
@@ -583,10 +499,6 @@
|
||||
"VALIDATION_TIMEOUT": {
|
||||
"label": "檢查逾時(毫秒)"
|
||||
},
|
||||
"ENABLE_HISTORY_XML_REPLACE": {
|
||||
"label": "精簡舊圖",
|
||||
"description": "對話歷史裡的舊圖表只留簡短標記"
|
||||
},
|
||||
"ALLOW_PRIVATE_URLS": {
|
||||
"label": "存取內網",
|
||||
"description": "關閉後,自訂模型位址不能指向內網,更安全"
|
||||
@@ -697,7 +609,6 @@
|
||||
"lede": "描述一張圖,或上傳截圖、PDF。得到的是可以繼續編輯和匯出的 draw.io 圖。",
|
||||
"placeholder": "例如:使用者登入的時序圖,包含簡訊驗證碼和失敗重試",
|
||||
"recent": "最近的圖紙",
|
||||
"drawYourself": "從空白畫布開始",
|
||||
"openFileHint": "接著編輯已有的圖"
|
||||
"drawYourself": "從空白畫布開始"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,48 +3,25 @@
|
||||
"save": "保存",
|
||||
"cancel": "取消",
|
||||
"close": "关闭",
|
||||
"clear": "清除",
|
||||
"edit": "编辑",
|
||||
"delete": "删除",
|
||||
"loading": "加载中..."
|
||||
},
|
||||
"nav": {
|
||||
"editor": "编辑器",
|
||||
"newChat": "新建图纸",
|
||||
"github": "GitHub",
|
||||
"settings": "设置",
|
||||
"hidePanel": "隐藏聊天面板",
|
||||
"showPanel": "显示聊天面板",
|
||||
"aiChat": "AI 对话"
|
||||
},
|
||||
"providers": {
|
||||
"useServerDefault": "使用服务器默认值",
|
||||
"openai": "OpenAI",
|
||||
"anthropic": "Anthropic",
|
||||
"google": "Google",
|
||||
"azure": "Azure OpenAI",
|
||||
"openrouter": "OpenRouter",
|
||||
"deepseek": "DeepSeek",
|
||||
"siliconflow": "SiliconFlow",
|
||||
"modelscope": "ModelScope",
|
||||
"minimax": "MiniMax",
|
||||
"glm": "GLM",
|
||||
"qwen": "Qwen",
|
||||
"kimi": "Kimi",
|
||||
"qiniu": "Qiniu",
|
||||
"mimo": "MiMo (小米)"
|
||||
},
|
||||
"chat": {
|
||||
"placeholder": "描述您的图表或上传文件...",
|
||||
"inputLabel": "聊天输入框",
|
||||
"send": "发送",
|
||||
"stopGeneration": "停止生成",
|
||||
"sendMessage": "发送消息",
|
||||
"clearConversation": "清除对话",
|
||||
"uploadFile": "上传文件(图片、PDF、文本)",
|
||||
"minimalStyle": "简约",
|
||||
"styledMode": "精致",
|
||||
"minimalTooltip": "使用简约模式以加快生成速度(无颜色)",
|
||||
"regenerate": "重新生成响应",
|
||||
"copyResponse": "复制响应",
|
||||
"copied": "已复制!",
|
||||
@@ -82,17 +59,6 @@
|
||||
"accessCode": "访问码",
|
||||
"accessCodePlaceholder": "输入访问码",
|
||||
"accessCodeDescription": "使用此应用程序需要访问码。",
|
||||
"aiProvider": "AI 服务商设置",
|
||||
"aiProviderDescription": "使用您自己的 API 密钥来绕过使用限制。您的密钥仅存储在浏览器本地,不会存储在服务器上。",
|
||||
"provider": "服务商",
|
||||
"modelId": "模型 ID",
|
||||
"apiKey": "API 密钥",
|
||||
"apiKeyPlaceholder": "您的 API 密钥",
|
||||
"baseUrl": "基础 URL(可选)",
|
||||
"customEndpoint": "自定义端点 URL",
|
||||
"overrides": "覆盖",
|
||||
"clearSettings": "清除设置",
|
||||
"useServerDefault": "使用服务器默认值",
|
||||
"language": "语言",
|
||||
"languageDescription": "选择界面语言。",
|
||||
"theme": "主题",
|
||||
@@ -103,10 +69,6 @@
|
||||
"sendShortcutDescription": "选择发送消息的方式。",
|
||||
"enterToSend": "回车发送",
|
||||
"ctrlEnterToSend": "Cmd/Ctrl+回车发送",
|
||||
"diagramActions": "图表操作",
|
||||
"diagramActionsDescription": "管理图表历史记录和导出",
|
||||
"history": "历史记录",
|
||||
"download": "下载",
|
||||
"proxy": "代理设置",
|
||||
"proxyDescription": "配置 API 请求的 HTTP/HTTPS 代理(仅桌面版)",
|
||||
"httpProxy": "HTTP 代理",
|
||||
@@ -170,13 +132,9 @@
|
||||
"retryLimit": "已达到自动重试限制({max})。请手动重试。",
|
||||
"continuationRetryLimit": "已达到继续重试限制({max})。图表可能过于复杂。",
|
||||
"sessionCorrupted": "会话数据已损坏。重新开始。",
|
||||
"failedToSave": "无法保存消息到 localStorage",
|
||||
"failedToRestore": "无法从 localStorage 恢复",
|
||||
"failedToPersist": "卸载前无法持久化状态",
|
||||
"failedToExport": "获取图表数据时出错",
|
||||
"failedToLoadExample": "加载示例图片时出错",
|
||||
"failedToRecordFeedback": "记录您的反馈失败。请重试。",
|
||||
"storageUpdateFailed": "聊天已清除,但无法更新浏览器存储",
|
||||
"sessionSaveFailed": "无法保存这个对话。浏览器存储空间可能已满,请在历史记录里删除旧对话后重试。",
|
||||
"sessionSaveFailedLeave": "无法保存这个对话,浏览器存储空间可能已满。可以不保存它、直接继续,再在新对话的列表里删除旧对话。",
|
||||
"continueWithoutSaving": "不保存,继续",
|
||||
@@ -208,8 +166,6 @@
|
||||
"quota": {
|
||||
"dailyLimit": "已达每日配额",
|
||||
"tokenLimit": "已达每日 token 上限",
|
||||
"tpmLimit": "速率限制",
|
||||
"tpmMessage": "请求过多。请稍等片刻。",
|
||||
"tpmMessageDetailed": "达到速率限制(每分钟 {limit} token)。请等待 {seconds} 秒后再发送请求。",
|
||||
"messageApi": "看来您今天的体验次数已达上限。很高兴您玩得开心;为了让大家都能公平使用,演示站对用量做了限制。",
|
||||
"messageApiSelfHosted": null,
|
||||
@@ -221,7 +177,6 @@
|
||||
"configModel": "使用自己的 API Key",
|
||||
"selfHost": "自托管",
|
||||
"sponsor": "赞助",
|
||||
"learnMore": "了解更多 →",
|
||||
"usedOf": "{used}/{limit}"
|
||||
},
|
||||
"tools": {
|
||||
@@ -248,37 +203,8 @@
|
||||
"thoughtForOne": "思考了 1 秒",
|
||||
"thoughtBrief": "思考了几秒钟"
|
||||
},
|
||||
"dev": {
|
||||
"title": "开发:XML 流式模拟器",
|
||||
"preset": "预设:",
|
||||
"selectPreset": "选择预设...",
|
||||
"clear": "清除",
|
||||
"placeholder": "在此粘贴 mxCell XML 或选择预设...",
|
||||
"interval": "间隔:",
|
||||
"chars": "字符:",
|
||||
"streaming": "流式传输中...",
|
||||
"simulate": "模拟",
|
||||
"stop": "停止",
|
||||
"testQuotaToast": "测试配额提示",
|
||||
"simulatingMessage": "[开发] 模拟 XML 流式传输",
|
||||
"successMessage": "成功显示图表。"
|
||||
},
|
||||
"about": {
|
||||
"modelChange": "模型变更与用量限制",
|
||||
"walletCrying": "(别名:我的钱包顶不住了)",
|
||||
"seekingSponsorship": "寻求赞助(求大佬捞一把)",
|
||||
"contactMe": "联系我",
|
||||
"usageNotice": "由于使用量过高,我已将模型从 Claude 更换为 minimax-m2,并设置了一些用量限制。详情请查看关于页面。"
|
||||
},
|
||||
"sessionHistory": {
|
||||
"tooltip": "聊天历史",
|
||||
"newChat": "新对话",
|
||||
"empty": "还没有图纸",
|
||||
"emptyHint": "开始对话吧",
|
||||
"today": "今天",
|
||||
"yesterday": "昨天",
|
||||
"thisWeek": "本周",
|
||||
"earlier": "更早",
|
||||
"deleteTitle": "删除这张图纸?",
|
||||
"deleteDescription": "图纸和它的对话会被永久删除。",
|
||||
"justNow": "刚刚",
|
||||
@@ -351,20 +277,13 @@
|
||||
"regenerateWithFeedback": "使用验证反馈重新生成图表"
|
||||
},
|
||||
"modelConfig": {
|
||||
"configure": "配置",
|
||||
"addProvider": "添加服务商",
|
||||
"addModel": "添加模型",
|
||||
"modelId": "模型 ID",
|
||||
"modelLabel": "显示名称",
|
||||
"streaming": "启用流式输出",
|
||||
"deleteProvider": "删除服务商",
|
||||
"deleteModel": "删除模型",
|
||||
"noModels": "尚未配置模型。添加模型以开始使用。",
|
||||
"validationError": "测试没通过",
|
||||
"addModelFirst": "先添加一个模型。",
|
||||
"displayName": "显示名称",
|
||||
"bedrockApiKey": "Bedrock API Key",
|
||||
"bedrockApiKeyHint": "填了 API 密钥,下面的访问密钥就不用填。",
|
||||
"awsAccessKeyId": "AWS 访问密钥 ID",
|
||||
"awsSecretAccessKey": "AWS Secret Access Key",
|
||||
"awsRegion": "AWS 区域",
|
||||
@@ -372,7 +291,6 @@
|
||||
"apiKey": "API Key",
|
||||
"enterApiKey": "输入 API Key",
|
||||
"enterSecretKey": "输入 Secret Access Key",
|
||||
"baseUrl": "基础 URL",
|
||||
"optional": "(可选)",
|
||||
"getApiKey": "获取 API Key",
|
||||
"noTools": "不支持工具调用",
|
||||
@@ -388,8 +306,6 @@
|
||||
"modelIdEmpty": "模型 ID 不能为空",
|
||||
"modelIdExists": "此模型 ID 已存在",
|
||||
"deleteConfirmDesc": "确定要删除 {name} 吗?这将移除所有配置的模型且无法撤销。",
|
||||
"typeToConfirm": "输入 \"{name}\" 以确认",
|
||||
"typeProviderName": "输入服务商名称...",
|
||||
"requestFailed": "请求失败({status})",
|
||||
"cancel": "取消",
|
||||
"delete": "删除",
|
||||
@@ -583,10 +499,6 @@
|
||||
"VALIDATION_TIMEOUT": {
|
||||
"label": "检查超时(毫秒)"
|
||||
},
|
||||
"ENABLE_HISTORY_XML_REPLACE": {
|
||||
"label": "精简旧图",
|
||||
"description": "对话历史里的旧图表只留简短标记"
|
||||
},
|
||||
"ALLOW_PRIVATE_URLS": {
|
||||
"label": "访问内网",
|
||||
"description": "关闭后,自定义模型地址不能指向内网,更安全"
|
||||
@@ -697,7 +609,6 @@
|
||||
"lede": "描述一张图,或上传截图、PDF。得到的是可以继续编辑和导出的 draw.io 图。",
|
||||
"placeholder": "比如:用户登录的时序图,包含短信验证码和失败重试",
|
||||
"recent": "最近的图纸",
|
||||
"drawYourself": "从空白画布开始",
|
||||
"openFileHint": "接着编辑已有的图"
|
||||
"drawYourself": "从空白画布开始"
|
||||
}
|
||||
}
|
||||
|
||||
+3
-58
@@ -1,5 +1,6 @@
|
||||
import { type DBSchema, type IDBPDatabase, openDB } from "idb"
|
||||
import { nanoid } from "nanoid"
|
||||
import { isIndexedDBAvailable } from "./session-storage"
|
||||
|
||||
// Constants
|
||||
const DB_NAME = "next-ai-drawio-templates"
|
||||
@@ -14,7 +15,6 @@ export interface Template {
|
||||
description?: string
|
||||
createdAt: number
|
||||
updatedAt: number
|
||||
clickCount: number
|
||||
runCount: number
|
||||
lastUsedAt: number
|
||||
pinned: boolean
|
||||
@@ -24,12 +24,7 @@ export type TemplateCreateInput = Pick<Template, "prompt"> &
|
||||
Partial<
|
||||
Omit<
|
||||
Template,
|
||||
| "id"
|
||||
| "createdAt"
|
||||
| "updatedAt"
|
||||
| "clickCount"
|
||||
| "runCount"
|
||||
| "lastUsedAt"
|
||||
"id" | "createdAt" | "updatedAt" | "runCount" | "lastUsedAt"
|
||||
>
|
||||
>
|
||||
|
||||
@@ -37,12 +32,6 @@ interface TemplateDB extends DBSchema {
|
||||
templates: {
|
||||
key: string
|
||||
value: Template
|
||||
indexes: {
|
||||
"by-updated": number
|
||||
"by-pinned": number
|
||||
"by-run-count": number
|
||||
"by-last-used": number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,13 +53,7 @@ async function getDB(): Promise<IDBPDatabase<TemplateDB>> {
|
||||
upgrade(db, oldVersion) {
|
||||
if (oldVersion < 1) {
|
||||
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
||||
const templateStore = db.createObjectStore(STORE_NAME, {
|
||||
keyPath: "id",
|
||||
})
|
||||
templateStore.createIndex("by-updated", "updatedAt")
|
||||
templateStore.createIndex("by-pinned", "pinned")
|
||||
templateStore.createIndex("by-run-count", "runCount")
|
||||
templateStore.createIndex("by-last-used", "lastUsedAt")
|
||||
db.createObjectStore(STORE_NAME, { keyPath: "id" })
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -79,16 +62,6 @@ async function getDB(): Promise<IDBPDatabase<TemplateDB>> {
|
||||
return dbPromise
|
||||
}
|
||||
|
||||
// Check if IndexedDB is available
|
||||
export function isIndexedDBAvailable(): boolean {
|
||||
if (typeof window === "undefined") return false
|
||||
try {
|
||||
return "indexedDB" in window && window.indexedDB !== null
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// CRUD Operations
|
||||
|
||||
export async function getAllTemplates(): Promise<Template[]> {
|
||||
@@ -103,17 +76,6 @@ export async function getAllTemplates(): Promise<Template[]> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTemplate(id: string): Promise<Template | null> {
|
||||
if (!isIndexedDBAvailable()) return null
|
||||
try {
|
||||
const db = await getDB()
|
||||
return (await db.get(STORE_NAME, id)) || null
|
||||
} catch (error) {
|
||||
console.error("Failed to get template:", error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function createTemplate(
|
||||
input: TemplateCreateInput,
|
||||
): Promise<Template | null> {
|
||||
@@ -130,7 +92,6 @@ export async function createTemplate(
|
||||
description: input.description?.trim() || undefined,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
clickCount: 0,
|
||||
runCount: 0,
|
||||
lastUsedAt: 0,
|
||||
pinned: input.pinned ?? false,
|
||||
@@ -200,7 +161,6 @@ export async function duplicateTemplate(
|
||||
title: `${existing.title} ${copySuffix}`,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
clickCount: 0,
|
||||
runCount: 0,
|
||||
lastUsedAt: 0,
|
||||
pinned: false,
|
||||
@@ -215,20 +175,6 @@ export async function duplicateTemplate(
|
||||
|
||||
// Usage tracking
|
||||
|
||||
export async function incrementClickCount(id: string): Promise<void> {
|
||||
if (!isIndexedDBAvailable()) return
|
||||
try {
|
||||
const db = await getDB()
|
||||
const template = await db.get(STORE_NAME, id)
|
||||
if (!template) return
|
||||
template.clickCount += 1
|
||||
template.updatedAt = Date.now()
|
||||
await db.put(STORE_NAME, template)
|
||||
} catch (error) {
|
||||
console.error("Failed to increment click count:", error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function incrementRunCount(id: string): Promise<void> {
|
||||
if (!isIndexedDBAvailable()) return
|
||||
try {
|
||||
@@ -366,7 +312,6 @@ export async function importTemplates(
|
||||
description: t.description ? String(t.description) : undefined,
|
||||
createdAt: typeof t.createdAt === "number" ? t.createdAt : now,
|
||||
updatedAt: now,
|
||||
clickCount: typeof t.clickCount === "number" ? t.clickCount : 0,
|
||||
runCount: typeof t.runCount === "number" ? t.runCount : 0,
|
||||
lastUsedAt: typeof t.lastUsedAt === "number" ? t.lastUsedAt : 0,
|
||||
pinned: typeof t.pinned === "boolean" ? t.pinned : false,
|
||||
|
||||
@@ -52,7 +52,6 @@ export interface ProviderConfig {
|
||||
vertexApiKey?: string // Express Mode API key
|
||||
|
||||
models: ModelConfig[]
|
||||
validated?: boolean // Has API key been validated
|
||||
}
|
||||
|
||||
// The complete multi-model configuration
|
||||
@@ -60,9 +59,6 @@ export interface MultiModelConfig {
|
||||
version: 1
|
||||
providers: ProviderConfig[]
|
||||
selectedModelId?: string // Currently selected model's UUID
|
||||
// Older versions saved here whether untested models were listed in the
|
||||
// model picker; they always are now
|
||||
showUnvalidatedModels?: boolean
|
||||
}
|
||||
|
||||
// Flattened model for dropdown display
|
||||
@@ -86,10 +82,6 @@ export interface FlattenedModel {
|
||||
source?: "user" | "server"
|
||||
// Whether this model is the server default (matches AI_MODEL env var)
|
||||
isDefault?: boolean
|
||||
// Custom env var name(s) for server models
|
||||
// Can be a single string or array of strings for load balancing
|
||||
apiKeyEnv?: string | string[]
|
||||
baseUrlEnv?: string
|
||||
}
|
||||
|
||||
// Providers whose server credentials live in fixed env vars
|
||||
@@ -557,7 +549,6 @@ export function createProviderConfig(provider: ProviderName): ProviderConfig {
|
||||
apiKey: "",
|
||||
baseUrl: PROVIDER_INFO[provider].defaultBaseUrl,
|
||||
models: [],
|
||||
validated: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user