chore: import upstream snapshot with attribution
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:24:08 +08:00
commit 0d3cb498a3
5438 changed files with 1316560 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
# config-ts (TypeScript Configuration Example)
You can run this example with:
```bash
npx promptfoo@latest init --example config-ts
cd config-ts
```
This example demonstrates TypeScript configuration for promptfoo, including:
- Type-safe configuration with IDE autocompletion
- Dynamic schema generation using Zod
- Fun translation examples with creative language styles
## Prerequisites
- Node.js ^20.20.0 or >=22.22.0 (Node.js 20 support ends July 30, 2026; Node.js 24 LTS recommended)
- TypeScript loader (`tsx` recommended)
Install dependencies:
```bash
npm install
```
## Running Examples
### Basic TypeScript Configuration
```bash
NODE_OPTIONS="--import tsx" promptfoo eval -c promptfooconfig.ts
```
This example translates text into French and Pirate speak.
### Dynamic Schema Generation
```bash
NODE_OPTIONS="--import tsx" promptfoo eval -c promptfooconfig-with-schema.ts
```
This example shows structured JSON outputs with fun translations into Pirate speak, Shakespeare English, and Gen Z slang.
View results:
```bash
promptfoo view
```
## Examples Overview
### 1. Basic Configuration (`promptfooconfig.ts`)
Demonstrates:
- Type-safe configuration using the `UnifiedConfig` type
- Simple provider configuration with GPT-5 Mini
- Basic translation examples
### 2. Dynamic Schema Generation (`promptfooconfig-with-schema.ts`)
Shows advanced features:
- Zod schema for structured translation responses
- Automatic schema adaptation for different providers (OpenAI and Gemini)
- Structured JSON outputs with multiple fields (translation, language, confidence, funFactor, culturalNotes)
- JavaScript assertions for validating structured outputs
Both OpenAI and Gemini support strict schema enforcement to ensure outputs match your Zod schema exactly.
## TypeScript Support
Node.js currently requires external loaders to run TypeScript files directly:
- Supported Node.js versions support ES modules with the `--import` flag
- The `tsx` loader provides the best developer experience
- Future versions may include native TypeScript support
+21
View File
@@ -0,0 +1,21 @@
{
"name": "ts-config-example",
"version": "1.0.0",
"license": "MIT",
"private": true,
"description": "TypeScript configuration example for promptfoo with dynamic schema generation",
"scripts": {
"eval": "NODE_OPTIONS=\"--import tsx\" promptfoo eval -c promptfooconfig.ts",
"eval-schema": "NODE_OPTIONS=\"--import tsx\" promptfoo eval -c promptfooconfig-with-schema.ts",
"view": "promptfoo view"
},
"dependencies": {
"openai": "^6.37.0",
"tsx": "^4.21.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^25.1.0",
"promptfoo": "latest"
}
}
@@ -0,0 +1,145 @@
import { zodResponseFormat } from 'openai/helpers/zod.mjs';
import { TranslationResponseSchema } from './src/schemas/translation-response';
import type { UnifiedConfig } from 'promptfoo';
// Generate the response format for OpenAI
const responseFormat = zodResponseFormat(TranslationResponseSchema, 'translation_response');
// Helper to adapt schema for Gemini (removes OpenAI-specific fields)
function cleanSchemaForGemini(schema: any): any {
if (typeof schema !== 'object' || schema === null) {
return schema;
}
const cleaned = { ...schema };
// Remove properties that Gemini doesn't support
delete cleaned.additionalProperties;
delete cleaned.$schema;
// Recursively clean nested objects
if (cleaned.properties) {
cleaned.properties = Object.fromEntries(
Object.entries(cleaned.properties).map(([key, value]) => [key, cleanSchemaForGemini(value)]),
);
}
if (cleaned.items) {
cleaned.items = cleanSchemaForGemini(cleaned.items);
}
return cleaned;
}
const config: UnifiedConfig = {
description: 'Fun translation tests with structured outputs',
prompts: [
`You are a creative translator who adds personality to translations.
Translate this to {{language}}: "{{text}}"
Return a JSON response with your translation, confidence level, and any fun cultural notes.`,
],
providers: [
{
id: 'openai:chat:gpt-5.5',
label: 'GPT-5.5 (structured)',
config: {
response_format: responseFormat,
},
},
{
id: 'google:gemini-2.5-flash',
label: 'Gemini 2.5 Flash (structured)',
config: {
generationConfig: {
response_mime_type: 'application/json',
response_schema: cleanSchemaForGemini(responseFormat.json_schema.schema),
},
},
},
],
tests: [
{
vars: {
language: 'Pirate speak',
text: "I can't find my coffee",
},
assert: [
{
type: 'javascript',
value: `
// Handle both object and string outputs
const parsed = typeof output === 'object' ? output :
JSON.parse(output.replace(/^\`\`\`json\\s*|\\s*\`\`\`$/g, ''));
// Check for valid pirate speak patterns
const text = parsed.translation.toLowerCase();
const hasPirateSpeak = text.includes('arr') || text.includes('matey') ||
text.includes('ye') || text.includes("me ") ||
text.includes("'t ") || text.match(/\bt'\b/) ||
text.includes('brew');
return parsed.translation &&
parsed.language.toLowerCase().includes('pirate') &&
hasPirateSpeak;
`,
},
],
},
{
vars: {
language: 'Shakespeare English',
text: 'This app is broken',
},
assert: [
{
type: 'javascript',
value: `
const parsed = typeof output === 'object' ? output :
JSON.parse(output.replace(/^\`\`\`json\\s*|\\s*\`\`\`$/g, ''));
const text = parsed.translation.toLowerCase();
return parsed.translation &&
(text.includes('thou') || text.includes('thee') ||
text.includes('doth') || text.includes('hath') ||
text.includes('alas') || text.includes('lieth') ||
text.includes('woeful') || text.includes('undone') ||
text.includes('forsooth') || text.includes('prithee') ||
text.includes('verily') || text.match(/eth\\b/));
`,
},
],
},
{
vars: {
language: 'Gen Z slang',
text: "That's really impressive",
},
assert: [
{
type: 'javascript',
value: `
const parsed = typeof output === 'object' ? output :
JSON.parse(output.replace(/^\`\`\`json\\s*|\\s*\`\`\`$/g, ''));
const translation = parsed.translation.toLowerCase();
return parsed.translation &&
parsed.confidence > 0 &&
(translation.includes('slay') ||
translation.includes('fire') ||
translation.includes('bussin') ||
translation.includes('lit') ||
translation.includes('goat') ||
translation.includes('lowkey') ||
translation.includes('low-key') ||
translation.includes('no cap') ||
translation.includes(' fr') ||
translation.includes('insane'));
`,
},
],
},
],
};
export default config;
+38
View File
@@ -0,0 +1,38 @@
import type { UnifiedConfig } from 'promptfoo';
const config: UnifiedConfig = {
description: 'A translator built with LLM',
prompts: [
'Rephrase this in {{language}}: {{body}}',
'Translate this to conversational {{language}}: {{body}}',
],
providers: ['openai:chat:gpt-5.5'],
tests: [
{
vars: {
language: 'French',
body: 'Hello world',
},
},
{
vars: {
language: 'French',
body: "I'm hungry",
},
},
{
vars: {
language: 'Pirate',
body: 'Hello world',
},
},
{
vars: {
language: 'Pirate',
body: "I'm hungry",
},
},
],
};
export default config;
@@ -0,0 +1,12 @@
import { z } from 'zod';
// Fun schema for creative translation responses
export const TranslationResponseSchema = z.object({
translation: z.string().describe('The translated text'),
language: z.string().describe('The target language or style'),
confidence: z.number().min(0).max(1).describe('How confident the AI is (0-1)'),
funFactor: z.number().min(0).max(10).nullable().describe('Fun rating from 0-10'),
culturalNotes: z.string().nullable().describe('Any amusing cultural observations'),
});
export type TranslationResponse = z.infer<typeof TranslationResponseSchema>;
+17
View File
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"include": ["**/*.ts"],
"exclude": ["node_modules"]
}