Compare commits
3 Commits
whip/350-1
...
q/378-1776
| Author | SHA1 | Date | |
|---|---|---|---|
| 19369e273a | |||
| 954fd992eb | |||
|
|
f35f56e397 |
44
cron/jobs.py
44
cron/jobs.py
@@ -363,6 +363,45 @@ def save_jobs(jobs: List[Dict[str, Any]]):
|
||||
raise
|
||||
|
||||
|
||||
# Patterns that reference local services unreachable on cloud endpoints
|
||||
_LOCAL_SERVICE_CHECK_PATTERNS = [
|
||||
re.compile(r"\b(?:check|verify)\s+(?:that\s+)?ollama\b", re.IGNORECASE),
|
||||
re.compile(r"\bcurl\s+(?:localhost|127\.0\.0\.1)", re.IGNORECASE),
|
||||
re.compile(r"\bpoll\s+localhost\b", re.IGNORECASE),
|
||||
re.compile(r"\bping\s+localhost\b", re.IGNORECASE),
|
||||
re.compile(r"localhost:\d+", re.IGNORECASE),
|
||||
re.compile(r"127\.0\.0\.1:\d+", re.IGNORECASE),
|
||||
]
|
||||
|
||||
|
||||
def _validate_job_prompt_local_refs(prompt: str, base_url: Optional[str] = None) -> List[str]:
|
||||
"""Check if a cron job prompt references local services.
|
||||
|
||||
Returns list of warning messages (empty = no issues).
|
||||
Warnings are advisory — jobs are NOT rejected.
|
||||
"""
|
||||
warnings = []
|
||||
if not prompt:
|
||||
return warnings
|
||||
|
||||
refs = []
|
||||
for pat in _LOCAL_SERVICE_CHECK_PATTERNS:
|
||||
found = pat.findall(prompt)
|
||||
if found:
|
||||
refs.extend(found[:2])
|
||||
|
||||
if refs:
|
||||
refs_str = ", ".join(f"'{r}'" for r in refs[:5])
|
||||
warnings.append(
|
||||
f"Prompt references local services ({refs_str}) which may be "
|
||||
f"unreachable if the job runs on a cloud provider. "
|
||||
f"Consider setting provider='ollama' or base_url='http://localhost:11434/v1'."
|
||||
)
|
||||
|
||||
return warnings
|
||||
|
||||
|
||||
|
||||
def create_job(
|
||||
prompt: str,
|
||||
schedule: str,
|
||||
@@ -457,6 +496,11 @@ def create_job(
|
||||
"origin": origin, # Tracks where job was created for "origin" delivery
|
||||
}
|
||||
|
||||
# Validate prompt for local service references (#378)
|
||||
_warnings = _validate_job_prompt_local_refs(prompt, normalized_base_url)
|
||||
for w in _warnings:
|
||||
logging.getLogger("cron.jobs").warning("Job '%s': %s", job_id, w)
|
||||
|
||||
jobs = load_jobs()
|
||||
jobs.append(job)
|
||||
save_jobs(jobs)
|
||||
|
||||
28
run_agent.py
28
run_agent.py
@@ -1001,30 +1001,10 @@ class AIAgent:
|
||||
self._session_db = session_db
|
||||
self._parent_session_id = parent_session_id
|
||||
self._last_flushed_db_idx = 0 # tracks DB-write cursor to prevent duplicate writes
|
||||
if self._session_db:
|
||||
try:
|
||||
self._session_db.create_session(
|
||||
session_id=self.session_id,
|
||||
source=self.platform or os.environ.get("HERMES_SESSION_SOURCE", "cli"),
|
||||
model=self.model,
|
||||
model_config={
|
||||
"max_iterations": self.max_iterations,
|
||||
"reasoning_config": reasoning_config,
|
||||
"max_tokens": max_tokens,
|
||||
},
|
||||
user_id=None,
|
||||
parent_session_id=self._parent_session_id,
|
||||
)
|
||||
except Exception as e:
|
||||
# Transient SQLite lock contention (e.g. CLI and gateway writing
|
||||
# concurrently) must NOT permanently disable session_search for
|
||||
# this agent. Keep _session_db alive — subsequent message
|
||||
# flushes and session_search calls will still work once the
|
||||
# lock clears. The session row may be missing from the index
|
||||
# for this run, but that is recoverable (flushes upsert rows).
|
||||
logger.warning(
|
||||
"Session DB create_session failed (session_search still available): %s", e
|
||||
)
|
||||
# Lazy session creation: defer until first message flush (#314).
|
||||
# _flush_messages_to_session_db() calls ensure_session() which uses
|
||||
# INSERT OR IGNORE — creating the row only when messages arrive.
|
||||
# This eliminates 32% of sessions that are created but never used.
|
||||
|
||||
# In-memory todo list for task planning (one per agent/session)
|
||||
from tools.todo_tool import TodoStore
|
||||
|
||||
Reference in New Issue
Block a user