@output.ai/cli 0.7.9 → 0.7.11-dev.pr263-8f8e94a

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.
Files changed (20) hide show
  1. package/dist/generated/sdk_versions.json +2 -2
  2. package/dist/services/messages.js +1 -1
  3. package/dist/templates/agent_instructions/dotoutputai/AGENTS.md.template +1 -1
  4. package/dist/templates/project/README.md.template +38 -1
  5. package/dist/templates/project/src/shared/clients/pokeapi.ts.template +43 -0
  6. package/dist/templates/project/src/shared/utils/string.ts.template +3 -0
  7. package/dist/templates/project/src/workflows/poke_battle/evaluators.ts.template +47 -0
  8. package/dist/templates/project/src/workflows/poke_battle/prompts/evaluate_realism@v1.prompt.template +26 -0
  9. package/dist/templates/project/src/workflows/poke_battle/prompts/generate_screenplay@v1.prompt.template +20 -0
  10. package/dist/templates/project/src/workflows/poke_battle/scenarios/pikachu_vs_charmander.json.template +4 -0
  11. package/dist/templates/project/src/workflows/poke_battle/steps.ts.template +58 -0
  12. package/dist/templates/project/src/workflows/poke_battle/utils.ts.template +7 -0
  13. package/dist/templates/project/src/workflows/poke_battle/workflow.ts.template +45 -0
  14. package/dist/templates/workflow/README.md.template +96 -75
  15. package/dist/templates/workflow/evaluators.ts.template +23 -0
  16. package/package.json +1 -1
  17. package/dist/templates/project/src/workflows/example_question/prompts/answer_question@v1.prompt.template +0 -13
  18. package/dist/templates/project/src/workflows/example_question/scenarios/question_ada_lovelace.json.template +0 -3
  19. package/dist/templates/project/src/workflows/example_question/steps.ts.template +0 -16
  20. package/dist/templates/project/src/workflows/example_question/workflow.ts.template +0 -22
@@ -1,6 +1,6 @@
1
1
  {
2
- "core": "0.2.2",
2
+ "core": "0.3.0",
3
3
  "llm": "0.2.8",
4
4
  "http": "0.1.1",
5
- "cli": "0.7.9"
5
+ "cli": "0.7.11"
6
6
  }
@@ -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 example_question --input src/workflows/example_question/scenarios/question_ada_lovelace.json',
180
+ command: 'npx output workflow run poke_battle --input src/workflows/poke_battle/scenarios/pikachu_vs_charmander.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, shared_steps.ts, types.ts, consts.ts, utils.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
 
@@ -7,6 +7,43 @@
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
+
10
47
  ## Getting Started
11
48
 
12
49
  ### 1. Install Dependencies
@@ -44,7 +81,7 @@ This starts:
44
81
  In a new terminal:
45
82
 
46
83
  ```bash
47
- npx output workflow run example_question --input '{"question": "who really is ada lovelace?"}'
84
+ npx output workflow run poke_battle --input src/workflows/poke_battle/scenarios/pikachu_vs_charmander.json
48
85
  ```
49
86
 
50
87
  ### 5. Stop Services
