@output.ai/cli 0.7.8-dev.pr263-a59dd0e → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/sdk_versions.json +6 -0
- package/dist/services/messages.js +1 -1
- package/dist/templates/agent_instructions/dotoutputai/AGENTS.md.template +2 -2
- package/dist/templates/project/README.md.template +1 -38
- package/dist/templates/project/src/workflows/example_question/prompts/answer_question@v1.prompt.template +13 -0
- package/dist/templates/project/src/workflows/example_question/scenarios/question_ada_lovelace.json.template +3 -0
- package/dist/templates/project/src/workflows/example_question/steps.ts.template +16 -0
- package/dist/templates/project/src/workflows/example_question/workflow.ts.template +22 -0
- package/dist/templates/workflow/README.md.template +75 -96
- package/dist/utils/sdk_versions.js +2 -26
- package/dist/utils/sdk_versions.spec.js +1 -1
- package/package.json +3 -2
- package/dist/templates/project/src/shared/clients/pokeapi.ts.template +0 -29
- package/dist/templates/project/src/shared/utils/string.ts.template +0 -3
- package/dist/templates/project/src/workflows/poke_battle/evaluators.ts.template +0 -44
- package/dist/templates/project/src/workflows/poke_battle/prompts/evaluate_realism@v1.prompt.template +0 -24
- package/dist/templates/project/src/workflows/poke_battle/prompts/generate_screenplay@v1.prompt.template +0 -18
- package/dist/templates/project/src/workflows/poke_battle/scenarios/pikachu_vs_charmander.json.template +0 -8
- package/dist/templates/project/src/workflows/poke_battle/steps.ts.template +0 -37
- package/dist/templates/project/src/workflows/poke_battle/utils.ts.template +0 -7
- package/dist/templates/project/src/workflows/poke_battle/workflow.ts.template +0 -47
- package/dist/templates/workflow/evaluators.ts.template +0 -23
|
@@ -177,7 +177,7 @@ export const getProjectSuccessMessage = (folderName, installSuccess, envConfigur
|
|
|
177
177
|
note: 'Launches Temporal, Redis, PostgreSQL, API, Worker, and UI'
|
|
178
178
|
}, {
|
|
179
179
|
step: 'Run example workflow',
|
|
180
|
-
command: 'npx output workflow run
|
|
180
|
+
command: 'npx output workflow run example_question --input src/workflows/example_question/scenarios/question_ada_lovelace.json',
|
|
181
181
|
note: 'Execute in a new terminal after services are running'
|
|
182
182
|
}, {
|
|
183
183
|
step: 'Monitor workflows',
|
|
@@ -186,7 +186,7 @@ export default workflow({
|
|
|
186
186
|
});
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
**Allowed imports**: steps.ts, evaluators.ts,
|
|
189
|
+
**Allowed imports**: steps.ts, evaluators.ts, shared_steps.ts, types.ts, consts.ts, utils.ts
|
|
190
190
|
|
|
191
191
|
**Forbidden in workflows**: Direct API calls, Math.random(), Date.now(), dynamic imports
|
|
192
192
|
|
|
@@ -389,7 +389,7 @@ After creating a new workflow, you likely need restart the worker container for
|
|
|
389
389
|
|
|
390
390
|
```bash
|
|
391
391
|
# Check running containers
|
|
392
|
-
docker ps --filter "name=output" --format "{{.Names}}: {{.Status}}"
|
|
392
|
+
docker ps --filter "name=output" --format "\{{.Names}}: \{{.Status}}"
|
|
393
393
|
|
|
394
394
|
# Restart the worker (adjust container name based on your project)
|
|
395
395
|
docker restart <project-name>-worker-1
|
|
@@ -7,43 +7,6 @@
|
|
|
7
7
|
- Node.js >= 24.3
|
|
8
8
|
- Docker and Docker Compose (for local development)
|
|
9
9
|
|
|
10
|
-
## Project Structure
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
src/
|
|
14
|
-
├── shared/ # Shared code across workflows
|
|
15
|
-
│ ├── clients/ # API clients (e.g., pokeapi.ts)
|
|
16
|
-
│ └── utils/ # Utility functions (e.g., string.ts)
|
|
17
|
-
└── workflows/ # Workflow definitions
|
|
18
|
-
└── poke_battle/ # Example workflow
|
|
19
|
-
├── workflow.ts # Main workflow
|
|
20
|
-
├── steps.ts # Workflow steps
|
|
21
|
-
├── evaluators.ts # Quality evaluators
|
|
22
|
-
├── utils.ts # Local utilities
|
|
23
|
-
├── prompts/ # LLM prompts
|
|
24
|
-
└── scenarios/ # Test scenarios
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### Shared Directory
|
|
28
|
-
|
|
29
|
-
The `src/shared/` directory contains code shared across multiple workflows:
|
|
30
|
-
|
|
31
|
-
- **`shared/clients/`** - API clients using `@output.ai/http` for external services
|
|
32
|
-
- **`shared/utils/`** - Helper functions and utilities
|
|
33
|
-
|
|
34
|
-
### Import Rules
|
|
35
|
-
|
|
36
|
-
**Workflows** can import from:
|
|
37
|
-
- Local steps, evaluators, and utilities
|
|
38
|
-
- Shared steps, evaluators, clients, and utilities
|
|
39
|
-
|
|
40
|
-
**Steps and Evaluators** can import from:
|
|
41
|
-
- Local utilities and clients
|
|
42
|
-
- Shared utilities and clients
|
|
43
|
-
|
|
44
|
-
**Steps and Evaluators cannot** import from:
|
|
45
|
-
- Other steps or evaluators (Temporal activity isolation)
|
|
46
|
-
|
|
47
10
|
## Getting Started
|
|
48
11
|
|
|
49
12
|
### 1. Install Dependencies
|
|
@@ -81,7 +44,7 @@ This starts:
|
|
|
81
44
|
In a new terminal:
|
|
82
45
|
|
|
83
46
|
```bash
|
|
84
|
-
npx output workflow run
|
|
47
|
+
npx output workflow run example_question --input '{"question": "who really is ada lovelace?"}'
|
|
85
48
|
```
|
|
86
49
|
|
|
87
50
|
### 5. Stop Services
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
provider: anthropic
|
|
3
|
+
model: claude-opus-4-1-20250805
|
|
4
|
+
temperature: 0.7
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<system>
|
|
8
|
+
You are a helpful assistant. Answer the user's question concisely and clearly.
|
|
9
|
+
</system>
|
|
10
|
+
|
|
11
|
+
<user>
|
|
12
|
+
Answer the following question: \{{ question }}
|
|
13
|
+
</user>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { step, z } from '@output.ai/core';
|
|
2
|
+
import { generateText } from '@output.ai/llm';
|
|
3
|
+
|
|
4
|
+
export const answerQuestion = step( {
|
|
5
|
+
name: 'answerQuestion',
|
|
6
|
+
description: 'Answer a question using an LLM',
|
|
7
|
+
inputSchema: z.string(),
|
|
8
|
+
outputSchema: z.string(),
|
|
9
|
+
fn: async question => {
|
|
10
|
+
const { result } = await generateText( {
|
|
11
|
+
prompt: 'answer_question@v1',
|
|
12
|
+
variables: { question }
|
|
13
|
+
} );
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
} );
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { workflow, z } from '@output.ai/core';
|
|
2
|
+
import { answerQuestion } from './steps.js';
|
|
3
|
+
|
|
4
|
+
export default workflow( {
|
|
5
|
+
name: 'example_question',
|
|
6
|
+
description: '{{description}}',
|
|
7
|
+
inputSchema: z.object( {
|
|
8
|
+
question: z.string().describe( 'A question to answer' )
|
|
9
|
+
} ),
|
|
10
|
+
outputSchema: z.object( {
|
|
11
|
+
answer: z.string().describe( 'The answer to the question' )
|
|
12
|
+
} ),
|
|
13
|
+
fn: async input => {
|
|
14
|
+
const answer = await answerQuestion( input.question );
|
|
15
|
+
return { answer };
|
|
16
|
+
},
|
|
17
|
+
options: {
|
|
18
|
+
retry: {
|
|
19
|
+
maximumAttempts: 3
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
} );
|
|
@@ -10,50 +10,8 @@ This workflow was generated using the Output SDK CLI. It provides a starting poi
|
|
|
10
10
|
|
|
11
11
|
- `workflow.ts` - Main workflow definition with input/output schemas
|
|
12
12
|
- `steps.ts` - Activity/step definitions with input/output schemas
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
15
|
-
|
|
16
|
-
## File Organization
|
|
17
|
-
|
|
18
|
-
You can organize your workflow files in two ways:
|
|
19
|
-
|
|
20
|
-
**Flat files:**
|
|
21
|
-
```
|
|
22
|
-
workflow/
|
|
23
|
-
├── workflow.ts
|
|
24
|
-
├── steps.ts
|
|
25
|
-
├── evaluators.ts
|
|
26
|
-
└── utils.ts
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Folder-based:**
|
|
30
|
-
```
|
|
31
|
-
workflow/
|
|
32
|
-
├── workflow.ts
|
|
33
|
-
├── steps/
|
|
34
|
-
│ ├── fetch_data.ts
|
|
35
|
-
│ └── process_data.ts
|
|
36
|
-
├── evaluators/
|
|
37
|
-
│ └── quality.ts
|
|
38
|
-
└── utils/
|
|
39
|
-
└── helpers.ts
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Import Rules
|
|
43
|
-
|
|
44
|
-
**Important:** Steps and evaluators are Temporal activities. Activities cannot call other activities.
|
|
45
|
-
|
|
46
|
-
**Steps can import from:**
|
|
47
|
-
- Local utilities (`./utils.ts`, `./utils/*.ts`)
|
|
48
|
-
- Shared utilities (`../../shared/utils/*.ts`)
|
|
49
|
-
- Shared clients (`../../shared/clients/*.ts`)
|
|
50
|
-
|
|
51
|
-
**Steps cannot import from:**
|
|
52
|
-
- Other steps or evaluators (activity isolation)
|
|
53
|
-
- Workflow files
|
|
54
|
-
|
|
55
|
-
**Workflows can import from:**
|
|
56
|
-
- Steps, evaluators, and utilities (local and shared)
|
|
13
|
+
- `prompt@v1.prompt` - Example LLM prompt template
|
|
14
|
+
- `.env` - Environment variables for API keys and configuration
|
|
57
15
|
|
|
58
16
|
## Setup
|
|
59
17
|
|
|
@@ -105,109 +63,121 @@ Example:
|
|
|
105
63
|
|
|
106
64
|
### Workflow Structure
|
|
107
65
|
|
|
108
|
-
The workflow follows the Output SDK conventions:
|
|
66
|
+
The workflow follows the new Output SDK conventions:
|
|
109
67
|
|
|
110
68
|
```typescript
|
|
111
|
-
import { workflow
|
|
112
|
-
import { myStep } from './steps.js';
|
|
113
|
-
|
|
69
|
+
import { workflow } from '@output.ai/core';
|
|
70
|
+
import { myStep, anotherStep } from './steps.js';
|
|
71
|
+
|
|
72
|
+
const inputSchema = {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
// Define your input properties
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const outputSchema = {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: {
|
|
82
|
+
// Define your output properties
|
|
83
|
+
}
|
|
84
|
+
};
|
|
114
85
|
|
|
115
86
|
export default workflow( {
|
|
116
87
|
name: 'workflowName',
|
|
117
88
|
description: 'Workflow description',
|
|
118
|
-
inputSchema
|
|
119
|
-
outputSchema
|
|
89
|
+
inputSchema,
|
|
90
|
+
outputSchema,
|
|
120
91
|
fn: async ( input ) => {
|
|
92
|
+
// Call steps directly
|
|
121
93
|
const result = await myStep( input );
|
|
122
|
-
|
|
123
|
-
return { result, qualityScore: score };
|
|
94
|
+
return result;
|
|
124
95
|
}
|
|
125
96
|
} );
|
|
126
97
|
```
|
|
127
98
|
|
|
128
99
|
### Adding New Steps
|
|
129
100
|
|
|
130
|
-
Define steps in `steps.ts` with schemas:
|
|
101
|
+
1. Define new steps in `steps.ts` with schemas:
|
|
131
102
|
|
|
132
103
|
```typescript
|
|
133
|
-
import { step
|
|
104
|
+
import { step } from '@output.ai/core';
|
|
105
|
+
|
|
106
|
+
const inputSchema = {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
value: { type: 'number' }
|
|
110
|
+
},
|
|
111
|
+
required: ['value']
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const outputSchema = {
|
|
115
|
+
type: 'object',
|
|
116
|
+
properties: {
|
|
117
|
+
result: { type: 'string' }
|
|
118
|
+
}
|
|
119
|
+
};
|
|
134
120
|
|
|
135
121
|
export const myStep = step( {
|
|
136
122
|
name: 'myStep',
|
|
137
123
|
description: 'Description of what this step does',
|
|
138
|
-
inputSchema
|
|
139
|
-
|
|
140
|
-
} )
|
|
141
|
-
|
|
142
|
-
result: z.string()
|
|
143
|
-
} ),
|
|
144
|
-
fn: async ( input ) => {
|
|
124
|
+
inputSchema,
|
|
125
|
+
outputSchema,
|
|
126
|
+
fn: async ( input: { value: number } ) => {
|
|
127
|
+
// Step implementation
|
|
145
128
|
return { result: `Processed ${input.value}` };
|
|
146
129
|
}
|
|
147
130
|
} );
|
|
148
131
|
```
|
|
149
132
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Define evaluators in `evaluators.ts`:
|
|
133
|
+
2. Import and use the step in your workflow (`workflow.ts`):
|
|
153
134
|
|
|
154
135
|
```typescript
|
|
155
|
-
import {
|
|
156
|
-
import { generateText } from '@output.ai/llm';
|
|
136
|
+
import { myStep } from './steps.js';
|
|
157
137
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
description: 'Evaluate output quality',
|
|
161
|
-
inputSchema: z.object( {
|
|
162
|
-
input: z.any(),
|
|
163
|
-
output: z.any()
|
|
164
|
-
} ),
|
|
165
|
-
outputSchema: z.object( {
|
|
166
|
-
score: z.number().min( 0 ).max( 100 )
|
|
167
|
-
} ),
|
|
168
|
-
fn: async ( data ) => {
|
|
169
|
-
const { result } = await generateText( {
|
|
170
|
-
prompt: 'evaluate@v1',
|
|
171
|
-
variables: { input: data.input, output: data.output }
|
|
172
|
-
} );
|
|
173
|
-
return { score: parseInt( result, 10 ) };
|
|
174
|
-
}
|
|
175
|
-
} );
|
|
138
|
+
// Inside workflow fn:
|
|
139
|
+
const result = await myStep( { value: 42 } );
|
|
176
140
|
```
|
|
177
141
|
|
|
178
142
|
### Using LLM in Steps
|
|
179
143
|
|
|
144
|
+
The template includes an example of using LLM with prompts:
|
|
145
|
+
|
|
180
146
|
```typescript
|
|
181
147
|
import { generateText } from '@output.ai/llm';
|
|
182
148
|
|
|
183
149
|
export const llmStep = step( {
|
|
184
150
|
name: 'llmStep',
|
|
185
151
|
description: 'Generate text using LLM',
|
|
186
|
-
inputSchema:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
152
|
+
inputSchema: {
|
|
153
|
+
type: 'object',
|
|
154
|
+
properties: {
|
|
155
|
+
userInput: { type: 'string' }
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
outputSchema: { type: 'string' },
|
|
159
|
+
fn: async ( input: { userInput: string } ) => {
|
|
160
|
+
const response = await generateText( {
|
|
192
161
|
prompt: 'prompt@v1',
|
|
193
162
|
variables: { userInput: input.userInput }
|
|
194
163
|
} );
|
|
195
|
-
return
|
|
164
|
+
return response;
|
|
196
165
|
}
|
|
197
166
|
} );
|
|
198
167
|
```
|
|
199
168
|
|
|
200
169
|
### Creating Prompt Templates
|
|
201
170
|
|
|
202
|
-
Create prompt files
|
|
171
|
+
Create new prompt files following the pattern:
|
|
203
172
|
- File naming: `promptName@v1.prompt`
|
|
204
|
-
- Include YAML frontmatter with model
|
|
173
|
+
- Include YAML frontmatter with provider and model
|
|
205
174
|
- Use LiquidJS syntax for variables: `{{ variableName }}`
|
|
206
175
|
|
|
207
176
|
Example prompt file:
|
|
208
177
|
```
|
|
209
178
|
---
|
|
210
|
-
|
|
179
|
+
provider: anthropic
|
|
180
|
+
model: claude-3-5-sonnet-latest
|
|
211
181
|
---
|
|
212
182
|
|
|
213
183
|
{{ userInput }}
|
|
@@ -225,10 +195,19 @@ To test your workflow:
|
|
|
225
195
|
|
|
226
196
|
Example execution:
|
|
227
197
|
```bash
|
|
228
|
-
|
|
198
|
+
curl -X POST http://localhost:3001/workflow \
|
|
199
|
+
-H "Content-Type: application/json" \
|
|
200
|
+
-d '{
|
|
201
|
+
"workflowName": "{{workflowName}}",
|
|
202
|
+
"input": {
|
|
203
|
+
"prompt": "Tell me about workflows",
|
|
204
|
+
"data": { "value": 42, "type": "example" }
|
|
205
|
+
}
|
|
206
|
+
}'
|
|
229
207
|
```
|
|
230
208
|
|
|
231
209
|
## Resources
|
|
232
210
|
|
|
233
|
-
- [Output SDK Documentation](https://
|
|
211
|
+
- [Output SDK Documentation](https://github.com/growthxai/output-sdk)
|
|
234
212
|
- [Temporal Documentation](https://docs.temporal.io)
|
|
213
|
+
- [AI SDK Documentation](https://sdk.vercel.ai/docs)
|
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { join, dirname } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
const readPackageVersion = async (sdkRoot, packagePath) => {
|
|
5
|
-
const pkg = await (async () => {
|
|
6
|
-
try {
|
|
7
|
-
const content = await readFile(join(sdkRoot, packagePath), 'utf-8');
|
|
8
|
-
return JSON.parse(content);
|
|
9
|
-
}
|
|
10
|
-
catch (error) {
|
|
11
|
-
throw new Error(`Failed to read version from ${packagePath}: ${error}`);
|
|
12
|
-
}
|
|
13
|
-
})();
|
|
14
|
-
if (typeof pkg.version !== 'string') {
|
|
15
|
-
throw new Error(`Version is not a string in ${packagePath}`);
|
|
16
|
-
}
|
|
17
|
-
return pkg.version;
|
|
18
|
-
};
|
|
1
|
+
import sdkVersions from '../generated/sdk_versions.json' with { type: 'json' };
|
|
19
2
|
export async function getSDKVersions() {
|
|
20
|
-
|
|
21
|
-
const [core, llm, http, cli] = await Promise.all([
|
|
22
|
-
readPackageVersion(sdkRoot, 'core/package.json'),
|
|
23
|
-
readPackageVersion(sdkRoot, 'llm/package.json'),
|
|
24
|
-
readPackageVersion(sdkRoot, 'http/package.json'),
|
|
25
|
-
readPackageVersion(sdkRoot, 'cli/package.json')
|
|
26
|
-
]);
|
|
27
|
-
return { core, llm, http, cli };
|
|
3
|
+
return sdkVersions;
|
|
28
4
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import { getSDKVersions } from './sdk_versions.js';
|
|
3
3
|
describe('getSDKVersions', () => {
|
|
4
|
-
it('should
|
|
4
|
+
it('should return all SDK package versions', async () => {
|
|
5
5
|
const versions = await getSDKVersions();
|
|
6
6
|
expect(versions).toHaveProperty('core');
|
|
7
7
|
expect(versions).toHaveProperty('llm');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@output.ai/cli",
|
|
3
|
-
"version": "0.7.8
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "CLI for Output.ai workflow generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"copy-assets": "./bin/copyassets.sh",
|
|
19
19
|
"test": "vitest run",
|
|
20
20
|
"generate:api": "orval --config ./orval.config.ts",
|
|
21
|
-
"
|
|
21
|
+
"update:versions": "node scripts/update_sdk_versions.js",
|
|
22
|
+
"prebuild": "npm run generate:api && npm run update:versions"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
25
|
"@anthropic-ai/claude-agent-sdk": "0.1.71",
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { httpClient, HttpClientOptions } from '@output.ai/http';
|
|
2
|
-
|
|
3
|
-
export interface Pokemon {
|
|
4
|
-
name: string;
|
|
5
|
-
types: string[];
|
|
6
|
-
abilities: string[];
|
|
7
|
-
stats: { name: string; value: number }[];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface PokeApiPokemon {
|
|
11
|
-
name: string;
|
|
12
|
-
types: object[];
|
|
13
|
-
abilities: object[];
|
|
14
|
-
stats: object[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const basePokeApiClient = httpClient( {
|
|
18
|
-
prefixUrl: 'https://pokeapi.co/api/v2'
|
|
19
|
-
} );
|
|
20
|
-
|
|
21
|
-
const pokemonClient = basePokeApiClient.extend( options => ( {
|
|
22
|
-
prefixUrl: `${options.prefixUrl}/pokemon`,
|
|
23
|
-
timeout: 3000
|
|
24
|
-
} ) as HttpClientOptions );
|
|
25
|
-
|
|
26
|
-
export async function getPokemon( name: string ): Promise<Pokemon> {
|
|
27
|
-
const response = await pokemonClient.get<PokeApiPokemon>( name );
|
|
28
|
-
return response.json() as Promise<Pokemon>;
|
|
29
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { evaluator, z, EvaluationNumberResult } from '@output.ai/core';
|
|
2
|
-
import { generateObject } from '@output.ai/llm';
|
|
3
|
-
import type { Pokemon } from '../../shared/clients/pokeapi.js';
|
|
4
|
-
|
|
5
|
-
export const evaluateBattleRealism = evaluator( {
|
|
6
|
-
name: 'evaluate_battle_realism',
|
|
7
|
-
description: 'Evaluate how realistic the Pokemon battle screenplay is',
|
|
8
|
-
inputSchema: z.object( {
|
|
9
|
-
screenplay: z.string(),
|
|
10
|
-
pokemon1: z.object( {
|
|
11
|
-
name: z.string(),
|
|
12
|
-
types: z.array( z.string() ),
|
|
13
|
-
abilities: z.array( z.string() ),
|
|
14
|
-
stats: z.array( z.object( { name: z.string(), value: z.number() } ) )
|
|
15
|
-
} ),
|
|
16
|
-
pokemon2: z.object( {
|
|
17
|
-
name: z.string(),
|
|
18
|
-
types: z.array( z.string() ),
|
|
19
|
-
abilities: z.array( z.string() ),
|
|
20
|
-
stats: z.array( z.object( { name: z.string(), value: z.number() } ) )
|
|
21
|
-
} )
|
|
22
|
-
} ),
|
|
23
|
-
fn: async ( input: { screenplay: string; pokemon1: Pokemon; pokemon2: Pokemon } ) => {
|
|
24
|
-
const { result } = await generateObject( {
|
|
25
|
-
prompt: 'evaluate_realism@v1',
|
|
26
|
-
variables: {
|
|
27
|
-
pokemon1Name: input.pokemon1.name,
|
|
28
|
-
pokemon1Types: input.pokemon1.types.join( '/' ),
|
|
29
|
-
pokemon1Stats: input.pokemon1.stats.map( s => `${s.name}: ${s.value}` ).join( ', ' ),
|
|
30
|
-
pokemon2Name: input.pokemon2.name,
|
|
31
|
-
pokemon2Types: input.pokemon2.types.join( '/' ),
|
|
32
|
-
pokemon2Stats: input.pokemon2.stats.map( s => `${s.name}: ${s.value}` ).join( ', ' ),
|
|
33
|
-
screenplay: input.screenplay
|
|
34
|
-
},
|
|
35
|
-
schema: z.object( {
|
|
36
|
-
score: z.number().min( 0 ).max( 100 ).describe( 'Realism score 0-100' )
|
|
37
|
-
} )
|
|
38
|
-
} );
|
|
39
|
-
return new EvaluationNumberResult( {
|
|
40
|
-
value: result.score,
|
|
41
|
-
confidence: 0.9
|
|
42
|
-
} );
|
|
43
|
-
}
|
|
44
|
-
} );
|
package/dist/templates/project/src/workflows/poke_battle/prompts/evaluate_realism@v1.prompt.template
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
provider: anthropic
|
|
3
|
-
model: claude-haiku-4-5
|
|
4
|
-
temperature: 0.7
|
|
5
|
-
maxTokens: 8192
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Evaluate this Pokemon battle screenplay for realism.
|
|
9
|
-
|
|
10
|
-
Consider:
|
|
11
|
-
- Are the moves/abilities used consistent with each Pokemon's actual abilities?
|
|
12
|
-
- Is the battle outcome realistic given their types and stats?
|
|
13
|
-
- Does the pacing feel like a real battle?
|
|
14
|
-
|
|
15
|
-
\{{ pokemon1Name }}'s Stat Sheet:
|
|
16
|
-
|
|
17
|
-
\{{ pokemon1Description }}
|
|
18
|
-
|
|
19
|
-
\{{ pokemon2Name }}'s Stat Sheet:
|
|
20
|
-
|
|
21
|
-
\{{ pokemon2Description }}
|
|
22
|
-
|
|
23
|
-
Screenplay:
|
|
24
|
-
\{{ screenplay }}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
provider: anthropic
|
|
3
|
-
model: claude-haiku-4-5
|
|
4
|
-
temperature: 0.7
|
|
5
|
-
maxTokens: 8192
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Write a dramatic 5-minute screenplay of a Pokemon battle between \{{ pokemon1Name }} and \{{ pokemon2Name }}.
|
|
9
|
-
|
|
10
|
-
\{{ pokemon1Name }}'s Stat Sheet:
|
|
11
|
-
|
|
12
|
-
\{{ pokemon1Description }}
|
|
13
|
-
|
|
14
|
-
\{{ pokemon2Name }}'s Stat Sheet:
|
|
15
|
-
|
|
16
|
-
\{{ pokemon2Description }}
|
|
17
|
-
|
|
18
|
-
Include dramatic moments, skill usage that matches their actual abilities, and a decisive outcome based on their type matchups. Format it as a proper screenplay with scene descriptions and dialogue.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { step, z } from '@output.ai/core';
|
|
2
|
-
import { generateText } from '@output.ai/llm';
|
|
3
|
-
import type { Pokemon } from '../../shared/clients/pokeapi.js';
|
|
4
|
-
|
|
5
|
-
export const generateScreenplay = step( {
|
|
6
|
-
name: 'generate_screenplay',
|
|
7
|
-
description: 'Generate a dramatic 5-minute Pokemon battle screenplay',
|
|
8
|
-
inputSchema: z.object( {
|
|
9
|
-
pokemon1: z.object( {
|
|
10
|
-
name: z.string(),
|
|
11
|
-
types: z.array( z.object() ),
|
|
12
|
-
abilities: z.array( z.object() ),
|
|
13
|
-
stats: z.array( z.object() )
|
|
14
|
-
} ),
|
|
15
|
-
pokemon2: z.object( {
|
|
16
|
-
name: z.string(),
|
|
17
|
-
types: z.array( z.object() ),
|
|
18
|
-
abilities: z.array( z.object() ),
|
|
19
|
-
stats: z.array( z.object() )
|
|
20
|
-
} )
|
|
21
|
-
} ),
|
|
22
|
-
outputSchema: z.object( {
|
|
23
|
-
screenplay: z.string()
|
|
24
|
-
} ),
|
|
25
|
-
fn: async ( input: { pokemon1: Pokemon; pokemon2: Pokemon } ) => {
|
|
26
|
-
const { result } = await generateText( {
|
|
27
|
-
prompt: 'generate_screenplay@v1',
|
|
28
|
-
variables: {
|
|
29
|
-
pokemon1Name: input.pokemon1.name,
|
|
30
|
-
pokemon2Name: input.pokemon2.name,
|
|
31
|
-
pokemon1Description: JSON.stringify( input.pokemon1 ),
|
|
32
|
-
pokemon2Description: JSON.stringify( input.pokemon2 )
|
|
33
|
-
}
|
|
34
|
-
} );
|
|
35
|
-
return { screenplay: result };
|
|
36
|
-
}
|
|
37
|
-
} );
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { workflow, z } from '@output.ai/core';
|
|
2
|
-
import { lowercase } from '../../shared/utils/string.js';
|
|
3
|
-
import { getPokemon } from '../../shared/clients/pokeapi.js';
|
|
4
|
-
import { generateScreenplay } from './steps.js';
|
|
5
|
-
import { evaluateBattleRealism } from './evaluators.js';
|
|
6
|
-
import { createWorkflowOutput } from './utils.js';
|
|
7
|
-
|
|
8
|
-
export default workflow( {
|
|
9
|
-
name: 'poke_battle',
|
|
10
|
-
description: '{{description}}',
|
|
11
|
-
inputSchema: z.object( {
|
|
12
|
-
pokemon1Name: z.string().describe( 'Name of the first Pokemon' ),
|
|
13
|
-
pokemon2Name: z.string().describe( 'Name of the second Pokemon' )
|
|
14
|
-
} ),
|
|
15
|
-
outputSchema: z.object( {
|
|
16
|
-
screenplay: z.string().describe( 'A 5-minute battle screenplay' ),
|
|
17
|
-
confidenceScore: z.number().describe( 'Realism confidence score 0-100' ),
|
|
18
|
-
summary: z.string().describe( 'Battle summary with confidence' )
|
|
19
|
-
} ),
|
|
20
|
-
fn: async input => {
|
|
21
|
-
// Use shared util to normalize names
|
|
22
|
-
const name1 = lowercase( input.pokemon1Name );
|
|
23
|
-
const name2 = lowercase( input.pokemon2Name );
|
|
24
|
-
|
|
25
|
-
// Use shared client to fetch Pokemon data
|
|
26
|
-
const pokemon1 = await getPokemon( name1 );
|
|
27
|
-
const pokemon2 = await getPokemon( name2 );
|
|
28
|
-
|
|
29
|
-
// Generate the battle screenplay
|
|
30
|
-
const { screenplay } = await generateScreenplay( { pokemon1, pokemon2 } );
|
|
31
|
-
|
|
32
|
-
// Evaluate realism
|
|
33
|
-
const evaluation = await evaluateBattleRealism( {
|
|
34
|
-
screenplay,
|
|
35
|
-
pokemon1,
|
|
36
|
-
pokemon2
|
|
37
|
-
} );
|
|
38
|
-
|
|
39
|
-
// Use local util to format output
|
|
40
|
-
return createWorkflowOutput( screenplay, evaluation.value );
|
|
41
|
-
},
|
|
42
|
-
options: {
|
|
43
|
-
retry: {
|
|
44
|
-
maximumAttempts: 3
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
} );
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { evaluator, z } from '@output.ai/core';
|
|
2
|
-
|
|
3
|
-
// Example evaluator - customize for your workflow
|
|
4
|
-
export const evaluate{{WorkflowName}} = evaluator( {
|
|
5
|
-
name: 'evaluate_{{workflowName}}',
|
|
6
|
-
description: 'Evaluate the quality of {{workflowName}} output',
|
|
7
|
-
inputSchema: z.object( {
|
|
8
|
-
input: z.any(),
|
|
9
|
-
output: z.any()
|
|
10
|
-
} ),
|
|
11
|
-
outputSchema: z.object( {
|
|
12
|
-
score: z.number().min( 0 ).max( 100 ).describe( 'Quality score 0-100' ),
|
|
13
|
-
feedback: z.string().describe( 'Feedback on the output quality' )
|
|
14
|
-
} ),
|
|
15
|
-
fn: async () => {
|
|
16
|
-
// TODO: Implement evaluation logic
|
|
17
|
-
// Use LLM or custom logic to score the output quality
|
|
18
|
-
return {
|
|
19
|
-
score: 100,
|
|
20
|
-
feedback: 'Evaluation not yet implemented'
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
} );
|