Files
moeka-project/packages/provider-inference/src/providers/cloud/perplexity-ai/index.ts
T
Garfield Lee 59a064ea80 refactor(stage-ui): extract provider-inference package for runtime-neutral definitions (#2444)
## Summary

Extract runtime-neutral provider definitions from `@proj-airi/stage-ui`
into a new `@proj-airi/provider-inference` package that runs in both
Node.js and browser without Vue/Pinia dependencies.

## What changed

- **New package** `packages/provider-inference/` — owns
`ProviderDefinition`, `ProviderRegistry`, validators, and all provider
modules (cloud + local)
- **Provider modules relocated** — ~45 providers moved from
`stage-ui/src/libs/providers/providers/` to
`provider-inference/src/providers/cloud/` and
`provider-inference/src/providers/local/`
- **Type decoupling** — `ProviderContext.t` changed from
`ComposerTranslation` (Vue) to generic `ProviderTranslator`, removing
the Vue dependency from core types
- **stage-ui types slimmed** — `types.ts` now re-exports from
`provider-inference` and only adds the Vue-specific `ProviderViews`
extension
- **validators/run.ts** — becomes a pass-through re-export
- **Registry** — portable `createProviderRegistry()` with deterministic
ordering and duplicate-id detection

## Verification

```bash
pnpm -F @proj-airi/provider-inference typecheck
pnpm -F @proj-airi/provider-inference test:node
pnpm -F @proj-airi/provider-inference test:browser
pnpm -F @proj-airi/provider-inference build
pnpm -F @proj-airi/stage-ui typecheck
pnpm -F @proj-airi/stage-web typecheck
pnpm -F @proj-airi/stage-tamagotchi typecheck
pnpm lint
```

## Why

Provider definitions were tightly coupled to Vue (`ComposerTranslation`,
`Component`), preventing reuse in non-Vue runtimes (Node.js services,
tests, future Electron backend). This extraction creates a clean
boundary: runtime-neutral definitions live in `provider-inference`,
while Vue/Pinia-specific concerns stay in `stage-ui`.
2026-09-02 19:35:25 +08:00

91 lines
3.3 KiB
TypeScript

import type { ModelInfo } from '../../../types'
import { createPerplexity } from '@xsai-ext/providers/create'
import { z } from 'zod'
import { ProviderValidationCheck } from '../../../types'
import { createOpenAICompatibleValidators } from '../../../validators'
import { defineProvider } from '../../registry'
const perplexityConfigSchema = z.object({
apiKey: z
.string('API Key'),
baseUrl: z
.string('Base URL')
.optional()
.default('https://api.perplexity.ai/'),
})
type PerplexityConfig = z.input<typeof perplexityConfigSchema>
export const providerPerplexityAI = defineProvider<PerplexityConfig, 'perplexity-ai'>({
id: 'perplexity-ai',
name: 'Perplexity',
nameLocalize: ({ t }) => t('settings.pages.providers.provider.perplexity.title'),
description: 'perplexity.ai',
descriptionLocalize: ({ t }) => t('settings.pages.providers.provider.perplexity.description'),
tasks: ['chat'],
icon: 'i-lobe-icons:perplexity',
iconColor: 'i-lobe-icons:perplexity-color',
createProviderConfig: ({ t }) => perplexityConfigSchema.extend({
apiKey: perplexityConfigSchema.shape.apiKey.meta({
labelLocalized: t('settings.pages.providers.catalog.edit.config.common.fields.field.api-key.label'),
descriptionLocalized: t('settings.pages.providers.catalog.edit.config.common.fields.field.api-key.description'),
placeholderLocalized: t('settings.pages.providers.catalog.edit.config.common.fields.field.api-key.placeholder'),
type: 'password',
}),
baseUrl: perplexityConfigSchema.shape.baseUrl.meta({
labelLocalized: t('settings.pages.providers.catalog.edit.config.common.fields.field.base-url.label'),
descriptionLocalized: t('settings.pages.providers.catalog.edit.config.common.fields.field.base-url.description'),
placeholderLocalized: t('settings.pages.providers.catalog.edit.config.common.fields.field.base-url.placeholder'),
}),
}),
createProvider(config) {
return createPerplexity(config.apiKey, config.baseUrl)
},
validationRequiredWhen(config) {
return !!config.apiKey?.trim()
},
extraMethods: {
async listModels() {
return [
{
id: 'sonar',
name: 'Sonar',
provider: 'perplexity-ai',
description: 'Lightweight, cost-effective search model with grounding.',
contextLength: 127072,
},
{
id: 'sonar-pro',
name: 'Sonar Pro',
provider: 'perplexity-ai',
description: 'Advanced search offering with grounding, supporting complex queries and follow-ups.',
contextLength: 200000,
},
{
id: 'sonar-reasoning-pro',
name: 'Sonar Reasoning Pro',
provider: 'perplexity-ai',
description: 'Precise reasoning offering with Chain of Thought (CoT).',
contextLength: 127072,
},
{
id: 'sonar-deep-research',
name: 'Sonar Deep Research',
provider: 'perplexity-ai',
description: 'Expert-level research model conducting exhaustive searches and generating comprehensive reports.',
contextLength: 200000,
},
] satisfies ModelInfo[]
},
},
validators: {
...createOpenAICompatibleValidators({
checks: [ProviderValidationCheck.Connectivity, ProviderValidationCheck.ChatCompletions],
}),
},
})