@@ -0,0 +1,43 @@
1
+ import { httpClient, HttpClientOptions } from '@output.ai/http';
2
+
3
+ export interface Pokemon {
4
+ name: string;
5
+ types: Array<{ type: { name: string } }>;
6
+ abilities: Array<{ ability: { name: string }; is_hidden: boolean }>;
7
+ stats: Array<{ stat: { name: string }; base_stat: number }>;
8
+ }
9
+
10
+ const basePokeApiClient = httpClient( {
11
+ prefixUrl: 'https://pokeapi.co/api/v2'
12
+ } );
13
+
14
+ const pokemonClient = basePokeApiClient.extend( options => ( {
15
+ prefixUrl: `${options.prefixUrl}/pokemon`,
16
+ timeout: 10000
17
+ } ) as HttpClientOptions );
18
+
19
+ /**
20
+ * Fetch Pokemon data from PokeAPI, extracting only the relevant fields.
21
+ * The full API response is huge (sprites, all moves, etc.), so we filter
22
+ * to just what's needed for the battle screenplay.
23
+ */
24
+ export async function getPokemon( name: string ): Promise<Pokemon> {
25
+ const response = await pokemonClient.get( name );
26
+ const data = await response.json() as Record<string, unknown>;
27
+
28
+ // Extract only the fields we need to avoid sending huge payloads to LLM
29
+ return {
30
+ name: data.name as string,
31
+ types: ( data.types as Array<{ type: { name: string } }> ).map( t => ( {
32
+ type: { name: t.type.name }
33
+ } ) ),
34
+ abilities: ( data.abilities as Array<{ ability: { name: string }; is_hidden: boolean }> ).map( a => ( {
35
+ ability: { name: a.ability.name },
36
+ is_hidden: a.is_hidden
37
+ } ) ),
38
+ stats: ( data.stats as Array<{ stat: { name: string }; base_stat: number }> ).map( s => ( {
39
+ stat: { name: s.stat.name },
40
+ base_stat: s.base_stat
41
+ } ) )
42
+ };
43
+ }
@@ -0,0 +1,3 @@
1
+ export function lowercase( str: string ): string {
2
+ return str.toLowerCase();
3
+ }
@@ -0,0 +1,47 @@
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
+ const pokemonSchema = z.object( {
6
+ name: z.string(),
7
+ types: z.array( z.object( {
8
+ type: z.object( { name: z.string() } )
9
+ } ) ),
10
+ abilities: z.array( z.object( {
11
+ ability: z.object( { name: z.string() } ),
12
+ is_hidden: z.boolean()
13
+ } ) ),
14
+ stats: z.array( z.object( {
15
+ stat: z.object( { name: z.string() } ),
16
+ base_stat: z.number()
17
+ } ) )
18
+ } );
19
+
20
+ export const evaluateBattleRealism = evaluator( {
21
+ name: 'evaluate_battle_realism',
22
+ description: 'Evaluate how realistic the Pokemon battle screenplay is',
23
+ inputSchema: z.object( {
24
+ screenplay: z.string(),
25
+ pokemon1: pokemonSchema,
26
+ pokemon2: pokemonSchema
27
+ } ),
28
+ fn: async ( input: { screenplay: string; pokemon1: Pokemon; pokemon2: Pokemon } ) => {
29
+ const { result } = await generateObject( {
30
+ prompt: 'evaluate_realism@v1',
31
+ variables: {
32
+ pokemon1Name: input.pokemon1.name,
33
+ pokemon1Description: JSON.stringify( input.pokemon1 ),
34
+ pokemon2Name: input.pokemon2.name,
35
+ pokemon2Description: JSON.stringify( input.pokemon2 ),
36
+ screenplay: input.screenplay
37
+ },
38
+ schema: z.object( {
39
+ score: z.number().min( 0 ).max( 100 ).describe( 'Realism score 0-100' )
40
+ } )
41
+ } );
42
+ return new EvaluationNumberResult( {
43
+ value: result.score,
44
+ confidence: 0.9
45
+ } );
46
+ }
47
+ } );
@@ -0,0 +1,26 @@
1
+ ---
2
+ provider: anthropic
3
+ model: claude-haiku-4-5
4
+ temperature: 0.7
5
+ maxTokens: 8192
6
+ ---
7
+
8
+ <user>
9
+ Evaluate this Pokemon battle screenplay for realism.
10
+
11
+ Consider:
12
+ - Are the moves/abilities used consistent with each Pokemon's actual abilities?
13
+ - Is the battle outcome realistic given their types and stats?
14
+ - Does the pacing feel like a real battle?
15
+
16
+ \{{ pokemon1Name }}'s Stat Sheet:
17
+
18
+ \{{ pokemon1Description }}
19
+
20
+ \{{ pokemon2Name }}'s Stat Sheet:
21
+
22
+ \{{ pokemon2Description }}
23
+
24
+ Screenplay:
25
+ \{{ screenplay }}
26
+ </user>
@@ -0,0 +1,20 @@
1
+ ---
2
+ provider: anthropic
3
+ model: claude-haiku-4-5
4
+ temperature: 0.7
5
+ maxTokens: 8192
6
+ ---
7
+
8
+ <user>
9
+ Write a dramatic 5-minute screenplay of a Pokemon battle between \{{ pokemon1Name }} and \{{ pokemon2Name }}.
10
+
11
+ \{{ pokemon1Name }}'s Stat Sheet:
12
+
13
+ \{{ pokemon1Description }}
14
+
15
+ \{{ pokemon2Name }}'s Stat Sheet:
16
+
17
+ \{{ pokemon2Description }}
18
+
19
+ 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.
20
+ </user>
@@ -0,0 +1,4 @@
1
+ {
2
+ "pokemon1Name": "pikachu",
3
+ "pokemon2Name": "charmander"
4
+ }
@@ -0,0 +1,58 @@
1
+ import { step, z } from '@output.ai/core';
2
+ import { generateText } from '@output.ai/llm';
3
+ import { getPokemon, type Pokemon } from '../../shared/clients/pokeapi.js';
4
+
5
+ const pokemonSchema = z.object( {
6
+ name: z.string(),
7
+ types: z.array( z.object( {
8
+ type: z.object( { name: z.string() } )
9
+ } ) ),
10
+ abilities: z.array( z.object( {
11
+ ability: z.object( { name: z.string() } ),
12
+ is_hidden: z.boolean()
13
+ } ) ),
14
+ stats: z.array( z.object( {
15
+ stat: z.object( { name: z.string() } ),
16
+ base_stat: z.number()
17
+ } ) )
18
+ } );
19
+
20
+ /**
21
+ * Step to fetch Pokemon data and generate a battle screenplay.
22
+ * HTTP clients must be used inside steps (activities), not directly in workflows,
23
+ * because workflows run in a sandboxed environment without Node.js APIs.
24
+ */
25
+ export const generateScreenplay = step( {
26
+ name: 'generate_screenplay',
27
+ description: 'Fetch Pokemon data and generate a dramatic 5-minute battle screenplay',
28
+ inputSchema: z.object( {
29
+ pokemon1Name: z.string().describe( 'Name of the first Pokemon' ),
30
+ pokemon2Name: z.string().describe( 'Name of the second Pokemon' )
31
+ } ),
32
+ outputSchema: z.object( {
33
+ screenplay: z.string(),
34
+ pokemon1: pokemonSchema,
35
+ pokemon2: pokemonSchema
36
+ } ),
37
+ fn: async ( input: { pokemon1Name: string; pokemon2Name: string } ) => {
38
+ // Fetch Pokemon data inside the step (activities can use HTTP clients)
39
+ const pokemon1 = await getPokemon( input.pokemon1Name );
40
+ const pokemon2 = await getPokemon( input.pokemon2Name );
41
+
42
+ const { result } = await generateText( {
43
+ prompt: 'generate_screenplay@v1',
44
+ variables: {
45
+ pokemon1Name: pokemon1.name,
46
+ pokemon2Name: pokemon2.name,
47
+ pokemon1Description: JSON.stringify( pokemon1 ),
48
+ pokemon2Description: JSON.stringify( pokemon2 )
49
+ }
50
+ } );
51
+
52
+ return {
53
+ screenplay: result,
54
+ pokemon1: pokemon1 as Pokemon,
55
+ pokemon2: pokemon2 as Pokemon
56
+ };
57
+ }
58
+ } );
@@ -0,0 +1,7 @@
1
+ export function createWorkflowOutput( screenplay: string, confidenceScore: number ) {
2
+ return {
3
+ screenplay,
4
+ confidenceScore,
5
+ summary: `Battle screenplay (${confidenceScore}% confidence)`
6
+ };
7
+ }
@@ -0,0 +1,45 @@
1
+ import { workflow, z } from '@output.ai/core';
2
+ import { lowercase } from '../../shared/utils/string.js';
3
+ import { generateScreenplay } from './steps.js';
4
+ import { evaluateBattleRealism } from './evaluators.js';
5
+ import { createWorkflowOutput } from './utils.js';
6
+
7
+ export default workflow( {
8
+ name: 'poke_battle',
9
+ description: '{{description}}',
10
+ inputSchema: z.object( {
11
+ pokemon1Name: z.string().describe( 'Name of the first Pokemon' ),
12
+ pokemon2Name: z.string().describe( 'Name of the second Pokemon' )
13
+ } ),
14
+ outputSchema: z.object( {
15
+ screenplay: z.string().describe( 'A 5-minute battle screenplay' ),
16
+ confidenceScore: z.number().describe( 'Realism confidence score 0-100' ),
17
+ summary: z.string().describe( 'Battle summary with confidence' )
18
+ } ),
19
+ fn: async input => {
20
+ // Use shared util to normalize names
21
+ const name1 = lowercase( input.pokemon1Name );
22
+ const name2 = lowercase( input.pokemon2Name );
23
+
24
+ // Generate the battle screenplay (fetches Pokemon data inside the step)
25
+ const { screenplay, pokemon1, pokemon2 } = await generateScreenplay( {
26
+ pokemon1Name: name1,
27
+ pokemon2Name: name2
28
+ } );
29
+
30
+ // Evaluate realism
31
+ const evaluation = await evaluateBattleRealism( {
32
+ screenplay,
33
+ pokemon1,
34
+ pokemon2
35
+ } );
36
+
37
+ // Use local util to format output
38
+ return createWorkflowOutput( screenplay, evaluation.value );
39
+ },
40
+ options: {
41
+ retry: {
42
+ maximumAttempts: 3
43
+ }
44
+ }
45
+ } );
@@ -10,8 +10,50 @@ 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
- - `prompt@v1.prompt` - Example LLM prompt template
14
- - `.env` - Environment variables for API keys and configuration
13
+ - `evaluators.ts` - Quality evaluators for workflow outputs
14
+ - `prompts/` - LLM prompt templates
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)
15
57
 
