auto-coder-web 0.1.13__py3-none-any.whl → 0.1.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,156 @@
1
+ import os
2
+ import json
3
+ import uuid
4
+ import logging
5
+ import asyncio
6
+ import aiofiles
7
+ from fastapi import APIRouter, HTTPException
8
+ from pydantic import BaseModel
9
+ from typing import List, Optional
10
+ from datetime import datetime
11
+ from pathlib import Path
12
+
13
+ router = APIRouter()
14
+
15
+ # 配置存储路径
16
+ TODO_FILE = Path(".auto-coder/auto-coder.web/todos/todos.json")
17
+
18
+ # 确保目录存在
19
+ TODO_FILE.parent.mkdir(parents=True, exist_ok=True)
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ class TodoItem(BaseModel):
24
+ id: str
25
+ title: str
26
+ status: str # pending/developing/testing/done
27
+ priority: str # P0/P1/P2/P3
28
+ tags: List[str] = []
29
+ owner: Optional[str] = None
30
+ due_date: Optional[str] = None
31
+ created_at: str
32
+ updated_at: str
33
+
34
+ class CreateTodoRequest(BaseModel):
35
+ title: str
36
+ priority: str
37
+ tags: List[str] = []
38
+
39
+ class ReorderTodoRequest(BaseModel):
40
+ source_status: str
41
+ source_index: int
42
+ destination_status: str
43
+ destination_index: int
44
+ todo_id: str
45
+
46
+ async def load_todos() -> List[TodoItem]:
47
+ """异步加载所有待办事项"""
48
+ if not await asyncio.to_thread(lambda: TODO_FILE.exists()):
49
+ return []
50
+
51
+ try:
52
+ async with aiofiles.open(TODO_FILE, mode='r') as f:
53
+ content = await f.read()
54
+ return [TodoItem(**item) for item in json.loads(content)]
55
+ except (json.JSONDecodeError, FileNotFoundError):
56
+ logger.error("Failed to parse todos.json, returning empty list")
57
+ return []
58
+
59
+ async def save_todos(todos: List[TodoItem]):
60
+ """异步保存待办事项"""
61
+ async with aiofiles.open(TODO_FILE, mode='w') as f:
62
+ await f.write(json.dumps([todo.dict() for todo in todos], indent=2,ensure_ascii=False))
63
+
64
+ @router.get("/api/todos", response_model=List[TodoItem])
65
+ async def get_all_todos():
66
+ """获取所有待办事项"""
67
+ return await load_todos()
68
+
69
+ @router.post("/api/todos", response_model=TodoItem)
70
+ async def create_todo(request: CreateTodoRequest):
71
+ """创建新待办事项"""
72
+ todos = await load_todos()
73
+
74
+ new_todo = TodoItem(
75
+ id=str(uuid.uuid4()),
76
+ title=request.title,
77
+ status="pending",
78
+ priority=request.priority,
79
+ tags=request.tags,
80
+ created_at=datetime.now().isoformat(),
81
+ updated_at=datetime.now().isoformat()
82
+ )
83
+
84
+ todos.append(new_todo)
85
+ await save_todos(todos)
86
+ return new_todo
87
+
88
+ @router.put("/api/todos/{todo_id}", response_model=TodoItem)
89
+ async def update_todo(todo_id: str, update_data: dict):
90
+ """更新待办事项"""
91
+ todos = await load_todos()
92
+
93
+ for index, todo in enumerate(todos):
94
+ if todo.id == todo_id:
95
+ updated_data = todos[index].dict()
96
+ updated_data.update(update_data)
97
+ updated_data["updated_at"] = datetime.now().isoformat()
98
+ todos[index] = TodoItem(**updated_data)
99
+ await save_todos(todos)
100
+ return todos[index]
101
+
102
+ raise HTTPException(status_code=404, detail="Todo not found")
103
+
104
+ @router.delete("/api/todos/{todo_id}")
105
+ async def delete_todo(todo_id: str):
106
+ """删除待办事项"""
107
+ todos = await load_todos()
108
+ new_todos = [todo for todo in todos if todo.id != todo_id]
109
+
110
+ if len(new_todos) == len(todos):
111
+ raise HTTPException(status_code=404, detail="Todo not found")
112
+
113
+ await save_todos(new_todos)
114
+ return {"status": "success"}
115
+
116
+ @router.post("/api/todos/reorder")
117
+ async def reorder_todos(request: ReorderTodoRequest):
118
+ """处理拖放排序"""
119
+ todos = await load_todos()
120
+
121
+ # 找到移动的待办事项
122
+ moved_todo = next((t for t in todos if t.id == request.todo_id), None)
123
+ if not moved_todo:
124
+ raise HTTPException(status_code=404, detail="Todo not found")
125
+
126
+ # 移除原位置
127
+ todos = [t for t in todos if t.id != request.todo_id]
128
+
129
+ # 更新状态
130
+ moved_todo.status = request.destination_status
131
+ moved_todo.updated_at = datetime.now().isoformat()
132
+
133
+ # 插入新位置
134
+ todos.insert(
135
+ await get_insert_index(todos, request.destination_status, request.destination_index),
136
+ moved_todo
137
+ )
138
+
139
+ await save_todos(todos)
140
+ return {"status": "success"}
141
+
142
+ async def get_insert_index(todos: List[TodoItem], status: str, destination_index: int) -> int:
143
+ """计算插入位置的绝对索引"""
144
+ status_todos = [i for i, t in enumerate(todos) if t.status == status]
145
+ if not status_todos:
146
+ return len(todos)
147
+
148
+ # 确保目标索引在有效范围内
149
+ destination_index = min(max(destination_index, 0), len(status_todos))
150
+
151
+ # 如果目标列没有项目,直接插入到最后
152
+ if not status_todos:
153
+ return len(todos)
154
+
155
+ # 返回目标列中对应位置的索引
156
+ return status_todos[destination_index] if destination_index < len(status_todos) else status_todos[-1] + 1
@@ -0,0 +1,72 @@
1
+ from pydantic import BaseModel
2
+ from typing import List, Dict, Any, Optional
3
+ from datetime import datetime
4
+
5
+
6
+ class EventGetRequest(BaseModel):
7
+ request_id: str
8
+
9
+
10
+ class EventResponseRequest(BaseModel):
11
+ request_id: str
12
+ event: Dict[str, str]
13
+ response: str
14
+
15
+
16
+ class CompletionItem(BaseModel):
17
+ name: str
18
+ path: str
19
+ display: str
20
+ location: Optional[str] = None
21
+
22
+
23
+ class CompletionResponse(BaseModel):
24
+ completions: List[CompletionItem]
25
+
26
+
27
+ class ChatList(BaseModel):
28
+ name: str
29
+ messages: List[Dict[str, Any]]
30
+
31
+
32
+ class HistoryQuery(BaseModel):
33
+ query: str
34
+ timestamp: Optional[str] = None
35
+
36
+
37
+ class ValidationResponse(BaseModel):
38
+ success: bool
39
+ message: str = ""
40
+ queries: List[HistoryQuery] = []
41
+
42
+
43
+ class QueryWithFileNumber(BaseModel):
44
+ query: str
45
+ timestamp: Optional[str] = None
46
+ file_number: int
47
+ response: Optional[str] = None
48
+ urls: Optional[List[str]] = None
49
+
50
+
51
+ class ValidationResponseWithFileNumbers(BaseModel):
52
+ success: bool
53
+ message: str = ""
54
+ queries: List[QueryWithFileNumber] = []
55
+
56
+
57
+ class FileContentResponse(BaseModel):
58
+ success: bool
59
+ message: str = ""
60
+ content: Optional[str] = None
61
+
62
+
63
+ class FileChange(BaseModel):
64
+ path: str
65
+ change_type: str # "added" 或 "modified"
66
+
67
+
68
+ class CommitDiffResponse(BaseModel):
69
+ success: bool
70
+ message: str = ""
71
+ diff: Optional[str] = None
72
+ file_changes: Optional[List[FileChange]] = None
auto_coder_web/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.13"
1
+ __version__ = "0.1.15"
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "/static/css/main.10e5dd19.css",
4
- "main.js": "/static/js/main.74620d2e.js",
4
+ "main.js": "/static/js/main.34adf43b.js",
5
5
  "static/js/453.d855a71b.chunk.js": "/static/js/453.d855a71b.chunk.js",
6
6
  "index.html": "/index.html",
7
7
  "main.10e5dd19.css.map": "/static/css/main.10e5dd19.css.map",
8
- "main.74620d2e.js.map": "/static/js/main.74620d2e.js.map",
8
+ "main.34adf43b.js.map": "/static/js/main.34adf43b.js.map",
9
9
  "453.d855a71b.chunk.js.map": "/static/js/453.d855a71b.chunk.js.map"
10
10
  },
11
11
  "entrypoints": [
12
12
  "static/css/main.10e5dd19.css",
13
- "static/js/main.74620d2e.js"
13
+ "static/js/main.34adf43b.js"
14
14
  ]
15
15
  }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.74620d2e.js"></script><link href="/static/css/main.10e5dd19.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.34adf43b.js"></script><link href="/static/css/main.10e5dd19.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>