MCPcopy Create free account
hub / github.com/AutoForgeAI/autoforge / _query_claude

Method _query_claude

server/services/spec_chat_session.py:247–422  ·  view source on GitHub ↗

Internal method to query Claude and stream responses. Handles tool calls (Write) and text responses. Supports multimodal content with image attachments. IMPORTANT: Spec creation requires BOTH files to be written: 1. app_spec.txt - the main specification

(
        self,
        message: str,
        attachments: list[ImageAttachment] | None = None
    )

Source from the content-addressed store, hash-verified

245 }
246
247 async def _query_claude(
248 self,
249 message: str,
250 attachments: list[ImageAttachment] | None = None
251 ) -> AsyncGenerator[dict, None]:
252 """
253 Internal method to query Claude and stream responses.
254
255 Handles tool calls (Write) and text responses.
256 Supports multimodal content with image attachments.
257
258 IMPORTANT: Spec creation requires BOTH files to be written:
259 1. app_spec.txt - the main specification
260 2. initializer_prompt.md - tells the agent how many features to create
261
262 We only signal spec_complete when BOTH files are verified on disk.
263 """
264 if not self.client:
265 return
266
267 # Build the message content
268 if attachments and len(attachments) > 0:
269 # Multimodal message: build content blocks array
270 content_blocks: list[dict[str, Any]] = []
271
272 # Add text block if there's text
273 if message:
274 content_blocks.append({"type": "text", "text": message})
275
276 # Add image blocks
277 for att in attachments:
278 content_blocks.append({
279 "type": "image",
280 "source": {
281 "type": "base64",
282 "media_type": att.mimeType,
283 "data": att.base64Data,
284 }
285 })
286
287 # Send multimodal content to Claude using async generator format
288 # The SDK's query() accepts AsyncIterable[dict] for custom message formats
289 await self.client.query(make_multimodal_message(content_blocks))
290 logger.info(f"Sent multimodal message with {len(attachments)} image(s)")
291 else:
292 # Text-only message: use string format
293 await self.client.query(message)
294
295 current_text = ""
296
297 # Track pending writes for BOTH required files
298 pending_writes: dict[str, dict[str, Any] | None] = {
299 "app_spec": None, # {"tool_id": ..., "path": ...}
300 "initializer": None, # {"tool_id": ..., "path": ...}
301 }
302
303 # Track which files have been successfully written
304 files_written = {

Callers 2

startMethod · 0.95
send_messageMethod · 0.95

Calls 1

make_multimodal_messageFunction · 0.85

Tested by

no test coverage detected