16
58
  ## Setup
17
59
 
@@ -63,121 +105,109 @@ Example:
63
105
 
64
106
  ### Workflow Structure
65
107
 
66
- The workflow follows the new Output SDK conventions:
108
+ The workflow follows the Output SDK conventions:
67
109
 
68
110
  ```typescript
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
- };
111
+ import { workflow, z } from '@output.ai/core';
112
+ import { myStep } from './steps.js';
113
+ import { evaluateQuality } from './evaluators.js';
85
114
 
86
115
  export default workflow( {
87
116
  name: 'workflowName',
88
117
  description: 'Workflow description',
89
- inputSchema,
90
- outputSchema,
118
+ inputSchema: z.object( { /* ... */ } ),
119
+ outputSchema: z.object( { /* ... */ } ),
91
120
  fn: async ( input ) => {
92
- // Call steps directly
93
121
  const result = await myStep( input );
94
- return result;
122
+ const { score } = await evaluateQuality( { input, output: result } );
123
+ return { result, qualityScore: score };
95
124
  }
96
125
  } );
97
126
  ```
98
127
 
99
128
  ### Adding New Steps
100
129
 
101
- 1. Define new steps in `steps.ts` with schemas:
130
+ Define steps in `steps.ts` with schemas:
102
131
 
103
132
  ```typescript
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
- };
133
+ import { step, z } from '@output.ai/core';
120
134
 
121
135
  export const myStep = step( {
122
136
  name: 'myStep',
123
137
  description: 'Description of what this step does',
124
- inputSchema,
125
- outputSchema,
126
- fn: async ( input: { value: number } ) => {
127
- // Step implementation
138
+ inputSchema: z.object( {
139
+ value: z.number()
140
+ } ),
141
+ outputSchema: z.object( {
142
+ result: z.string()
143
+ } ),
144
+ fn: async ( input ) => {
128
145
  return { result: `Processed ${input.value}` };
129
146
  }
130
147
  } );
131
148
  ```
