subagent thinking accordion; indicator fixes; script details & edit

This commit is contained in:
2026-04-20 15:09:37 -04:00
parent a188268906
commit b1d4459809
25 changed files with 2041 additions and 174 deletions

View File

@@ -197,26 +197,6 @@ def _get_env_yml() -> Optional[Path]:
return p if p.exists() else None
def _populate_indicator_types_from_disk(workspace_store, category_manager) -> None:
"""Scan existing indicators and add any missing entries to indicator_types store."""
existing = workspace_store.read('indicator_types')
existing_types = (existing.get('data') or {}).get('types') or {}
list_result = category_manager.list_items('indicator')
items = list_result.get('items', [])
added = 0
for item in items:
item_name = item.get('name', '')
if not item_name:
continue
pandas_ta_name = f"custom_{sanitize_name(item_name).lower()}"
if pandas_ta_name not in existing_types:
_upsert_indicator_type(workspace_store, category_manager, item_name)
added += 1
if added > 0:
logging.info(f"Populated {added} indicator type(s) from disk into indicator_types store")
# =============================================================================
# Configuration
@@ -436,6 +416,15 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
"type": "string",
"description": "LLM-generated description of what this does (required)"
},
"details": {
"type": "string",
"description": (
"Full markdown description of the code with sufficient detail that another coding agent "
"could functionally reproduce the implementation from this field alone. "
"Include: purpose, algorithm, all parameters and their semantics, data feed usage, "
"formulas, edge cases, and any non-obvious implementation choices (required)."
)
},
"code": {
"type": "string",
"description": "Python implementation code"
@@ -453,7 +442,7 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
)
}
},
"required": ["category", "name", "description", "code"]
"required": ["category", "name", "description", "details", "code"]
}
),
Tool(
@@ -500,6 +489,27 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
"type": "string",
"description": "Updated description (optional, omit to keep existing)"
},
"details": {
"type": "string",
"description": "Full replacement for the details field. Use only when rewriting the entire description; prefer 'detail_patches' for targeted edits."
},
"detail_patches": {
"type": "array",
"description": (
"Targeted edits to the details field as old/new string pairs. Preferred over 'details' for small changes. "
"Each patch: {\"old_string\": \"exact text to find\", \"new_string\": \"replacement text\"}. "
"old_string must be unique in the details field (add surrounding context if needed). "
"Patches are applied in order. Mutually exclusive with 'details'."
),
"items": {
"type": "object",
"properties": {
"old_string": {"type": "string"},
"new_string": {"type": "string"}
},
"required": ["old_string", "new_string"]
}
},
"metadata": {
"type": "object",
"description": (
@@ -912,6 +922,7 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
category=arguments.get("category", ""),
name=arguments.get("name", ""),
description=arguments.get("description", ""),
details=arguments.get("details", ""),
code=arguments.get("code", ""),
metadata=arguments.get("metadata")
)
@@ -947,6 +958,8 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
code=arguments.get("code"),
patches=arguments.get("patches"),
description=arguments.get("description"),
details=arguments.get("details"),
detail_patches=arguments.get("detail_patches"),
metadata=arguments.get("metadata")
)
content = []