Initial commit with translated description
This commit is contained in:
97
workflows/README.md
Normal file
97
workflows/README.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Lobster Workflows
|
||||
|
||||
This directory contains [Lobster](https://github.com/openclaw/lobster) workflow definitions for the finance-news skill.
|
||||
|
||||
## Available Workflows
|
||||
|
||||
### `briefing.yaml` - Market Briefing with Approval
|
||||
|
||||
Generates a market briefing and sends to WhatsApp with an approval gate.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Run via Lobster CLI
|
||||
lobster "workflows.run --file ~/projects/finance-news-openclaw-skill/workflows/briefing.yaml"
|
||||
|
||||
# With custom args
|
||||
lobster "workflows.run --file workflows/briefing.yaml --args-json '{\"time\":\"evening\",\"lang\":\"en\"}'"
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
| Arg | Default | Description |
|
||||
|-----|---------|-------------|
|
||||
| `time` | `morning` | Briefing type: `morning` or `evening` |
|
||||
| `lang` | `de` | Language: `en` or `de` |
|
||||
| `channel` | `whatsapp` | Delivery channel: `whatsapp` or `telegram` |
|
||||
| `target` | env var | Group name, JID, phone number, or Telegram chat ID |
|
||||
| `fast` | `false` | Use fast mode (shorter timeouts) |
|
||||
|
||||
**Environment Variables:**
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `FINANCE_NEWS_CHANNEL` | Default channel: `whatsapp` or `telegram` |
|
||||
| `FINANCE_NEWS_TARGET` | Default target (group name, phone, chat ID) |
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# WhatsApp group (default)
|
||||
lobster "workflows.run --file workflows/briefing.yaml"
|
||||
|
||||
# Telegram group
|
||||
lobster "workflows.run --file workflows/briefing.yaml --args-json '{\"channel\":\"telegram\",\"target\":\"-1001234567890\"}'"
|
||||
|
||||
# WhatsApp DM to phone number
|
||||
lobster "workflows.run --file workflows/briefing.yaml --args-json '{\"target\":\"+15551234567\"}'"
|
||||
|
||||
# Telegram DM to user
|
||||
lobster "workflows.run --file workflows/briefing.yaml --args-json '{\"channel\":\"telegram\",\"target\":\"@username\"}'"
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. **Generate** - Runs Docker container to produce briefing JSON
|
||||
2. **Approve** - Halts for human review (shows briefing preview)
|
||||
3. **Send** - Delivers to channel (WhatsApp/Telegram) after approval
|
||||
|
||||
**Requirements:**
|
||||
- Docker with `finance-news-briefing` image built
|
||||
- `jq` for JSON parsing
|
||||
- `openclaw` CLI for message delivery
|
||||
|
||||
## Adding to Lobster Registry
|
||||
|
||||
To make these workflows available as named workflows in Lobster:
|
||||
|
||||
```typescript
|
||||
// In lobster/src/workflows/registry.ts
|
||||
export const workflowRegistry = {
|
||||
// ... existing workflows
|
||||
'finance.briefing': {
|
||||
name: 'finance.briefing',
|
||||
description: 'Generate market briefing with approval gate for WhatsApp/Telegram',
|
||||
argsSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
time: { type: 'string', enum: ['morning', 'evening'], default: 'morning' },
|
||||
lang: { type: 'string', enum: ['en', 'de'], default: 'de' },
|
||||
channel: { type: 'string', enum: ['whatsapp', 'telegram'], default: 'whatsapp' },
|
||||
target: { type: 'string', description: 'Group name, JID, phone, or chat ID' },
|
||||
fast: { type: 'boolean', default: false },
|
||||
},
|
||||
},
|
||||
examples: [
|
||||
{ args: { time: 'morning', lang: 'de' }, description: 'German morning briefing to WhatsApp' },
|
||||
{ args: { channel: 'telegram', target: '-1001234567890' }, description: 'Send to Telegram group' },
|
||||
],
|
||||
sideEffects: ['message.send'],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Why Lobster?
|
||||
|
||||
Using Lobster instead of direct cron execution provides:
|
||||
|
||||
- **Approval gates** - Review briefing before it's sent
|
||||
- **Resumability** - If interrupted, continue from last step
|
||||
- **Token efficiency** - One workflow call vs. multiple LLM tool calls
|
||||
- **Determinism** - Same inputs = same outputs
|
||||
45
workflows/alerts-cron.yaml
Normal file
45
workflows/alerts-cron.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
# Price Alerts Workflow for Cron (No Approval Gate)
|
||||
# Usage: lobster run --file workflows/alerts-cron.yaml --args-json '{"lang":"en"}'
|
||||
#
|
||||
# Schedule: 2:00 PM PT / 5:00 PM ET (1 hour after market close)
|
||||
# Checks price alerts against current prices (including after-hours)
|
||||
|
||||
name: finance.alerts.cron
|
||||
description: Check price alerts and send triggered alerts to WhatsApp/Telegram
|
||||
|
||||
args:
|
||||
lang:
|
||||
default: en
|
||||
description: "Language: en or de"
|
||||
channel:
|
||||
default: "${FINANCE_NEWS_CHANNEL:-whatsapp}"
|
||||
description: "Delivery channel: whatsapp or telegram"
|
||||
target:
|
||||
default: "${FINANCE_NEWS_TARGET}"
|
||||
description: "Target: group name, JID, or chat ID"
|
||||
|
||||
steps:
|
||||
# Check alerts against current prices
|
||||
- id: check_alerts
|
||||
command: |
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
python3 "$SKILL_DIR/scripts/alerts.py" check --lang "${lang}"
|
||||
description: Check price alerts against current prices
|
||||
|
||||
# Send alert message if there's content
|
||||
- id: send_alerts
|
||||
command: |
|
||||
MSG=$(cat)
|
||||
MSG=$(echo "$MSG" | tr -d '\r')
|
||||
# Only send if message has actual content (not just "No price data" message)
|
||||
if echo "$MSG" | grep -q "IN BUY ZONE\|IN KAUFZONE\|WATCHING\|BEOBACHTUNG"; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
echo "Sent price alerts to ${channel}"
|
||||
else
|
||||
echo "No triggered alerts or watchlist items to send"
|
||||
fi
|
||||
stdin: $check_alerts.stdout
|
||||
description: Send price alerts to channel
|
||||
101
workflows/briefing-cron.yaml
Normal file
101
workflows/briefing-cron.yaml
Normal file
@@ -0,0 +1,101 @@
|
||||
# Finance Briefing Workflow for Cron (No Approval Gate)
|
||||
# Usage: lobster run --file workflows/briefing-cron.yaml --args-json '{"time":"morning","lang":"de"}'
|
||||
#
|
||||
# This workflow:
|
||||
# 1. Generates a market briefing via Docker
|
||||
# 2. Translates portfolio headlines (German)
|
||||
# 3. Sends directly to messaging channel (no approval)
|
||||
|
||||
name: finance.briefing.cron
|
||||
description: Generate market briefing and send to WhatsApp/Telegram (auto-approve for cron)
|
||||
|
||||
args:
|
||||
time:
|
||||
default: morning
|
||||
description: "Briefing type: morning or evening"
|
||||
lang:
|
||||
default: de
|
||||
description: "Language: en or de"
|
||||
channel:
|
||||
default: "${FINANCE_NEWS_CHANNEL:-whatsapp}"
|
||||
description: "Delivery channel: whatsapp or telegram"
|
||||
target:
|
||||
default: "${FINANCE_NEWS_TARGET}"
|
||||
description: "Target: group name, JID, phone number, or Telegram chat ID (requires FINANCE_NEWS_TARGET env var if not specified)"
|
||||
fast:
|
||||
default: "false"
|
||||
description: "Use fast mode: true or false"
|
||||
|
||||
steps:
|
||||
# Generate briefing and save to temp file
|
||||
- id: generate
|
||||
command: |
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
FAST_FLAG=""
|
||||
if [ "${fast}" = "true" ]; then FAST_FLAG="--fast"; fi
|
||||
OUTFILE="/tmp/lobster-briefing-$$.json"
|
||||
# Resolve openbb-quote symlink for Docker mount
|
||||
OPENBB_BIN=$(realpath "$HOME/.local/bin/openbb-quote" 2>/dev/null || echo "")
|
||||
OPENBB_MOUNT=""
|
||||
if [ -f "$OPENBB_BIN" ]; then
|
||||
OPENBB_MOUNT="-v $OPENBB_BIN:/usr/local/bin/openbb-quote:ro"
|
||||
fi
|
||||
docker run --rm \
|
||||
-v "$SKILL_DIR/config:/app/config:ro" \
|
||||
-v "$SKILL_DIR/scripts:/app/scripts:ro" \
|
||||
$OPENBB_MOUNT \
|
||||
finance-news-briefing python3 scripts/briefing.py \
|
||||
--time "${time}" \
|
||||
--lang "${lang}" \
|
||||
--json \
|
||||
$FAST_FLAG > "$OUTFILE"
|
||||
# Output the file path for subsequent steps
|
||||
echo "$OUTFILE"
|
||||
description: Generate briefing via Docker
|
||||
|
||||
# Translate portfolio headlines (if German)
|
||||
- id: translate
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
OUTFILE=$(echo "$OUTFILE" | tr -d '\n')
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
if [ "${lang}" = "de" ]; then
|
||||
python3 "$SKILL_DIR/scripts/translate_portfolio.py" "$OUTFILE" --lang de || true
|
||||
fi
|
||||
echo "$OUTFILE"
|
||||
stdin: $generate.stdout
|
||||
description: Translate portfolio headlines via openclaw
|
||||
|
||||
# Send macro briefing (market overview) - NO APPROVAL GATE
|
||||
- id: send_macro
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
OUTFILE=$(echo "$OUTFILE" | tr -d '\n')
|
||||
MSG=$(jq -r '.macro_message // empty' "$OUTFILE")
|
||||
if [ -n "$MSG" ]; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
else
|
||||
echo "No macro message to send"
|
||||
fi
|
||||
stdin: $translate.stdout
|
||||
description: Send macro briefing
|
||||
|
||||
# Send portfolio briefing (stock movers)
|
||||
- id: send_portfolio
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
OUTFILE=$(echo "$OUTFILE" | tr -d '\n')
|
||||
MSG=$(jq -r '.portfolio_message // empty' "$OUTFILE")
|
||||
if [ -n "$MSG" ]; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
else
|
||||
echo "No portfolio message to send"
|
||||
fi
|
||||
stdin: $translate.stdout
|
||||
description: Send portfolio briefing
|
||||
115
workflows/briefing.yaml
Normal file
115
workflows/briefing.yaml
Normal file
@@ -0,0 +1,115 @@
|
||||
# Finance Briefing Workflow for Lobster
|
||||
# Usage: lobster "workflows.run --file workflows/briefing.yaml --args-json '{\"time\":\"morning\",\"lang\":\"de\"}'"
|
||||
#
|
||||
# This workflow:
|
||||
# 1. Generates a market briefing via Docker
|
||||
# 2. Halts for approval before sending
|
||||
# 3. Sends to messaging channel after approval
|
||||
|
||||
name: finance.briefing
|
||||
description: Generate market briefing and send to WhatsApp/Telegram with approval gate
|
||||
|
||||
args:
|
||||
time:
|
||||
default: morning
|
||||
description: "Briefing type: morning or evening"
|
||||
lang:
|
||||
default: de
|
||||
description: "Language: en or de"
|
||||
channel:
|
||||
default: "${FINANCE_NEWS_CHANNEL:-whatsapp}"
|
||||
description: "Delivery channel: whatsapp or telegram"
|
||||
target:
|
||||
default: "${FINANCE_NEWS_TARGET}"
|
||||
description: "Target: group name, JID, phone number, or Telegram chat ID (requires FINANCE_NEWS_TARGET env var if not specified)"
|
||||
fast:
|
||||
default: "false"
|
||||
description: "Use fast mode: true or false"
|
||||
|
||||
steps:
|
||||
# Generate briefing and save to temp file
|
||||
- id: generate
|
||||
command: |
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
FAST_FLAG=""
|
||||
if [ "${fast}" = "true" ]; then FAST_FLAG="--fast"; fi
|
||||
OUTFILE="/tmp/lobster-briefing-$$.json"
|
||||
# Resolve openbb-quote symlink for Docker mount
|
||||
OPENBB_BIN=$(realpath "$HOME/.local/bin/openbb-quote" 2>/dev/null || echo "")
|
||||
OPENBB_MOUNT=""
|
||||
if [ -f "$OPENBB_BIN" ]; then
|
||||
OPENBB_MOUNT="-v $OPENBB_BIN:/usr/local/bin/openbb-quote:ro"
|
||||
fi
|
||||
docker run --rm \
|
||||
-v "$SKILL_DIR/config:/app/config:ro" \
|
||||
-v "$SKILL_DIR/scripts:/app/scripts:ro" \
|
||||
$OPENBB_MOUNT \
|
||||
finance-news-briefing python3 scripts/briefing.py \
|
||||
--time "${time}" \
|
||||
--lang "${lang}" \
|
||||
--json \
|
||||
$FAST_FLAG > "$OUTFILE"
|
||||
# Output the file path for subsequent steps
|
||||
echo "$OUTFILE"
|
||||
description: Generate briefing via Docker
|
||||
|
||||
# Translate portfolio headlines (if German)
|
||||
- id: translate
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
OUTFILE=$(echo "$OUTFILE" | tr -d '\n')
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
if [ "${lang}" = "de" ]; then
|
||||
python3 "$SKILL_DIR/scripts/translate_portfolio.py" "$OUTFILE" --lang de || true
|
||||
fi
|
||||
echo "$OUTFILE"
|
||||
stdin: $generate.stdout
|
||||
description: Translate portfolio headlines via openclaw
|
||||
|
||||
# Approval gate - workflow halts here until user approves
|
||||
- id: approve
|
||||
approval: required
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
echo "Briefing saved to: $OUTFILE"
|
||||
echo "Target: ${target}"
|
||||
echo "Channel: ${channel}"
|
||||
cat "$OUTFILE" | jq -r '.macro_message' | head -20
|
||||
echo "..."
|
||||
echo "Review above. Approve to send."
|
||||
stdin: $translate.stdout
|
||||
description: Approval gate before message delivery
|
||||
|
||||
# Send macro briefing (market overview)
|
||||
- id: send_macro
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
OUTFILE=$(echo "$OUTFILE" | tr -d '\n')
|
||||
MSG=$(jq -r '.macro_message // empty' "$OUTFILE")
|
||||
if [ -n "$MSG" ]; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
else
|
||||
echo "No macro message to send"
|
||||
fi
|
||||
stdin: $translate.stdout
|
||||
description: Send macro briefing
|
||||
|
||||
# Send portfolio briefing (stock movers)
|
||||
- id: send_portfolio
|
||||
command: |
|
||||
OUTFILE=$(cat)
|
||||
OUTFILE=$(echo "$OUTFILE" | tr -d '\n')
|
||||
MSG=$(jq -r '.portfolio_message // empty' "$OUTFILE")
|
||||
if [ -n "$MSG" ]; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
else
|
||||
echo "No portfolio message to send"
|
||||
fi
|
||||
stdin: $translate.stdout
|
||||
description: Send portfolio briefing
|
||||
45
workflows/earnings-cron.yaml
Normal file
45
workflows/earnings-cron.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
# Earnings Alert Workflow for Cron (No Approval Gate)
|
||||
# Usage: lobster run --file workflows/earnings-cron.yaml --args-json '{"lang":"en"}'
|
||||
#
|
||||
# Schedule: 6:00 AM PT / 9:00 AM ET (30 min before market open)
|
||||
# Sends today's earnings calendar to WhatsApp/Telegram
|
||||
|
||||
name: finance.earnings.cron
|
||||
description: Send earnings alerts for today's reports
|
||||
|
||||
args:
|
||||
lang:
|
||||
default: en
|
||||
description: "Language: en or de"
|
||||
channel:
|
||||
default: "${FINANCE_NEWS_CHANNEL:-whatsapp}"
|
||||
description: "Delivery channel: whatsapp or telegram"
|
||||
target:
|
||||
default: "${FINANCE_NEWS_TARGET}"
|
||||
description: "Target: group name, JID, or chat ID"
|
||||
|
||||
steps:
|
||||
# Check earnings calendar for today and this week
|
||||
- id: check_earnings
|
||||
command: |
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
python3 "$SKILL_DIR/scripts/earnings.py" check --lang "${lang}"
|
||||
description: Get today's earnings calendar
|
||||
|
||||
# Send earnings alert if there's content
|
||||
- id: send_earnings
|
||||
command: |
|
||||
MSG=$(cat)
|
||||
MSG=$(echo "$MSG" | tr -d '\r')
|
||||
# Only send if there are actual earnings today
|
||||
if echo "$MSG" | grep -q "EARNINGS TODAY\|EARNINGS HEUTE"; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
echo "Sent earnings alert to ${channel}"
|
||||
else
|
||||
echo "No earnings today - skipping message"
|
||||
fi
|
||||
stdin: $check_earnings.stdout
|
||||
description: Send earnings alert to channel
|
||||
45
workflows/earnings-weekly-cron.yaml
Normal file
45
workflows/earnings-weekly-cron.yaml
Normal file
@@ -0,0 +1,45 @@
|
||||
# Weekly Earnings Alert Workflow for Cron (No Approval Gate)
|
||||
# Usage: lobster run --file workflows/earnings-weekly-cron.yaml --args-json '{"lang":"en"}'
|
||||
#
|
||||
# Schedule: Sunday 7:00 AM PT (before market week starts)
|
||||
# Sends upcoming week's earnings calendar to WhatsApp/Telegram
|
||||
|
||||
name: finance.earnings.weekly.cron
|
||||
description: Send weekly earnings preview for portfolio stocks
|
||||
|
||||
args:
|
||||
lang:
|
||||
default: en
|
||||
description: "Language: en or de"
|
||||
channel:
|
||||
default: "${FINANCE_NEWS_CHANNEL:-whatsapp}"
|
||||
description: "Delivery channel: whatsapp or telegram"
|
||||
target:
|
||||
default: "${FINANCE_NEWS_TARGET}"
|
||||
description: "Target: group name, JID, or chat ID"
|
||||
|
||||
steps:
|
||||
# Check earnings calendar for upcoming week
|
||||
- id: check_earnings
|
||||
command: |
|
||||
SKILL_DIR="${SKILL_DIR:-$HOME/projects/skills/personal/finance-news}"
|
||||
python3 "$SKILL_DIR/scripts/earnings.py" check --week --lang "${lang}"
|
||||
description: Get upcoming week's earnings calendar
|
||||
|
||||
# Send earnings alert if there's content
|
||||
- id: send_earnings
|
||||
command: |
|
||||
MSG=$(cat)
|
||||
MSG=$(echo "$MSG" | tr -d '\r')
|
||||
# Only send if there are actual earnings next week
|
||||
if echo "$MSG" | grep -qE "EARNINGS (NEXT WEEK|NÄCHSTE WOCHE)"; then
|
||||
openclaw message send \
|
||||
--channel "${channel}" \
|
||||
--target "${target}" \
|
||||
--message "$MSG"
|
||||
echo "Sent weekly earnings preview to ${channel}"
|
||||
else
|
||||
echo "No earnings next week - skipping message"
|
||||
fi
|
||||
stdin: $check_earnings.stdout
|
||||
description: Send weekly earnings alert to channel
|
||||
Reference in New Issue
Block a user