mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-03 23:02:31 +08:00
Compare commits
1 Commits
fix/openai
...
fix/langfu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81e6c02fb4 |
2
.github/workflows/docker-build.yml
vendored
2
.github/workflows/docker-build.yml
vendored
@@ -63,8 +63,6 @@ jobs:
|
|||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
build-args: |
|
|
||||||
NEXT_PUBLIC_SHOW_ABOUT_AND_NOTICE=true
|
|
||||||
|
|
||||||
# Push to AWS ECR for App Runner auto-deploy
|
# Push to AWS ECR for App Runner auto-deploy
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
|
|||||||
@@ -26,10 +26,6 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
|||||||
ARG NEXT_PUBLIC_DRAWIO_BASE_URL=https://embed.diagrams.net
|
ARG NEXT_PUBLIC_DRAWIO_BASE_URL=https://embed.diagrams.net
|
||||||
ENV NEXT_PUBLIC_DRAWIO_BASE_URL=${NEXT_PUBLIC_DRAWIO_BASE_URL}
|
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)
|
# Build Next.js application (standalone mode)
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ export default function AboutCN() {
|
|||||||
(TPS/TPM)。一旦超限,系统就会暂停,导致请求失败。
|
(TPS/TPM)。一旦超限,系统就会暂停,导致请求失败。
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
由于使用量过高,我已将模型从 Opus 4.5 更换为{" "}
|
由于使用量过高,我已将模型从 Claude 更换为{" "}
|
||||||
<span className="font-semibold text-amber-700">
|
<span className="font-semibold text-amber-700">
|
||||||
Haiku 4.5
|
minimax-m2
|
||||||
</span>
|
</span>
|
||||||
,以降低成本。
|
,以降低成本。
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -126,9 +126,9 @@ export default function AboutJA() {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
利用量の増加に伴い、コスト削減のためモデルを
|
利用量の増加に伴い、コスト削減のためモデルを
|
||||||
Opus 4.5 から{" "}
|
Claude から{" "}
|
||||||
<span className="font-semibold text-amber-700">
|
<span className="font-semibold text-amber-700">
|
||||||
Haiku 4.5
|
minimax-m2
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
に変更しました。
|
に変更しました。
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -129,9 +129,9 @@ export default function About() {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Due to the high usage, I have changed the
|
Due to the high usage, I have changed the
|
||||||
model from Opus 4.5 to{" "}
|
model from Claude to{" "}
|
||||||
<span className="font-semibold text-amber-700">
|
<span className="font-semibold text-amber-700">
|
||||||
Haiku 4.5
|
minimax-m2
|
||||||
</span>
|
</span>
|
||||||
, which is more cost-effective.
|
, which is more cost-effective.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1281,6 +1281,24 @@ Continue from EXACTLY where you stopped.`,
|
|||||||
About
|
About
|
||||||
</Link>
|
</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>
|
||||||
<div className="flex items-center gap-1 justify-end overflow-visible">
|
<div className="flex items-center gap-1 justify-end overflow-visible">
|
||||||
<ButtonWithTooltip
|
<ButtonWithTooltip
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ import {
|
|||||||
} from "@/components/ui/select"
|
} from "@/components/ui/select"
|
||||||
import { useDictionary } from "@/hooks/use-dictionary"
|
import { useDictionary } from "@/hooks/use-dictionary"
|
||||||
import type { UseModelConfigReturn } from "@/hooks/use-model-config"
|
import type { UseModelConfigReturn } from "@/hooks/use-model-config"
|
||||||
import { formatMessage } from "@/lib/i18n/utils"
|
|
||||||
import type { ProviderConfig, ProviderName } from "@/lib/types/model-config"
|
import type { ProviderConfig, ProviderName } from "@/lib/types/model-config"
|
||||||
import { PROVIDER_INFO, SUGGESTED_MODELS } from "@/lib/types/model-config"
|
import { PROVIDER_INFO, SUGGESTED_MODELS } from "@/lib/types/model-config"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
@@ -108,12 +107,10 @@ function ValidationButton({
|
|||||||
status,
|
status,
|
||||||
onClick,
|
onClick,
|
||||||
disabled,
|
disabled,
|
||||||
dict,
|
|
||||||
}: {
|
}: {
|
||||||
status: ValidationStatus
|
status: ValidationStatus
|
||||||
onClick: () => void
|
onClick: () => void
|
||||||
disabled: boolean
|
disabled: boolean
|
||||||
dict: ReturnType<typeof useDictionary>
|
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
@@ -132,10 +129,10 @@ function ValidationButton({
|
|||||||
) : status === "success" ? (
|
) : status === "success" ? (
|
||||||
<>
|
<>
|
||||||
<Check className="h-4 w-4 mr-1.5" />
|
<Check className="h-4 w-4 mr-1.5" />
|
||||||
{dict.modelConfig.verified}
|
Verified
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
dict.modelConfig.test
|
"Test"
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
@@ -409,7 +406,7 @@ export function ModelConfigDialog({
|
|||||||
<div className="w-56 flex-shrink-0 flex flex-col border-r bg-muted/20">
|
<div className="w-56 flex-shrink-0 flex flex-col border-r bg-muted/20">
|
||||||
<div className="px-4 py-3 border-b">
|
<div className="px-4 py-3 border-b">
|
||||||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||||
{dict.modelConfig.providers}
|
Providers
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -421,7 +418,7 @@ export function ModelConfigDialog({
|
|||||||
<Plus className="h-5 w-5 text-muted-foreground" />
|
<Plus className="h-5 w-5 text-muted-foreground" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
{dict.modelConfig.addProviderHint}
|
Add a provider to get started
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -487,11 +484,7 @@ export function ModelConfigDialog({
|
|||||||
>
|
>
|
||||||
<SelectTrigger className="h-9 bg-background hover:bg-accent">
|
<SelectTrigger className="h-9 bg-background hover:bg-accent">
|
||||||
<Plus className="h-4 w-4 mr-2 text-muted-foreground" />
|
<Plus className="h-4 w-4 mr-2 text-muted-foreground" />
|
||||||
<SelectValue
|
<SelectValue placeholder="Add Provider" />
|
||||||
placeholder={
|
|
||||||
dict.modelConfig.addProvider
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{availableProviders.map((p) => (
|
{availableProviders.map((p) => (
|
||||||
@@ -559,27 +552,15 @@ export function ModelConfigDialog({
|
|||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
{selectedProvider.models
|
{selectedProvider.models
|
||||||
.length === 0
|
.length === 0
|
||||||
? dict.modelConfig
|
? "No models configured"
|
||||||
.noModelsConfigured
|
: `${selectedProvider.models.length} model${selectedProvider.models.length > 1 ? "s" : ""} configured`}
|
||||||
: formatMessage(
|
|
||||||
dict.modelConfig
|
|
||||||
.modelsConfiguredCount,
|
|
||||||
{
|
|
||||||
count: selectedProvider
|
|
||||||
.models
|
|
||||||
.length,
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{selectedProvider.validated && (
|
{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">
|
<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" />
|
<Check className="h-3.5 w-3.5" />
|
||||||
<span className="text-xs font-medium">
|
<span className="text-xs font-medium">
|
||||||
{
|
Verified
|
||||||
dict.modelConfig
|
|
||||||
.verified
|
|
||||||
}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -589,12 +570,7 @@ export function ModelConfigDialog({
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
||||||
<Settings2 className="h-4 w-4" />
|
<Settings2 className="h-4 w-4" />
|
||||||
<span>
|
<span>Configuration</span>
|
||||||
{
|
|
||||||
dict.modelConfig
|
|
||||||
.configuration
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-xl border bg-card p-4 space-y-4">
|
<div className="rounded-xl border bg-card p-4 space-y-4">
|
||||||
@@ -605,10 +581,7 @@ export function ModelConfigDialog({
|
|||||||
className="text-xs font-medium flex items-center gap-1.5"
|
className="text-xs font-medium flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<Tag className="h-3.5 w-3.5 text-muted-foreground" />
|
<Tag className="h-3.5 w-3.5 text-muted-foreground" />
|
||||||
{
|
Display Name
|
||||||
dict.modelConfig
|
|
||||||
.displayName
|
|
||||||
}
|
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="provider-name"
|
id="provider-name"
|
||||||
@@ -643,11 +616,8 @@ export function ModelConfigDialog({
|
|||||||
className="text-xs font-medium flex items-center gap-1.5"
|
className="text-xs font-medium flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<Key className="h-3.5 w-3.5 text-muted-foreground" />
|
<Key className="h-3.5 w-3.5 text-muted-foreground" />
|
||||||
{
|
AWS Access Key
|
||||||
dict
|
ID
|
||||||
.modelConfig
|
|
||||||
.awsAccessKeyId
|
|
||||||
}
|
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="aws-access-key-id"
|
id="aws-access-key-id"
|
||||||
@@ -679,11 +649,8 @@ export function ModelConfigDialog({
|
|||||||
className="text-xs font-medium flex items-center gap-1.5"
|
className="text-xs font-medium flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<Key className="h-3.5 w-3.5 text-muted-foreground" />
|
<Key className="h-3.5 w-3.5 text-muted-foreground" />
|
||||||
{
|
AWS Secret
|
||||||
dict
|
Access Key
|
||||||
.modelConfig
|
|
||||||
.awsSecretAccessKey
|
|
||||||
}
|
|
||||||
</Label>
|
</Label>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Input
|
<Input
|
||||||
@@ -707,11 +674,7 @@ export function ModelConfigDialog({
|
|||||||
.value,
|
.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
placeholder={
|
placeholder="Enter your secret access key"
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.enterSecretKey
|
|
||||||
}
|
|
||||||
className="h-9 pr-10 font-mono text-xs"
|
className="h-9 pr-10 font-mono text-xs"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@@ -744,11 +707,7 @@ export function ModelConfigDialog({
|
|||||||
className="text-xs font-medium flex items-center gap-1.5"
|
className="text-xs font-medium flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<Link2 className="h-3.5 w-3.5 text-muted-foreground" />
|
<Link2 className="h-3.5 w-3.5 text-muted-foreground" />
|
||||||
{
|
AWS Region
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.awsRegion
|
|
||||||
}
|
|
||||||
</Label>
|
</Label>
|
||||||
<Select
|
<Select
|
||||||
value={
|
value={
|
||||||
@@ -765,13 +724,7 @@ export function ModelConfigDialog({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="h-9 font-mono text-xs hover:bg-accent">
|
<SelectTrigger className="h-9 font-mono text-xs hover:bg-accent">
|
||||||
<SelectValue
|
<SelectValue placeholder="Select region" />
|
||||||
placeholder={
|
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.selectRegion
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="max-h-64">
|
<SelectContent className="max-h-64">
|
||||||
<SelectItem value="us-east-1">
|
<SelectItem value="us-east-1">
|
||||||
@@ -866,16 +819,10 @@ export function ModelConfigDialog({
|
|||||||
"success" ? (
|
"success" ? (
|
||||||
<>
|
<>
|
||||||
<Check className="h-4 w-4 mr-1.5" />
|
<Check className="h-4 w-4 mr-1.5" />
|
||||||
{
|
Verified
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.verified
|
|
||||||
}
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
dict
|
"Test"
|
||||||
.modelConfig
|
|
||||||
.test
|
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
{validationStatus ===
|
{validationStatus ===
|
||||||
@@ -899,11 +846,7 @@ export function ModelConfigDialog({
|
|||||||
className="text-xs font-medium flex items-center gap-1.5"
|
className="text-xs font-medium flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<Key className="h-3.5 w-3.5 text-muted-foreground" />
|
<Key className="h-3.5 w-3.5 text-muted-foreground" />
|
||||||
{
|
API Key
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.apiKey
|
|
||||||
}
|
|
||||||
</Label>
|
</Label>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="relative flex-1">
|
<div className="relative flex-1">
|
||||||
@@ -927,11 +870,7 @@ export function ModelConfigDialog({
|
|||||||
.value,
|
.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
placeholder={
|
placeholder="Enter your API key"
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.enterApiKey
|
|
||||||
}
|
|
||||||
className="h-9 pr-10 font-mono text-xs"
|
className="h-9 pr-10 font-mono text-xs"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@@ -985,16 +924,10 @@ export function ModelConfigDialog({
|
|||||||
"success" ? (
|
"success" ? (
|
||||||
<>
|
<>
|
||||||
<Check className="h-4 w-4 mr-1.5" />
|
<Check className="h-4 w-4 mr-1.5" />
|
||||||
{
|
Verified
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.verified
|
|
||||||
}
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
dict
|
"Test"
|
||||||
.modelConfig
|
|
||||||
.test
|
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1017,17 +950,9 @@ export function ModelConfigDialog({
|
|||||||
className="text-xs font-medium flex items-center gap-1.5"
|
className="text-xs font-medium flex items-center gap-1.5"
|
||||||
>
|
>
|
||||||
<Link2 className="h-3.5 w-3.5 text-muted-foreground" />
|
<Link2 className="h-3.5 w-3.5 text-muted-foreground" />
|
||||||
{
|
Base URL
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.baseUrl
|
|
||||||
}
|
|
||||||
<span className="text-muted-foreground font-normal">
|
<span className="text-muted-foreground font-normal">
|
||||||
{
|
(optional)
|
||||||
dict
|
|
||||||
.modelConfig
|
|
||||||
.optional
|
|
||||||
}
|
|
||||||
</span>
|
</span>
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
@@ -1049,9 +974,7 @@ export function ModelConfigDialog({
|
|||||||
.provider
|
.provider
|
||||||
]
|
]
|
||||||
.defaultBaseUrl ||
|
.defaultBaseUrl ||
|
||||||
dict
|
"Custom endpoint URL"
|
||||||
.modelConfig
|
|
||||||
.customEndpoint
|
|
||||||
}
|
}
|
||||||
className="h-9 font-mono text-xs"
|
className="h-9 font-mono text-xs"
|
||||||
/>
|
/>
|
||||||
@@ -1066,20 +989,12 @@ export function ModelConfigDialog({
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
||||||
<Sparkles className="h-4 w-4" />
|
<Sparkles className="h-4 w-4" />
|
||||||
<span>
|
<span>Models</span>
|
||||||
{
|
|
||||||
dict.modelConfig
|
|
||||||
.models
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Input
|
<Input
|
||||||
placeholder={
|
placeholder="Custom model ID..."
|
||||||
dict.modelConfig
|
|
||||||
.customModelId
|
|
||||||
}
|
|
||||||
value={
|
value={
|
||||||
customModelInput
|
customModelInput
|
||||||
}
|
}
|
||||||
@@ -1173,12 +1088,8 @@ export function ModelConfigDialog({
|
|||||||
<span className="text-xs">
|
<span className="text-xs">
|
||||||
{availableSuggestions.length ===
|
{availableSuggestions.length ===
|
||||||
0
|
0
|
||||||
? dict
|
? "All added"
|
||||||
.modelConfig
|
: "Suggested"}
|
||||||
.allAdded
|
|
||||||
: dict
|
|
||||||
.modelConfig
|
|
||||||
.suggested}
|
|
||||||
</span>
|
</span>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent className="max-h-72">
|
<SelectContent className="max-h-72">
|
||||||
@@ -1213,10 +1124,7 @@ export function ModelConfigDialog({
|
|||||||
<Sparkles className="h-5 w-5 text-muted-foreground" />
|
<Sparkles className="h-5 w-5 text-muted-foreground" />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{
|
No models configured
|
||||||
dict.modelConfig
|
|
||||||
.noModelsConfigured
|
|
||||||
}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -1383,9 +1291,7 @@ export function ModelConfigDialog({
|
|||||||
!newModelId
|
!newModelId
|
||||||
) {
|
) {
|
||||||
showError(
|
showError(
|
||||||
dict
|
"Model ID cannot be empty",
|
||||||
.modelConfig
|
|
||||||
.modelIdEmpty,
|
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1413,9 +1319,7 @@ export function ModelConfigDialog({
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
showError(
|
showError(
|
||||||
dict
|
"This model ID already exists",
|
||||||
.modelConfig
|
|
||||||
.modelIdExists,
|
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1479,10 +1383,7 @@ export function ModelConfigDialog({
|
|||||||
className="text-muted-foreground hover:text-destructive hover:bg-destructive/10"
|
className="text-muted-foreground hover:text-destructive hover:bg-destructive/10"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-4 w-4 mr-2" />
|
<Trash2 className="h-4 w-4 mr-2" />
|
||||||
{
|
Delete Provider
|
||||||
dict.modelConfig
|
|
||||||
.deleteProvider
|
|
||||||
}
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1494,10 +1395,11 @@ export function ModelConfigDialog({
|
|||||||
<Server className="h-8 w-8 text-primary/60" />
|
<Server className="h-8 w-8 text-primary/60" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="font-semibold mb-1">
|
<h3 className="font-semibold mb-1">
|
||||||
{dict.modelConfig.configureProviders}
|
Configure AI Providers
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-sm text-muted-foreground max-w-xs">
|
<p className="text-sm text-muted-foreground max-w-xs">
|
||||||
{dict.modelConfig.selectProviderHint}
|
Select a provider from the list or add a new
|
||||||
|
one to configure API keys and models
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -1508,7 +1410,7 @@ export function ModelConfigDialog({
|
|||||||
<div className="px-6 py-3 border-t bg-muted/20">
|
<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">
|
<p className="text-xs text-muted-foreground text-center flex items-center justify-center gap-1.5">
|
||||||
<Key className="h-3 w-3" />
|
<Key className="h-3 w-3" />
|
||||||
{dict.modelConfig.apiKeyStored}
|
API keys are stored locally in your browser
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@@ -1527,16 +1429,19 @@ export function ModelConfigDialog({
|
|||||||
<AlertCircle className="h-6 w-6 text-destructive" />
|
<AlertCircle className="h-6 w-6 text-destructive" />
|
||||||
</div>
|
</div>
|
||||||
<AlertDialogTitle className="text-center">
|
<AlertDialogTitle className="text-center">
|
||||||
{dict.modelConfig.deleteProvider}
|
Delete Provider
|
||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription className="text-center">
|
<AlertDialogDescription className="text-center">
|
||||||
{formatMessage(dict.modelConfig.deleteConfirmDesc, {
|
Are you sure you want to delete{" "}
|
||||||
name: selectedProvider
|
<span className="font-medium text-foreground">
|
||||||
|
{selectedProvider
|
||||||
? selectedProvider.name ||
|
? selectedProvider.name ||
|
||||||
PROVIDER_INFO[selectedProvider.provider]
|
PROVIDER_INFO[selectedProvider.provider]
|
||||||
.label
|
.label
|
||||||
: "this provider",
|
: "this provider"}
|
||||||
})}
|
</span>
|
||||||
|
? This will remove all configured models and cannot
|
||||||
|
be undone.
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
{selectedProvider &&
|
{selectedProvider &&
|
||||||
@@ -1546,16 +1451,11 @@ export function ModelConfigDialog({
|
|||||||
htmlFor="delete-confirm"
|
htmlFor="delete-confirm"
|
||||||
className="text-sm text-muted-foreground"
|
className="text-sm text-muted-foreground"
|
||||||
>
|
>
|
||||||
{formatMessage(
|
Type "
|
||||||
dict.modelConfig.typeToConfirm,
|
{selectedProvider.name ||
|
||||||
{
|
PROVIDER_INFO[selectedProvider.provider]
|
||||||
name:
|
.label}
|
||||||
selectedProvider.name ||
|
" to confirm
|
||||||
PROVIDER_INFO[
|
|
||||||
selectedProvider.provider
|
|
||||||
].label,
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="delete-confirm"
|
id="delete-confirm"
|
||||||
@@ -1563,17 +1463,13 @@ export function ModelConfigDialog({
|
|||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setDeleteConfirmText(e.target.value)
|
setDeleteConfirmText(e.target.value)
|
||||||
}
|
}
|
||||||
placeholder={
|
placeholder="Type provider name..."
|
||||||
dict.modelConfig.typeProviderName
|
|
||||||
}
|
|
||||||
className="h-9"
|
className="h-9"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel>
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||||
{dict.modelConfig.cancel}
|
|
||||||
</AlertDialogCancel>
|
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={handleDeleteProvider}
|
onClick={handleDeleteProvider}
|
||||||
disabled={
|
disabled={
|
||||||
@@ -1586,7 +1482,7 @@ export function ModelConfigDialog({
|
|||||||
}
|
}
|
||||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90 disabled:opacity-50"
|
className="bg-destructive text-destructive-foreground hover:bg-destructive/90 disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{dict.modelConfig.delete}
|
Delete
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
ModelSelectorTrigger,
|
ModelSelectorTrigger,
|
||||||
} from "@/components/ai-elements/model-selector"
|
} from "@/components/ai-elements/model-selector"
|
||||||
import { ButtonWithTooltip } from "@/components/button-with-tooltip"
|
import { ButtonWithTooltip } from "@/components/button-with-tooltip"
|
||||||
import { useDictionary } from "@/hooks/use-dictionary"
|
|
||||||
import type { FlattenedModel } from "@/lib/types/model-config"
|
import type { FlattenedModel } from "@/lib/types/model-config"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -68,7 +67,6 @@ export function ModelSelector({
|
|||||||
onConfigure,
|
onConfigure,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}: ModelSelectorProps) {
|
}: ModelSelectorProps) {
|
||||||
const dict = useDictionary()
|
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
// Only show validated models in the selector
|
// Only show validated models in the selector
|
||||||
const validatedModels = useMemo(
|
const validatedModels = useMemo(
|
||||||
@@ -98,8 +96,8 @@ export function ModelSelector({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tooltipContent = selectedModel
|
const tooltipContent = selectedModel
|
||||||
? `${selectedModel.modelId} ${dict.modelConfig.clickToChange}`
|
? `${selectedModel.modelId} (click to change)`
|
||||||
: `${dict.modelConfig.usingServerDefault} ${dict.modelConfig.clickToChange}`
|
: "Using server default model (click to change)"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModelSelectorRoot open={open} onOpenChange={setOpen}>
|
<ModelSelectorRoot open={open} onOpenChange={setOpen}>
|
||||||
@@ -113,26 +111,22 @@ export function ModelSelector({
|
|||||||
>
|
>
|
||||||
<Bot className="h-4 w-4 flex-shrink-0 text-muted-foreground" />
|
<Bot className="h-4 w-4 flex-shrink-0 text-muted-foreground" />
|
||||||
<span className="text-xs truncate">
|
<span className="text-xs truncate">
|
||||||
{selectedModel
|
{selectedModel ? selectedModel.modelId : "Default"}
|
||||||
? selectedModel.modelId
|
|
||||||
: dict.modelConfig.default}
|
|
||||||
</span>
|
</span>
|
||||||
<ChevronDown className="h-3 w-3 flex-shrink-0 text-muted-foreground" />
|
<ChevronDown className="h-3 w-3 flex-shrink-0 text-muted-foreground" />
|
||||||
</ButtonWithTooltip>
|
</ButtonWithTooltip>
|
||||||
</ModelSelectorTrigger>
|
</ModelSelectorTrigger>
|
||||||
<ModelSelectorContent title={dict.modelConfig.selectModel}>
|
<ModelSelectorContent title="Select Model">
|
||||||
<ModelSelectorInput
|
<ModelSelectorInput placeholder="Search models..." />
|
||||||
placeholder={dict.modelConfig.searchModels}
|
|
||||||
/>
|
|
||||||
<ModelSelectorList>
|
<ModelSelectorList>
|
||||||
<ModelSelectorEmpty>
|
<ModelSelectorEmpty>
|
||||||
{validatedModels.length === 0 && models.length > 0
|
{validatedModels.length === 0 && models.length > 0
|
||||||
? dict.modelConfig.noVerifiedModels
|
? "No verified models. Test your models first."
|
||||||
: dict.modelConfig.noModelsFound}
|
: "No models found."}
|
||||||
</ModelSelectorEmpty>
|
</ModelSelectorEmpty>
|
||||||
|
|
||||||
{/* Server Default Option */}
|
{/* Server Default Option */}
|
||||||
<ModelSelectorGroup heading={dict.modelConfig.default}>
|
<ModelSelectorGroup heading="Default">
|
||||||
<ModelSelectorItem
|
<ModelSelectorItem
|
||||||
value="__server_default__"
|
value="__server_default__"
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
@@ -151,7 +145,7 @@ export function ModelSelector({
|
|||||||
/>
|
/>
|
||||||
<Server className="mr-2 h-4 w-4 text-muted-foreground" />
|
<Server className="mr-2 h-4 w-4 text-muted-foreground" />
|
||||||
<ModelSelectorName>
|
<ModelSelectorName>
|
||||||
{dict.modelConfig.serverDefault}
|
Server Default
|
||||||
</ModelSelectorName>
|
</ModelSelectorName>
|
||||||
</ModelSelectorItem>
|
</ModelSelectorItem>
|
||||||
</ModelSelectorGroup>
|
</ModelSelectorGroup>
|
||||||
@@ -207,13 +201,13 @@ export function ModelSelector({
|
|||||||
>
|
>
|
||||||
<Settings2 className="mr-2 h-4 w-4" />
|
<Settings2 className="mr-2 h-4 w-4" />
|
||||||
<ModelSelectorName>
|
<ModelSelectorName>
|
||||||
{dict.modelConfig.configureModels}
|
Configure Models...
|
||||||
</ModelSelectorName>
|
</ModelSelectorName>
|
||||||
</ModelSelectorItem>
|
</ModelSelectorItem>
|
||||||
</ModelSelectorGroup>
|
</ModelSelectorGroup>
|
||||||
{/* Info text */}
|
{/* Info text */}
|
||||||
<div className="px-3 py-2 text-xs text-muted-foreground border-t">
|
<div className="px-3 py-2 text-xs text-muted-foreground border-t">
|
||||||
{dict.modelConfig.onlyVerifiedShown}
|
Only verified models are shown
|
||||||
</div>
|
</div>
|
||||||
</ModelSelectorList>
|
</ModelSelectorList>
|
||||||
</ModelSelectorContent>
|
</ModelSelectorContent>
|
||||||
|
|||||||
@@ -19,13 +19,10 @@ export function register() {
|
|||||||
const spanName = otelSpan.name
|
const spanName = otelSpan.name
|
||||||
// Skip Next.js HTTP infrastructure spans
|
// Skip Next.js HTTP infrastructure spans
|
||||||
if (
|
if (
|
||||||
spanName.startsWith("POST") ||
|
spanName.startsWith("POST /") ||
|
||||||
spanName.startsWith("GET") ||
|
spanName.startsWith("GET /") ||
|
||||||
spanName.startsWith("RSC") ||
|
|
||||||
spanName.includes("BaseServer") ||
|
spanName.includes("BaseServer") ||
|
||||||
spanName.includes("handleRequest") ||
|
spanName.includes("handleRequest")
|
||||||
spanName.includes("resolve page") ||
|
|
||||||
spanName.includes("start response")
|
|
||||||
) {
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -39,5 +36,4 @@ export function register() {
|
|||||||
|
|
||||||
// Register globally so AI SDK's telemetry also uses this processor
|
// Register globally so AI SDK's telemetry also uses this processor
|
||||||
tracerProvider.register()
|
tracerProvider.register()
|
||||||
console.log("[Langfuse] Instrumentation initialized successfully")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ function parseIntSafe(
|
|||||||
* Supports various AI SDK providers with their unique configuration options
|
* Supports various AI SDK providers with their unique configuration options
|
||||||
*
|
*
|
||||||
* Environment variables:
|
* Environment variables:
|
||||||
* - OPENAI_REASONING_EFFORT: OpenAI reasoning effort level (minimal/low/medium/high) - for o1/o3/o4/gpt-5
|
* - OPENAI_REASONING_EFFORT: OpenAI reasoning effort level (minimal/low/medium/high) - for o1/o3/gpt-5
|
||||||
* - OPENAI_REASONING_SUMMARY: OpenAI reasoning summary (auto/detailed) - auto-enabled for o1/o3/o4/gpt-5
|
* - OPENAI_REASONING_SUMMARY: OpenAI reasoning summary (none/brief/detailed) - auto-enabled for o1/o3/gpt-5
|
||||||
* - ANTHROPIC_THINKING_BUDGET_TOKENS: Anthropic thinking budget in tokens (1024-64000)
|
* - ANTHROPIC_THINKING_BUDGET_TOKENS: Anthropic thinking budget in tokens (1024-64000)
|
||||||
* - ANTHROPIC_THINKING_TYPE: Anthropic thinking type (enabled)
|
* - ANTHROPIC_THINKING_TYPE: Anthropic thinking type (enabled)
|
||||||
* - GOOGLE_THINKING_BUDGET: Google Gemini 2.5 thinking budget in tokens (1024-100000)
|
* - GOOGLE_THINKING_BUDGET: Google Gemini 2.5 thinking budget in tokens (1024-100000)
|
||||||
@@ -118,19 +118,18 @@ function buildProviderOptions(
|
|||||||
const reasoningEffort = process.env.OPENAI_REASONING_EFFORT
|
const reasoningEffort = process.env.OPENAI_REASONING_EFFORT
|
||||||
const reasoningSummary = process.env.OPENAI_REASONING_SUMMARY
|
const reasoningSummary = process.env.OPENAI_REASONING_SUMMARY
|
||||||
|
|
||||||
// OpenAI reasoning models (o1, o3, o4, gpt-5) need reasoningSummary to return thoughts
|
// OpenAI reasoning models (o1, o3, gpt-5) need reasoningSummary to return thoughts
|
||||||
if (
|
if (
|
||||||
modelId &&
|
modelId &&
|
||||||
(modelId.includes("o1") ||
|
(modelId.includes("o1") ||
|
||||||
modelId.includes("o3") ||
|
modelId.includes("o3") ||
|
||||||
modelId.includes("o4") ||
|
|
||||||
modelId.includes("gpt-5"))
|
modelId.includes("gpt-5"))
|
||||||
) {
|
) {
|
||||||
options.openai = {
|
options.openai = {
|
||||||
// Auto-enable reasoning summary for reasoning models
|
// Auto-enable reasoning summary for reasoning models (default: detailed)
|
||||||
// Use 'auto' as default since not all models support 'detailed'
|
|
||||||
reasoningSummary:
|
reasoningSummary:
|
||||||
(reasoningSummary as "auto" | "detailed") || "auto",
|
(reasoningSummary as "none" | "brief" | "detailed") ||
|
||||||
|
"detailed",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optionally configure reasoning effort
|
// Optionally configure reasoning effort
|
||||||
@@ -153,7 +152,8 @@ function buildProviderOptions(
|
|||||||
}
|
}
|
||||||
if (reasoningSummary) {
|
if (reasoningSummary) {
|
||||||
options.openai.reasoningSummary = reasoningSummary as
|
options.openai.reasoningSummary = reasoningSummary as
|
||||||
| "auto"
|
| "none"
|
||||||
|
| "brief"
|
||||||
| "detailed"
|
| "detailed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,9 +593,7 @@ export function getAIModel(overrides?: ClientOverrides): ModelConfig {
|
|||||||
apiKey,
|
apiKey,
|
||||||
...(baseURL && { baseURL }),
|
...(baseURL && { baseURL }),
|
||||||
})
|
})
|
||||||
// Use Responses API (default) instead of .chat() to support reasoning
|
model = customOpenAI.chat(modelId)
|
||||||
// for gpt-5, o1, o3, o4 models. Chat Completions API does not emit reasoning events.
|
|
||||||
model = customOpenAI(modelId)
|
|
||||||
} else {
|
} else {
|
||||||
model = openai(modelId)
|
model = openai(modelId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,47 +202,6 @@
|
|||||||
"apiKeyStored": "API keys are stored locally in your browser",
|
"apiKeyStored": "API keys are stored locally in your browser",
|
||||||
"test": "Test",
|
"test": "Test",
|
||||||
"validationError": "Validation failed",
|
"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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,47 +202,6 @@
|
|||||||
"apiKeyStored": "APIキーはブラウザにローカル保存されます",
|
"apiKeyStored": "APIキーはブラウザにローカル保存されます",
|
||||||
"test": "テスト",
|
"test": "テスト",
|
||||||
"validationError": "検証に失敗しました",
|
"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": "検証済みのモデルのみ表示"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,47 +202,6 @@
|
|||||||
"apiKeyStored": "API 密钥存储在您的浏览器本地",
|
"apiKeyStored": "API 密钥存储在您的浏览器本地",
|
||||||
"test": "测试",
|
"test": "测试",
|
||||||
"validationError": "验证失败",
|
"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": "仅显示已验证的模型"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "next-ai-draw-io",
|
"name": "next-ai-draw-io",
|
||||||
"version": "0.4.6",
|
"version": "0.4.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "next-ai-draw-io",
|
"name": "next-ai-draw-io",
|
||||||
"version": "0.4.6",
|
"version": "0.4.5",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/amazon-bedrock": "^3.0.70",
|
"@ai-sdk/amazon-bedrock": "^3.0.70",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "next-ai-draw-io",
|
"name": "next-ai-draw-io",
|
||||||
"version": "0.4.6",
|
"version": "0.4.5",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist-electron/main/index.js",
|
"main": "dist-electron/main/index.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user