Compare commits

..

8 Commits

Author SHA1 Message Date
dayuan.jiang
76d453b533 chore: upgrade AI SDK to v6.0.1
- Upgrade ai package from ^5.0.89 to ^6.0.1
- Upgrade @ai-sdk/* provider packages to latest v3/v4
- Update convertToModelMessages call to async (new API)
- Fix usage.cachedInputTokens to usage.inputTokenDetails?.cacheReadTokens
2025-12-23 13:13:21 +09:00
Dayuan Jiang
8cb7494d16 feat(i18n): add translations for model configuration UI (#368)
- Add ~40 new translation keys for model-config-dialog and model-selector
- Support English, Chinese, and Japanese translations
- Replace all hardcoded strings with dictionary lookups
2025-12-23 11:42:27 +09:00
Dayuan Jiang
98625dd72a docs: update about page model info to Haiku 4.5 (#367) 2025-12-23 10:22:31 +09:00
Dayuan Jiang
b5734aa5e1 chore: hide notice icon from header (#366) 2025-12-23 10:08:14 +09:00
Dayuan Jiang
87cdc53665 fix: improve Langfuse span filter to exclude all Next.js infrastructure traces (#365)
* debug: add log to verify instrumentation initialization

* fix: improve Langfuse span filter to exclude all Next.js infrastructure traces
2025-12-23 09:47:23 +09:00
Dayuan Jiang
b4fc259de8 chore: bump version to 0.4.6 (#364)
* chore: bump version to 0.4.6

* style: auto-format with Biome

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-12-23 09:09:39 +09:00
Dayuan Jiang
28f9a81e7b chore: add build-time arg for showing About and Notice (#360) 2025-12-23 01:06:42 +09:00
Dayuan Jiang
0f67884ead fix: include instrumentation.ts in standalone build for Langfuse (#359)
Add outputFileTracingIncludes to next.config.ts to ensure instrumentation.ts
is included in standalone builds (required for App Runner deployment)
2025-12-23 01:03:11 +09:00
15 changed files with 461 additions and 369 deletions

View File

@@ -63,6 +63,8 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
build-args: |
NEXT_PUBLIC_SHOW_ABOUT_AND_NOTICE=true
# Push to AWS ECR for App Runner auto-deploy
- name: Configure AWS credentials

View File

@@ -26,6 +26,10 @@ ENV NEXT_TELEMETRY_DISABLED=1
ARG NEXT_PUBLIC_DRAWIO_BASE_URL=https://embed.diagrams.net
ENV NEXT_PUBLIC_DRAWIO_BASE_URL=${NEXT_PUBLIC_DRAWIO_BASE_URL}
# Build-time argument to show About link and Notice icon
ARG NEXT_PUBLIC_SHOW_ABOUT_AND_NOTICE=false
ENV NEXT_PUBLIC_SHOW_ABOUT_AND_NOTICE=${NEXT_PUBLIC_SHOW_ABOUT_AND_NOTICE}
# Build Next.js application (standalone mode)
RUN npm run build

View File

@@ -117,9 +117,9 @@ export default function AboutCN() {
(TPS/TPM)
</p>
<p>
使 Claude {" "}
使 Opus 4.5 {" "}
<span className="font-semibold text-amber-700">
minimax-m2
Haiku 4.5
</span>
</p>

View File

@@ -126,9 +126,9 @@ export default function AboutJA() {
</p>
<p>
Claude {" "}
Opus 4.5 {" "}
<span className="font-semibold text-amber-700">
minimax-m2
Haiku 4.5
</span>{" "}
</p>

View File

@@ -129,9 +129,9 @@ export default function About() {
</p>
<p>
Due to the high usage, I have changed the
model from Claude to{" "}
model from Opus 4.5 to{" "}
<span className="font-semibold text-amber-700">
minimax-m2
Haiku 4.5
</span>
, which is more cost-effective.
</p>

View File

@@ -248,7 +248,7 @@ ${userInputText}
"""`
// Convert UIMessages to ModelMessages and add system message
const modelMessages = convertToModelMessages(messages)
const modelMessages = await convertToModelMessages(messages)
// DEBUG: Log incoming messages structure
console.log("[route.ts] Incoming messages count:", messages.length)
@@ -686,7 +686,8 @@ Call this tool to get shape names and usage syntax for a specific library.`,
// Total input = non-cached + cached (these are separate counts)
// Note: cacheWriteInputTokens is not available on finish part
const totalInputTokens =
(usage.inputTokens ?? 0) + (usage.cachedInputTokens ?? 0)
(usage.inputTokens ?? 0) +
(usage.inputTokenDetails?.cacheReadTokens ?? 0)
return {
inputTokens: totalInputTokens,
outputTokens: usage.outputTokens ?? 0,

View File

@@ -1281,24 +1281,6 @@ Continue from EXACTLY where you stopped.`,
About
</Link>
)}
{!isMobile &&
process.env.NEXT_PUBLIC_SHOW_ABOUT_AND_NOTICE ===
"true" && (
<Link
href="/about"
target="_blank"
rel="noopener noreferrer"
>
<ButtonWithTooltip
tooltipContent="Due to high usage, I have changed the model to minimax-m2 and added some usage limits. See About page for details."
variant="ghost"
size="icon"
className="h-6 w-6 text-amber-500 hover:text-amber-600"
>
<AlertTriangle className="h-4 w-4" />
</ButtonWithTooltip>
</Link>
)}
</div>
<div className="flex items-center gap-1 justify-end overflow-visible">
<ButtonWithTooltip

View File

@@ -52,6 +52,7 @@ import {
} from "@/components/ui/select"
import { useDictionary } from "@/hooks/use-dictionary"
import type { UseModelConfigReturn } from "@/hooks/use-model-config"
import { formatMessage } from "@/lib/i18n/utils"
import type { ProviderConfig, ProviderName } from "@/lib/types/model-config"
import { PROVIDER_INFO, SUGGESTED_MODELS } from "@/lib/types/model-config"
import { cn } from "@/lib/utils"
@@ -107,10 +108,12 @@ function ValidationButton({
status,
onClick,
disabled,
dict,
}: {
status: ValidationStatus
onClick: () => void
disabled: boolean
dict: ReturnType<typeof useDictionary>
}) {
return (
<Button
@@ -129,10 +132,10 @@ function ValidationButton({
) : status === "success" ? (
<>
<Check className="h-4 w-4 mr-1.5" />
Verified
{dict.modelConfig.verified}
</>
) : (
"Test"
dict.modelConfig.test
)}
</Button>
)
@@ -406,7 +409,7 @@ export function ModelConfigDialog({
<div className="w-56 flex-shrink-0 flex flex-col border-r bg-muted/20">
<div className="px-4 py-3 border-b">
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
Providers
{dict.modelConfig.providers}
</span>
</div>
@@ -418,7 +421,7 @@ export function ModelConfigDialog({
<Plus className="h-5 w-5 text-muted-foreground" />
</div>
<p className="text-xs text-muted-foreground">
Add a provider to get started
{dict.modelConfig.addProviderHint}
</p>
</div>
) : (
@@ -484,7 +487,11 @@ export function ModelConfigDialog({
>
<SelectTrigger className="h-9 bg-background hover:bg-accent">
<Plus className="h-4 w-4 mr-2 text-muted-foreground" />
<SelectValue placeholder="Add Provider" />
<SelectValue
placeholder={
dict.modelConfig.addProvider
}
/>
</SelectTrigger>
<SelectContent>
{availableProviders.map((p) => (
@@ -552,15 +559,27 @@ export function ModelConfigDialog({
<p className="text-xs text-muted-foreground">
{selectedProvider.models
.length === 0
? "No models configured"
: `${selectedProvider.models.length} model${selectedProvider.models.length > 1 ? "s" : ""} configured`}
? dict.modelConfig
.noModelsConfigured
: formatMessage(
dict.modelConfig
.modelsConfiguredCount,
{
count: selectedProvider
.models
.length,
},
)}
</p>
</div>
{selectedProvider.validated && (
<div className="flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-emerald-500/10 text-emerald-600 dark:text-emerald-400">
<Check className="h-3.5 w-3.5" />
<span className="text-xs font-medium">
Verified
{
dict.modelConfig
.verified
}
</span>
</div>
)}
@@ -570,7 +589,12 @@ export function ModelConfigDialog({
<div className="space-y-4">
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<Settings2 className="h-4 w-4" />
<span>Configuration</span>
<span>
{
dict.modelConfig
.configuration
}
</span>
</div>
<div className="rounded-xl border bg-card p-4 space-y-4">
@@ -581,7 +605,10 @@ export function ModelConfigDialog({
className="text-xs font-medium flex items-center gap-1.5"
>
<Tag className="h-3.5 w-3.5 text-muted-foreground" />
Display Name
{
dict.modelConfig
.displayName
}
</Label>
<Input
id="provider-name"
@@ -616,8 +643,11 @@ export function ModelConfigDialog({
className="text-xs font-medium flex items-center gap-1.5"
>
<Key className="h-3.5 w-3.5 text-muted-foreground" />
AWS Access Key
ID
{
dict
.modelConfig
.awsAccessKeyId
}
</Label>
<Input
id="aws-access-key-id"
@@ -649,8 +679,11 @@ export function ModelConfigDialog({
className="text-xs font-medium flex items-center gap-1.5"
>
<Key className="h-3.5 w-3.5 text-muted-foreground" />
AWS Secret
Access Key
{
dict
.modelConfig
.awsSecretAccessKey
}
</Label>
<div className="relative">
<Input
@@ -674,7 +707,11 @@ export function ModelConfigDialog({
.value,
)
}
placeholder="Enter your secret access key"
placeholder={
dict
.modelConfig
.enterSecretKey
}
className="h-9 pr-10 font-mono text-xs"
/>
<button
@@ -707,7 +744,11 @@ export function ModelConfigDialog({
className="text-xs font-medium flex items-center gap-1.5"
>
<Link2 className="h-3.5 w-3.5 text-muted-foreground" />
AWS Region
{
dict
.modelConfig
.awsRegion
}
</Label>
<Select
value={
@@ -724,7 +765,13 @@ export function ModelConfigDialog({
}
>
<SelectTrigger className="h-9 font-mono text-xs hover:bg-accent">
<SelectValue placeholder="Select region" />
<SelectValue
placeholder={
dict
.modelConfig
.selectRegion
}
/>
</SelectTrigger>
<SelectContent className="max-h-64">
<SelectItem value="us-east-1">
@@ -819,10 +866,16 @@ export function ModelConfigDialog({
"success" ? (
<>
<Check className="h-4 w-4 mr-1.5" />
Verified
{
dict
.modelConfig
.verified
}
</>
) : (
"Test"
dict
.modelConfig
.test
)}
</Button>
{validationStatus ===
@@ -846,7 +899,11 @@ export function ModelConfigDialog({
className="text-xs font-medium flex items-center gap-1.5"
>
<Key className="h-3.5 w-3.5 text-muted-foreground" />
API Key
{
dict
.modelConfig
.apiKey
}
</Label>
<div className="flex gap-2">
<div className="relative flex-1">
@@ -870,7 +927,11 @@ export function ModelConfigDialog({
.value,
)
}
placeholder="Enter your API key"
placeholder={
dict
.modelConfig
.enterApiKey
}
className="h-9 pr-10 font-mono text-xs"
/>
<button
@@ -924,10 +985,16 @@ export function ModelConfigDialog({
"success" ? (
<>
<Check className="h-4 w-4 mr-1.5" />
Verified
{
dict
.modelConfig
.verified
}
</>
) : (
"Test"
dict
.modelConfig
.test
)}
</Button>
</div>
@@ -950,9 +1017,17 @@ export function ModelConfigDialog({
className="text-xs font-medium flex items-center gap-1.5"
>
<Link2 className="h-3.5 w-3.5 text-muted-foreground" />
Base URL
{
dict
.modelConfig
.baseUrl
}
<span className="text-muted-foreground font-normal">
(optional)
{
dict
.modelConfig
.optional
}
</span>
</Label>
<Input
@@ -974,7 +1049,9 @@ export function ModelConfigDialog({
.provider
]
.defaultBaseUrl ||
"Custom endpoint URL"
dict
.modelConfig
.customEndpoint
}
className="h-9 font-mono text-xs"
/>
@@ -989,12 +1066,20 @@ export function ModelConfigDialog({
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
<Sparkles className="h-4 w-4" />
<span>Models</span>
<span>
{
dict.modelConfig
.models
}
</span>
</div>
<div className="flex items-center gap-2">
<div className="relative">
<Input
placeholder="Custom model ID..."
placeholder={
dict.modelConfig
.customModelId
}
value={
customModelInput
}
@@ -1088,8 +1173,12 @@ export function ModelConfigDialog({
<span className="text-xs">
{availableSuggestions.length ===
0
? "All added"
: "Suggested"}
? dict
.modelConfig
.allAdded
: dict
.modelConfig
.suggested}
</span>
</SelectTrigger>
<SelectContent className="max-h-72">
@@ -1124,7 +1213,10 @@ export function ModelConfigDialog({
<Sparkles className="h-5 w-5 text-muted-foreground" />
</div>
<p className="text-sm text-muted-foreground">
No models configured
{
dict.modelConfig
.noModelsConfigured
}
</p>
</div>
) : (
@@ -1291,7 +1383,9 @@ export function ModelConfigDialog({
!newModelId
) {
showError(
"Model ID cannot be empty",
dict
.modelConfig
.modelIdEmpty,
)
return
}
@@ -1319,7 +1413,9 @@ export function ModelConfigDialog({
)
) {
showError(
"This model ID already exists",
dict
.modelConfig
.modelIdExists,
)
return
}
@@ -1383,7 +1479,10 @@ export function ModelConfigDialog({
className="text-muted-foreground hover:text-destructive hover:bg-destructive/10"
>
<Trash2 className="h-4 w-4 mr-2" />
Delete Provider
{
dict.modelConfig
.deleteProvider
}
</Button>
</div>
</div>
@@ -1395,11 +1494,10 @@ export function ModelConfigDialog({
<Server className="h-8 w-8 text-primary/60" />
</div>
<h3 className="font-semibold mb-1">
Configure AI Providers
{dict.modelConfig.configureProviders}
</h3>
<p className="text-sm text-muted-foreground max-w-xs">
Select a provider from the list or add a new
one to configure API keys and models
{dict.modelConfig.selectProviderHint}
</p>
</div>
)}
@@ -1410,7 +1508,7 @@ export function ModelConfigDialog({
<div className="px-6 py-3 border-t bg-muted/20">
<p className="text-xs text-muted-foreground text-center flex items-center justify-center gap-1.5">
<Key className="h-3 w-3" />
API keys are stored locally in your browser
{dict.modelConfig.apiKeyStored}
</p>
</div>
</DialogContent>
@@ -1429,19 +1527,16 @@ export function ModelConfigDialog({
<AlertCircle className="h-6 w-6 text-destructive" />
</div>
<AlertDialogTitle className="text-center">
Delete Provider
{dict.modelConfig.deleteProvider}
</AlertDialogTitle>
<AlertDialogDescription className="text-center">
Are you sure you want to delete{" "}
<span className="font-medium text-foreground">
{selectedProvider
{formatMessage(dict.modelConfig.deleteConfirmDesc, {
name: selectedProvider
? selectedProvider.name ||
PROVIDER_INFO[selectedProvider.provider]
.label
: "this provider"}
</span>
? This will remove all configured models and cannot
be undone.
: "this provider",
})}
</AlertDialogDescription>
</AlertDialogHeader>
{selectedProvider &&
@@ -1451,11 +1546,16 @@ export function ModelConfigDialog({
htmlFor="delete-confirm"
className="text-sm text-muted-foreground"
>
Type &quot;
{selectedProvider.name ||
PROVIDER_INFO[selectedProvider.provider]
.label}
&quot; to confirm
{formatMessage(
dict.modelConfig.typeToConfirm,
{
name:
selectedProvider.name ||
PROVIDER_INFO[
selectedProvider.provider
].label,
},
)}
</Label>
<Input
id="delete-confirm"
@@ -1463,13 +1563,17 @@ export function ModelConfigDialog({
onChange={(e) =>
setDeleteConfirmText(e.target.value)
}
placeholder="Type provider name..."
placeholder={
dict.modelConfig.typeProviderName
}
className="h-9"
/>
</div>
)}
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel>
{dict.modelConfig.cancel}
</AlertDialogCancel>
<AlertDialogAction
onClick={handleDeleteProvider}
disabled={
@@ -1482,7 +1586,7 @@ export function ModelConfigDialog({
}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90 disabled:opacity-50"
>
Delete
{dict.modelConfig.delete}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>

View File

@@ -16,6 +16,7 @@ import {
ModelSelectorTrigger,
} from "@/components/ai-elements/model-selector"
import { ButtonWithTooltip } from "@/components/button-with-tooltip"
import { useDictionary } from "@/hooks/use-dictionary"
import type { FlattenedModel } from "@/lib/types/model-config"
import { cn } from "@/lib/utils"
@@ -67,6 +68,7 @@ export function ModelSelector({
onConfigure,
disabled = false,
}: ModelSelectorProps) {
const dict = useDictionary()
const [open, setOpen] = useState(false)
// Only show validated models in the selector
const validatedModels = useMemo(
@@ -96,8 +98,8 @@ export function ModelSelector({
}
const tooltipContent = selectedModel
? `${selectedModel.modelId} (click to change)`
: "Using server default model (click to change)"
? `${selectedModel.modelId} ${dict.modelConfig.clickToChange}`
: `${dict.modelConfig.usingServerDefault} ${dict.modelConfig.clickToChange}`
return (
<ModelSelectorRoot open={open} onOpenChange={setOpen}>
@@ -111,22 +113,26 @@ export function ModelSelector({
>
<Bot className="h-4 w-4 flex-shrink-0 text-muted-foreground" />
<span className="text-xs truncate">
{selectedModel ? selectedModel.modelId : "Default"}
{selectedModel
? selectedModel.modelId
: dict.modelConfig.default}
</span>
<ChevronDown className="h-3 w-3 flex-shrink-0 text-muted-foreground" />
</ButtonWithTooltip>
</ModelSelectorTrigger>
<ModelSelectorContent title="Select Model">
<ModelSelectorInput placeholder="Search models..." />
<ModelSelectorContent title={dict.modelConfig.selectModel}>
<ModelSelectorInput
placeholder={dict.modelConfig.searchModels}
/>
<ModelSelectorList>
<ModelSelectorEmpty>
{validatedModels.length === 0 && models.length > 0
? "No verified models. Test your models first."
: "No models found."}
? dict.modelConfig.noVerifiedModels
: dict.modelConfig.noModelsFound}
</ModelSelectorEmpty>
{/* Server Default Option */}
<ModelSelectorGroup heading="Default">
<ModelSelectorGroup heading={dict.modelConfig.default}>
<ModelSelectorItem
value="__server_default__"
onSelect={handleSelect}
@@ -145,7 +151,7 @@ export function ModelSelector({
/>
<Server className="mr-2 h-4 w-4 text-muted-foreground" />
<ModelSelectorName>
Server Default
{dict.modelConfig.serverDefault}
</ModelSelectorName>
</ModelSelectorItem>
</ModelSelectorGroup>
@@ -201,13 +207,13 @@ export function ModelSelector({
>
<Settings2 className="mr-2 h-4 w-4" />
<ModelSelectorName>
Configure Models...
{dict.modelConfig.configureModels}
</ModelSelectorName>
</ModelSelectorItem>
</ModelSelectorGroup>
{/* Info text */}
<div className="px-3 py-2 text-xs text-muted-foreground border-t">
Only verified models are shown
{dict.modelConfig.onlyVerifiedShown}
</div>
</ModelSelectorList>
</ModelSelectorContent>

View File

@@ -19,10 +19,13 @@ export function register() {
const spanName = otelSpan.name
// Skip Next.js HTTP infrastructure spans
if (
spanName.startsWith("POST /") ||
spanName.startsWith("GET /") ||
spanName.startsWith("POST") ||
spanName.startsWith("GET") ||
spanName.startsWith("RSC") ||
spanName.includes("BaseServer") ||
spanName.includes("handleRequest")
spanName.includes("handleRequest") ||
spanName.includes("resolve page") ||
spanName.includes("start response")
) {
return false
}
@@ -36,4 +39,5 @@ export function register() {
// Register globally so AI SDK's telemetry also uses this processor
tracerProvider.register()
console.log("[Langfuse] Instrumentation initialized successfully")
}

View File

@@ -202,6 +202,47 @@
"apiKeyStored": "API keys are stored locally in your browser",
"test": "Test",
"validationError": "Validation failed",
"addModelFirst": "Add at least one model to validate"
"addModelFirst": "Add at least one model to validate",
"providers": "Providers",
"addProviderHint": "Add a provider to get started",
"verified": "Verified",
"configuration": "Configuration",
"displayName": "Display Name",
"awsAccessKeyId": "AWS Access Key ID",
"awsSecretAccessKey": "AWS Secret Access Key",
"awsRegion": "AWS Region",
"selectRegion": "Select region",
"apiKey": "API Key",
"enterApiKey": "Enter your API key",
"enterSecretKey": "Enter your secret access key",
"baseUrl": "Base URL",
"optional": "(optional)",
"customEndpoint": "Custom endpoint URL",
"models": "Models",
"customModelId": "Custom model ID...",
"allAdded": "All added",
"suggested": "Suggested",
"noModelsConfigured": "No models configured",
"modelIdEmpty": "Model ID cannot be empty",
"modelIdExists": "This model ID already exists",
"configureProviders": "Configure AI Providers",
"selectProviderHint": "Select a provider from the list or add a new one to configure API keys and models",
"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 provider name...",
"modelsConfiguredCount": "{count} model(s) configured",
"validationFailedCount": "{count} model(s) failed validation",
"cancel": "Cancel",
"delete": "Delete",
"clickToChange": "(click to change)",
"usingServerDefault": "Using server default model",
"selectModel": "Select Model",
"searchModels": "Search models...",
"noVerifiedModels": "No verified models. Test your models first.",
"noModelsFound": "No models found.",
"default": "Default",
"serverDefault": "Server Default",
"configureModels": "Configure Models...",
"onlyVerifiedShown": "Only verified models are shown"
}
}

View File

@@ -202,6 +202,47 @@
"apiKeyStored": "APIキーはブラウザにローカル保存されます",
"test": "テスト",
"validationError": "検証に失敗しました",
"addModelFirst": "検証するには少なくとも1つのモデルを追加してください"
"addModelFirst": "検証するには少なくとも1つのモデルを追加してください",
"providers": "プロバイダー",
"addProviderHint": "プロバイダーを追加して開始",
"verified": "検証済み",
"configuration": "設定",
"displayName": "表示名",
"awsAccessKeyId": "AWS アクセスキー ID",
"awsSecretAccessKey": "AWS シークレットアクセスキー",
"awsRegion": "AWS リージョン",
"selectRegion": "リージョンを選択",
"apiKey": "API キー",
"enterApiKey": "API キーを入力",
"enterSecretKey": "シークレットアクセスキーを入力",
"baseUrl": "ベース URL",
"optional": "(オプション)",
"customEndpoint": "カスタムエンドポイント URL",
"models": "モデル",
"customModelId": "カスタムモデル ID...",
"allAdded": "すべて追加済み",
"suggested": "おすすめ",
"noModelsConfigured": "モデルが設定されていません",
"modelIdEmpty": "モデル ID は空にできません",
"modelIdExists": "このモデル ID は既に存在します",
"configureProviders": "AI プロバイダーを設定",
"selectProviderHint": "リストからプロバイダーを選択するか、新規追加して API キーとモデルを設定",
"deleteConfirmDesc": "{name} を削除してもよろしいですか?設定されたすべてのモデルが削除され、元に戻せません。",
"typeToConfirm": "確認のため「{name}」と入力",
"typeProviderName": "プロバイダー名を入力...",
"modelsConfiguredCount": "{count} 個のモデルを設定済み",
"validationFailedCount": "{count} 個のモデルの検証に失敗",
"cancel": "キャンセル",
"delete": "削除",
"clickToChange": "(クリックして変更)",
"usingServerDefault": "サーバーデフォルトモデルを使用中",
"selectModel": "モデルを選択",
"searchModels": "モデルを検索...",
"noVerifiedModels": "検証済みのモデルがありません。先にモデルをテストしてください。",
"noModelsFound": "モデルが見つかりません。",
"default": "デフォルト",
"serverDefault": "サーバーデフォルト",
"configureModels": "モデルを設定...",
"onlyVerifiedShown": "検証済みのモデルのみ表示"
}
}

View File

@@ -202,6 +202,47 @@
"apiKeyStored": "API 密钥存储在您的浏览器本地",
"test": "测试",
"validationError": "验证失败",
"addModelFirst": "请先添加至少一个模型以进行验证"
"addModelFirst": "请先添加至少一个模型以进行验证",
"providers": "提供商",
"addProviderHint": "添加提供商即可开始使用",
"verified": "已验证",
"configuration": "配置",
"displayName": "显示名称",
"awsAccessKeyId": "AWS 访问密钥 ID",
"awsSecretAccessKey": "AWS Secret Access Key",
"awsRegion": "AWS 区域",
"selectRegion": "选择区域",
"apiKey": "API 密钥",
"enterApiKey": "输入您的 API 密钥",
"enterSecretKey": "输入您的 Secret Key",
"baseUrl": "基础 URL",
"optional": "(可选)",
"customEndpoint": "自定义端点 URL",
"models": "模型",
"customModelId": "自定义模型 ID...",
"allAdded": "已全部添加",
"suggested": "推荐",
"noModelsConfigured": "尚未配置模型",
"modelIdEmpty": "模型 ID 不能为空",
"modelIdExists": "此模型 ID 已存在",
"configureProviders": "配置 AI 提供商",
"selectProviderHint": "从列表中选择提供商或添加新的以配置 API 密钥和模型",
"deleteConfirmDesc": "确定要删除 {name} 吗?这将移除所有配置的模型且无法撤销。",
"typeToConfirm": "输入 \"{name}\" 以确认",
"typeProviderName": "输入提供商名称...",
"modelsConfiguredCount": "已配置 {count} 个模型",
"validationFailedCount": "{count} 个模型验证失败",
"cancel": "取消",
"delete": "删除",
"clickToChange": "(点击更改)",
"usingServerDefault": "使用服务器默认模型",
"selectModel": "选择模型",
"searchModels": "搜索模型...",
"noVerifiedModels": "没有已验证的模型。请先测试您的模型。",
"noModelsFound": "未找到模型。",
"default": "默认",
"serverDefault": "服务器默认",
"configureModels": "配置模型...",
"onlyVerifiedShown": "仅显示已验证的模型"
}
}

