documenting action spec
This commit is contained in:
179
docs/QUICKREF-output-formats.md
Normal file
179
docs/QUICKREF-output-formats.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Quick Reference: Action Output Formats
|
||||
|
||||
## TL;DR
|
||||
|
||||
Actions can specify how their stdout should be parsed:
|
||||
- `text` (default): No parsing, raw stdout only
|
||||
- `json`: Parse last line as JSON
|
||||
- `yaml`: Parse entire output as YAML
|
||||
- `jsonl`: Parse each line as JSON, return array
|
||||
|
||||
## Action Definition
|
||||
|
||||
```yaml
|
||||
name: my_action
|
||||
output_format: json # text | json | yaml | jsonl
|
||||
output_schema:
|
||||
type: object # Use 'array' for jsonl
|
||||
properties:
|
||||
result: { type: string }
|
||||
```
|
||||
|
||||
## Format Behaviors
|
||||
|
||||
| Format | Parses | Result | Best For |
|
||||
|--------|--------|--------|----------|
|
||||
| `text` | Nothing | `null` | Simple messages, logs |
|
||||
| `json` | Last line | Object/Value | API responses, single results |
|
||||
| `yaml` | Entire stdout | Object/Value | Configs, nested data |
|
||||
| `jsonl` | Each line | Array | Lists, streaming, batches |
|
||||
|
||||
## Examples
|
||||
|
||||
### Text (no parsing)
|
||||
```bash
|
||||
echo "Hello, World!"
|
||||
# Result: null (stdout captured separately)
|
||||
```
|
||||
|
||||
### JSON (last line)
|
||||
```bash
|
||||
echo "Processing..."
|
||||
echo '{"status": 200, "data": "success"}'
|
||||
# Result: {"status": 200, "data": "success"}
|
||||
```
|
||||
|
||||
### YAML (entire output)
|
||||
```bash
|
||||
cat <<EOF
|
||||
version: 1.0
|
||||
settings:
|
||||
enabled: true
|
||||
timeout: 30
|
||||
EOF
|
||||
# Result: {"version": "1.0", "settings": {...}}
|
||||
```
|
||||
|
||||
### JSONL (each line → array)
|
||||
```bash
|
||||
echo '{"id": 1, "name": "Alice"}'
|
||||
echo '{"id": 2, "name": "Bob"}'
|
||||
echo '{"id": 3, "name": "Charlie"}'
|
||||
# Result: [{"id": 1, ...}, {"id": 2, ...}, {"id": 3, ...}]
|
||||
```
|
||||
|
||||
## Action Script Templates
|
||||
|
||||
### Bash + JSON
|
||||
```bash
|
||||
#!/bin/bash
|
||||
result=$(do_work)
|
||||
echo "{\"result\": \"$result\", \"status\": \"ok\"}"
|
||||
```
|
||||
|
||||
### Python + JSON
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
result = do_work()
|
||||
print(json.dumps({"result": result, "status": "ok"}))
|
||||
```
|
||||
|
||||
### Bash + JSONL
|
||||
```bash
|
||||
#!/bin/bash
|
||||
for item in $(ls); do
|
||||
size=$(stat -f%z "$item")
|
||||
echo "{\"name\": \"$item\", \"size\": $size}"
|
||||
done
|
||||
```
|
||||
|
||||
### Python + JSONL
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
for item in get_items():
|
||||
print(json.dumps({"id": item.id, "value": item.value}))
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Informational + Result (JSON)
|
||||
```bash
|
||||
echo "Starting process..." >&2 # Log to stderr
|
||||
echo "Processing 100 items..." >&2
|
||||
echo '{"processed": 100, "errors": 0}' # JSON on last line
|
||||
```
|
||||
|
||||
### Mixed Output (JSONL)
|
||||
```bash
|
||||
echo "Scanning directory..." >&2 # Non-JSON ignored
|
||||
echo '{"file": "a.txt", "size": 1024}' # Valid JSON
|
||||
echo "Found 2 files" >&2 # Non-JSON ignored
|
||||
echo '{"file": "b.txt", "size": 2048}' # Valid JSON
|
||||
```
|
||||
|
||||
## Execution Result Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"exit_code": 0,
|
||||
"succeeded": true,
|
||||
"duration_ms": 142,
|
||||
"stdout": "raw output here",
|
||||
"stderr": "logs here",
|
||||
"data": { /* parsed result based on output_format */ }
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
✅ **DO**
|
||||
- Use `text` for simple logging/messages
|
||||
- Use `json` for structured single results
|
||||
- Use `jsonl` for lists and batches
|
||||
- Write one JSON object per line (no pretty-print)
|
||||
- Log to stderr, output to stdout
|
||||
- Use non-zero exit codes for failures
|
||||
|
||||
❌ **DON'T**
|
||||
- Mix error messages in stdout (use stderr)
|
||||
- Pretty-print JSON across multiple lines
|
||||
- Assume parsing will always succeed
|
||||
- Use `jsonl` without `type: array` in schema
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**No result parsed?**
|
||||
- Check exit code is 0
|
||||
- Verify JSON is on last line (`json`)
|
||||
- Ensure one JSON per line (`jsonl`)
|
||||
- Check for syntax errors in output
|
||||
- Parsing failures don't cause execution failure
|
||||
|
||||
**JSONL returning empty array?**
|
||||
- Check each line is valid JSON
|
||||
- Ensure no trailing empty lines
|
||||
- Invalid lines are silently skipped
|
||||
|
||||
**Result is null but expected data?**
|
||||
- Verify `output_format` matches output
|
||||
- Check stdout contains expected format
|
||||
- Parsing is best-effort (no errors thrown)
|
||||
|
||||
## Database
|
||||
|
||||
```sql
|
||||
-- Check action output format
|
||||
SELECT ref, output_format FROM action WHERE ref = 'core.http_request';
|
||||
|
||||
-- Update action output format
|
||||
UPDATE action SET output_format = 'jsonl' WHERE ref = 'mypack.myaction';
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [Full Documentation](action-output-formats.md)
|
||||
- [Pack Structure](pack-structure.md)
|
||||
- [Parameter Delivery](parameter-delivery.md)
|
||||
- [Execution System](execution-system.md)
|
||||
Reference in New Issue
Block a user