feat: add @tag model override support and remove Qdrant dependencies

- Add model-tags parser for @Tag syntax in chat messages
- Support Anthropic models (Sonnet, Haiku, Opus) via @tag
- Remove Qdrant vector database from infrastructure and configs
- Simplify license model config to use null fallbacks
- Add greeting stream after model switch via @tag
- Fix protobuf field names to camelCase for v7 compatibility
- Add 429 rate limit retry logic with exponential backoff
- Remove RAG references from agent harness documentation
This commit is contained in:
2026-04-27 20:55:18 -04:00
parent 6f937f9e5e
commit d41fcd0499
50 changed files with 956 additions and 798 deletions

View File

@@ -48,6 +48,7 @@ COPY --from=builder /build/env /opt/conda/envs/dexorder
# Copy application code
COPY dexorder/ /app/dexorder/
COPY main.py /app/
COPY environment.yml /app/
# Copy generated protobuf code from builder
COPY --from=builder /build/dexorder/generated/ /app/dexorder/generated/

View File

@@ -1156,15 +1156,23 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
meta_parts.append(f"error: {result['error']}")
if result.get("revision"):
meta_parts.append(f"revision: {result['revision']}")
if result.get("validation") and not result["validation"].get("success"):
if result.get("validation"):
val = result["validation"]
error_detail = val.get('error') or ''
if val.get('output'):
error_detail = f"{error_detail}\n{val['output']}" if error_detail else val['output']
meta_parts.append(f"validation error: {error_detail.strip()}")
if not val.get("success"):
error_detail = val.get('error') or ''
if val.get('output'):
error_detail = f"{error_detail}\n{val['output']}" if error_detail else val['output']
meta_parts.append(f"validation error: {error_detail.strip()}")
elif val.get("output"):
# Always show output — may contain ⚠ WARNING for all-NaN / all-zero results
meta_parts.append(f"validation output: {val['output']}")
content.append(TextContent(type="text", text="\n".join(meta_parts)))
if result.get("execution"):
exec_content = result["execution"].get("content", [])
exec_result = result["execution"]
exec_content = exec_result.get("content", [])
if not exec_content and exec_result.get("output"):
# _execute_indicator returns plain {"output": str}, not MCP {"content": [...]}
exec_content = [TextContent(type="text", text=exec_result["output"])]
content.extend(exec_content)
image_count = sum(1 for item in exec_content if item.type == "image")
logging.info(f"PythonWrite '{arguments.get('name')}': returning {len(content)} items, {image_count} images")
@@ -1208,15 +1216,23 @@ def create_mcp_server(config: Config, event_publisher: EventPublisher) -> Server
meta_parts.append(f"error: {result['error']}")
if result.get("revision"):
meta_parts.append(f"revision: {result['revision']}")
if result.get("validation") and not result["validation"].get("success"):
if result.get("validation"):
val = result["validation"]
error_detail = val.get('error') or ''
if val.get('output'):
error_detail = f"{error_detail}\n{val['output']}" if error_detail else val['output']
meta_parts.append(f"validation error: {error_detail.strip()}")
if not val.get("success"):
error_detail = val.get('error') or ''
if val.get('output'):
error_detail = f"{error_detail}\n{val['output']}" if error_detail else val['output']
meta_parts.append(f"validation error: {error_detail.strip()}")
elif val.get("output"):
# Always show output — may contain ⚠ WARNING for all-NaN / all-zero results
meta_parts.append(f"validation output: {val['output']}")
content.append(TextContent(type="text", text="\n".join(meta_parts)))
if result.get("execution"):
exec_content = result["execution"].get("content", [])
exec_result = result["execution"]
exec_content = exec_result.get("content", [])
if not exec_content and exec_result.get("output"):
# _execute_indicator returns plain {"output": str}, not MCP {"content": [...]}
exec_content = [TextContent(type="text", text=exec_result["output"])]
content.extend(exec_content)
image_count = sum(1 for item in exec_content if item.type == "image")
logging.info(f"PythonEdit '{arguments.get('name')}': returning {len(content)} items, {image_count} images")