Skip to content

Commit 5a3b858

Browse files
authored
feat: enable activity/todo/tips set interval (#66)
1 parent a340e3f commit 5a3b858

7 files changed

Lines changed: 531 additions & 219 deletions

File tree

config/config.yaml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,22 @@ prompts:
184184

185185
# Content generation service configuration
186186
content_generation:
187-
enabled: true
188-
auto_start: true
187+
# Task configurations
188+
activity:
189+
enabled: true
190+
interval: 900 # Seconds, minimum 600 (10 minutes), recommended 900-1800 (15-30 minutes)
191+
192+
tips:
193+
enabled: true
194+
interval: 3600 # Seconds, minimum 1800 (30 minutes), recommended 3600-7200 (1-2 hours)
189195

190-
# Generation switches
191-
enable_report_generation: true
192-
enable_activity_generation: true
193-
enable_todo_generation: true
194-
enable_tips_generation: true
196+
todos:
197+
enabled: true
198+
interval: 1800 # Seconds, minimum 1800 (30 minutes), recommended 1800-3600 (30-60 minutes)
199+
200+
report:
201+
enabled: true
202+
time: "08:00" # Daily report generation time (HH:MM)
195203

196204

197205
tools:

opencontext/config/config_manager.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def save_user_settings(self, settings: Dict[str, Any]) -> bool:
293293
if not self._config:
294294
logger.error("Main configuration not loaded")
295295
return False
296-
296+
297297
# Get user settings path
298298
user_setting_path = self._config.get("user_setting_path")
299299
if not user_setting_path:
@@ -303,15 +303,30 @@ def save_user_settings(self, settings: Dict[str, Any]) -> bool:
303303
dir_name = os.path.dirname(user_setting_path)
304304
if dir_name:
305305
os.makedirs(dir_name, exist_ok=True)
306-
306+
307+
# Load existing user settings
307308
user_settings = {}
309+
if os.path.exists(user_setting_path):
310+
with open(user_setting_path, 'r', encoding='utf-8') as f:
311+
existing_settings = yaml.safe_load(f)
312+
if existing_settings:
313+
user_settings = existing_settings
314+
315+
# Update with new settings
308316
if "vlm_model" in settings:
309317
user_settings["vlm_model"] = settings["vlm_model"]
310318
if "embedding_model" in settings:
311319
user_settings["embedding_model"] = settings["embedding_model"]
320+
if "content_generation" in settings:
321+
user_settings["content_generation"] = settings["content_generation"]
322+
323+
# Save to file
312324
with open(user_setting_path, 'w', encoding='utf-8') as f:
313325
yaml.dump(user_settings, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
326+
314327
logger.info(f"User settings saved successfully: {user_setting_path}")
328+
329+
# Merge into current config
315330
self._config = self.deep_merge(self._config, user_settings)
316331
return True
317332
except Exception as e:

opencontext/managers/consumption_manager.py

Lines changed: 249 additions & 95 deletions
Large diffs are not rendered by default.

opencontext/server/component_initializer.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,10 @@ def initialize_completion_service(self) -> Optional[CompletionService]:
177177

178178
def initialize_consumption_components(self) -> ConsumptionManager:
179179
consumption_manager = ConsumptionManager()
180-
181-
# Start scheduled tasks if configured
180+
181+
# Start scheduled tasks (individual tasks controlled by their enabled flags)
182182
content_generation_config = self.config.get("content_generation", {})
183-
if content_generation_config.get("enabled", True) and content_generation_config.get("auto_start", True):
184-
consumption_manager.start_scheduled_tasks(content_generation_config)
185-
logger.info("Content generation scheduled tasks auto-started")
183+
consumption_manager.start_scheduled_tasks(content_generation_config)
186184

187185
logger.info("Context consumption components initialization complete")
188186
return consumption_manager

opencontext/server/context_operations.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ def add_screenshot(
7777
context_processor_callback
7878
) -> Optional[str]:
7979
"""Add a screenshot to the system."""
80-
logger.info(f"Adding screenshot: path={path}, window={window}, create_time={create_time}, app={app}")
8180

8281
# Validate inputs
8382
if not path:

opencontext/server/routes/content_generation.py

Lines changed: 94 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
"""
99

1010
from typing import Optional
11-
from pydantic import BaseModel
12-
from fastapi import APIRouter, Depends, Query
11+
from pydantic import BaseModel, Field
12+
from fastapi import APIRouter, Depends
1313

1414
from opencontext.server.opencontext import OpenContext
1515
from opencontext.utils.logging_utils import get_logger
@@ -19,59 +19,112 @@
1919
logger = get_logger(__name__)
2020
router = APIRouter(tags=["content-generation"])
2121

22-
@router.get("/api/content_generation/status")
23-
async def get_content_generation_status(
22+
# ==================== Data Models ====================
23+
24+
class ActivityConfig(BaseModel):
25+
"""Configuration for activity task"""
26+
enabled: Optional[bool] = None
27+
interval: Optional[int] = Field(None, ge=600, description="Interval in seconds, minimum 600 (10 minutes)")
28+
29+
30+
class TipsConfig(BaseModel):
31+
"""Configuration for tips task"""
32+
enabled: Optional[bool] = None
33+
interval: Optional[int] = Field(None, ge=1800, description="Interval in seconds, minimum 1800 (30 minutes)")
34+
35+
36+
class TodosConfig(BaseModel):
37+
"""Configuration for todos task"""
38+
enabled: Optional[bool] = None
39+
interval: Optional[int] = Field(None, ge=1800, description="Interval in seconds, minimum 1800 (30 minutes)")
40+
41+
42+
class ReportConfig(BaseModel):
43+
"""Configuration for daily report"""
44+
enabled: Optional[bool] = None
45+
time: Optional[str] = Field(None, pattern=r"^\d{2}:\d{2}$", description="Time in HH:MM format")
46+
47+
48+
class ContentGenerationConfig(BaseModel):
49+
"""Complete content generation configuration"""
50+
activity: Optional[ActivityConfig] = None
51+
tips: Optional[TipsConfig] = None
52+
todos: Optional[TodosConfig] = None
53+
report: Optional[ReportConfig] = None
54+
55+
56+
@router.get("/api/content_generation/config")
57+
async def get_content_generation_config(
2458
opencontext: OpenContext = Depends(get_context_lab),
2559
_auth: str = auth_dependency
2660
):
27-
"""Get content generation service status"""
61+
"""
62+
Get content generation configuration
63+
"""
2864
try:
2965
if not hasattr(opencontext, 'consumption_manager') or not opencontext.consumption_manager:
30-
return convert_resp(data={
31-
"enabled": False,
32-
"message": "Consumption manager not initialized"
33-
})
34-
35-
status = opencontext.consumption_manager.get_scheduled_tasks_status()
36-
return convert_resp(data=status)
37-
66+
return convert_resp(code=500, status=500, message="Consumption manager not initialized")
67+
68+
config = opencontext.consumption_manager.get_task_config()
69+
return convert_resp(data=config)
70+
3871
except Exception as e:
39-
logger.exception(f"Error getting content generation status: {e}")
40-
return convert_resp(code=500, status=500, message=f"Failed to get status: {str(e)}")
72+
logger.exception(f"Error getting content generation config: {e}")
73+
return convert_resp(code=500, status=500, message=f"Failed to get config: {str(e)}")
4174

4275

43-
@router.post("/api/content_generation/start")
44-
async def start_content_generation(
76+
@router.post("/api/content_generation/config")
77+
async def update_content_generation_config(
78+
config: ContentGenerationConfig,
4579
opencontext: OpenContext = Depends(get_context_lab),
4680
_auth: str = auth_dependency
4781
):
48-
"""Start content generation scheduled tasks"""
82+
"""
83+
Update content generation configuration (supports partial updates)
84+
"""
4985
try:
5086
if not hasattr(opencontext, 'consumption_manager') or not opencontext.consumption_manager:
5187
return convert_resp(code=500, status=500, message="Consumption manager not initialized")
52-
53-
content_generation_config = opencontext.config.get("content_generation", {})
54-
opencontext.consumption_manager.start_scheduled_tasks(content_generation_config)
55-
56-
return convert_resp(data={"message": "Content generation tasks started"})
57-
58-
except Exception as e:
59-
logger.exception(f"Error starting content generation: {e}")
60-
return convert_resp(code=500, status=500, message=f"Failed to start: {str(e)}")
88+
config_dict = {}
89+
for task_name in ['activity', 'tips', 'todos']:
90+
task_config = getattr(config, task_name, None)
91+
if task_config is not None:
92+
task_dict = {}
93+
if task_config.enabled is not None:
94+
task_dict['enabled'] = task_config.enabled
95+
if task_config.interval is not None:
96+
task_dict['interval'] = task_config.interval
97+
if task_dict:
98+
config_dict[task_name] = task_dict
99+
if config.report is not None:
100+
report_dict = {}
101+
if config.report.enabled is not None:
102+
report_dict['enabled'] = config.report.enabled
103+
if config.report.time is not None:
104+
report_dict['time'] = config.report.time
105+
if report_dict:
106+
config_dict['report'] = report_dict
61107

108+
if not config_dict:
109+
return convert_resp(code=400, status=400, message="No valid configuration provided")
110+
111+
if opencontext.consumption_manager.update_task_config(config_dict):
112+
try:
113+
from opencontext.config.global_config import GlobalConfig
114+
config_manager = GlobalConfig.get_instance().get_config_manager()
115+
116+
# Get current user settings and update content_generation section
117+
updated_config = opencontext.consumption_manager.get_task_config()
118+
config_manager.save_user_settings({"content_generation": updated_config})
119+
logger.info("Configuration saved to user_settings.yaml")
120+
except Exception as e:
121+
logger.error(f"Failed to save configuration to file: {e}")
122+
# Continue even if save fails - configuration is still applied in memory
123+
124+
return convert_resp(message="Configuration updated successfully")
125+
else:
126+
return convert_resp(code=500, status=500, message="Failed to update configuration")
62127

63-
@router.post("/api/content_generation/stop")
64-
async def stop_content_generation(
65-
opencontext: OpenContext = Depends(get_context_lab),
66-
_auth: str = auth_dependency
67-
):
68-
"""Stop content generation scheduled tasks"""
69-
try:
70-
if hasattr(opencontext, 'consumption_manager') and opencontext.consumption_manager:
71-
opencontext.consumption_manager.stop_scheduled_tasks()
72-
73-
return convert_resp(data={"message": "Content generation tasks stopped"})
74-
75128
except Exception as e:
76-
logger.exception(f"Error stopping content generation: {e}")
77-
return convert_resp(code=500, status=500, message=f"Failed to stop: {str(e)}")
129+
logger.exception(f"Error updating content generation config: {e}")
130+
return convert_resp(code=500, status=500, message=f"Failed to update config: {str(e)}")

0 commit comments

Comments
 (0)