132
149
 
133
- 2. Import and use the step in your workflow (`workflow.ts`):
150
+ ### Adding Evaluators
151
+
152
+ Define evaluators in `evaluators.ts`:
134
153
 
135
154
  ```typescript
136
- import { myStep } from './steps.js';
155
+ import { evaluator, z } from '@output.ai/core';
156
+ import { generateText } from '@output.ai/llm';
137
157
 
138
- // Inside workflow fn:
139
- const result = await myStep( { value: 42 } );
158
+ export const evaluateQuality = evaluator( {
159
+ name: 'evaluate_quality',
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
+ } );
140
176
  ```
141
177
 
142
178
  ### Using LLM in Steps
143
179
 
144
- The template includes an example of using LLM with prompts:
145
-
146
180
  ```typescript
147
181
  import { generateText } from '@output.ai/llm';
148
182
 
149
183
  export const llmStep = step( {
150
184
  name: 'llmStep',
151
185
  description: 'Generate text using LLM',
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( {
186
+ inputSchema: z.object( {
187
+ userInput: z.string()
188
+ } ),
189
+ outputSchema: z.string(),
190
+ fn: async ( input ) => {
191
+ const { result } = await generateText( {
161
192
  prompt: 'prompt@v1',
162
193
  variables: { userInput: input.userInput }
163
194
  } );
164
- return response;
195
+ return result;
165
196
  }
166
197
  } );
167
198
  ```
