Files
ai/gateway/docs/details-edit-protocol.md

4.2 KiB

Details Edit Protocol

This document describes the WebSocket message protocol for reading and editing the details field of category items (indicators, strategies, research scripts) from the web client.

Background

Every category item stored in the sandbox has a details field: a full markdown description of the implementation with enough detail that another coding agent could reproduce the code from it alone. The web client can display this field, allow the user to edit it in plain text, and submit the revised version — the gateway then diffs the old vs new details and instructs the appropriate subagent to update the Python code accordingly.

The details field is intentionally filtered out of the workspace _types stores (see mcp-tool-wrapper.ts:filterTypeStoreState) because it can be several kilobytes of markdown. The read/update protocol below provides direct, on-demand access.


Message Flow

1. Read Details

Client → Server

{
  "type": "read_details",
  "category": "indicator" | "strategy" | "research",
  "name": "My Indicator Name"
}

Server → Client (success)

{
  "type": "details_data",
  "category": "indicator",
  "name": "My Indicator Name",
  "details": "## My Indicator\n\nFull markdown description..."
}

Server → Client (error)

{
  "type": "details_error",
  "category": "indicator",
  "name": "My Indicator Name",
  "error": "Item not found or has no details"
}

2. Submit Updated Details

Client → Server

{
  "type": "update_details",
  "category": "indicator" | "strategy" | "research",
  "name": "My Indicator Name",
  "details": "## My Indicator\n\nRevised full markdown description..."
}

The gateway will:

  1. Read the current details from the sandbox via PythonRead
  2. Compute a unified diff between the old and new text
  3. If no changes are detected, reply immediately with details_updated (success)
  4. Otherwise, invoke the appropriate subagent (indicator / strategy / research) with instructions to update the Python code according to the diff, and also persist the new details text

While the subagent is running, the server streams progress events using the same event types as normal agent interactions:

{ "type": "subagent_chunk",    "agentName": "indicator", "content": "Reading current implementation..." }
{ "type": "subagent_tool_call", "agentName": "indicator", "toolName": "PythonRead",  "label": "PythonRead" }
{ "type": "subagent_tool_call", "agentName": "indicator", "toolName": "PythonEdit",  "label": "PythonEdit" }
{ "type": "subagent_chunk",    "agentName": "indicator", "content": "Applied patch. Validation passed." }

Server → Client (completion)

{
  "type": "details_updated",
  "category": "indicator",
  "name": "My Indicator Name",
  "success": true
}

or on failure:

{
  "type": "details_updated",
  "category": "indicator",
  "name": "My Indicator Name",
  "success": false,
  "error": "Failed to update details"
}

Workspace Sync After Update

When the subagent calls PythonEdit, the sandbox returns a _workspace_sync payload in the MCP response. The gateway automatically applies this to the {category}_types workspace store and sends a WebSocket patch message to the client (the normal workspace sync path). The client should listen for these patches to refresh any UI that displays list metadata (name, description).

The details field itself is not in the workspace store — the client must call read_details again if it needs the refreshed details text after an update.


Implementation Notes

Component File Responsibility
WebSocket routing src/channels/websocket-handler.ts Parse read_details / update_details, stream subagent events, send details_data / details_updated
Harness methods src/harness/agent-harness.ts readDetails(), streamDetailsUpdate()
Diff utility src/harness/agent-harness.ts buildUnifiedDiff(), computeLCS() (module-level helpers)
Instruction builder src/harness/agent-harness.ts buildDetailsUpdateInstruction()
Details filter src/tools/mcp/mcp-tool-wrapper.ts filterTypeStoreState() — strips details before workspace sync