-
Notifications
You must be signed in to change notification settings - Fork 15
feat/nanobot-integration #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
3119c96
985b142
01754d7
6d4b29d
541502c
f038f57
893375e
7158cd1
2be6057
36bfa9c
2ca39fc
0edf7f8
536d2c3
662aaee
7c7c714
ee15111
88805b5
08443a5
62b10ed
0346ab4
92d2916
184e7fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,6 +113,10 @@ class ChatRequest(BaseModel): | |
| # Mode: "ask" (read-only) or "agent" (full editing) | ||
| mode: str = "ask" | ||
|
|
||
| # Direct apply mode: when True, file edits are written directly to storage | ||
| # instead of creating shadow documents. Used by nanobot/API consumers. | ||
| directApply: bool = False | ||
|
|
||
| # Session support | ||
| sessionId: Optional[str] = None | ||
|
|
||
|
|
@@ -142,6 +146,17 @@ class ChatRequest(BaseModel): | |
| conversationId: Optional[str] = None | ||
|
|
||
|
|
||
| class SyncChatRequest(BaseModel): | ||
| """Synchronous chat request for programmatic invocation (e.g., from nanobot)""" | ||
|
|
||
| projectId: str | ||
| message: str | ||
| userId: Optional[str] = None | ||
| mode: str = "agent" | ||
| referencedFiles: Optional[List[str]] = [] | ||
| conversationHistory: Optional[List[Dict[str, Any]]] = None | ||
|
|
||
|
|
||
| # ============================================================================ | ||
| # API Endpoints | ||
| # ============================================================================ | ||
|
|
@@ -225,6 +240,7 @@ async def event_generator(): | |
| session_id=request.sessionId or request.conversationId, | ||
| mode=request.mode, # "ask" or "agent" | ||
| user_id=request.actorId, | ||
| direct_apply=request.directApply, | ||
|
||
| ): | ||
| yield output.to_sse() | ||
|
|
||
|
|
@@ -275,3 +291,54 @@ async def get_config(): | |
| "compressionThreshold": config.context_compression_threshold, | ||
| "compressionTarget": config.context_compression_target, | ||
| } | ||
|
|
||
|
|
||
| @router.post("/run-sync") | ||
| async def run_chat_sync(request: SyncChatRequest): | ||
| """ | ||
| Synchronous chat endpoint for programmatic invocation. | ||
|
|
||
| Unlike /run which streams SSE events, this endpoint waits for the agent | ||
| to complete and returns a JSON response. Used by nanobot and other API | ||
| consumers that need to invoke litewrite's built-in AI agent. | ||
|
|
||
| The agent runs in direct-apply mode: file edits are written directly | ||
| to storage (via /api/internal/files/edit) instead of creating shadow | ||
| documents that require frontend review. | ||
|
|
||
| Returns: | ||
| JSON with success status and the agent's response text. | ||
| """ | ||
| from services.chat_1_5 import ChatService | ||
|
|
||
| service = ChatService(verbose=True) | ||
|
|
||
| # Build query with file references if provided | ||
| query_parts = [request.message] | ||
| if request.referencedFiles: | ||
| refs = [f"[[FILE:{f}]]" for f in request.referencedFiles] | ||
| query_parts = [" ".join(refs) + " " + request.message] | ||
| query = "\n".join(query_parts) | ||
|
|
||
| try: | ||
| result = await service.run_sync( | ||
| project_id=request.projectId, | ||
| user_id=request.userId or "", | ||
| query=query, | ||
| mode=request.mode, | ||
| conversation_history=request.conversationHistory, | ||
| direct_apply=True, # Always direct-apply for sync endpoint | ||
| ) | ||
|
|
||
| return { | ||
| "success": True, | ||
| "response": result, | ||
| } | ||
|
|
||
| except Exception as e: | ||
| logger.error(f"[run-sync] Error: {e}", exc_info=True) | ||
| return { | ||
| "success": False, | ||
| "error": str(e), | ||
| "response": "", | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
directApplyflag is documented as the switch to bypass shadow documents, but it is never read or forwarded intoChatService.run/ToolContextfor the streaming/api/chat/runendpoint. As a result, API consumers that setdirectApply: truewill still get shadow-document edits instead of direct writes, which contradicts the fieldโs contract and breaks the intended integration flow. This should be wired through toChatService.run(or removed if unsupported) so the flag actually affects edit behavior.Useful? React with ๐ย / ๐.