Hardcode Python default empty response
This commit is contained in:
13
README.md
13
README.md
@@ -146,15 +146,14 @@ All routes are local-only and intended for `localhost` usage.
|
||||
**Purpose**
|
||||
|
||||
- Return the next pending instruction, if one exists.
|
||||
- If none exists, wait for a configurable duration, then return either an empty response or a configured default response.
|
||||
- If none exists, wait for a configurable duration, then return the server-controlled default response.
|
||||
- Record agent activity so the UI can infer whether an agent is currently connected/recently active.
|
||||
|
||||
**Suggested input schema**
|
||||
|
||||
```json
|
||||
{
|
||||
"agent_id": "optional-string",
|
||||
"default_response_override": "optional-string"
|
||||
"agent_id": "optional-string"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -194,7 +193,7 @@ All routes are local-only and intended for `localhost` usage.
|
||||
"status": "ok",
|
||||
"result_type": "default_response",
|
||||
"instruction": null,
|
||||
"response": "No new instructions available.",
|
||||
"response": "call this tool `get_user_request` again to fetch latest user input...",
|
||||
"remaining_pending": 0,
|
||||
"waited_seconds": 10
|
||||
}
|
||||
@@ -250,7 +249,7 @@ Returns current server and agent summary.
|
||||
},
|
||||
"settings": {
|
||||
"default_wait_seconds": 10,
|
||||
"default_empty_response": "No new instructions available.",
|
||||
"default_empty_response": "call this tool `get_user_request` again to fetch latest user input...",
|
||||
"agent_stale_after_seconds": 30
|
||||
}
|
||||
}
|
||||
@@ -347,7 +346,7 @@ Returns editable runtime settings.
|
||||
```json
|
||||
{
|
||||
"default_wait_seconds": 10,
|
||||
"default_empty_response": "No new instructions available.",
|
||||
"default_empty_response": "call this tool `get_user_request` again to fetch latest user input...",
|
||||
"agent_stale_after_seconds": 30
|
||||
}
|
||||
```
|
||||
@@ -562,7 +561,7 @@ The server starts on `http://localhost:8000` by default.
|
||||
| `DB_PATH` | `data/local_mcp.sqlite3` | SQLite database path |
|
||||
| `LOG_LEVEL` | `INFO` | Logging level |
|
||||
| `DEFAULT_WAIT_SECONDS` | `10` | Default tool wait timeout |
|
||||
| `DEFAULT_EMPTY_RESPONSE` | _(empty)_ | Default response when queue is empty |
|
||||
| `DEFAULT_EMPTY_RESPONSE` | `call this tool \`get_user_request\` again to fetch latest user input...` | Default response when queue is empty |
|
||||
| `AGENT_STALE_AFTER_SECONDS` | `30` | Seconds of inactivity before agent shown as idle |
|
||||
| `MCP_STATELESS` | `true` | `true` for stateless sessions (survives restarts, recommended); `false` for stateful |
|
||||
| `API_TOKEN` | _(empty)_ | When set, all `/api/*` and `/mcp` requests require `Authorization: Bearer <token>`; web UI prompts for the token on first load |
|
||||
|
||||
@@ -9,6 +9,9 @@ import os
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
DEFAULT_EMPTY_RESPONSE = "call this tool `get_user_request` again to fetch latest user input..."
|
||||
|
||||
|
||||
@dataclass
|
||||
class Settings:
|
||||
# Server
|
||||
@@ -23,7 +26,7 @@ class Settings:
|
||||
|
||||
# MCP / queue behaviour (runtime-editable values are stored in DB; these are defaults for first run)
|
||||
default_wait_seconds: int = 10
|
||||
default_empty_response: str = ""
|
||||
default_empty_response: str = DEFAULT_EMPTY_RESPONSE
|
||||
agent_stale_after_seconds: int = 30
|
||||
|
||||
# MCP server name
|
||||
@@ -53,7 +56,7 @@ def load_settings() -> Settings:
|
||||
db_path=os.getenv("DB_PATH", "data/local_mcp.sqlite3"),
|
||||
log_level=os.getenv("LOG_LEVEL", "INFO"),
|
||||
default_wait_seconds=int(os.getenv("DEFAULT_WAIT_SECONDS", "10")),
|
||||
default_empty_response=os.getenv("DEFAULT_EMPTY_RESPONSE", ""),
|
||||
default_empty_response=os.getenv("DEFAULT_EMPTY_RESPONSE", DEFAULT_EMPTY_RESPONSE),
|
||||
agent_stale_after_seconds=int(os.getenv("AGENT_STALE_AFTER_SECONDS", "30")),
|
||||
mcp_server_name=os.getenv("MCP_SERVER_NAME", "local-mcp"),
|
||||
mcp_stateless=_parse_bool(os.getenv("MCP_STATELESS", "true"), default=True),
|
||||
|
||||
@@ -12,6 +12,8 @@ import threading
|
||||
from contextlib import contextmanager
|
||||
from typing import Generator
|
||||
|
||||
from app.config import DEFAULT_EMPTY_RESPONSE
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Module-level lock for write serialisation (consume atomicity, settings writes, etc.)
|
||||
@@ -102,7 +104,7 @@ CREATE TABLE IF NOT EXISTS agent_activity (
|
||||
|
||||
_DEFAULT_SETTINGS = {
|
||||
"default_wait_seconds": "10",
|
||||
"default_empty_response": "",
|
||||
"default_empty_response": DEFAULT_EMPTY_RESPONSE,
|
||||
"agent_stale_after_seconds": "30",
|
||||
}
|
||||
|
||||
@@ -119,6 +121,10 @@ def _seed_defaults(conn: sqlite3.Connection) -> None:
|
||||
"INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)",
|
||||
(key, value),
|
||||
)
|
||||
conn.execute(
|
||||
"UPDATE settings SET value = ? WHERE key = 'default_empty_response' AND value = ''",
|
||||
(_DEFAULT_SETTINGS["default_empty_response"],),
|
||||
)
|
||||
conn.commit()
|
||||
logger.debug("Default settings seeded")
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from typing import Optional
|
||||
|
||||
from mcp.server.fastmcp import FastMCP, Context
|
||||
|
||||
from app.config import settings
|
||||
from app.config import DEFAULT_EMPTY_RESPONSE, settings
|
||||
from app.services import config_service, event_service, instruction_service, status_service
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -38,9 +38,6 @@ _MAX_WAIT_SECONDS = 86400 # 24 hours
|
||||
# multiple keepalive progress updates.
|
||||
DEFAULT_WAIT_SECONDS = 50
|
||||
|
||||
# Default response when queue is empty after waiting
|
||||
DEFAULT_EMPTY_RESPONSE = "call this tool `get_user_request` again to fetch latest user input..."
|
||||
|
||||
# Per-agent generation counter — incremented on every new call.
|
||||
# The wait loop only consumes an instruction when it holds the latest generation,
|
||||
# preventing abandoned (timed-out) coroutines from silently consuming queue items.
|
||||
@@ -65,7 +62,6 @@ KEEPALIVE_INTERVAL_SECONDS: float = 5.0
|
||||
@mcp.tool()
|
||||
async def get_user_request(
|
||||
agent_id: str = "unknown",
|
||||
default_response_override: Optional[str] = None,
|
||||
ctx: Optional[Context] = None,
|
||||
) -> dict:
|
||||
"""
|
||||
@@ -76,8 +72,6 @@ async def get_user_request(
|
||||
|
||||
Args:
|
||||
agent_id: An identifier for this agent instance (used to track connectivity).
|
||||
default_response_override: Override the server-default empty response text
|
||||
for this single call.
|
||||
|
||||
Returns:
|
||||
A dict with keys: status, result_type, instruction, response,
|
||||
@@ -222,11 +216,7 @@ async def get_user_request(
|
||||
status_service.record_agent_activity(agent_id, "empty")
|
||||
event_service.broadcast("status.changed", {})
|
||||
|
||||
empty_response = (
|
||||
default_response_override
|
||||
if default_response_override is not None
|
||||
else DEFAULT_EMPTY_RESPONSE
|
||||
)
|
||||
empty_response = DEFAULT_EMPTY_RESPONSE
|
||||
result_type = "default_response" if empty_response else "empty"
|
||||
|
||||
if _i_am_active():
|
||||
|
||||
@@ -7,21 +7,20 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from app.config import DEFAULT_EMPTY_RESPONSE
|
||||
from app.database import get_conn, get_write_conn
|
||||
from app.models import ConfigResponse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_SETTING_KEYS = {"default_wait_seconds", "default_empty_response", "agent_stale_after_seconds"}
|
||||
|
||||
|
||||
def get_config() -> ConfigResponse:
|
||||
with get_conn() as conn:
|
||||
rows = conn.execute("SELECT key, value FROM settings").fetchall()
|
||||
data = {r["key"]: r["value"] for r in rows}
|
||||
return ConfigResponse(
|
||||
default_wait_seconds=int(data.get("default_wait_seconds", 10)),
|
||||
default_empty_response=data.get("default_empty_response", ""),
|
||||
default_empty_response=data.get("default_empty_response") or DEFAULT_EMPTY_RESPONSE,
|
||||
agent_stale_after_seconds=int(data.get("agent_stale_after_seconds", 30)),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user