bizy-ai 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl
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.
- agent/cli.py +208 -12
- agent/models.py +23 -8
- agent/plan_manager.py +320 -0
- agent/tasks.py +98 -13
- agent/weekly_review.py +10 -10
- {bizy_ai-1.0.1.dist-info → bizy_ai-1.1.0.dist-info}/METADATA +52 -2
- bizy_ai-1.1.0.dist-info/RECORD +21 -0
- scripts/load_business_plan.py +110 -0
- scripts/migrate_db.py +40 -0
- scripts/scheduler.py +94 -0
- bizy_ai-1.0.1.dist-info/RECORD +0 -18
- scripts/agent_cli.py +0 -232
- {bizy_ai-1.0.1.dist-info → bizy_ai-1.1.0.dist-info}/WHEEL +0 -0
- {bizy_ai-1.0.1.dist-info → bizy_ai-1.1.0.dist-info}/entry_points.txt +0 -0
- {bizy_ai-1.0.1.dist-info → bizy_ai-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {bizy_ai-1.0.1.dist-info → bizy_ai-1.1.0.dist-info}/top_level.txt +0 -0
agent/tasks.py
CHANGED
@@ -233,19 +233,104 @@ class TaskManager:
|
|
233
233
|
}
|
234
234
|
|
235
235
|
def get_task_velocity(self, days=30):
|
236
|
-
"""
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
if not
|
244
|
-
return 0
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
236
|
+
"""
|
237
|
+
Calculate average tasks completed per day over a period.
|
238
|
+
Uses actual completed_at timestamps for accurate velocity calculation.
|
239
|
+
"""
|
240
|
+
# Get tasks completed in the specified period
|
241
|
+
completed_tasks = self.get_completed_tasks_this_week(days=days)
|
242
|
+
|
243
|
+
if not completed_tasks:
|
244
|
+
return 0.0
|
245
|
+
|
246
|
+
# Calculate velocity as tasks per day
|
247
|
+
velocity = len(completed_tasks) / days
|
248
|
+
return velocity
|
249
|
+
|
250
|
+
def get_completed_tasks_this_week(self, days=7):
|
251
|
+
"""Get tasks completed in the last N days based on completed_at timestamp"""
|
252
|
+
# Use UTC time to match database timestamps
|
253
|
+
now = datetime.utcnow()
|
254
|
+
start_date = now - timedelta(days=days)
|
255
|
+
|
256
|
+
completed_tasks = self.session.query(Task).filter(
|
257
|
+
and_(
|
258
|
+
Task.status == 'completed',
|
259
|
+
Task.completed_at >= start_date,
|
260
|
+
Task.completed_at <= now
|
261
|
+
)
|
262
|
+
).order_by(Task.completed_at.desc()).all()
|
263
|
+
|
264
|
+
return completed_tasks
|
265
|
+
|
266
|
+
def get_created_tasks_this_week(self, days=7):
|
267
|
+
"""Get tasks created in the last N days based on created_at timestamp"""
|
268
|
+
# Use UTC time to match database timestamps
|
269
|
+
now = datetime.utcnow()
|
270
|
+
start_date = now - timedelta(days=days)
|
271
|
+
|
272
|
+
created_tasks = self.session.query(Task).filter(
|
273
|
+
and_(
|
274
|
+
Task.created_at >= start_date,
|
275
|
+
Task.created_at <= now
|
276
|
+
)
|
277
|
+
).order_by(Task.created_at.desc()).all()
|
278
|
+
|
279
|
+
return created_tasks
|
280
|
+
|
281
|
+
def get_weekly_task_stats(self, days=7):
|
282
|
+
"""
|
283
|
+
Get weekly statistics based on actual task completion dates (completed_at).
|
284
|
+
This is more accurate than DailyLog-based stats as it reflects actual work completed.
|
285
|
+
"""
|
286
|
+
completed_tasks = self.get_completed_tasks_this_week(days)
|
287
|
+
created_tasks = self.get_created_tasks_this_week(days)
|
288
|
+
|
289
|
+
# Calculate statistics
|
290
|
+
tasks_completed = len(completed_tasks)
|
291
|
+
tasks_created = len(created_tasks)
|
292
|
+
|
293
|
+
# Calculate completion rate (completed vs created this week)
|
294
|
+
completion_rate = (tasks_completed / tasks_created * 100) if tasks_created > 0 else 0
|
295
|
+
|
296
|
+
# Calculate total estimated hours
|
297
|
+
total_estimated_hours = sum(
|
298
|
+
task.estimated_hours or 0 for task in completed_tasks
|
299
|
+
)
|
300
|
+
|
301
|
+
# Calculate total actual hours
|
302
|
+
total_actual_hours = sum(
|
303
|
+
task.actual_hours or 0 for task in completed_tasks
|
304
|
+
)
|
305
|
+
|
306
|
+
# Break down by category
|
307
|
+
categories = {}
|
308
|
+
for task in completed_tasks:
|
309
|
+
category = task.category or 'uncategorized'
|
310
|
+
if category not in categories:
|
311
|
+
categories[category] = 0
|
312
|
+
categories[category] += 1
|
313
|
+
|
314
|
+
# Break down by priority
|
315
|
+
priorities = {}
|
316
|
+
for task in completed_tasks:
|
317
|
+
priority = task.priority
|
318
|
+
if priority not in priorities:
|
319
|
+
priorities[priority] = 0
|
320
|
+
priorities[priority] += 1
|
321
|
+
|
322
|
+
return {
|
323
|
+
'tasks_completed_this_week': tasks_completed,
|
324
|
+
'tasks_created_this_week': tasks_created,
|
325
|
+
'completion_rate': completion_rate,
|
326
|
+
'total_estimated_hours': total_estimated_hours,
|
327
|
+
'total_actual_hours': total_actual_hours,
|
328
|
+
'completed_tasks': [task.to_dict() for task in completed_tasks],
|
329
|
+
'categories': categories,
|
330
|
+
'priorities': priorities,
|
331
|
+
'period_days': days
|
332
|
+
}
|
333
|
+
|
249
334
|
def close(self):
|
250
335
|
"""Close the database session"""
|
251
336
|
self.session.close()
|
agent/weekly_review.py
CHANGED
@@ -25,22 +25,22 @@ def run_weekly_review():
|
|
25
25
|
task_mgr = TaskManager()
|
26
26
|
planner = BusinessPlanner()
|
27
27
|
|
28
|
-
# Get weekly statistics
|
29
|
-
weekly_stats = task_mgr.
|
30
|
-
|
28
|
+
# Get weekly statistics based on actual task completions
|
29
|
+
weekly_stats = task_mgr.get_weekly_task_stats()
|
30
|
+
|
31
31
|
# Get goal progress
|
32
32
|
active_goals = planner.get_active_goals()
|
33
33
|
goals_progress = "\n".join([
|
34
34
|
f"- {g.title}: {g.progress_percentage:.0f}% complete"
|
35
35
|
for g in active_goals[:5]
|
36
36
|
]) if active_goals else "No active goals"
|
37
|
-
|
38
|
-
# Get key events
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
|
38
|
+
# Get key events from completed tasks
|
39
|
+
completed_tasks = weekly_stats.get('completed_tasks', [])
|
40
|
+
key_events_str = "\n".join([
|
41
|
+
f"✓ {task['title']}" + (f" ({task['category']})" if task['category'] else "")
|
42
|
+
for task in completed_tasks[:10]
|
43
|
+
]) if completed_tasks else "No tasks completed this week"
|
44
44
|
|
45
45
|
# Generate review
|
46
46
|
console.print("[dim]Generating comprehensive analysis...[/dim]\n")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: bizy-ai
|
3
|
-
Version: 1.0
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: AI-powered business planning and execution agent
|
5
5
|
Author: Reid Chatham
|
6
6
|
License: MIT
|
@@ -37,6 +37,13 @@ Requires-Dist: rich>=13.0.0
|
|
37
37
|
Requires-Dist: python-dateutil>=2.8.2
|
38
38
|
Requires-Dist: click>=8.1.0
|
39
39
|
Requires-Dist: jinja2>=3.1.2
|
40
|
+
Provides-Extra: dev
|
41
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
42
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
43
|
+
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
|
44
|
+
Requires-Dist: pytest-watch>=4.2.0; extra == "dev"
|
45
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
46
|
+
Requires-Dist: flake8>=6.1.0; extra == "dev"
|
40
47
|
Dynamic: license-file
|
41
48
|
Dynamic: requires-python
|
42
49
|
|
@@ -88,7 +95,50 @@ pip install -e .
|
|
88
95
|
./setup.sh
|
89
96
|
```
|
90
97
|
|
91
|
-
See **[INSTALL.md](INSTALL.md)** for detailed installation options.
|
98
|
+
See **[INSTALL.md](docs/INSTALL.md)** for detailed installation options.
|
99
|
+
|
100
|
+
---
|
101
|
+
|
102
|
+
## Development
|
103
|
+
|
104
|
+
### Test-Driven Development (TDD)
|
105
|
+
|
106
|
+
This project follows TDD principles. All new features must:
|
107
|
+
|
108
|
+
1. **Write tests first** - Define expected behavior
|
109
|
+
2. **Run tests (they should fail)** - Red phase
|
110
|
+
3. **Implement feature** - Green phase
|
111
|
+
4. **Refactor** - Clean up code
|
112
|
+
|
113
|
+
### Running Tests
|
114
|
+
|
115
|
+
```bash
|
116
|
+
# Run all tests with coverage
|
117
|
+
make test
|
118
|
+
|
119
|
+
# Run tests in watch mode
|
120
|
+
make test-watch
|
121
|
+
|
122
|
+
# Run specific test file
|
123
|
+
pytest tests/test_tasks.py -v
|
124
|
+
```
|
125
|
+
|
126
|
+
### Database Environments
|
127
|
+
|
128
|
+
- **Production**: `~/.business-agent/tasks.db` - Your actual business data 🔒
|
129
|
+
- **Development**: `~/.business-agent/dev_tasks.db` - Safe for experimentation ⚙️
|
130
|
+
- **Test**: In-memory - Isolated, clean for each test 🧪
|
131
|
+
|
132
|
+
```bash
|
133
|
+
# Use development database
|
134
|
+
export BIZY_ENV=development
|
135
|
+
make dev
|
136
|
+
|
137
|
+
# Use production database (default)
|
138
|
+
export BIZY_ENV=production
|
139
|
+
```
|
140
|
+
|
141
|
+
See **[CONTRIBUTING.md](CONTRIBUTING.md)** for detailed development guidelines.
|
92
142
|
|
93
143
|
---
|
94
144
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
agent/__init__.py,sha256=pHeIDi-ibuwZqaNqxdIDRvzedWtPywssbaYIDawMcvQ,88
|
2
|
+
agent/cli.py,sha256=J-TlTArbSD2eHkn93Kt7Y7YXZb84NJPGj3XDRgUPsZw,15186
|
3
|
+
agent/core.py,sha256=UILN_DjsSr91KN3YyQaD_cZgF9vW8m827-W0pZMTUnM,6561
|
4
|
+
agent/evening_review.py,sha256=Y4d-t62zfaufM8mnSvkhBBZ0wMw1R8jtj4cN8r30t4E,4929
|
5
|
+
agent/models.py,sha256=Et7GDIW8E-S444j0AbqoFrvNXL4hJ9iWPM989CS34E0,8727
|
6
|
+
agent/morning_brief.py,sha256=zcu4nUOnIQtoZTiK1XlEjuudiUAABrps3PvAwt2Avmk,4732
|
7
|
+
agent/plan_manager.py,sha256=7ipJBW-QS308dSpULjJGcDPjsXKA-yVh1mljFejCv_U,12225
|
8
|
+
agent/planner.py,sha256=-KlyZ-2jMQTUy0QVZCH_NuubENU-UrPXVhat3ju54ew,13114
|
9
|
+
agent/research.py,sha256=HvqGHENQ0v1lJadGYNuf3eb6fZoR6qzzIPzqcsnhFSE,6429
|
10
|
+
agent/tasks.py,sha256=PzisO_2a7Hgplxf3CxnGYLG-Fg8O9ylHYC5193cHyZo,12155
|
11
|
+
agent/weekly_review.py,sha256=83fYwe3hKEhqAQfMlj7WmvvMhTNHtUnqr1PFXCHRGWo,2394
|
12
|
+
bizy_ai-1.1.0.dist-info/licenses/LICENSE,sha256=__BSNgmbeWQ1IA57XKyGhQajUNcF-pZjvBAY268fCWM,1069
|
13
|
+
scripts/init_db.py,sha256=lF1rJAuaeOX19dYQKURzePYWmjkjLPH_4L0D2OiRgQA,3376
|
14
|
+
scripts/load_business_plan.py,sha256=gb4_NPL39PX5yie7zENYgViPBoTqHaLYbTGXPdZU9wM,3560
|
15
|
+
scripts/migrate_db.py,sha256=b51nlLn62nThDGRNqPbxT3jNM2Zdg56hKyymYFTcrUk,1220
|
16
|
+
scripts/scheduler.py,sha256=4LDL7Mb8ZWeOFpy6i8LuMff4HWjFwm10XrcMpLkZmUY,3459
|
17
|
+
bizy_ai-1.1.0.dist-info/METADATA,sha256=9zDRI0w3sQuFbGFPFbZC97Gq0kY-vbeyFMjk99OWjxo,13726
|
18
|
+
bizy_ai-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
19
|
+
bizy_ai-1.1.0.dist-info/entry_points.txt,sha256=yDZc2xFUlCOPuHtAaNissB16AZFzOnOL8xeStkDujAg,39
|
20
|
+
bizy_ai-1.1.0.dist-info/top_level.txt,sha256=k5ce4bNe_tK9tse1lxY4b8nPSipbtgoA28GHmM2ojwk,14
|
21
|
+
bizy_ai-1.1.0.dist-info/RECORD,,
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""Script to load business plan from YAML into the database"""
|
3
|
+
|
4
|
+
import yaml
|
5
|
+
import sys
|
6
|
+
import os
|
7
|
+
from datetime import datetime
|
8
|
+
from agent.models import get_session, BusinessPlan
|
9
|
+
from rich.console import Console
|
10
|
+
from rich.panel import Panel
|
11
|
+
from rich.prompt import Prompt
|
12
|
+
|
13
|
+
console = Console()
|
14
|
+
|
15
|
+
def load_business_plan(file_path=None, plan_name=None):
|
16
|
+
"""Load a business plan from YAML into database"""
|
17
|
+
|
18
|
+
console.print()
|
19
|
+
|
20
|
+
# If no file path provided, request one
|
21
|
+
if not file_path:
|
22
|
+
file_path = Prompt.ask("📁 [bold]Enter path to business plan YAML file[/bold]")
|
23
|
+
|
24
|
+
# Expand user path if needed
|
25
|
+
file_path = os.path.expanduser(file_path)
|
26
|
+
|
27
|
+
# Check if file exists
|
28
|
+
if not os.path.exists(file_path):
|
29
|
+
console.print(f"[bold red]❌ Error: File not found: {file_path}[/bold red]")
|
30
|
+
return False
|
31
|
+
|
32
|
+
# Read the YAML file
|
33
|
+
try:
|
34
|
+
with open(file_path, 'r') as f:
|
35
|
+
file_content = f.read()
|
36
|
+
plan_data = yaml.safe_load(file_content)
|
37
|
+
except Exception as e:
|
38
|
+
console.print(f"[bold red]❌ Error reading YAML file: {e}[/bold red]")
|
39
|
+
return False
|
40
|
+
|
41
|
+
session = get_session()
|
42
|
+
|
43
|
+
try:
|
44
|
+
# Get plan name: CLI option > YAML 'name' field > first # header > prompt user
|
45
|
+
if not plan_name:
|
46
|
+
# Try to get name from YAML 'name' field
|
47
|
+
plan_name = plan_data.get('name')
|
48
|
+
|
49
|
+
if not plan_name:
|
50
|
+
# Try to extract from first # header in file
|
51
|
+
for line in file_content.split('\n'):
|
52
|
+
line = line.strip()
|
53
|
+
if line.startswith('# ') and not line.startswith('##'):
|
54
|
+
plan_name = line[2:].strip()
|
55
|
+
break
|
56
|
+
|
57
|
+
if not plan_name:
|
58
|
+
# Prompt user for name
|
59
|
+
plan_name = Prompt.ask(f"📝 [bold]Enter business plan name[/bold]")
|
60
|
+
|
61
|
+
# Deactivate any existing active plans
|
62
|
+
active_plans = session.query(BusinessPlan).filter_by(is_active=True).all()
|
63
|
+
for plan in active_plans:
|
64
|
+
plan.is_active = False
|
65
|
+
console.print(f"[yellow]⚠ Deactivated existing plan: {plan.name}[/yellow]")
|
66
|
+
|
67
|
+
# Create new business plan
|
68
|
+
new_plan = BusinessPlan(
|
69
|
+
name=plan_name,
|
70
|
+
version=plan_data.get('version', '1.0'),
|
71
|
+
vision=plan_data.get('vision', ''),
|
72
|
+
mission=plan_data.get('mission', ''),
|
73
|
+
value_proposition=plan_data.get('value_proposition', ''),
|
74
|
+
target_market=plan_data.get('target_market', ''),
|
75
|
+
revenue_model=plan_data.get('revenue_model', ''),
|
76
|
+
is_active=True
|
77
|
+
)
|
78
|
+
|
79
|
+
session.add(new_plan)
|
80
|
+
session.commit()
|
81
|
+
|
82
|
+
console.print(Panel(
|
83
|
+
f"[green]✅ Business Plan Loaded Successfully[/green]\n\n"
|
84
|
+
f"Name: {new_plan.name}\n"
|
85
|
+
f"Version: {new_plan.version}\n"
|
86
|
+
f"ID: {new_plan.id}\n"
|
87
|
+
f"Created: {new_plan.created_at.strftime('%Y-%m-%d %H:%M:%S')}\n"
|
88
|
+
f"Active: {'Yes' if new_plan.is_active else 'No'}",
|
89
|
+
title="Success",
|
90
|
+
border_style="green"
|
91
|
+
))
|
92
|
+
|
93
|
+
console.print()
|
94
|
+
return True
|
95
|
+
|
96
|
+
except Exception as e:
|
97
|
+
console.print(f"[bold red]❌ Error creating business plan: {e}[/bold red]")
|
98
|
+
session.rollback()
|
99
|
+
return False
|
100
|
+
finally:
|
101
|
+
session.close()
|
102
|
+
|
103
|
+
if __name__ == "__main__":
|
104
|
+
# Check for command line argument
|
105
|
+
if len(sys.argv) > 1:
|
106
|
+
file_path = sys.argv[1]
|
107
|
+
else:
|
108
|
+
file_path = None
|
109
|
+
|
110
|
+
load_business_plan(file_path)
|
scripts/migrate_db.py
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""Migrate database to add name and updated_at columns to business_plans table"""
|
3
|
+
|
4
|
+
import sqlite3
|
5
|
+
import os
|
6
|
+
|
7
|
+
db_path = os.path.expanduser('~/.business-agent/tasks.db')
|
8
|
+
|
9
|
+
print(f"Migrating database at: {db_path}")
|
10
|
+
|
11
|
+
conn = sqlite3.connect(db_path)
|
12
|
+
cursor = conn.cursor()
|
13
|
+
|
14
|
+
try:
|
15
|
+
# Check if name column exists
|
16
|
+
cursor.execute("PRAGMA table_info(business_plans)")
|
17
|
+
columns = [row[1] for row in cursor.fetchall()]
|
18
|
+
|
19
|
+
if 'name' not in columns:
|
20
|
+
print("Adding 'name' column to business_plans table...")
|
21
|
+
cursor.execute("ALTER TABLE business_plans ADD COLUMN name VARCHAR(255)")
|
22
|
+
print("✅ Added 'name' column")
|
23
|
+
else:
|
24
|
+
print("✓ 'name' column already exists")
|
25
|
+
|
26
|
+
if 'updated_at' not in columns:
|
27
|
+
print("Adding 'updated_at' column to business_plans table...")
|
28
|
+
cursor.execute("ALTER TABLE business_plans ADD COLUMN updated_at DATETIME")
|
29
|
+
print("✅ Added 'updated_at' column")
|
30
|
+
else:
|
31
|
+
print("✓ 'updated_at' column already exists")
|
32
|
+
|
33
|
+
conn.commit()
|
34
|
+
print("\n✅ Database migration completed successfully!")
|
35
|
+
|
36
|
+
except Exception as e:
|
37
|
+
print(f"❌ Error during migration: {e}")
|
38
|
+
conn.rollback()
|
39
|
+
finally:
|
40
|
+
conn.close()
|
scripts/scheduler.py
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Business Agent Main Scheduler
|
4
|
+
Runs automated daily tasks on schedule
|
5
|
+
"""
|
6
|
+
|
7
|
+
import schedule
|
8
|
+
import time
|
9
|
+
import subprocess
|
10
|
+
import sys
|
11
|
+
from datetime import datetime
|
12
|
+
from rich.console import Console
|
13
|
+
from dotenv import load_dotenv
|
14
|
+
|
15
|
+
load_dotenv()
|
16
|
+
|
17
|
+
console = Console()
|
18
|
+
|
19
|
+
def run_script(script_name, description):
|
20
|
+
"""Run a Python script and handle errors"""
|
21
|
+
console.print(f"\n[bold cyan]Running {description}...[/bold cyan]")
|
22
|
+
console.print(f"[dim]{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}[/dim]\n")
|
23
|
+
|
24
|
+
try:
|
25
|
+
result = subprocess.run(
|
26
|
+
[sys.executable, f"scripts/{script_name}"],
|
27
|
+
capture_output=False,
|
28
|
+
text=True
|
29
|
+
)
|
30
|
+
|
31
|
+
if result.returncode == 0:
|
32
|
+
console.print(f"[green]✓ {description} completed successfully[/green]\n")
|
33
|
+
else:
|
34
|
+
console.print(f"[yellow]⚠ {description} finished with warnings[/yellow]\n")
|
35
|
+
|
36
|
+
except Exception as e:
|
37
|
+
console.print(f"[red]✗ Error running {description}: {e}[/red]\n")
|
38
|
+
|
39
|
+
def run_morning_brief():
|
40
|
+
"""Run morning briefing"""
|
41
|
+
run_script("morning_brief.py", "Morning Briefing")
|
42
|
+
|
43
|
+
def run_evening_review():
|
44
|
+
"""Run evening review"""
|
45
|
+
run_script("evening_review.py", "Evening Review")
|
46
|
+
|
47
|
+
def run_weekly_review():
|
48
|
+
"""Run weekly review"""
|
49
|
+
run_script("weekly_review.py", "Weekly Review")
|
50
|
+
|
51
|
+
def main():
|
52
|
+
console.print("\n[bold cyan]═══════════════════════════════════════════[/bold cyan]")
|
53
|
+
console.print("[bold cyan] 🤖 Business Agent Scheduler Started[/bold cyan]")
|
54
|
+
console.print("[bold cyan]═══════════════════════════════════════════[/bold cyan]\n")
|
55
|
+
|
56
|
+
# Schedule jobs
|
57
|
+
# Morning briefing: Monday-Friday at 8:00 AM
|
58
|
+
schedule.every().monday.at("08:00").do(run_morning_brief)
|
59
|
+
schedule.every().tuesday.at("08:00").do(run_morning_brief)
|
60
|
+
schedule.every().wednesday.at("08:00").do(run_morning_brief)
|
61
|
+
schedule.every().thursday.at("08:00").do(run_morning_brief)
|
62
|
+
schedule.every().friday.at("08:00").do(run_morning_brief)
|
63
|
+
|
64
|
+
# Evening review: Monday-Friday at 6:00 PM
|
65
|
+
schedule.every().monday.at("18:00").do(run_evening_review)
|
66
|
+
schedule.every().tuesday.at("18:00").do(run_evening_review)
|
67
|
+
schedule.every().wednesday.at("18:00").do(run_evening_review)
|
68
|
+
schedule.every().thursday.at("18:00").do(run_evening_review)
|
69
|
+
schedule.every().friday.at("18:00").do(run_evening_review)
|
70
|
+
|
71
|
+
# Weekly review: Sunday at 7:00 PM
|
72
|
+
schedule.every().sunday.at("19:00").do(run_weekly_review)
|
73
|
+
|
74
|
+
console.print("[bold]📅 Scheduled Tasks:[/bold]")
|
75
|
+
console.print(" • Morning Briefings: Mon-Fri at 8:00 AM")
|
76
|
+
console.print(" • Evening Reviews: Mon-Fri at 6:00 PM")
|
77
|
+
console.print(" • Weekly Review: Sunday at 7:00 PM")
|
78
|
+
console.print()
|
79
|
+
console.print("[dim]Press Ctrl+C to stop the scheduler[/dim]")
|
80
|
+
console.print()
|
81
|
+
|
82
|
+
# Keep the scheduler running
|
83
|
+
try:
|
84
|
+
while True:
|
85
|
+
schedule.run_pending()
|
86
|
+
time.sleep(60) # Check every minute
|
87
|
+
|
88
|
+
except KeyboardInterrupt:
|
89
|
+
console.print("\n\n[yellow]Scheduler stopped by user[/yellow]")
|
90
|
+
console.print("[dim]All scheduled tasks have been cancelled[/dim]\n")
|
91
|
+
sys.exit(0)
|
92
|
+
|
93
|
+
if __name__ == "__main__":
|
94
|
+
main()
|
bizy_ai-1.0.1.dist-info/RECORD
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
agent/__init__.py,sha256=pHeIDi-ibuwZqaNqxdIDRvzedWtPywssbaYIDawMcvQ,88
|
2
|
-
agent/cli.py,sha256=8raEuVh3rEDRQS8QGROu_ONiGdEPAwZEP2-gshrb3mA,7264
|
3
|
-
agent/core.py,sha256=UILN_DjsSr91KN3YyQaD_cZgF9vW8m827-W0pZMTUnM,6561
|
4
|
-
agent/evening_review.py,sha256=Y4d-t62zfaufM8mnSvkhBBZ0wMw1R8jtj4cN8r30t4E,4929
|
5
|
-
agent/models.py,sha256=6bDSLXRxztF50J0AoTi5PX3ckf74oPhyQXfOccfVGdk,7937
|
6
|
-
agent/morning_brief.py,sha256=zcu4nUOnIQtoZTiK1XlEjuudiUAABrps3PvAwt2Avmk,4732
|
7
|
-
agent/planner.py,sha256=-KlyZ-2jMQTUy0QVZCH_NuubENU-UrPXVhat3ju54ew,13114
|
8
|
-
agent/research.py,sha256=HvqGHENQ0v1lJadGYNuf3eb6fZoR6qzzIPzqcsnhFSE,6429
|
9
|
-
agent/tasks.py,sha256=PaQzRcnzp5HPWVlQKG3KLwdNBNqHTsqCuoGmRwRh8dA,9041
|
10
|
-
agent/weekly_review.py,sha256=ljwy0Aq6yFE_gs8TQjJKCO9Ob59fXsu8L_gDPiRQdmc,2298
|
11
|
-
bizy_ai-1.0.1.dist-info/licenses/LICENSE,sha256=__BSNgmbeWQ1IA57XKyGhQajUNcF-pZjvBAY268fCWM,1069
|
12
|
-
scripts/agent_cli.py,sha256=sG-iRmFZCzm5SkqDtVV1KzZ293SEtvFpY8A1_b69dJU,6971
|
13
|
-
scripts/init_db.py,sha256=lF1rJAuaeOX19dYQKURzePYWmjkjLPH_4L0D2OiRgQA,3376
|
14
|
-
bizy_ai-1.0.1.dist-info/METADATA,sha256=YLRhUVVs_Ve3a5wXC6aIt3etvyJaWW2-NZKY8HLKtoo,12480
|
15
|
-
bizy_ai-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
16
|
-
bizy_ai-1.0.1.dist-info/entry_points.txt,sha256=yDZc2xFUlCOPuHtAaNissB16AZFzOnOL8xeStkDujAg,39
|
17
|
-
bizy_ai-1.0.1.dist-info/top_level.txt,sha256=k5ce4bNe_tK9tse1lxY4b8nPSipbtgoA28GHmM2ojwk,14
|
18
|
-
bizy_ai-1.0.1.dist-info/RECORD,,
|