@output.ai/cli 0.0.0

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 (37) hide show
  1. package/README.md +55 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +5 -0
  6. package/dist/commands/workflow/generate.d.ts +16 -0
  7. package/dist/commands/workflow/generate.js +74 -0
  8. package/dist/commands/workflow/generate.spec.d.ts +1 -0
  9. package/dist/commands/workflow/generate.spec.js +119 -0
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +1 -0
  12. package/dist/index.spec.d.ts +1 -0
  13. package/dist/index.spec.js +6 -0
  14. package/dist/services/template_processor.d.ts +14 -0
  15. package/dist/services/template_processor.js +42 -0
  16. package/dist/services/workflow_generator.d.ts +5 -0
  17. package/dist/services/workflow_generator.js +40 -0
  18. package/dist/templates/workflow/.env.template +7 -0
  19. package/dist/templates/workflow/README.md.template +215 -0
  20. package/dist/templates/workflow/prompt@v1.prompt.template +13 -0
  21. package/dist/templates/workflow/steps.ts.template +77 -0
  22. package/dist/templates/workflow/workflow.ts.template +73 -0
  23. package/dist/types/errors.d.ts +24 -0
  24. package/dist/types/errors.js +35 -0
  25. package/dist/types/generator.d.ts +26 -0
  26. package/dist/types/generator.js +1 -0
  27. package/dist/utils/paths.d.ts +24 -0
  28. package/dist/utils/paths.js +35 -0
  29. package/dist/utils/template.d.ts +9 -0
  30. package/dist/utils/template.js +30 -0
  31. package/dist/utils/template.spec.d.ts +1 -0
  32. package/dist/utils/template.spec.js +71 -0
  33. package/dist/utils/validation.d.ts +13 -0
  34. package/dist/utils/validation.js +25 -0
  35. package/dist/utils/validation.spec.d.ts +1 -0
  36. package/dist/utils/validation.spec.js +137 -0
  37. package/package.json +60 -0
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # @output.ai/cli
2
+
3
+ CLI tool for generating Output.ai workflows.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Install globally from the CLI package
9
+ cd sdk/cli && npm link
10
+
11
+ # Or run directly from the monorepo
12
+ npx @output.ai/cli
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Generate a Workflow
18
+
19
+ ```bash
20
+ # Generate a complete workflow with example steps
21
+ output-cli workflow generate my-workflow --description "My awesome workflow"
22
+
23
+ # Generate a minimal skeleton workflow
24
+ output-cli workflow generate my-workflow --skeleton
25
+
26
+ # Generate in a specific directory
27
+ output-cli workflow generate my-workflow --output-dir ./src/workflows
28
+
29
+ # Force overwrite existing workflow
30
+ output-cli workflow generate my-workflow --force
31
+ ```
32
+
33
+ #### Command Options
34
+
35
+ - `--description, -d` - Description of the workflow
36
+ - `--skeleton, -s` - Generate minimal skeleton without example steps
37
+ - `--output-dir, -o` - Output directory (default: `output-workflows/src`)
38
+ - `--force, -f` - Overwrite existing directory
39
+
40
+ #### Generated Structure
41
+
42
+ The CLI creates a complete workflow structure:
43
+
44
+ ```
45
+ my-workflow/
46
+ ├── index.ts # Main workflow definition
47
+ ├── steps.ts # Activity/step implementations
48
+ ├── types.ts # TypeScript interfaces
49
+ ├── prompt@v1.prompt # LLM prompt template (if not skeleton)
50
+ └── README.md # Workflow documentation
51
+ ```
52
+
53
+ ## About
54
+
55
+ Built with [OCLIF](https://oclif.io) - see their documentation for advanced CLI features, plugins, and configuration options.
package/bin/dev.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node --loader ts-node/esm --no-warnings=ExperimentalWarning "%~dp0\dev" %*
package/bin/dev.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env -S node --loader ts-node/esm --disable-warning=ExperimentalWarning
2
+
3
+ import { execute } from '@oclif/core';
4
+
5
+ await execute( { development: true, dir: import.meta.url } );
package/bin/run.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\run" %*
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execute } from '@oclif/core';
4
+
5
+ await execute( { dir: import.meta.url } );
@@ -0,0 +1,16 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Generate extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ skeleton: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
7
+ description: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ 'output-dir': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
+ force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
10
+ };
11
+ static args: {
12
+ name: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
13
+ };
14
+ run(): Promise<void>;
15
+ private displaySuccess;
16
+ }
@@ -0,0 +1,74 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { generateWorkflow } from '../../services/workflow_generator.js';
3
+ import { DEFAULT_OUTPUT_DIRS } from '../../utils/paths.js';
4
+ export default class Generate extends Command {
5
+ static description = 'Generate a new Flow SDK workflow';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %> my-workflow',
8
+ '<%= config.bin %> <%= command.id %> my-workflow --skeleton',
9
+ '<%= config.bin %> <%= command.id %> data-processing --description "Process and transform data"'
10
+ ];
11
+ static flags = {
12
+ skeleton: Flags.boolean({
13
+ char: 's',
14
+ description: 'Generate minimal skeleton workflow without example steps',
15
+ default: false
16
+ }),
17
+ description: Flags.string({
18
+ char: 'd',
19
+ description: 'Description of the workflow',
20
+ required: false
21
+ }),
22
+ 'output-dir': Flags.string({
23
+ char: 'o',
24
+ description: 'Output directory for the workflow',
25
+ default: DEFAULT_OUTPUT_DIRS.workflows
26
+ }),
27
+ force: Flags.boolean({
28
+ char: 'f',
29
+ description: 'Overwrite existing directory',
30
+ default: false
31
+ })
32
+ };
33
+ static args = {
34
+ name: Args.string({
35
+ required: true,
36
+ description: 'Name of the workflow to generate'
37
+ })
38
+ };
39
+ async run() {
40
+ const { args, flags } = await this.parse(Generate);
41
+ // Check if skeleton flag is required
42
+ if (!flags.skeleton) {
43
+ this.error('Full workflow generation not implemented yet. Please use --skeleton flag');
44
+ }
45
+ try {
46
+ const result = await generateWorkflow({
47
+ name: args.name,
48
+ description: flags.description,
49
+ outputDir: flags['output-dir'],
50
+ skeleton: flags.skeleton,
51
+ force: flags.force
52
+ });
53
+ this.displaySuccess(result);
54
+ }
55
+ catch (error) {
56
+ if (error instanceof Error) {
57
+ this.error(error.message);
58
+ }
59
+ throw error;
60
+ }
61
+ }
62
+ displaySuccess(result) {
63
+ this.log(`\n[SUCCESS] Workflow "${result.workflowName}" created successfully!`);
64
+ this.log(`\nLocation: ${result.targetDir}`);
65
+ this.log('\n-- Next steps --');
66
+ this.log(` 1. cd ${result.targetDir}`);
67
+ this.log(' 2. Edit the workflow files to customize your implementation');
68
+ this.log(' 3. If using @output.ai/llm, configure your .env file with LLM provider credentials:');
69
+ this.log(' - ANTHROPIC_API_KEY for Claude');
70
+ this.log(' - OPENAI_API_KEY for OpenAI');
71
+ this.log(' 4. Build and run with the worker');
72
+ this.log('\nCheck the README.md for workflow-specific documentation.');
73
+ }
74
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,119 @@
1
+ /* eslint-disable no-restricted-syntax, @typescript-eslint/no-explicit-any, init-declarations */
2
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
3
+ import Generate from './generate.js';
4
+ import { generateWorkflow } from '../../services/workflow_generator.js';
5
+ import { InvalidNameError, WorkflowExistsError } from '../../types/errors.js';
6
+ // Mock the generateWorkflow function
7
+ vi.mock('../../services/workflow_generator.js');
8
+ describe('Generate Command', () => {
9
+ let mockGenerateWorkflow;
10
+ let logSpy;
11
+ const createCommand = () => {
12
+ const cmd = new Generate([], {});
13
+ // Mock OCLIF methods
14
+ cmd.log = vi.fn();
15
+ cmd.error = vi.fn((message) => {
16
+ throw new Error(message);
17
+ });
18
+ // Mock parse method
19
+ cmd.parse = vi.fn();
20
+ logSpy = cmd.log;
21
+ return cmd;
22
+ };
23
+ beforeEach(() => {
24
+ vi.clearAllMocks();
25
+ // Mock generateWorkflow function
26
+ mockGenerateWorkflow = vi.mocked(generateWorkflow);
27
+ });
28
+ describe('successful workflow generation', () => {
29
+ it('should generate workflow with skeleton flag', async () => {
30
+ const cmd = createCommand();
31
+ // Mock parse return
32
+ cmd.parse.mockResolvedValue({
33
+ args: { name: 'test-workflow' },
34
+ flags: {
35
+ skeleton: true,
36
+ description: 'Test description',
37
+ 'output-dir': '/tmp',
38
+ force: false
39
+ }
40
+ });
41
+ // Mock successful generation
42
+ mockGenerateWorkflow.mockResolvedValue({
43
+ workflowName: 'test-workflow',
44
+ targetDir: '/tmp/test-workflow',
45
+ filesCreated: ['index.ts', 'steps.ts', 'types.ts']
46
+ });
47
+ await cmd.run();
48
+ expect(mockGenerateWorkflow).toHaveBeenCalledWith({
49
+ name: 'test-workflow',
50
+ description: 'Test description',
51
+ outputDir: '/tmp',
52
+ skeleton: true,
53
+ force: false
54
+ });
55
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('[SUCCESS] Workflow "test-workflow" created successfully!'));
56
+ });
57
+ it('should require skeleton flag and reject without it', async () => {
58
+ const cmd = createCommand();
59
+ cmd.parse.mockResolvedValue({
60
+ args: { name: 'test-workflow' },
61
+ flags: {
62
+ skeleton: false,
63
+ 'output-dir': '/tmp',
64
+ force: false
65
+ }
66
+ });
67
+ await expect(cmd.run()).rejects.toThrow('Full workflow generation not implemented yet. Please use --skeleton flag');
68
+ expect(mockGenerateWorkflow).not.toHaveBeenCalled();
69
+ });
70
+ });
71
+ describe('error handling', () => {
72
+ it('should handle invalid name error', async () => {
73
+ const cmd = createCommand();
74
+ cmd.parse.mockResolvedValue({
75
+ args: { name: 'invalid name' },
76
+ flags: { 'output-dir': '/tmp', skeleton: true, force: false }
77
+ });
78
+ mockGenerateWorkflow.mockRejectedValue(new InvalidNameError('invalid name'));
79
+ await expect(cmd.run()).rejects.toThrow(/Invalid workflow name/i);
80
+ });
81
+ it('should handle workflow exists error', async () => {
82
+ const cmd = createCommand();
83
+ cmd.parse.mockResolvedValue({
84
+ args: { name: 'existing-workflow' },
85
+ flags: { 'output-dir': '/tmp', skeleton: true, force: false }
86
+ });
87
+ mockGenerateWorkflow.mockRejectedValue(new WorkflowExistsError('existing-workflow', '/tmp/existing-workflow'));
88
+ await expect(cmd.run()).rejects.toThrow(/already exists/i);
89
+ });
90
+ it('should re-throw non-CLI errors', async () => {
91
+ const cmd = createCommand();
92
+ cmd.parse.mockResolvedValue({
93
+ args: { name: 'test-workflow' },
94
+ flags: { 'output-dir': '/tmp', skeleton: true, force: false }
95
+ });
96
+ const systemError = new Error('System error');
97
+ mockGenerateWorkflow.mockRejectedValue(systemError);
98
+ await expect(cmd.run()).rejects.toThrow(systemError);
99
+ });
100
+ });
101
+ describe('success display', () => {
102
+ it('should display correct success message and next steps', async () => {
103
+ const cmd = createCommand();
104
+ cmd.parse.mockResolvedValue({
105
+ args: { name: 'my-workflow' },
106
+ flags: { 'output-dir': '/custom/path', skeleton: true, force: false }
107
+ });
108
+ mockGenerateWorkflow.mockResolvedValue({
109
+ workflowName: 'my-workflow',
110
+ targetDir: '/custom/path/my-workflow',
111
+ filesCreated: ['index.ts', 'steps.ts', 'types.ts']
112
+ });
113
+ await cmd.run();
114
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('[SUCCESS] Workflow "my-workflow" created successfully!'));
115
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Location: /custom/path/my-workflow'));
116
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('-- Next steps --'));
117
+ });
118
+ });
119
+ });
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ describe('CLI', () => {
3
+ it('should be initialized', () => {
4
+ expect(true).toBe(true);
5
+ });
6
+ });
@@ -0,0 +1,14 @@
1
+ import type { TemplateFile } from '../types/generator.js';
2
+ /**
3
+ * Get list of template files from a directory
4
+ * Automatically discovers all .template files and derives output names
5
+ */
6
+ export declare function getTemplateFiles(templatesDir: string): Promise<TemplateFile[]>;
7
+ /**
8
+ * Process a single template file
9
+ */
10
+ export declare function processTemplateFile(templateFile: TemplateFile, targetDir: string, variables: Record<string, string>): Promise<void>;
11
+ /**
12
+ * Process all template files
13
+ */
14
+ export declare function processAllTemplates(templateFiles: TemplateFile[], targetDir: string, variables: Record<string, string>): Promise<string[]>;
@@ -0,0 +1,42 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { processTemplate } from '../utils/template.js';
4
+ const TEMPLATE_EXTENSION = '.template';
5
+ function isTemplateFile(file) {
6
+ return file.endsWith(TEMPLATE_EXTENSION);
7
+ }
8
+ function fileToTemplateFile(file, templatesDir) {
9
+ return {
10
+ name: file,
11
+ path: path.join(templatesDir, file),
12
+ outputName: file.replace(TEMPLATE_EXTENSION, '')
13
+ };
14
+ }
15
+ /**
16
+ * Get list of template files from a directory
17
+ * Automatically discovers all .template files and derives output names
18
+ */
19
+ export async function getTemplateFiles(templatesDir) {
20
+ const files = await fs.readdir(templatesDir);
21
+ return files
22
+ .filter(isTemplateFile)
23
+ .map(file => fileToTemplateFile(file, templatesDir));
24
+ }
25
+ /**
26
+ * Process a single template file
27
+ */
28
+ export async function processTemplateFile(templateFile, targetDir, variables) {
29
+ const templateContent = await fs.readFile(templateFile.path, 'utf-8');
30
+ const processedContent = processTemplate(templateContent, variables);
31
+ const outputPath = path.join(targetDir, templateFile.outputName);
32
+ await fs.writeFile(outputPath, processedContent, 'utf-8');
33
+ }
34
+ /**
35
+ * Process all template files
36
+ */
37
+ export async function processAllTemplates(templateFiles, targetDir, variables) {
38
+ return Promise.all(templateFiles.map(async (templateFile) => {
39
+ await processTemplateFile(templateFile, targetDir, variables);
40
+ return templateFile.outputName;
41
+ }));
42
+ }
@@ -0,0 +1,5 @@
1
+ import type { WorkflowGenerationConfig, WorkflowGenerationResult } from '../types/generator.js';
2
+ /**
3
+ * Generate a new workflow
4
+ */
5
+ export declare function generateWorkflow(config: WorkflowGenerationConfig): Promise<WorkflowGenerationResult>;
@@ -0,0 +1,40 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import { WorkflowExistsError } from '../types/errors.js';
3
+ import { createTargetDir, getTemplateDir } from '../utils/paths.js';
4
+ import { validateWorkflowName, validateOutputDirectory } from '../utils/validation.js';
5
+ import { prepareTemplateVariables } from '../utils/template.js';
6
+ import { getTemplateFiles, processAllTemplates } from './template_processor.js';
7
+ /**
8
+ * Validate the generation configuration
9
+ */
10
+ function validateConfig(config) {
11
+ validateWorkflowName(config.name);
12
+ validateOutputDirectory(config.outputDir);
13
+ }
14
+ /**
15
+ * Check if target directory exists and handle accordingly
16
+ */
17
+ import * as fsSync from 'node:fs';
18
+ async function checkTargetDirectory(targetDir, force) {
19
+ if (fsSync.existsSync(targetDir) && !force) {
20
+ throw new WorkflowExistsError('', targetDir);
21
+ }
22
+ }
23
+ /**
24
+ * Generate a new workflow
25
+ */
26
+ export async function generateWorkflow(config) {
27
+ validateConfig(config);
28
+ const targetDir = createTargetDir(config.outputDir, config.name);
29
+ const templatesDir = getTemplateDir('workflow');
30
+ await checkTargetDirectory(targetDir, config.force);
31
+ await fs.mkdir(targetDir, { recursive: true });
32
+ const variables = prepareTemplateVariables(config.name, config.description || '');
33
+ const templateFiles = await getTemplateFiles(templatesDir);
34
+ const filesCreated = await processAllTemplates(templateFiles, targetDir, variables);
35
+ return {
36
+ workflowName: config.name,
37
+ targetDir,
38
+ filesCreated
39
+ };
40
+ }
@@ -0,0 +1,7 @@
1
+ # API Keys for LLM providers
2
+ OPENAI_API_KEY=your_openai_api_key_here
3
+ ANTHROPIC_API_KEY=your_anthropic_api_key_here
4
+
5
+ # Optional: Additional configuration
6
+ # NODE_ENV=development
7
+ # LOG_LEVEL=info
@@ -0,0 +1,215 @@
1
+ # {{WorkflowName}} Workflow
2
+
3
+ {{description}}
4
+
5
+ ## Overview
6
+
7
+ This workflow was generated using the Flow SDK CLI. It provides a starting point for building Temporal-based workflows with LLM integration.
8
+
9
+ ## Files
10
+
11
+ - `workflow.ts` - Main workflow definition with input/output schemas
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
15
+
16
+ ## Setup
17
+
18
+ ### Environment Variables
19
+
20
+ Before running the workflow, configure your API keys in the `.env` file:
21
+
22
+ ```bash
23
+ # Required for LLM functionality
24
+ OPENAI_API_KEY=your_openai_api_key_here
25
+ ANTHROPIC_API_KEY=your_anthropic_api_key_here
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Workflow Input
31
+
32
+ The workflow expects input matching the input schema defined in `workflow.ts`.
33
+
34
+ Example:
35
+ ```typescript
36
+ {
37
+ prompt: "Tell me about workflows",
38
+ data: {
39
+ value: 42,
40
+ type: "example"
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### Workflow Output
46
+
47
+ The workflow returns output matching the output schema defined in `workflow.ts`.
48
+
49
+ Example:
50
+ ```typescript
51
+ {
52
+ llmResponse: "Generated text from LLM",
53
+ processedData: {
54
+ processed: true,
55
+ timestamp: "2024-01-01T00:00:00Z",
56
+ data: { value: 42, type: "example" }
57
+ },
58
+ message: "Workflow completed successfully"
59
+ }
60
+ ```
61
+
62
+ ## Development
63
+
64
+ ### Workflow Structure
65
+
66
+ The workflow follows the new Flow SDK conventions:
67
+
68
+ ```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
+ };
85
+
86
+ export default workflow( {
87
+ name: 'workflowName',
88
+ description: 'Workflow description',
89
+ inputSchema,
90
+ outputSchema,
91
+ fn: async ( input ) => {
92
+ // Call steps directly
93
+ const result = await myStep( input );
94
+ return result;
95
+ }
96
+ } );
97
+ ```
98
+
99
+ ### Adding New Steps
100
+
101
+ 1. Define new steps in `steps.ts` with schemas:
102
+
103
+ ```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
+ };
120
+
121
+ export const myStep = step( {
122
+ name: 'myStep',
123
+ description: 'Description of what this step does',
124
+ inputSchema,
125
+ outputSchema,
126
+ fn: async ( input: { value: number } ) => {
127
+ // Step implementation
128
+ return { result: `Processed ${input.value}` };
129
+ }
130
+ } );
131
+ ```
132
+
133
+ 2. Import and use the step in your workflow (`workflow.ts`):
134
+
135
+ ```typescript
136
+ import { myStep } from './steps.js';
137
+
138
+ // Inside workflow fn:
139
+ const result = await myStep( { value: 42 } );
140
+ ```
141
+
142
+ ### Using LLM in Steps
143
+
144
+ The template includes an example of using LLM with prompts:
145
+
146
+ ```typescript
147
+ import { loadPrompt } from '@output.ai/prompt';
148
+ import { generateText } from '@output.ai/llm';
149
+ import type { Prompt } from '@output.ai/llm';
150
+
151
+ export const llmStep = step( {
152
+ name: 'llmStep',
153
+ description: 'Generate text using LLM',
154
+ inputSchema: {
155
+ type: 'object',
156
+ properties: {
157
+ userInput: { type: 'string' }
158
+ }
159
+ },
160
+ outputSchema: { type: 'string' },
161
+ fn: async ( input: { userInput: string } ) => {
162
+ const prompt = loadPrompt( 'prompt@v1', {
163
+ userInput: input.userInput
164
+ } );
165
+ const response = await generateText( prompt as Prompt );
166
+ return response;
167
+ }
168
+ } );
169
+ ```
170
+
171
+ ### Creating Prompt Templates
172
+
173
+ Create new prompt files following the pattern:
174
+ - File naming: `promptName@v1.prompt`
175
+ - Include YAML frontmatter with provider and model
176
+ - Use LiquidJS syntax for variables: `{{ variableName }}`
177
+
178
+ Example prompt file:
179
+ ```
180
+ ---
181
+ provider: anthropic
182
+ model: claude-3-5-sonnet-latest
183
+ ---
184
+
185
+ {{ userInput }}
186
+
187
+ Please provide a helpful response.
188
+ ```
189
+
190
+ ## Testing
191
+
192
+ To test your workflow:
193
+
194
+ 1. Build the parent project containing this workflow
195
+ 2. Start the Flow worker
196
+ 3. Execute the workflow using the Flow SDK API
197
+
198
+ Example execution:
199
+ ```bash
200
+ curl -X POST http://localhost:3001/workflow \
201
+ -H "Content-Type: application/json" \
202
+ -d '{
203
+ "workflowName": "{{workflowName}}",
204
+ "input": {
205
+ "prompt": "Tell me about workflows",
206
+ "data": { "value": 42, "type": "example" }
207
+ }
208
+ }'
209
+ ```
210
+
211
+ ## Resources
212
+
213
+ - [Flow SDK Documentation](https://github.com/growthxai/flow-sdk)
214
+ - [Temporal Documentation](https://docs.temporal.io)
215
+ - [AI SDK Documentation](https://sdk.vercel.ai/docs)
@@ -0,0 +1,13 @@
1
+ ---
2
+ provider: anthropic
3
+ model: claude-sonnet-4-20250514
4
+ temperature: 0.7
5
+ ---
6
+
7
+ <assistant>
8
+ You are a helpful assistant for the {{workflowName}} workflow.
9
+ </assistant>
10
+
11
+ <user>
12
+ {{ userInput }}
13
+ </user>