168
199
 
169
200
  ### Creating Prompt Templates
170
201
 
171
- Create new prompt files following the pattern:
202
+ Create prompt files in `prompts/` following the pattern:
172
203
  - File naming: `promptName@v1.prompt`
173
- - Include YAML frontmatter with provider and model
204
+ - Include YAML frontmatter with model
174
205
  - Use LiquidJS syntax for variables: `{{ variableName }}`
175
206
 
176
207
  Example prompt file:
177
208
  ```
178
209
  ---
179
- provider: anthropic
180
- model: claude-3-5-sonnet-latest
210
+ model: anthropic/claude-sonnet-4-20250514
181
211
  ---
182
212
 
183
213
  {{ userInput }}
@@ -195,19 +225,10 @@ To test your workflow:
195
225
 
196
226
  Example execution:
197
227
  ```bash
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
- }'
228
+ npx output workflow run {{workflowName}} --input '{"prompt": "Hello"}'
207
229
  ```
208
230
 
209
231
  ## Resources
210
232
 
211
- - [Output SDK Documentation](https://github.com/growthxai/output-sdk)
233
+ - [Output SDK Documentation](https://docs.output.ai)
212
234
  - [Temporal Documentation](https://docs.temporal.io)
213
- - [AI SDK Documentation](https://sdk.vercel.ai/docs)
@@ -0,0 +1,23 @@
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
+ } );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@output.ai/cli",
3
- "version": "0.7.9",
3
+ "version": "0.7.11-dev.pr263-8f8e94a",
4
4
  "description": "CLI for Output.ai workflow generation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,13 +0,0 @@
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>
@@ -1,3 +0,0 @@
1
- {
2
- "question": "who really is ada lovelace?"
3
- }
@@ -1,16 +0,0 @@
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
- } );
@@ -1,22 +0,0 @@
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
- } );