383
package-lock.json generated
View File

@@ -1,29 +1,29 @@
{
"name": "next-ai-draw-io",
"version": "0.4.5",
"version": "0.4.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "next-ai-draw-io",
"version": "0.4.5",
"version": "0.4.6",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/amazon-bedrock": "^3.0.70",
"@ai-sdk/anthropic": "^2.0.44",
"@ai-sdk/azure": "^2.0.69",
"@ai-sdk/deepseek": "^1.0.30",
"@ai-sdk/gateway": "^2.0.21",
"@ai-sdk/google": "^2.0.0",
"@ai-sdk/openai": "^2.0.19",
"@ai-sdk/react": "^2.0.107",
"@ai-sdk/amazon-bedrock": "^4.0.1",
"@ai-sdk/anthropic": "^3.0.0",
"@ai-sdk/azure": "^3.0.0",
"@ai-sdk/deepseek": "^2.0.0",
"@ai-sdk/gateway": "^3.0.0",
"@ai-sdk/google": "^3.0.0",
"@ai-sdk/openai": "^3.0.0",
"@ai-sdk/react": "^3.0.1",
"@aws-sdk/credential-providers": "^3.943.0",
"@formatjs/intl-localematcher": "^0.7.2",
"@langfuse/client": "^4.4.9",
"@langfuse/otel": "^4.4.4",
"@langfuse/tracing": "^4.4.9",
"@next/third-parties": "^16.0.6",
"@openrouter/ai-sdk-provider": "^1.2.3",
"@openrouter/ai-sdk-provider": "^1.5.4",
"@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
"@opentelemetry/sdk-trace-node": "^2.2.0",
"@radix-ui/react-alert-dialog": "^1.1.15",
@@ -38,7 +38,7 @@
"@radix-ui/react-tooltip": "^1.1.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@xmldom/xmldom": "^0.9.8",
"ai": "^5.0.89",
"ai": "^6.0.1",
"base-64": "^1.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -93,14 +93,14 @@
}
},
"node_modules/@ai-sdk/amazon-bedrock": {
"version": "3.0.70",
"resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-3.0.70.tgz",
"integrity": "sha512-4NIBlwuS/iLKq2ynOqqyJ9imk/oyHuOzhBx88Bfm5I0ihQPKJ0dMMD1IKKuyDZvLRYKmlOEpa//P+/ZBp10drw==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@ai-sdk/amazon-bedrock/-/amazon-bedrock-4.0.1.tgz",
"integrity": "sha512-8Qu5wHTHYTwptZ1L4Sv8hvXMyKRNWUD6dH8wm+Zl8RDOEXZJNENS6zec7u/sWJKuvefL7j+xN8z3IVduhGfxig==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/anthropic": "2.0.56",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.19",
"@ai-sdk/anthropic": "3.0.0",
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0",
"@smithy/eventstream-codec": "^4.0.1",
"@smithy/util-utf8": "^4.0.0",
"aws4fetch": "^1.0.20"
@@ -112,48 +112,14 @@
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/amazon-bedrock/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.19",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.19.tgz",
"integrity": "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/anthropic": {
"version": "2.0.56",
"resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.56.tgz",
"integrity": "sha512-XHJKu0Yvfu9SPzRfsAFESa+9T7f2YJY6TxykKMfRsAwpeWAiX/Gbx5J5uM15AzYC3Rw8tVP3oH+j7jEivENirQ==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-3.0.0.tgz",
"integrity": "sha512-4BnxkXwRkvh+OB1ze0mHbskT90HL4MNrg6JUsRDkIsU9w5vitvGzxwc/XwlByUGMap/5I8/LZ3XZDzv6KViCuQ==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.19"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/anthropic/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.19",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.19.tgz",
"integrity": "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0"
},
"engines": {
"node": ">=18"
@@ -163,31 +129,14 @@
}
},
"node_modules/@ai-sdk/azure": {
"version": "2.0.69",
"resolved": "https://registry.npmjs.org/@ai-sdk/azure/-/azure-2.0.69.tgz",
"integrity": "sha512-0Y+f0XHviWw9ixB2Dkqyg07V67oczUh8adh4B/t0LgVMVkvOsf/WEzfYx2/LDqdvI/o8IYyJ6JzsCKpBwbS61g==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/azure/-/azure-3.0.0.tgz",
"integrity": "sha512-bY1EfX4aisnpOYcuZkmkuBIUc0noNT/25ZoWispSiMZMS53yF55xkT1SFM+cxDjJ4M3HVJwVuU6r1szA8f9IPA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/openai": "2.0.67",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.17"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/azure/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.17",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.17.tgz",
"integrity": "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
"@ai-sdk/openai": "3.0.0",
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0"
},
"engines": {
"node": ">=18"
@@ -197,14 +146,13 @@
}
},
"node_modules/@ai-sdk/deepseek": {
"version": "1.0.30",
"resolved": "https://registry.npmjs.org/@ai-sdk/deepseek/-/deepseek-1.0.30.tgz",
"integrity": "sha512-pafNclW9L8Z3WimaRwlpHrGbdeaDE/UklT3rMi2aoRRyrA+s7zGcFuu1zbO2ViLNlKfaS91XZa9MFAPXbIftUA==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/deepseek/-/deepseek-2.0.0.tgz",
"integrity": "sha512-qRX06mouHaF4OePE4S8W8+fLX7Iq4dWk7Ul4+SSPBzx6zBJKUqwHYW2XyPShNWhT4Rcogpl5yHJUrBaOExkiyg==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/openai-compatible": "1.0.28",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18"
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0"
},
"engines": {
"node": ">=18"
@@ -214,13 +162,13 @@
}
},
"node_modules/@ai-sdk/gateway": {
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.21.tgz",
"integrity": "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-3.0.0.tgz",
"integrity": "sha512-JcjePYVpbezv+XOxkxPemwnorjWpgDiiKWMYy6FXTCG2rFABIK2Co1bFxIUSDT4vYO6f1448x9rKbn38vbhDiA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.19",
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0",
"@vercel/oidc": "3.0.5"
},
"engines": {
@@ -230,15 +178,14 @@
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/gateway/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.19",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.19.tgz",
"integrity": "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==",
"node_modules/@ai-sdk/google": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-3.0.0.tgz",
"integrity": "sha512-KFS9pR7KGDyt7p1OQibglS3amoLjCXxwF7DVg+gL2RLcwFRQV0s6Tp7Q+PvGNFSqPdrPYW8mHyvn8ODK4WTImA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0"
},
"engines": {
"node": ">=18"
@@ -247,90 +194,14 @@
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/google": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-2.0.0.tgz",
"integrity": "sha512-35uWKG+aWm0QClJV/kNhcyR9IVrDkZoI1UlWvUCjwoqbCxj4/L/1LKKbpM3JSRa9u74ghHzBB0UjLHdgcIoanw==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4"
}
},
"node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.0.tgz",
"integrity": "sha512-BoQZtGcBxkeSH1zK+SRYNDtJPIPpacTeiMZqnG4Rv6xXjEwM0FH4MGs9c+PlhyEWmQCzjRM2HAotEydFhD4dYw==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.3",
"zod-to-json-schema": "^3.24.1"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4"
}
},
"node_modules/@ai-sdk/google/node_modules/@ai-sdk/provider-utils/node_modules/zod-to-json-schema": {
"version": "3.24.6",
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
"integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
"license": "ISC",
"peerDependencies": {
"zod": "^3.24.1"
}
},
"node_modules/@ai-sdk/openai": {
"version": "2.0.67",
"resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-2.0.67.tgz",
"integrity": "sha512-JhB3fUpY+IxAocyJt2PHuhfNwH+e+rDbZ8Q+d0hgSyNycuPRrV0xutLaf7mgDTvjr5FCrVEkXmM73tJprzZMiA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-3.0.0.tgz",
"integrity": "sha512-/o2xCQlRA+O0cAXIIBOfMeT35H6Fonzilz9r/IJojPOMQnmIL+0jPQVKOUPr5bouRqCjnwKpwuKEBRqm8jUZkQ==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.17"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/openai-compatible": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/@ai-sdk/openai-compatible/-/openai-compatible-1.0.28.tgz",
"integrity": "sha512-yKubDxLYtXyGUzkr9lNStf/lE/I+Okc8tmotvyABhsQHHieLKk6oV5fJeRJxhr67Ejhg+FRnwUOxAmjRoFM4dA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/openai/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.17",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.17.tgz",
"integrity": "sha512-TR3Gs4I3Tym4Ll+EPdzRdvo/rc8Js6c4nVhFLuvGLX/Y4V9ZcQMa/HTiYsHEgmYrf1zVi6Q145UEZUfleOwOjw==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0"
},
"engines": {
"node": ">=18"
@@ -340,9 +211,9 @@
}
},
"node_modules/@ai-sdk/provider": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz",
"integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.0.tgz",
"integrity": "sha512-m9ka3ptkPQbaHHZHqDXDF9C9B5/Mav0KTdky1k2HZ3/nrW2t1AgObxIVPyGDWQNS9FXT/FS6PIoSjpcP/No8rQ==",
"license": "Apache-2.0",
"dependencies": {
"json-schema": "^0.4.0"
@@ -352,13 +223,13 @@
}
},
"node_modules/@ai-sdk/provider-utils": {
"version": "3.0.18",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz",
"integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.0.tgz",
"integrity": "sha512-HyCyOls9I3a3e38+gtvOJOEjuw9KRcvbBnCL5GBuSmJvS9Jh9v3fz7pRC6ha1EUo/ZH1zwvLWYXBMtic8MTguA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"@ai-sdk/provider": "3.0.0",
"@standard-schema/spec": "^1.1.0",
"eventsource-parser": "^3.0.6"
},
"engines": {
@@ -369,13 +240,13 @@
}
},
"node_modules/@ai-sdk/react": {
"version": "2.0.107",
"resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-2.0.107.tgz",
"integrity": "sha512-rv0u+tAi2r2zJu2uSLXcC3TBgGrkQIWXRM+i6us6qcGmYQ2kOu2VYg+lxviOSGPhL9PVebvTlN5x8mf3rDqX+w==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-3.0.1.tgz",
"integrity": "sha512-XUPDMFgalNtqBQg+Q3UiiEmWE3PC5pAoc+Drs5Z1Mxqe57za+hKCEwViYADuqeZrc0q6PXTzbcFlQb3pjyGjcQ==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider-utils": "3.0.18",
"ai": "5.0.107",
"@ai-sdk/provider-utils": "4.0.0",
"ai": "6.0.1",
"swr": "^2.2.5",
"throttleit": "2.1.0"
},
@@ -383,13 +254,7 @@
"node": ">=18"
},
"peerDependencies": {
"react": "^18 || ^19 || ^19.0.0-rc",
"zod": "^3.25.76 || ^4.1.8"
},
"peerDependenciesMeta": {
"zod": {
"optional": true
}
"react": "^18 || ~19.0.1 || ~19.1.2 || ^19.2.1"
}
},
"node_modules/@alloc/quick-lru": {
@@ -2182,7 +2047,7 @@
},
"node_modules/@electron/windows-sign": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/@electron/windows-sign/-/windows-sign-1.2.2.tgz",
"resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz",
"integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==",
"dev": true,
"license": "BSD-2-Clause",
@@ -2204,7 +2069,7 @@
},
"node_modules/@electron/windows-sign/node_modules/fs-extra": {
"version": "11.3.3",
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.3.tgz",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz",
"integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==",
"dev": true,
"license": "MIT",
@@ -2221,7 +2086,7 @@
},
"node_modules/@electron/windows-sign/node_modules/jsonfile": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
"dev": true,
"license": "MIT",
@@ -2236,7 +2101,7 @@
},
"node_modules/@electron/windows-sign/node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
@@ -4020,12 +3885,12 @@
}
},
"node_modules/@openrouter/ai-sdk-provider": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@openrouter/ai-sdk-provider/-/ai-sdk-provider-1.2.3.tgz",
"integrity": "sha512-a6Nc8dPRHakRH9966YJ/HZJhLOds7DuPTscNZDoAr+Aw+tEFUlacSJMvb/b3gukn74mgbuaJRji9YOn62ipfVg==",
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@openrouter/ai-sdk-provider/-/ai-sdk-provider-1.5.4.tgz",
"integrity": "sha512-xrSQPUIH8n9zuyYZR0XK7Ba0h2KsjJcMkxnwaYfmv13pKs3sDkjPzVPPhlhzqBGddHb5cFEwJ9VFuFeDcxCDSw==",
"license": "Apache-2.0",
"dependencies": {
"@openrouter/sdk": "^0.1.8"
"@openrouter/sdk": "^0.1.27"
},
"engines": {
"node": ">=18"
@@ -4036,28 +3901,12 @@
}
},
"node_modules/@openrouter/sdk": {
"version": "0.1.11",
"resolved": "https://registry.npmjs.org/@openrouter/sdk/-/sdk-0.1.11.tgz",
"integrity": "sha512-OuPc8qqidL/PUM8+9WgrOfSR9+b6rKIWiezGcUJ54iPTdh+Gye5Qjut6hrLWlOCMZE7Z853gN90r1ft4iChj7Q==",
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/@openrouter/sdk/-/sdk-0.1.27.tgz",
"integrity": "sha512-RH//L10bSmc81q25zAZudiI4kNkLgxF2E+WU42vghp3N6TEvZ6F0jK7uT3tOxkEn91gzmMw9YVmDENy7SJsajQ==",
"license": "Apache-2.0",
"dependencies": {
"zod": "^3.25.0 || ^4.0.0"
},
"peerDependencies": {
"@tanstack/react-query": "^5",
"react": "^18 || ^19",
"react-dom": "^18 || ^19"
},
"peerDependenciesMeta": {
"@tanstack/react-query": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/@opentelemetry/api": {
@@ -7168,9 +7017,9 @@
}
},
"node_modules/@standard-schema/spec": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
"license": "MIT"
},
"node_modules/@swc/helpers": {
@@ -8287,14 +8136,14 @@
}
},
"node_modules/ai": {
"version": "5.0.107",
"resolved": "https://registry.npmjs.org/ai/-/ai-5.0.107.tgz",
"integrity": "sha512-laZlS9ZC/DZfSaxPgrBqI4mM+kxRvTPBBQfa74ceBFskkunZKEsaGVFNEs4cfyGa3nCCCl1WO/fjxixp4V8Zag==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ai/-/ai-6.0.1.tgz",
"integrity": "sha512-g/jPakC6h4vUJKDww0d6+VaJmfMC38UqH3kKsngiP+coT0uvCUdQ7lpFDJ0mNmamaOyRMaY2zwEB2RnTAaJU/w==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/gateway": "2.0.18",
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18",
"@ai-sdk/gateway": "3.0.0",
"@ai-sdk/provider": "3.0.0",
"@ai-sdk/provider-utils": "4.0.0",
"@opentelemetry/api": "1.9.0"
},
"engines": {
@@ -8304,23 +8153,6 @@
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/ai/node_modules/@ai-sdk/gateway": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.18.tgz",
"integrity": "sha512-sDQcW+6ck2m0pTIHW6BPHD7S125WD3qNkx/B8sEzJp/hurocmJ5Cni0ybExg6sQMGo+fr/GWOwpHF1cmCdg5rQ==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@ai-sdk/provider-utils": "3.0.18",
"@vercel/oidc": "3.0.5"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -9791,7 +9623,7 @@
},
"node_modules/cross-dirname": {
"version": "0.1.0",
"resolved": "https://registry.npmmirror.com/cross-dirname/-/cross-dirname-0.1.0.tgz",
"resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz",
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
"dev": true,
"license": "MIT",
@@ -10343,7 +10175,7 @@
},
"node_modules/electron-builder-squirrel-windows": {
"version": "26.0.12",
"resolved": "https://registry.npmmirror.com/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz",
"resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz",
"integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==",
"dev": true,
"license": "MIT",
@@ -10456,7 +10288,7 @@
},
"node_modules/electron-winstaller": {
"version": "5.4.0",
"resolved": "https://registry.npmmirror.com/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
"resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz",
"integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==",
"dev": true,
"hasInstallScript": true,
@@ -10478,7 +10310,7 @@
},
"node_modules/electron-winstaller/node_modules/fs-extra": {
"version": "7.0.1",
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-7.0.1.tgz",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"license": "MIT",
@@ -15552,6 +15384,35 @@
"zod": "^4.0.16"
}
},
"node_modules/ollama-ai-provider-v2/node_modules/@ai-sdk/provider": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz",
"integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==",
"license": "Apache-2.0",
"dependencies": {
"json-schema": "^0.4.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/ollama-ai-provider-v2/node_modules/@ai-sdk/provider-utils": {
"version": "3.0.19",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.19.tgz",
"integrity": "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.0",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
@@ -16040,7 +15901,7 @@
},
"node_modules/postject": {
"version": "1.0.0-alpha.6",
"resolved": "https://registry.npmmirror.com/postject/-/postject-1.0.0-alpha.6.tgz",
"resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz",
"integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==",
"dev": true,
"license": "MIT",
@@ -16058,7 +15919,7 @@
},
"node_modules/postject/node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"dev": true,
"license": "MIT",
@@ -17872,7 +17733,7 @@
},
"node_modules/temp": {
"version": "0.9.4",
"resolved": "https://registry.npmmirror.com/temp/-/temp-0.9.4.tgz",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
"dev": true,
"license": "MIT",
@@ -17936,7 +17797,7 @@
},
"node_modules/temp/node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"license": "MIT",
@@ -17950,7 +17811,7 @@
},
"node_modules/temp/node_modules/rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.6.3.tgz",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,

