@output.ai/cli 0.3.1-dev.pr156.0 → 0.4.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.
- package/README.md +2 -28
- package/dist/api/generated/api.d.ts +35 -59
- package/dist/api/generated/api.js +4 -13
- package/dist/assets/docker/docker-compose-dev.yml +2 -2
- package/dist/commands/workflow/debug.d.ts +2 -8
- package/dist/commands/workflow/debug.js +24 -164
- package/dist/commands/workflow/debug.spec.js +36 -0
- package/dist/commands/workflow/generate.js +3 -10
- package/dist/commands/workflow/generate.spec.js +6 -4
- package/dist/commands/workflow/{output.d.ts → result.d.ts} +1 -1
- package/dist/commands/workflow/{output.js → result.js} +8 -8
- package/dist/commands/workflow/result.test.js +23 -0
- package/dist/commands/workflow/start.js +1 -1
- package/dist/services/coding_agents.js +30 -0
- package/dist/services/coding_agents.spec.js +36 -61
- package/dist/services/messages.d.ts +1 -0
- package/dist/services/messages.js +65 -1
- package/dist/services/trace_reader.d.ts +14 -0
- package/dist/services/trace_reader.js +67 -0
- package/dist/services/trace_reader.spec.d.ts +1 -0
- package/dist/services/trace_reader.spec.js +164 -0
- package/dist/services/workflow_generator.spec.d.ts +1 -0
- package/dist/services/workflow_generator.spec.js +77 -0
- package/dist/templates/agent_instructions/AGENTS.md.template +209 -19
- package/dist/templates/agent_instructions/agents/context_fetcher.md.template +82 -0
- package/dist/templates/agent_instructions/agents/prompt_writer.md.template +595 -0
- package/dist/templates/agent_instructions/agents/workflow_planner.md.template +13 -4
- package/dist/templates/agent_instructions/agents/workflow_quality.md.template +244 -0
- package/dist/templates/agent_instructions/commands/build_workflow.md.template +52 -9
- package/dist/templates/agent_instructions/commands/plan_workflow.md.template +4 -4
- package/dist/templates/project/package.json.template +2 -2
- package/dist/templates/project/src/simple/scenarios/question_ada_lovelace.json.template +3 -0
- package/dist/templates/workflow/scenarios/test_input.json.template +7 -0
- package/dist/types/trace.d.ts +161 -0
- package/dist/types/trace.js +18 -0
- package/dist/utils/date_formatter.d.ts +8 -0
- package/dist/utils/date_formatter.js +19 -0
- package/dist/utils/template.spec.js +6 -0
- package/dist/utils/trace_formatter.d.ts +11 -61
- package/dist/utils/trace_formatter.js +384 -239
- package/package.json +2 -2
- package/dist/commands/workflow/debug.test.js +0 -107
- package/dist/commands/workflow/output.test.js +0 -23
- package/dist/utils/s3_downloader.d.ts +0 -49
- package/dist/utils/s3_downloader.js +0 -154
- /package/dist/commands/workflow/{debug.test.d.ts → debug.spec.d.ts} +0 -0
- /package/dist/commands/workflow/{output.test.d.ts → result.test.d.ts} +0 -0
- /package/dist/templates/workflow/{prompt@v1.prompt.template → prompts/prompt@v1.prompt.template} +0 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: workflow-quality
|
|
3
|
+
description: Use this agent when you need expert guidance on Output SDK implementation patterns, code quality, and best practices. Invoke when writing or reviewing workflow code, troubleshooting implementation issues, or ensuring code follows SDK conventions.
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: green
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Output SDK Best Practices Agent
|
|
9
|
+
|
|
10
|
+
## Identity
|
|
11
|
+
|
|
12
|
+
You are an Output SDK implementation expert who ensures workflow code follows best practices, avoids common pitfalls, and adheres to SDK conventions. You focus on code quality, correctness, and maintainability.
|
|
13
|
+
|
|
14
|
+
## Context Retrieval
|
|
15
|
+
|
|
16
|
+
Use the `context-fetcher` subagent to efficiently retrieve:
|
|
17
|
+
- **Existing Patterns**: Find similar implementations in `src/workflows/*/`
|
|
18
|
+
- **Project Conventions**: Check `.outputai/AGENTS.md` for project-specific rules
|
|
19
|
+
|
|
20
|
+
Use the `prompt-writer` subagent for:
|
|
21
|
+
- Creating new `.prompt` files
|
|
22
|
+
- Reviewing or debugging prompt template syntax
|
|
23
|
+
- Understanding Liquid.js syntax and YAML frontmatter
|
|
24
|
+
|
|
25
|
+
## Core Expertise
|
|
26
|
+
|
|
27
|
+
- **Workflow Implementation**: Correct patterns for workflow definitions and orchestration
|
|
28
|
+
- **Step Design**: Proper step boundaries, I/O schemas, and retry policies
|
|
29
|
+
- **LLM Integration**: Prompt file format, generation functions, template syntax
|
|
30
|
+
- **HTTP Client**: Traced HTTP requests with proper error handling
|
|
31
|
+
- **Type Safety**: Zod schemas and TypeScript integration
|
|
32
|
+
- **Error Handling**: ValidationError, FatalError, and retry strategies
|
|
33
|
+
|
|
34
|
+
## Critical Rules
|
|
35
|
+
|
|
36
|
+
### Import Conventions
|
|
37
|
+
|
|
38
|
+
**CRITICAL**: Always import `z` from `@output.ai/core`, NEVER from `zod` directly:
|
|
39
|
+
```typescript
|
|
40
|
+
// Wrong
|
|
41
|
+
import { z } from 'zod';
|
|
42
|
+
|
|
43
|
+
// Correct
|
|
44
|
+
import { z } from '@output.ai/core';
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Workflow Determinism
|
|
48
|
+
|
|
49
|
+
Workflows must be deterministic. They can ONLY:
|
|
50
|
+
- Call steps and evaluators
|
|
51
|
+
- Use control flow (if/else, loops)
|
|
52
|
+
- Access input parameters
|
|
53
|
+
|
|
54
|
+
Workflows must NOT contain:
|
|
55
|
+
- Direct HTTP/API calls (wrap in steps)
|
|
56
|
+
- `Math.random()`, `Date.now()`, `crypto.randomUUID()`
|
|
57
|
+
- Dynamic imports
|
|
58
|
+
- File system operations
|
|
59
|
+
|
|
60
|
+
### Step Boundaries
|
|
61
|
+
|
|
62
|
+
All I/O operations must be wrapped in steps:
|
|
63
|
+
```typescript
|
|
64
|
+
// Wrong - I/O in workflow
|
|
65
|
+
export default workflow({
|
|
66
|
+
fn: async (input) => {
|
|
67
|
+
const data = await fetch('https://api.example.com'); // ❌
|
|
68
|
+
return { data };
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Correct - I/O in step
|
|
73
|
+
export const fetchData = step({
|
|
74
|
+
name: 'fetchData',
|
|
75
|
+
fn: async (input) => {
|
|
76
|
+
const client = httpClient({ prefixUrl: 'https://api.example.com' });
|
|
77
|
+
return client.get('endpoint').json();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### No Try-Catch Wrapping
|
|
83
|
+
|
|
84
|
+
Don't wrap step calls in try-catch blocks. Allow failures to propagate:
|
|
85
|
+
```typescript
|
|
86
|
+
// Wrong
|
|
87
|
+
fn: async (input) => {
|
|
88
|
+
try {
|
|
89
|
+
const result = await myStep(input);
|
|
90
|
+
return result;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
throw new FatalError(error.message);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Correct
|
|
97
|
+
fn: async (input) => {
|
|
98
|
+
const result = await myStep(input);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### HTTP Client Usage
|
|
104
|
+
|
|
105
|
+
Never use axios directly. Use `@output.ai/http`:
|
|
106
|
+
```typescript
|
|
107
|
+
import { httpClient } from '@output.ai/http';
|
|
108
|
+
|
|
109
|
+
const client = httpClient({
|
|
110
|
+
prefixUrl: 'https://api.example.com',
|
|
111
|
+
timeout: 30000,
|
|
112
|
+
retry: { limit: 3 }
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// GET request
|
|
116
|
+
const data = await client.get('endpoint').json();
|
|
117
|
+
|
|
118
|
+
// POST request
|
|
119
|
+
const result = await client.post('endpoint', { json: payload }).json();
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### LLM Integration
|
|
123
|
+
|
|
124
|
+
Never call LLM APIs directly. Use `@output.ai/llm`:
|
|
125
|
+
```typescript
|
|
126
|
+
import { generateText, generateObject, generateArray, generateEnum } from '@output.ai/llm';
|
|
127
|
+
|
|
128
|
+
// Text generation
|
|
129
|
+
const text = await generateText({
|
|
130
|
+
prompt: 'prompts/my_prompt@v1',
|
|
131
|
+
variables: { topic: 'AI' }
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Structured output
|
|
135
|
+
const data = await generateObject({
|
|
136
|
+
prompt: 'prompts/extract@v1',
|
|
137
|
+
variables: { text },
|
|
138
|
+
schema: z.object({ title: z.string(), summary: z.string() })
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Schema Definitions
|
|
143
|
+
|
|
144
|
+
Define input/output schemas with Zod:
|
|
145
|
+
```typescript
|
|
146
|
+
import { step, z } from '@output.ai/core';
|
|
147
|
+
|
|
148
|
+
export const processData = step({
|
|
149
|
+
name: 'processData',
|
|
150
|
+
inputSchema: z.object({
|
|
151
|
+
id: z.string(),
|
|
152
|
+
count: z.number().optional()
|
|
153
|
+
}),
|
|
154
|
+
outputSchema: z.object({
|
|
155
|
+
result: z.string(),
|
|
156
|
+
processed: z.boolean()
|
|
157
|
+
}),
|
|
158
|
+
fn: async (input) => {
|
|
159
|
+
// input is typed as { id: string, count?: number }
|
|
160
|
+
return { result: input.id, processed: true };
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Retry Policies
|
|
166
|
+
|
|
167
|
+
Configure retry policies in step options:
|
|
168
|
+
```typescript
|
|
169
|
+
export const riskyStep = step({
|
|
170
|
+
name: 'riskyStep',
|
|
171
|
+
fn: async (input) => { /* ... */ },
|
|
172
|
+
options: {
|
|
173
|
+
retry: {
|
|
174
|
+
maximumAttempts: 3,
|
|
175
|
+
initialInterval: '1s',
|
|
176
|
+
maximumInterval: '10s',
|
|
177
|
+
backoffCoefficient: 2
|
|
178
|
+
},
|
|
179
|
+
startToCloseTimeout: '30s'
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Error Types
|
|
185
|
+
|
|
186
|
+
Use appropriate error types:
|
|
187
|
+
```typescript
|
|
188
|
+
import { FatalError, ValidationError } from '@output.ai/core';
|
|
189
|
+
|
|
190
|
+
// Non-retryable error (workflow fails immediately)
|
|
191
|
+
throw new FatalError('Critical failure - do not retry');
|
|
192
|
+
|
|
193
|
+
// Validation error (schema/input validation)
|
|
194
|
+
throw new ValidationError('Invalid input format');
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## File Structure
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
src/workflows/{name}/
|
|
201
|
+
workflow.ts # Workflow definition (orchestration only)
|
|
202
|
+
steps.ts # Step definitions (all I/O here)
|
|
203
|
+
evaluators.ts # Evaluators (optional)
|
|
204
|
+
types.ts # Shared types and schemas (optional)
|
|
205
|
+
prompts/ # Prompt files directory
|
|
206
|
+
name@v1.prompt # Versioned prompt templates
|
|
207
|
+
scenarios/ # Test scenarios directory
|
|
208
|
+
basic.json # Common run case examples
|
|
209
|
+
edge_cases.json # Edge case scenarios
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Allowed Imports in Workflows
|
|
213
|
+
|
|
214
|
+
Workflows can only import from:
|
|
215
|
+
- `steps.ts`, `evaluators.ts`, `shared_steps.ts`
|
|
216
|
+
- Whitelisted: `types.ts`, `consts.ts`, `utils.ts`, `variables.ts`, `tools.ts`
|
|
217
|
+
|
|
218
|
+
## Common Pitfalls
|
|
219
|
+
|
|
220
|
+
### 1. Zod Import Source
|
|
221
|
+
Always import `z` from `@output.ai/core`, never from `zod` directly. Different `z` instances create incompatible schemas.
|
|
222
|
+
|
|
223
|
+
### 2. Direct API Calls
|
|
224
|
+
Never make HTTP/LLM calls directly in workflows. Always wrap in steps.
|
|
225
|
+
|
|
226
|
+
### 3. Non-Deterministic Operations
|
|
227
|
+
No `Math.random()`, `Date.now()`, or `crypto` in workflows.
|
|
228
|
+
|
|
229
|
+
### 4. Try-Catch Blocks
|
|
230
|
+
Don't wrap step calls in try-catch. Let failures propagate for proper retry handling.
|
|
231
|
+
|
|
232
|
+
### 5. Missing Schemas
|
|
233
|
+
Always define inputSchema and outputSchema for type safety and validation.
|
|
234
|
+
|
|
235
|
+
## Example Interaction
|
|
236
|
+
|
|
237
|
+
**User**: "My workflow is failing with a type error on the schema"
|
|
238
|
+
**Agent**: Check that you're importing `z` from `@output.ai/core`, not `zod`. Different `z` instances create incompatible schemas.
|
|
239
|
+
|
|
240
|
+
**User**: "How do I make an HTTP request in my workflow?"
|
|
241
|
+
**Agent**: Create a step that uses `@output.ai/http`. Never make HTTP calls directly in the workflow function.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
*This agent specializes in Output SDK implementation best practices and code quality.*
|
|
@@ -25,7 +25,7 @@ Implement the workflow described in the plan document, following Output SDK patt
|
|
|
25
25
|
|
|
26
26
|
<process_flow>
|
|
27
27
|
|
|
28
|
-
<step number="1" name="plan_analysis">
|
|
28
|
+
<step number="1" name="plan_analysis" subagent="context-fetcher">
|
|
29
29
|
|
|
30
30
|
### Step 1: Plan Analysis
|
|
31
31
|
|
|
@@ -40,7 +40,7 @@ Read and understand the plan document.
|
|
|
40
40
|
|
|
41
41
|
</step>
|
|
42
42
|
|
|
43
|
-
<step number="2" name="workflow_implementation">
|
|
43
|
+
<step number="2" name="workflow_implementation" subagent="workflow-quality">
|
|
44
44
|
|
|
45
45
|
### Step 2: Workflow Implementation
|
|
46
46
|
|
|
@@ -85,7 +85,7 @@ export default workflow( {
|
|
|
85
85
|
|
|
86
86
|
</step>
|
|
87
87
|
|
|
88
|
-
<step number="3" name="steps_implementation">
|
|
88
|
+
<step number="3" name="steps_implementation" subagent="workflow-quality">
|
|
89
89
|
|
|
90
90
|
### Step 3: Steps Implementation
|
|
91
91
|
|
|
@@ -122,7 +122,7 @@ export const stepName = step( {
|
|
|
122
122
|
|
|
123
123
|
</step>
|
|
124
124
|
|
|
125
|
-
<step number="4" name="prompt_templates">
|
|
125
|
+
<step number="4" name="prompt_templates" subagent="prompt-writer">
|
|
126
126
|
|
|
127
127
|
### Step 4: Prompt Templates (if needed)
|
|
128
128
|
|
|
@@ -133,7 +133,7 @@ If the plan includes LLM-based steps, create prompt templates in `$3/prompts/`.
|
|
|
133
133
|
CREATE prompt_templates
|
|
134
134
|
UPDATE steps.ts to use loadPrompt and generateText
|
|
135
135
|
ELSE:
|
|
136
|
-
SKIP to step
|
|
136
|
+
SKIP to step 6
|
|
137
137
|
</decision_tree>
|
|
138
138
|
|
|
139
139
|
<llm_step_template>
|
|
@@ -197,9 +197,51 @@ Update `$3/README.md` with workflow-specific documentation.
|
|
|
197
197
|
|
|
198
198
|
</step>
|
|
199
199
|
|
|
200
|
-
<step number="6" name="
|
|
200
|
+
<step number="6" name="scenario_creation">
|
|
201
201
|
|
|
202
|
-
### Step 6:
|
|
202
|
+
### Step 6: Scenario File Creation
|
|
203
|
+
|
|
204
|
+
Create at least one scenario file in `$3/scenarios/` for testing the workflow.
|
|
205
|
+
|
|
206
|
+
<scenario_requirements>
|
|
207
|
+
- Create `scenarios/` directory if it doesn't exist
|
|
208
|
+
- Create `test_input.json` with valid example input matching the inputSchema
|
|
209
|
+
- Input values should be realistic and demonstrate the workflow's purpose
|
|
210
|
+
- JSON must be valid and parseable
|
|
211
|
+
</scenario_requirements>
|
|
212
|
+
|
|
213
|
+
<scenario_template>
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
// Populate with example values matching inputSchema
|
|
217
|
+
// Use realistic test data that demonstrates the workflow
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
</scenario_template>
|
|
221
|
+
|
|
222
|
+
<example>
|
|
223
|
+
For a workflow with inputSchema:
|
|
224
|
+
```typescript
|
|
225
|
+
z.object({
|
|
226
|
+
topic: z.string(),
|
|
227
|
+
maxLength: z.number().optional()
|
|
228
|
+
})
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Create `scenarios/test_input.json`:
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"topic": "The history of artificial intelligence",
|
|
235
|
+
"maxLength": 500
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
</example>
|
|
239
|
+
|
|
240
|
+
</step>
|
|
241
|
+
|
|
242
|
+
<step number="7" name="validation" subagent="workflow-quality">
|
|
243
|
+
|
|
244
|
+
### Step 7: Implementation Validation
|
|
203
245
|
|
|
204
246
|
Verify the implementation is complete and correct.
|
|
205
247
|
|
|
@@ -212,13 +254,14 @@ Verify the implementation is complete and correct.
|
|
|
212
254
|
- README is updated with accurate information
|
|
213
255
|
- Code follows Output SDK patterns
|
|
214
256
|
- TypeScript types are properly defined
|
|
257
|
+
- Scenario file exists with valid example input
|
|
215
258
|
</validation_checklist>
|
|
216
259
|
|
|
217
260
|
</step>
|
|
218
261
|
|
|
219
|
-
<step number="
|
|
262
|
+
<step number="8" name="post_flight_check">
|
|
220
263
|
|
|
221
|
-
### Step
|
|
264
|
+
### Step 8: Post-Flight Check
|
|
222
265
|
|
|
223
266
|
Verify the implementation is ready for use.
|
|
224
267
|
|
|
@@ -25,7 +25,7 @@ Generate detailed specifications for implementation of a new workflow.
|
|
|
25
25
|
|
|
26
26
|
<process_flow>
|
|
27
27
|
|
|
28
|
-
<step number="1" name="context_gathering">
|
|
28
|
+
<step number="1" name="context_gathering" subagent="context-fetcher">
|
|
29
29
|
|
|
30
30
|
### Step 1: Context Gathering
|
|
31
31
|
|
|
@@ -63,7 +63,7 @@ Clarify scope boundaries and technical considerations by asking numbered questio
|
|
|
63
63
|
</decision_tree>
|
|
64
64
|
</step>
|
|
65
65
|
|
|
66
|
-
<step number="3" name="workflow_design">
|
|
66
|
+
<step number="3" name="workflow_design" subagent="workflow-quality">
|
|
67
67
|
|
|
68
68
|
### Step 3: Workflow Design
|
|
69
69
|
|
|
@@ -109,7 +109,7 @@ export default workflow( {
|
|
|
109
109
|
```
|
|
110
110
|
</workflow_template>
|
|
111
111
|
|
|
112
|
-
<step number="4" name="step_design">
|
|
112
|
+
<step number="4" name="step_design" subagent="workflow-quality">
|
|
113
113
|
### Step 4: Step Design
|
|
114
114
|
|
|
115
115
|
Design the steps with clear boundaries.
|
|
@@ -130,7 +130,7 @@ export const sumValues = step( {
|
|
|
130
130
|
|
|
131
131
|
</step>
|
|
132
132
|
|
|
133
|
-
<step number="5" name="prompt_engineering">
|
|
133
|
+
<step number="5" name="prompt_engineering" subagent="prompt-writer">
|
|
134
134
|
|
|
135
135
|
### Step 5: Prompt Engineering
|
|
136
136
|
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@output.ai/core": "^{{coreVersion}}",
|
|
14
14
|
"@output.ai/llm": "^{{llmVersion}}",
|
|
15
|
-
"@output.ai/http": "^{{httpVersion}}"
|
|
16
|
-
"copyfiles": "^{{cliVersion}}"
|
|
15
|
+
"@output.ai/http": "^{{httpVersion}}"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
18
|
"@output.ai/cli": "latest",
|
|
20
19
|
"@types/node": "^22.0.0",
|
|
20
|
+
"copyfiles": "^1.0.0",
|
|
21
21
|
"typescript": "^5.7.0"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace types for workflow execution data.
|
|
3
|
+
*
|
|
4
|
+
* These types represent the structure of trace files generated during workflow execution,
|
|
5
|
+
* used for debugging, visualization, and analysis of workflow runs.
|
|
6
|
+
*/
|
|
7
|
+
/** Node kind values for trace events */
|
|
8
|
+
export type NodeKind = 'workflow' | 'activity' | 'step' | 'internal_step' | string;
|
|
9
|
+
/** Phase of a trace event lifecycle */
|
|
10
|
+
export type NodePhase = 'start' | 'end' | 'error' | string;
|
|
11
|
+
/** Execution status of a node */
|
|
12
|
+
export type NodeStatus = 'completed' | 'failed' | 'running' | string;
|
|
13
|
+
/**
|
|
14
|
+
* Details associated with a trace event.
|
|
15
|
+
* Contains input/output data and identifying information for the event.
|
|
16
|
+
*/
|
|
17
|
+
export interface TraceDetails {
|
|
18
|
+
/** Input data passed to the step/activity */
|
|
19
|
+
input?: unknown;
|
|
20
|
+
/** Output data returned from the step/activity */
|
|
21
|
+
output?: unknown;
|
|
22
|
+
/** Name of the activity (for activity events) */
|
|
23
|
+
activityName?: string;
|
|
24
|
+
/** Name of the step (for step events) */
|
|
25
|
+
stepName?: string;
|
|
26
|
+
/** Generic name field */
|
|
27
|
+
name?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A trace event representing a point in workflow execution.
|
|
31
|
+
* Used for timeline display and event-based analysis.
|
|
32
|
+
*/
|
|
33
|
+
export interface TraceEvent {
|
|
34
|
+
/** The type of event (workflow, activity, step, etc.) */
|
|
35
|
+
kind: NodeKind;
|
|
36
|
+
/** The lifecycle phase of the event */
|
|
37
|
+
phase: NodePhase;
|
|
38
|
+
/** Unix timestamp when the event occurred */
|
|
39
|
+
timestamp: number;
|
|
40
|
+
/** Unique identifier for the workflow run */
|
|
41
|
+
workflowId: string;
|
|
42
|
+
/** Name of the workflow being executed */
|
|
43
|
+
workflowName: string;
|
|
44
|
+
/** Additional event details including input/output */
|
|
45
|
+
details?: TraceDetails;
|
|
46
|
+
/** Child events for nested executions */
|
|
47
|
+
children?: TraceEvent[];
|
|
48
|
+
/** Error information if the event represents a failure */
|
|
49
|
+
error?: unknown;
|
|
50
|
+
/** Duration of the event in milliseconds */
|
|
51
|
+
duration?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A node in the debug tree representation of workflow execution.
|
|
55
|
+
* Contains more detailed timing and state information than TraceEvent.
|
|
56
|
+
*/
|
|
57
|
+
export interface DebugNode {
|
|
58
|
+
/** The type of node (workflow, activity, step, internal_step) */
|
|
59
|
+
kind?: NodeKind;
|
|
60
|
+
/** Alternative type field */
|
|
61
|
+
type?: string;
|
|
62
|
+
/** The name of the step or activity */
|
|
63
|
+
name?: string;
|
|
64
|
+
/** Name of the workflow (for workflow nodes) */
|
|
65
|
+
workflowName?: string;
|
|
66
|
+
/** Name of the step (for step nodes) */
|
|
67
|
+
stepName?: string;
|
|
68
|
+
/** Name of the activity (for activity nodes) */
|
|
69
|
+
activityName?: string;
|
|
70
|
+
/** The lifecycle phase of the node */
|
|
71
|
+
phase?: NodePhase;
|
|
72
|
+
/** Execution status (completed, failed, running) */
|
|
73
|
+
status?: NodeStatus;
|
|
74
|
+
/** Unix timestamp or ISO string when execution started */
|
|
75
|
+
startedAt?: number | string;
|
|
76
|
+
/** Unix timestamp when the event occurred */
|
|
77
|
+
timestamp?: number | string;
|
|
78
|
+
/** Unix timestamp or ISO string when execution ended */
|
|
79
|
+
endedAt?: number | string;
|
|
80
|
+
/** Unix timestamp when execution started (alternative field) */
|
|
81
|
+
startTime?: number;
|
|
82
|
+
/** Unix timestamp when execution ended (alternative field) */
|
|
83
|
+
endTime?: number;
|
|
84
|
+
/** Execution duration in milliseconds */
|
|
85
|
+
duration?: number;
|
|
86
|
+
/** Input data passed to the step/activity */
|
|
87
|
+
input?: unknown;
|
|
88
|
+
/** Output data returned from the step/activity */
|
|
89
|
+
output?: unknown;
|
|
90
|
+
/** Additional execution details */
|
|
91
|
+
details?: Record<string, unknown>;
|
|
92
|
+
/** Error information if the node failed */
|
|
93
|
+
error?: unknown;
|
|
94
|
+
/** Child nodes representing nested executions */
|
|
95
|
+
children?: DebugNode[];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Root structure of a workflow trace.
|
|
99
|
+
* Contains the execution tree and optional flat event list.
|
|
100
|
+
*/
|
|
101
|
+
export interface TraceStructure {
|
|
102
|
+
/** Root node of the execution tree */
|
|
103
|
+
root?: TraceEvent | DebugNode;
|
|
104
|
+
/** Flat list of execution events for timeline display */
|
|
105
|
+
events?: TraceEvent[];
|
|
106
|
+
/** Hierarchical tree of execution nodes (alternative to root.children) */
|
|
107
|
+
children?: DebugNode[];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The structure of a workflow trace file generated by Output SDK workflow runs.
|
|
111
|
+
* This file is written to the local filesystem during workflow execution and contains
|
|
112
|
+
* the complete execution history including timing, inputs, outputs, and any errors.
|
|
113
|
+
*/
|
|
114
|
+
export interface TraceData {
|
|
115
|
+
/** Root workflow execution information */
|
|
116
|
+
root: {
|
|
117
|
+
/** The name of the workflow that was executed */
|
|
118
|
+
workflowName: string;
|
|
119
|
+
/** Unique identifier for this workflow run */
|
|
120
|
+
workflowId: string;
|
|
121
|
+
/** Unix timestamp when the workflow started */
|
|
122
|
+
startTime: number;
|
|
123
|
+
/** Unix timestamp when the workflow ended */
|
|
124
|
+
endTime?: number;
|
|
125
|
+
/** Total workflow duration in milliseconds */
|
|
126
|
+
duration?: number;
|
|
127
|
+
/** Final workflow status */
|
|
128
|
+
status?: string;
|
|
129
|
+
/** Error information if the workflow failed */
|
|
130
|
+
error?: unknown;
|
|
131
|
+
};
|
|
132
|
+
/** Flat list of execution events for timeline display */
|
|
133
|
+
events?: Array<{
|
|
134
|
+
name: string;
|
|
135
|
+
phase: string;
|
|
136
|
+
timestamp: number;
|
|
137
|
+
details?: unknown;
|
|
138
|
+
}>;
|
|
139
|
+
/** Hierarchical tree of execution nodes */
|
|
140
|
+
children?: DebugNode[];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Extracted node information for display formatting.
|
|
144
|
+
* Used internally by the trace formatter.
|
|
145
|
+
*/
|
|
146
|
+
export interface NodeInfo {
|
|
147
|
+
/** Display name for the node */
|
|
148
|
+
name: string;
|
|
149
|
+
/** Formatted phase indicator */
|
|
150
|
+
phase: string;
|
|
151
|
+
/** Formatted duration string */
|
|
152
|
+
duration: string;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Type guard to check if a node is a TraceEvent.
|
|
156
|
+
*/
|
|
157
|
+
export declare const isTraceEvent: (node: TraceEvent | DebugNode) => node is TraceEvent;
|
|
158
|
+
/**
|
|
159
|
+
* Type guard to check if a value is a valid timestamp.
|
|
160
|
+
*/
|
|
161
|
+
export declare const isValidTimestamp: (value: unknown) => value is number | string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace types for workflow execution data.
|
|
3
|
+
*
|
|
4
|
+
* These types represent the structure of trace files generated during workflow execution,
|
|
5
|
+
* used for debugging, visualization, and analysis of workflow runs.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Type guard to check if a node is a TraceEvent.
|
|
9
|
+
*/
|
|
10
|
+
export const isTraceEvent = (node) => {
|
|
11
|
+
return 'workflowId' in node && 'timestamp' in node;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Type guard to check if a value is a valid timestamp.
|
|
15
|
+
*/
|
|
16
|
+
export const isValidTimestamp = (value) => {
|
|
17
|
+
return typeof value === 'number' || typeof value === 'string';
|
|
18
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a duration in milliseconds to a human-readable string.
|
|
3
|
+
* Uses date-fns for durations >= 1 minute, custom formatting for shorter durations.
|
|
4
|
+
*
|
|
5
|
+
* @param ms - Duration in milliseconds
|
|
6
|
+
* @returns Formatted duration string (e.g., "150ms", "2.50s", "3 minutes 45 seconds")
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatDuration(ms: number): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { formatDuration as formatDurationFns, intervalToDuration } from 'date-fns';
|
|
2
|
+
/**
|
|
3
|
+
* Format a duration in milliseconds to a human-readable string.
|
|
4
|
+
* Uses date-fns for durations >= 1 minute, custom formatting for shorter durations.
|
|
5
|
+
*
|
|
6
|
+
* @param ms - Duration in milliseconds
|
|
7
|
+
* @returns Formatted duration string (e.g., "150ms", "2.50s", "3 minutes 45 seconds")
|
|
8
|
+
*/
|
|
9
|
+
export function formatDuration(ms) {
|
|
10
|
+
const duration = intervalToDuration({ start: 0, end: ms });
|
|
11
|
+
if (ms < 1000) {
|
|
12
|
+
return `${ms}ms`;
|
|
13
|
+
}
|
|
14
|
+
if (ms < 60000) {
|
|
15
|
+
const seconds = ms / 1000;
|
|
16
|
+
return `${seconds.toFixed(2)}s`;
|
|
17
|
+
}
|
|
18
|
+
return formatDurationFns(duration, { format: ['minutes', 'seconds'] });
|
|
19
|
+
}
|
|
@@ -53,6 +53,12 @@ describe('Template Utilities', () => {
|
|
|
53
53
|
expect(processTemplate(template, variables))
|
|
54
54
|
.toBe('myWorkflowName and MyWorkflowName');
|
|
55
55
|
});
|
|
56
|
+
it('should preserve escaped curly braces for Liquid.js examples', () => {
|
|
57
|
+
const template = 'Use Liquid: \\{{ variable }} and {% if %}...{% endif %}';
|
|
58
|
+
const variables = {};
|
|
59
|
+
expect(processTemplate(template, variables))
|
|
60
|
+
.toBe('Use Liquid: {{ variable }} and {% if %}...{% endif %}');
|
|
61
|
+
});
|
|
56
62
|
});
|
|
57
63
|
describe('prepareTemplateVariables', () => {
|
|
58
64
|
it('should prepare variables from workflow name and description', () => {
|