feat: Initialize test-ai-sdk project with Bun
- Add README.md with installation and usage instructions. - Create bun.lock and pnpm-lock.yaml for dependency management. - Implement main functionality in index.ts to test AI providers. - Add opencode.json configuration for various AI providers. - Create package.json to define project dependencies and scripts. - Add TypeScript configuration in tsconfig.json for project setup. - Implement test scripts for different AI providers in src directory.
This commit is contained in:
36
.gitignore
vendored
Normal file
36
.gitignore
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# dependencies (bun install)
|
||||
node_modules
|
||||
|
||||
# output
|
||||
out
|
||||
dist
|
||||
*.tgz
|
||||
|
||||
# code coverage
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# logs
|
||||
logs
|
||||
_.log
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# caches
|
||||
.eslintcache
|
||||
.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
|
||||
!.env*example
|
||||
6
AGENTS.md
Normal file
6
AGENTS.md
Normal file
@@ -0,0 +1,6 @@
|
||||
这是一个 bun 项目,测试 ai-sdk 功能。包是通过以下命令安装的:
|
||||
|
||||
```bash
|
||||
bun add ai
|
||||
bun add @ai-sdk/openai
|
||||
```
|
||||
106
CLAUDE.md
Normal file
106
CLAUDE.md
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
Default to using Bun instead of Node.js.
|
||||
|
||||
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
||||
- Use `bun test` instead of `jest` or `vitest`
|
||||
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
||||
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
||||
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
||||
- Use `bunx <package> <command>` instead of `npx <package> <command>`
|
||||
- Bun automatically loads .env, so don't use dotenv.
|
||||
|
||||
## APIs
|
||||
|
||||
- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
|
||||
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
||||
- `Bun.redis` for Redis. Don't use `ioredis`.
|
||||
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
||||
- `WebSocket` is built-in. Don't use `ws`.
|
||||
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
||||
- Bun.$`ls` instead of execa.
|
||||
|
||||
## Testing
|
||||
|
||||
Use `bun test` to run tests.
|
||||
|
||||
```ts#index.test.ts
|
||||
import { test, expect } from "bun:test";
|
||||
|
||||
test("hello world", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
|
||||
|
||||
Server:
|
||||
|
||||
```ts#index.ts
|
||||
import index from "./index.html"
|
||||
|
||||
Bun.serve({
|
||||
routes: {
|
||||
"/": index,
|
||||
"/api/users/:id": {
|
||||
GET: (req) => {
|
||||
return new Response(JSON.stringify({ id: req.params.id }));
|
||||
},
|
||||
},
|
||||
},
|
||||
// optional websocket support
|
||||
websocket: {
|
||||
open: (ws) => {
|
||||
ws.send("Hello, world!");
|
||||
},
|
||||
message: (ws, message) => {
|
||||
ws.send(message);
|
||||
},
|
||||
close: (ws) => {
|
||||
// handle close
|
||||
}
|
||||
},
|
||||
development: {
|
||||
hmr: true,
|
||||
console: true,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
|
||||
|
||||
```html#index.html
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello, world!</h1>
|
||||
<script type="module" src="./frontend.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
With the following `frontend.tsx`:
|
||||
|
||||
```tsx#frontend.tsx
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
// import .css files directly and it works
|
||||
import './index.css';
|
||||
|
||||
const root = createRoot(document.body);
|
||||
|
||||
export default function Frontend() {
|
||||
return <h1>Hello, world!</h1>;
|
||||
}
|
||||
|
||||
root.render(<Frontend />);
|
||||
```
|
||||
|
||||
Then, run index.ts
|
||||
|
||||
```sh
|
||||
bun --hot ./index.ts
|
||||
```
|
||||
|
||||
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
|
||||
15
README.md
Normal file
15
README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# test-ai-sdk
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.3.6. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
||||
72
bun.lock
Normal file
72
bun.lock
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "test-ai-sdk",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^3.0.35",
|
||||
"@ai-sdk/openai": "^3.0.25",
|
||||
"@ai-sdk/openai-compatible": "^2.0.26",
|
||||
"@kevisual/ai": "^0.0.24",
|
||||
"ai": "^6.0.67",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"dotenv": "^17.2.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.35", "https://registry.npmmirror.com/@ai-sdk/anthropic/-/anthropic-3.0.35.tgz", { "dependencies": { "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Y3g/5uVj621XSB9lGF7WrD7qR+orhV5xpaYkRF8kfj2j4W7e7BBGIvxcdsCf85FjJbc6tKQdNTZ84ZEqT3Y5TQ=="],
|
||||
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.32", "https://registry.npmmirror.com/@ai-sdk/gateway/-/gateway-3.0.32.tgz", { "dependencies": { "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7clZRr07P9rpur39t1RrbIe7x8jmwnwUWI8tZs+BvAfX3NFgdSVGGIaT7bTz2pb08jmLXzTSDbrOTqAQ7uBkBQ=="],
|
||||
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@3.0.25", "https://registry.npmmirror.com/@ai-sdk/openai/-/openai-3.0.25.tgz", { "dependencies": { "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-DsaN46R98+D1W3lU3fKuPU3ofacboLaHlkAwxJPgJ8eup1AJHmPK1N1y10eJJbJcF6iby8Tf/vanoZxc9JPUfw=="],
|
||||
|
||||
"@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.26", "https://registry.npmmirror.com/@ai-sdk/openai-compatible/-/openai-compatible-2.0.26.tgz", { "dependencies": { "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-l6jdFjI1C2eDAEm7oo+dnRn0oG1EkcyqfbEZ7ozT0TnYrah6amX2JkftYMP1GRzNtAeCB3WNN8XspXdmi6ZNlQ=="],
|
||||
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.7", "https://registry.npmmirror.com/@ai-sdk/provider/-/provider-3.0.7.tgz", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-VkPLrutM6VdA924/mG8OS+5frbVTcu6e046D2bgDo00tehBANR1QBJ/mPcZ9tXMFOsVcm6SQArOregxePzTFPw=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.13", "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-4.0.13.tgz", { "dependencies": { "@ai-sdk/provider": "3.0.7", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-HHG72BN4d+OWTcq2NwTxOm/2qvk1duYsnhCDtsbYwn/h/4zeqURu1S0+Cn0nY2Ysq9a9HGKvrYuMn9bgFhR2Og=="],
|
||||
|
||||
"@kevisual/ai": ["@kevisual/ai@0.0.24", "https://registry.npmmirror.com/@kevisual/ai/-/ai-0.0.24.tgz", { "dependencies": { "@kevisual/logger": "^0.0.4", "@kevisual/permission": "^0.0.3", "@kevisual/query": "^0.0.38" } }, "sha512-7jvZk1/L//VIClK7usuNgN4ZA9Etgbooka1Sj5quE/0UywR+NNnwqXVZ89Y1fBhI1TkhauDsdJBAtcQ7r/vbVw=="],
|
||||
|
||||
"@kevisual/logger": ["@kevisual/logger@0.0.4", "https://registry.npmmirror.com/@kevisual/logger/-/logger-0.0.4.tgz", {}, "sha512-+fpr92eokSxoGOW1SIRl/27lPuO+zyY+feR5o2Q4YCNlAdt2x64NwC/w8r/3NEC5QenLgd4K0azyKTI2mHbARw=="],
|
||||
|
||||
"@kevisual/permission": ["@kevisual/permission@0.0.3", "https://registry.npmmirror.com/@kevisual/permission/-/permission-0.0.3.tgz", {}, "sha512-8JsA/5O5Ax/z+M+MYpFYdlioHE6jNmWMuFSokBWYs9CCAHNiSKMR01YLkoVDoPvncfH/Y8F5K/IEXRCbptuMNA=="],
|
||||
|
||||
"@kevisual/query": ["@kevisual/query@0.0.38", "https://registry.npmmirror.com/@kevisual/query/-/query-0.0.38.tgz", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-bfvbSodsZyMfwY+1T2SvDeOCKsT/AaIxlVe0+B1R/fNhlg2MDq2CP0L9HKiFkEm+OXrvXcYDMKPUituVUM5J6Q=="],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "https://registry.npmmirror.com/@opentelemetry/api/-/api-1.9.0.tgz", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "https://registry.npmmirror.com/@standard-schema/spec/-/spec-1.1.0.tgz", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.8", "https://registry.npmmirror.com/@types/bun/-/bun-1.3.8.tgz", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
|
||||
|
||||
"@types/node": ["@types/node@25.2.0", "https://registry.npmmirror.com/@types/node/-/node-25.2.0.tgz", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w=="],
|
||||
|
||||
"@vercel/oidc": ["@vercel/oidc@3.1.0", "https://registry.npmmirror.com/@vercel/oidc/-/oidc-3.1.0.tgz", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="],
|
||||
|
||||
"ai": ["ai@6.0.67", "https://registry.npmmirror.com/ai/-/ai-6.0.67.tgz", { "dependencies": { "@ai-sdk/gateway": "3.0.32", "@ai-sdk/provider": "3.0.7", "@ai-sdk/provider-utils": "4.0.13", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xBnTcByHCj3OcG6V8G1s6zvSEqK0Bdiu+IEXYcpGrve1iGFFRgcrKeZtr/WAW/7gupnSvBbDF24BEv1OOfqi1g=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.8", "https://registry.npmmirror.com/bun-types/-/bun-types-1.3.8.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
|
||||
|
||||
"dotenv": ["dotenv@17.2.3", "https://registry.npmmirror.com/dotenv/-/dotenv-17.2.3.tgz", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
|
||||
|
||||
"eventsource-parser": ["eventsource-parser@3.0.6", "https://registry.npmmirror.com/eventsource-parser/-/eventsource-parser-3.0.6.tgz", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
|
||||
|
||||
"json-schema": ["json-schema@0.4.0", "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "https://registry.npmmirror.com/undici-types/-/undici-types-7.16.0.tgz", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"zod": ["zod@4.3.6", "https://registry.npmmirror.com/zod/-/zod-4.3.6.tgz", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
||||
}
|
||||
}
|
||||
96
index.ts
Normal file
96
index.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
||||
import { createAnthropic } from '@ai-sdk/anthropic';
|
||||
import { generateText } from 'ai';
|
||||
import 'dotenv/config';
|
||||
interface ProviderConfig {
|
||||
npm: string;
|
||||
name: string;
|
||||
models: Record<string, { name: string }>;
|
||||
options: {
|
||||
baseURL?: string;
|
||||
apiKey: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface OpenCodeConfig {
|
||||
provider: Record<string, ProviderConfig>;
|
||||
}
|
||||
|
||||
// 解析环境变量占位符 {env:VAR_NAME}
|
||||
function resolveEnvVars(value: string): string {
|
||||
return value.replace(/{env:([^}]+)}/g, (_, varName) => {
|
||||
const envValue = process.env[varName];
|
||||
if (!envValue) {
|
||||
throw new Error(`Environment variable ${varName} is not set`);
|
||||
}
|
||||
return envValue;
|
||||
});
|
||||
}
|
||||
|
||||
async function testProvider(providerName: string, config: ProviderConfig) {
|
||||
console.log(`\nTesting provider: ${config.name}`);
|
||||
|
||||
const apiKey = resolveEnvVars(config.options.apiKey);
|
||||
const baseURL = config.options.baseURL ? resolveEnvVars(config.options.baseURL) : undefined;
|
||||
|
||||
let provider;
|
||||
console.log('baseURL:', baseURL);
|
||||
console.log('apiKey:', apiKey ? '[REDACTED]' : '[MISSING]');
|
||||
if (config.npm === '@ai-sdk/openai-compatible') {
|
||||
provider = createOpenAICompatible({
|
||||
baseURL: baseURL!,
|
||||
name: providerName,
|
||||
apiKey,
|
||||
});
|
||||
} else if (config.npm === '@ai-sdk/anthropic') {
|
||||
provider = createAnthropic({
|
||||
baseURL: baseURL,
|
||||
apiKey,
|
||||
});
|
||||
} else {
|
||||
throw new Error(`Unsupported npm package: ${config.npm}`);
|
||||
}
|
||||
|
||||
const modelKeys = Object.keys(config.models);
|
||||
if (modelKeys.length === 0) {
|
||||
throw new Error('No models configured for this provider');
|
||||
}
|
||||
const modelName = modelKeys[0];
|
||||
|
||||
try {
|
||||
const result = await generateText({
|
||||
model: provider(modelName),
|
||||
prompt: 'Say hello in one sentence.',
|
||||
});
|
||||
|
||||
console.log(`Model: ${modelName}`);
|
||||
console.log(`Response: ${result.text}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Error: ${error}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const config: OpenCodeConfig = await Bun.file('opencode.json').json();
|
||||
|
||||
console.log('Loaded opencode.json configuration');
|
||||
console.log(`Found ${Object.keys(config.provider).length} provider(s)`);
|
||||
|
||||
const results = await Promise.all(
|
||||
Object.entries(config.provider).map(([name, config]) =>
|
||||
testProvider(name, config).catch((error) => {
|
||||
console.error(`Provider ${name} failed: ${error}`);
|
||||
return false;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
console.log('\n=== Summary ===');
|
||||
Object.keys(config.provider).forEach((name, i) => {
|
||||
console.log(`${name}: ${results[i] ? '✓ Success' : '✗ Failed'}`);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
104
opencode.json
Normal file
104
opencode.json
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"autoshare": false,
|
||||
"share": "disabled",
|
||||
"autoupdate": true,
|
||||
"permission": "allow",
|
||||
"watcher": {
|
||||
"ignore": [
|
||||
"node_modules/**",
|
||||
"dist/**",
|
||||
".git/**"
|
||||
]
|
||||
},
|
||||
"plugin": [],
|
||||
"provider": {
|
||||
"custom-zhipu": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "国内智谱AI",
|
||||
"models": {
|
||||
"GLM-4.7": {
|
||||
"name": "GLM-4.7"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseURL": "https://open.bigmodel.cn/api/coding/paas/v4",
|
||||
"apiKey": "{env:ZHIPU_API_KEY}"
|
||||
}
|
||||
},
|
||||
"custom-minimax": {
|
||||
"npm": "@ai-sdk/anthropic",
|
||||
"name": "国内MiniMax",
|
||||
"models": {
|
||||
"MiniMax-M2.1": {
|
||||
"name": "MiniMax-M2.1"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseURL": "https://api.minimaxi.com/anthropic/v1",
|
||||
"apiKey": "{env:MINIMAX_API_KEY}"
|
||||
}
|
||||
},
|
||||
"custom-doubao": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "国内火山AI",
|
||||
"models": {
|
||||
"ark-code-latest": {
|
||||
"name": "ark-code-latest"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseURL": "https://ark.cn-beijing.volces.com/api/coding/v3",
|
||||
"apiKey": "{env:VOLCENGINE_API_KEY}"
|
||||
}
|
||||
},
|
||||
"custom-bailian": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "国内百炼AI开发订阅 xx",
|
||||
"models": {
|
||||
"qwen3-coder-plus": {
|
||||
"name": "qwen3-coder-plus"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseURL": "https://coding.dashscope.aliyuncs.com/v1",
|
||||
"apiKey": "{env:BAILIAN_CODE_API_KEY}"
|
||||
}
|
||||
},
|
||||
"custom-cnb": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "国内CNB开发订阅 xx",
|
||||
"models": {
|
||||
"hunyuan": {
|
||||
"name": "hunyuan-a13b"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseURL": "https://api.cnb.cool/{env:CNB_REPO_SLUG}/-/ai/",
|
||||
"apiKey": "{env:CNB_API_KEY}"
|
||||
}
|
||||
},
|
||||
"custom-kevisual": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "自用newapi搭建的开发集合订阅 xx",
|
||||
"models": {
|
||||
"qwen3-coder-plus": {
|
||||
"name": "qwen3-coder-plus"
|
||||
},
|
||||
"ark-code-latest": {
|
||||
"name": "ark-code-latest"
|
||||
},
|
||||
"GLM-4.7": {
|
||||
"name": "GLM-4.7"
|
||||
},
|
||||
"MiniMax-M2.1": {
|
||||
"name": "MiniMax-M2.1"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"baseURL": "https://newapi.kevisual.cn/v1",
|
||||
"apiKey": "{env:KEVISUAL_NEW_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
package.json
Normal file
20
package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "test-ai-sdk",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
"dotenv": "^17.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^3.0.35",
|
||||
"@ai-sdk/openai": "^3.0.25",
|
||||
"@ai-sdk/openai-compatible": "^2.0.26",
|
||||
"@kevisual/ai": "^0.0.24",
|
||||
"ai": "^6.0.67"
|
||||
}
|
||||
}
|
||||
216
pnpm-lock.yaml
generated
Normal file
216
pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,216 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@ai-sdk/anthropic':
|
||||
specifier: ^3.0.35
|
||||
version: 3.0.35(zod@4.3.6)
|
||||
'@ai-sdk/openai':
|
||||
specifier: ^3.0.25
|
||||
version: 3.0.25(zod@4.3.6)
|
||||
'@ai-sdk/openai-compatible':
|
||||
specifier: ^2.0.26
|
||||
version: 2.0.26(zod@4.3.6)
|
||||
'@kevisual/ai':
|
||||
specifier: ^0.0.24
|
||||
version: 0.0.24
|
||||
ai:
|
||||
specifier: ^6.0.67
|
||||
version: 6.0.67(zod@4.3.6)
|
||||
devDependencies:
|
||||
'@types/bun':
|
||||
specifier: latest
|
||||
version: 1.3.8
|
||||
dotenv:
|
||||
specifier: ^17.2.3
|
||||
version: 17.2.3
|
||||
|
||||
packages:
|
||||
|
||||
'@ai-sdk/anthropic@3.0.35':
|
||||
resolution: {integrity: sha512-Y3g/5uVj621XSB9lGF7WrD7qR+orhV5xpaYkRF8kfj2j4W7e7BBGIvxcdsCf85FjJbc6tKQdNTZ84ZEqT3Y5TQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4.1.8
|
||||
|
||||
'@ai-sdk/gateway@3.0.32':
|
||||
resolution: {integrity: sha512-7clZRr07P9rpur39t1RrbIe7x8jmwnwUWI8tZs+BvAfX3NFgdSVGGIaT7bTz2pb08jmLXzTSDbrOTqAQ7uBkBQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4.1.8
|
||||
|
||||
'@ai-sdk/openai-compatible@2.0.26':
|
||||
resolution: {integrity: sha512-l6jdFjI1C2eDAEm7oo+dnRn0oG1EkcyqfbEZ7ozT0TnYrah6amX2JkftYMP1GRzNtAeCB3WNN8XspXdmi6ZNlQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4.1.8
|
||||
|
||||
'@ai-sdk/openai@3.0.25':
|
||||
resolution: {integrity: sha512-DsaN46R98+D1W3lU3fKuPU3ofacboLaHlkAwxJPgJ8eup1AJHmPK1N1y10eJJbJcF6iby8Tf/vanoZxc9JPUfw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4.1.8
|
||||
|
||||
'@ai-sdk/provider-utils@4.0.13':
|
||||
resolution: {integrity: sha512-HHG72BN4d+OWTcq2NwTxOm/2qvk1duYsnhCDtsbYwn/h/4zeqURu1S0+Cn0nY2Ysq9a9HGKvrYuMn9bgFhR2Og==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4.1.8
|
||||
|
||||
'@ai-sdk/provider@3.0.7':
|
||||
resolution: {integrity: sha512-VkPLrutM6VdA924/mG8OS+5frbVTcu6e046D2bgDo00tehBANR1QBJ/mPcZ9tXMFOsVcm6SQArOregxePzTFPw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@kevisual/ai@0.0.24':
|
||||
resolution: {integrity: sha512-7jvZk1/L//VIClK7usuNgN4ZA9Etgbooka1Sj5quE/0UywR+NNnwqXVZ89Y1fBhI1TkhauDsdJBAtcQ7r/vbVw==}
|
||||
|
||||
'@kevisual/logger@0.0.4':
|
||||
resolution: {integrity: sha512-+fpr92eokSxoGOW1SIRl/27lPuO+zyY+feR5o2Q4YCNlAdt2x64NwC/w8r/3NEC5QenLgd4K0azyKTI2mHbARw==}
|
||||
|
||||
'@kevisual/permission@0.0.3':
|
||||
resolution: {integrity: sha512-8JsA/5O5Ax/z+M+MYpFYdlioHE6jNmWMuFSokBWYs9CCAHNiSKMR01YLkoVDoPvncfH/Y8F5K/IEXRCbptuMNA==}
|
||||
|
||||
'@kevisual/query@0.0.38':
|
||||
resolution: {integrity: sha512-bfvbSodsZyMfwY+1T2SvDeOCKsT/AaIxlVe0+B1R/fNhlg2MDq2CP0L9HKiFkEm+OXrvXcYDMKPUituVUM5J6Q==}
|
||||
|
||||
'@opentelemetry/api@1.9.0':
|
||||
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
'@standard-schema/spec@1.1.0':
|
||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||
|
||||
'@types/bun@1.3.8':
|
||||
resolution: {integrity: sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA==}
|
||||
|
||||
'@types/node@25.2.0':
|
||||
resolution: {integrity: sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==}
|
||||
|
||||
'@vercel/oidc@3.1.0':
|
||||
resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
|
||||
engines: {node: '>= 20'}
|
||||
|
||||
ai@6.0.67:
|
||||
resolution: {integrity: sha512-xBnTcByHCj3OcG6V8G1s6zvSEqK0Bdiu+IEXYcpGrve1iGFFRgcrKeZtr/WAW/7gupnSvBbDF24BEv1OOfqi1g==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
zod: ^3.25.76 || ^4.1.8
|
||||
|
||||
bun-types@1.3.8:
|
||||
resolution: {integrity: sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q==}
|
||||
|
||||
dotenv@17.2.3:
|
||||
resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
eventsource-parser@3.0.6:
|
||||
resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
json-schema@0.4.0:
|
||||
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
|
||||
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
undici-types@7.16.0:
|
||||
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||
|
||||
zod@4.3.6:
|
||||
resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
|
||||
|
||||
snapshots:
|
||||
|
||||
'@ai-sdk/anthropic@3.0.35(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 3.0.7
|
||||
'@ai-sdk/provider-utils': 4.0.13(zod@4.3.6)
|
||||
zod: 4.3.6
|
||||
|
||||
'@ai-sdk/gateway@3.0.32(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 3.0.7
|
||||
'@ai-sdk/provider-utils': 4.0.13(zod@4.3.6)
|
||||
'@vercel/oidc': 3.1.0
|
||||
zod: 4.3.6
|
||||
|
||||
'@ai-sdk/openai-compatible@2.0.26(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 3.0.7
|
||||
'@ai-sdk/provider-utils': 4.0.13(zod@4.3.6)
|
||||
zod: 4.3.6
|
||||
|
||||
'@ai-sdk/openai@3.0.25(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 3.0.7
|
||||
'@ai-sdk/provider-utils': 4.0.13(zod@4.3.6)
|
||||
zod: 4.3.6
|
||||
|
||||
'@ai-sdk/provider-utils@4.0.13(zod@4.3.6)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 3.0.7
|
||||
'@standard-schema/spec': 1.1.0
|
||||
eventsource-parser: 3.0.6
|
||||
zod: 4.3.6
|
||||
|
||||
'@ai-sdk/provider@3.0.7':
|
||||
dependencies:
|
||||
json-schema: 0.4.0
|
||||
|
||||
'@kevisual/ai@0.0.24':
|
||||
dependencies:
|
||||
'@kevisual/logger': 0.0.4
|
||||
'@kevisual/permission': 0.0.3
|
||||
'@kevisual/query': 0.0.38
|
||||
|
||||
'@kevisual/logger@0.0.4': {}
|
||||
|
||||
'@kevisual/permission@0.0.3': {}
|
||||
|
||||
'@kevisual/query@0.0.38':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@opentelemetry/api@1.9.0': {}
|
||||
|
||||
'@standard-schema/spec@1.1.0': {}
|
||||
|
||||
'@types/bun@1.3.8':
|
||||
dependencies:
|
||||
bun-types: 1.3.8
|
||||
|
||||
'@types/node@25.2.0':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@vercel/oidc@3.1.0': {}
|
||||
|
||||
ai@6.0.67(zod@4.3.6):
|
||||
dependencies:
|
||||
'@ai-sdk/gateway': 3.0.32(zod@4.3.6)
|
||||
'@ai-sdk/provider': 3.0.7
|
||||
'@ai-sdk/provider-utils': 4.0.13(zod@4.3.6)
|
||||
'@opentelemetry/api': 1.9.0
|
||||
zod: 4.3.6
|
||||
|
||||
bun-types@1.3.8:
|
||||
dependencies:
|
||||
'@types/node': 25.2.0
|
||||
|
||||
dotenv@17.2.3: {}
|
||||
|
||||
eventsource-parser@3.0.6: {}
|
||||
|
||||
json-schema@0.4.0: {}
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
zod@4.3.6: {}
|
||||
16
src/index.ts
Normal file
16
src/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
||||
import { generateText } from 'ai';
|
||||
|
||||
// 使用自定义 doubao provider
|
||||
const doubao = createOpenAICompatible({
|
||||
baseURL: 'https://ark.cn-beijing.volces.com/api/coding/v3',
|
||||
name: 'custom-doubao',
|
||||
apiKey: process.env.DOUBAO_API_KEY!,
|
||||
});
|
||||
|
||||
const { text } = await generateText({
|
||||
model: doubao('ark-code-latest'),
|
||||
prompt: 'What is an agent?',
|
||||
});
|
||||
|
||||
console.log(text);
|
||||
33
src/test-bailian-debug.ts
Normal file
33
src/test-bailian-debug.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import 'dotenv/config';
|
||||
|
||||
const endpoint = 'https://coding.dashscope.aliyuncs.com/apps/anthropic/messages';
|
||||
|
||||
// 测试不同的认证方式
|
||||
const authMethods = [
|
||||
{ name: 'x-api-key', headers: { 'x-api-key': process.env.BAILIAN_CODE_API_KEY! } },
|
||||
{ name: 'Authorization Bearer', headers: { 'Authorization': `Bearer ${process.env.BAILIAN_CODE_API_KEY!}` } },
|
||||
{ name: 'Authorization Bearer sk-', headers: { 'Authorization': `Bearer sk-${process.env.BAILIAN_CODE_API_KEY!}` } },
|
||||
{ name: 'Authorization sk-', headers: { 'Authorization': `sk-${process.env.BAILIAN_CODE_API_KEY!}` } },
|
||||
];
|
||||
|
||||
for (const { name, headers } of authMethods) {
|
||||
console.log(`\nTesting: ${name}`);
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...headers,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'qwen3-coder-plus',
|
||||
max_tokens: 100,
|
||||
messages: [{ role: 'user', content: 'Hello' }],
|
||||
}),
|
||||
});
|
||||
|
||||
console.log(`Status: ${response.status}`);
|
||||
const text = await response.text();
|
||||
if (text) {
|
||||
console.log(`Response: ${text.substring(0, 300)}`);
|
||||
}
|
||||
}
|
||||
23
src/test-bailian.ts
Normal file
23
src/test-bailian.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
||||
import { createAnthropic } from '@ai-sdk/anthropic';
|
||||
import { generateText } from 'ai';
|
||||
import 'dotenv/config';
|
||||
|
||||
// 尝试不同的端点配置
|
||||
const bailian = createOpenAICompatible({
|
||||
baseURL: 'https://coding.dashscope.aliyuncs.com/v1',
|
||||
name: 'custom-bailian',
|
||||
apiKey: process.env.BAILIAN_CODE_API_KEY!,
|
||||
});
|
||||
// const bailian = createAnthropic({
|
||||
// baseURL: 'https://coding.dashscope.aliyuncs.com/apps/anthropic/messages',
|
||||
// name: 'custom-bailian',
|
||||
// apiKey: process.env.BAILIAN_CODE_API_KEY!,
|
||||
// });
|
||||
|
||||
const { text } = await generateText({
|
||||
model: bailian('qwen3-coder-plus'),
|
||||
prompt: 'What is an agent?',
|
||||
});
|
||||
|
||||
console.log('Response:', text);
|
||||
46
src/test-cnb-debug.ts
Normal file
46
src/test-cnb-debug.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'dotenv/config';
|
||||
|
||||
function resolveEnvVars(value: string): string {
|
||||
return value.replace(/{env:([^}]+)}/g, (_, varName) => {
|
||||
const envValue = process.env[varName];
|
||||
if (!envValue) {
|
||||
throw new Error(`Environment variable ${varName} is not set`);
|
||||
}
|
||||
return envValue;
|
||||
});
|
||||
}
|
||||
|
||||
const endpoint = 'https://cnb.cool/kevisual/cnb/-/ai/chat/completions';
|
||||
const apiKey = process.env.CNB_API_KEY!;
|
||||
|
||||
console.log('Endpoint:', endpoint);
|
||||
console.log('API Key:', apiKey ? 'Set' : 'Not set');
|
||||
console.log('API Key length:', apiKey.length);
|
||||
console.log('API Key prefix:', apiKey.substring(0, 10) + '...');
|
||||
|
||||
// 尝试不同的认证头
|
||||
const authHeaders = [
|
||||
{ name: 'Authorization Bearer', headers: { 'Authorization': `Bearer ${apiKey}` } },
|
||||
{ name: 'Authorization (no Bearer)', headers: { 'Authorization': apiKey } },
|
||||
{ name: 'x-api-key', headers: { 'x-api-key': apiKey } },
|
||||
{ name: 'api-key', headers: { 'api-key': apiKey } },
|
||||
];
|
||||
|
||||
for (const { name, headers } of authHeaders) {
|
||||
console.log(`\n=== Testing: ${name} ===`);
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...headers,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'hunyuan-a13b',
|
||||
messages: [{ role: 'user', content: '你好' }],
|
||||
}),
|
||||
});
|
||||
|
||||
console.log(`Status: ${response.status}`);
|
||||
const text = await response.text();
|
||||
console.log('Response:', text);
|
||||
}
|
||||
28
src/test-cnb.ts
Normal file
28
src/test-cnb.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
||||
import { generateText } from 'ai';
|
||||
import 'dotenv/config';
|
||||
|
||||
// 解析环境变量占位符
|
||||
function resolveEnvVars(value: string): string {
|
||||
return value.replace(/{env:([^}]+)}/g, (_, varName) => {
|
||||
const envValue = process.env[varName];
|
||||
if (!envValue) {
|
||||
throw new Error(`Environment variable ${varName} is not set`);
|
||||
}
|
||||
return envValue;
|
||||
});
|
||||
}
|
||||
|
||||
// 使用 custom-cnb provider
|
||||
const cnb = createOpenAICompatible({
|
||||
baseURL: resolveEnvVars('{env:CNB_API_ENDPOINT}/{env:CNB_REPO_SLUG}/-/ai/'),
|
||||
name: 'custom-cnb',
|
||||
apiKey: process.env.CNB_API_KEY!,
|
||||
});
|
||||
|
||||
const { text } = await generateText({
|
||||
model: cnb('hunyuan-a13b'),
|
||||
prompt: 'What is an agent?',
|
||||
});
|
||||
|
||||
console.log('Response:', text);
|
||||
26
src/test-kevisual.ts
Normal file
26
src/test-kevisual.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
||||
import { generateText } from 'ai';
|
||||
import 'dotenv/config';
|
||||
|
||||
// 使用 custom-kevisual provider (聚合了多个模型)
|
||||
const kevisual = createOpenAICompatible({
|
||||
baseURL: 'https://newapi.kevisual.cn/v1',
|
||||
name: 'custom-kevisual',
|
||||
apiKey: process.env.KEVISUAL_NEW_API_KEY!,
|
||||
});
|
||||
|
||||
// 测试所有可用模型
|
||||
const models = ['qwen3-coder-plus', 'ark-code-latest', 'GLM-4.7', 'MiniMax-M2.1'];
|
||||
|
||||
for (const model of models) {
|
||||
console.log(`\n=== Testing model: ${model} ===`);
|
||||
try {
|
||||
const { text } = await generateText({
|
||||
model: kevisual(model),
|
||||
prompt: 'Say hello in one sentence.',
|
||||
});
|
||||
console.log(`Response: ${text}`);
|
||||
} catch (error) {
|
||||
console.error(`Error: ${error}`);
|
||||
}
|
||||
}
|
||||
29
tsconfig.json
Normal file
29
tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext"],
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user