View File

@@ -1,6 +1,6 @@
{
"name": "next-ai-draw-io",
"version": "0.4.5",
"version": "0.4.6",
"license": "Apache-2.0",
"private": true,
"main": "dist-electron/main/index.js",
@@ -24,21 +24,21 @@
"dist:all": "npm run electron:build && npm run electron:prepare && npx electron-builder --mac --win --linux"
},
"dependencies": {
"@ai-sdk/amazon-bedrock": "^3.0.70",
"@ai-sdk/anthropic": "^2.0.44",
"@ai-sdk/azure": "^2.0.69",
"@ai-sdk/deepseek": "^1.0.30",
"@ai-sdk/gateway": "^2.0.21",
"@ai-sdk/google": "^2.0.0",
"@ai-sdk/openai": "^2.0.19",
"@ai-sdk/react": "^2.0.107",
"@ai-sdk/amazon-bedrock": "^4.0.1",
"@ai-sdk/anthropic": "^3.0.0",
"@ai-sdk/azure": "^3.0.0",
"@ai-sdk/deepseek": "^2.0.0",
"@ai-sdk/gateway": "^3.0.0",
"@ai-sdk/google": "^3.0.0",
"@ai-sdk/openai": "^3.0.0",
"@ai-sdk/react": "^3.0.1",
"@aws-sdk/credential-providers": "^3.943.0",
"@formatjs/intl-localematcher": "^0.7.2",
"@langfuse/client": "^4.4.9",
"@langfuse/otel": "^4.4.4",
"@langfuse/tracing": "^4.4.9",
"@next/third-parties": "^16.0.6",
"@openrouter/ai-sdk-provider": "^1.2.3",
"@openrouter/ai-sdk-provider": "^1.5.4",
"@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
"@opentelemetry/sdk-trace-node": "^2.2.0",
"@radix-ui/react-alert-dialog": "^1.1.15",
@@ -53,7 +53,7 @@
"@radix-ui/react-tooltip": "^1.1.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@xmldom/xmldom": "^0.9.8",
"ai": "^5.0.89",
"ai": "^6.0.1",
"base-64": "^1.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -111,5 +111,10 @@
"tailwindcss": "^4",
"typescript": "^5",
"wait-on": "^9.0.3"
},
"overrides": {
"@openrouter/ai-sdk-provider": {
"ai": "^6.0.1"
}
}
}