auto-coder-web 0.1.24__py3-none-any.whl → 0.1.25__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.
Files changed (30) hide show
  1. auto_coder_web/auto_coder_runner_wrapper.py +7 -0
  2. auto_coder_web/common_router/__init__.py +0 -0
  3. auto_coder_web/common_router/auto_coder_conf_router.py +42 -0
  4. auto_coder_web/common_router/chat_list_router.py +75 -0
  5. auto_coder_web/common_router/completions_router.py +53 -0
  6. auto_coder_web/common_router/file_group_router.py +120 -0
  7. auto_coder_web/common_router/file_router.py +78 -0
  8. auto_coder_web/proxy.py +22 -472
  9. auto_coder_web/routers/chat_router.py +330 -0
  10. auto_coder_web/routers/coding_router.py +330 -0
  11. auto_coder_web/routers/config_router.py +199 -0
  12. auto_coder_web/routers/todo_router.py +463 -20
  13. auto_coder_web/version.py +1 -1
  14. auto_coder_web/web/asset-manifest.json +6 -6
  15. auto_coder_web/web/index.html +1 -1
  16. auto_coder_web/web/static/css/main.95277c5f.css +6 -0
  17. auto_coder_web/web/static/css/main.95277c5f.css.map +1 -0
  18. auto_coder_web/web/static/js/main.66c37ccf.js +3 -0
  19. auto_coder_web/web/static/js/{main.470202a1.js.LICENSE.txt → main.66c37ccf.js.LICENSE.txt} +40 -0
  20. auto_coder_web/web/static/js/{main.470202a1.js.map → main.66c37ccf.js.map} +1 -1
  21. {auto_coder_web-0.1.24.dist-info → auto_coder_web-0.1.25.dist-info}/METADATA +1 -1
  22. {auto_coder_web-0.1.24.dist-info → auto_coder_web-0.1.25.dist-info}/RECORD +27 -16
  23. {auto_coder_web-0.1.24.dist-info → auto_coder_web-0.1.25.dist-info}/top_level.txt +1 -0
  24. expert_routers/__init__.py +3 -0
  25. expert_routers/history_router.py +333 -0
  26. auto_coder_web/web/static/css/main.770925e5.css +0 -6
  27. auto_coder_web/web/static/css/main.770925e5.css.map +0 -1
  28. auto_coder_web/web/static/js/main.470202a1.js +0 -3
  29. {auto_coder_web-0.1.24.dist-info → auto_coder_web-0.1.25.dist-info}/WHEEL +0 -0
  30. {auto_coder_web-0.1.24.dist-info → auto_coder_web-0.1.25.dist-info}/entry_points.txt +0 -0
@@ -4,11 +4,15 @@ import uuid
4
4
  import logging
5
5
  import asyncio
6
6
  import aiofiles
7
- from fastapi import APIRouter, HTTPException
7
+ from fastapi import APIRouter, HTTPException, Depends, Request
8
8
  from pydantic import BaseModel
9
- from typing import List, Optional
9
+ from typing import List, Optional, Dict, Any
10
10
  from datetime import datetime
11
11
  from pathlib import Path
12
+ from threading import Thread
13
+ from autocoder.events.event_manager_singleton import get_event_manager, gengerate_event_file_path, get_event_file_path
14
+ from autocoder.events import event_content as EventContentCreator
15
+ from auto_coder_web.auto_coder_runner_wrapper import AutoCoderRunnerWrapper
12
16
 
13
17
  router = APIRouter()
14
18
 
@@ -20,6 +24,34 @@ TODO_FILE.parent.mkdir(parents=True, exist_ok=True)
20
24
 
21
25
  logger = logging.getLogger(__name__)
22
26
 
27
+
28
+ async def get_project_path(request: Request) -> str:
29
+ """
30
+ 从FastAPI请求上下文中获取项目路径
31
+ """
32
+ return request.app.state.project_path
33
+
34
+
35
+ class Task(BaseModel):
36
+ id: int
37
+ title: str
38
+ description: Optional[str] = None
39
+ references: Optional[List[str]] = []
40
+ steps: Optional[List[str]] = []
41
+ acceptance_criteria: Optional[List[str]] = []
42
+ priority: Optional[str] = None
43
+ estimate: Optional[str] = None
44
+ # 任务状态: pending/executing/completed/failed
45
+ status: Optional[str] = "pending"
46
+ event_file_id: Optional[str] = None # 关联的执行事件ID
47
+ next_task_ready: Optional[bool] = False # 标记下一个任务是否已准备好执行
48
+
49
+
50
+ class Dependency(BaseModel):
51
+ task: str
52
+ depends_on: List[str] = []
53
+
54
+
23
55
  class TodoItem(BaseModel):
24
56
  id: str
25
57
  title: str
@@ -30,12 +62,18 @@ class TodoItem(BaseModel):
30
62
  due_date: Optional[str] = None
31
63
  created_at: str
32
64
  updated_at: str
65
+ description: Optional[str] = None
66
+ tasks: Optional[List[Task]] = None
67
+ analysis: Optional[str] = None # 任务拆分分析
68
+ dependencies: Optional[List[Dependency]] = None # 子任务间的依赖关系
69
+
33
70
 
34
71
  class CreateTodoRequest(BaseModel):
35
72
  title: str
36
73
  priority: str
37
74
  tags: List[str] = []
38
75
 
76
+
39
77
  class ReorderTodoRequest(BaseModel):
40
78
  source_status: str
41
79
  source_index: int
@@ -43,11 +81,21 @@ class ReorderTodoRequest(BaseModel):
43
81
  destination_index: int
44
82
  todo_id: str
45
83
 
84
+
85
+ class ExecuteTaskResponse(BaseModel):
86
+ status: str
87
+ task_id: str
88
+ message: str
89
+ split_result: Optional[Dict[str, Any]] = None
90
+ current_task_index: Optional[int] = None
91
+ event_file_id: Optional[str] = None
92
+
93
+
46
94
  async def load_todos() -> List[TodoItem]:
47
95
  """异步加载所有待办事项"""
48
96
  if not await asyncio.to_thread(lambda: TODO_FILE.exists()):
49
97
  return []
50
-
98
+
51
99
  try:
52
100
  async with aiofiles.open(TODO_FILE, mode='r') as f:
53
101
  content = await f.read()
@@ -56,21 +104,24 @@ async def load_todos() -> List[TodoItem]:
56
104
  logger.error("Failed to parse todos.json, returning empty list")
57
105
  return []
58
106
 
107
+
59
108
  async def save_todos(todos: List[TodoItem]):
60
109
  """异步保存待办事项"""
61
110
  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))
111
+ await f.write(json.dumps([todo.dict() for todo in todos], indent=2, ensure_ascii=False))
112
+
63
113
 
64
114
  @router.get("/api/todos", response_model=List[TodoItem])
65
115
  async def get_all_todos():
66
116
  """获取所有待办事项"""
67
117
  return await load_todos()
68
118
 
119
+
69
120
  @router.post("/api/todos", response_model=TodoItem)
70
121
  async def create_todo(request: CreateTodoRequest):
71
122
  """创建新待办事项"""
72
123
  todos = await load_todos()
73
-
124
+
74
125
  new_todo = TodoItem(
75
126
  id=str(uuid.uuid4()),
76
127
  title=request.title,
@@ -80,77 +131,469 @@ async def create_todo(request: CreateTodoRequest):
80
131
  created_at=datetime.now().isoformat(),
81
132
  updated_at=datetime.now().isoformat()
82
133
  )
83
-
134
+
84
135
  todos.append(new_todo)
85
136
  await save_todos(todos)
86
137
  return new_todo
87
138
 
139
+
88
140
  @router.put("/api/todos/{todo_id}", response_model=TodoItem)
89
141
  async def update_todo(todo_id: str, update_data: dict):
90
142
  """更新待办事项"""
91
143
  todos = await load_todos()
92
-
144
+
93
145
  for index, todo in enumerate(todos):
94
146
  if todo.id == todo_id:
95
- updated_data = todos[index].dict()
147
+ updated_data = todos[index].model_dump()
96
148
  updated_data.update(update_data)
97
149
  updated_data["updated_at"] = datetime.now().isoformat()
98
150
  todos[index] = TodoItem(**updated_data)
99
151
  await save_todos(todos)
100
152
  return todos[index]
101
-
153
+
102
154
  raise HTTPException(status_code=404, detail="Todo not found")
103
155
 
156
+
104
157
  @router.delete("/api/todos/{todo_id}")
105
158
  async def delete_todo(todo_id: str):
106
159
  """删除待办事项"""
107
160
  todos = await load_todos()
108
161
  new_todos = [todo for todo in todos if todo.id != todo_id]
109
-
162
+
110
163
  if len(new_todos) == len(todos):
111
164
  raise HTTPException(status_code=404, detail="Todo not found")
112
-
165
+
113
166
  await save_todos(new_todos)
114
167
  return {"status": "success"}
115
168
 
169
+
170
+ @router.get("/api/todos/{todo_id}", response_model=TodoItem)
171
+ async def get_single_todo(todo_id: str):
172
+ """获取单个待办事项的详细信息"""
173
+ todos = await load_todos()
174
+
175
+ # 查找指定ID的待办事项
176
+ todo = next((t for t in todos if t.id == todo_id), None)
177
+
178
+ # 如果未找到,返回404错误
179
+ if not todo:
180
+ raise HTTPException(status_code=404, detail="Todo not found")
181
+
182
+ return todo
183
+
184
+
116
185
  @router.post("/api/todos/reorder")
117
186
  async def reorder_todos(request: ReorderTodoRequest):
118
187
  """处理拖放排序"""
119
188
  todos = await load_todos()
120
-
189
+
121
190
  # 找到移动的待办事项
122
191
  moved_todo = next((t for t in todos if t.id == request.todo_id), None)
123
192
  if not moved_todo:
124
193
  raise HTTPException(status_code=404, detail="Todo not found")
125
-
194
+
126
195
  # 移除原位置
127
196
  todos = [t for t in todos if t.id != request.todo_id]
128
-
197
+
129
198
  # 更新状态
130
199
  moved_todo.status = request.destination_status
131
200
  moved_todo.updated_at = datetime.now().isoformat()
132
-
201
+
133
202
  # 插入新位置
134
203
  todos.insert(
135
204
  await get_insert_index(todos, request.destination_status, request.destination_index),
136
205
  moved_todo
137
206
  )
138
-
207
+
139
208
  await save_todos(todos)
140
209
  return {"status": "success"}
141
210
 
211
+
142
212
  async def get_insert_index(todos: List[TodoItem], status: str, destination_index: int) -> int:
143
213
  """计算插入位置的绝对索引"""
144
214
  status_todos = [i for i, t in enumerate(todos) if t.status == status]
145
215
  if not status_todos:
146
216
  return len(todos)
147
-
217
+
148
218
  # 确保目标索引在有效范围内
149
219
  destination_index = min(max(destination_index, 0), len(status_todos))
150
-
220
+
151
221
  # 如果目标列没有项目,直接插入到最后
152
222
  if not status_todos:
153
223
  return len(todos)
154
-
224
+
155
225
  # 返回目标列中对应位置的索引
156
- return status_todos[destination_index] if destination_index < len(status_todos) else status_todos[-1] + 1
226
+ return status_todos[destination_index] if destination_index < len(status_todos) else status_todos[-1] + 1
227
+
228
+
229
+ async def get_project_path(request: Request) -> str:
230
+ """从FastAPI请求上下文中获取项目路径"""
231
+ return request.app.state.project_path
232
+
233
+
234
+ def generate_command_from_task(task: Task, todo: TodoItem) -> str:
235
+ """
236
+ 根据任务信息生成执行命令
237
+
238
+ Args:
239
+ task: 要执行的任务对象
240
+ todo: 所属的待办事项对象
241
+
242
+ Returns:
243
+ 用于执行的coding命令
244
+ """
245
+ # 构建任务上下文信息
246
+ context = {
247
+ "todo_title": todo.title,
248
+ "todo_description": todo.description or "",
249
+ "task_title": task.title,
250
+ "task_description": task.description or "",
251
+ "references": task.references or [],
252
+ "steps": task.steps or [],
253
+ "acceptance_criteria": task.acceptance_criteria or []
254
+ }
255
+
256
+ # 构建提示
257
+ prompt = f"""请根据以下任务需求帮我实现功能:
258
+
259
+ ## 主任务
260
+ 标题: {context['todo_title']}
261
+ 描述: {context['todo_description']}
262
+
263
+ ## 当前子任务
264
+ 标题: {context['task_title']}
265
+ 描述: {context['task_description']}
266
+
267
+ ## 实现步骤
268
+ {chr(10).join([f"- {step}" for step in context['steps']])}
269
+
270
+ ## 技术参考
271
+ {chr(10).join([f"- {ref}" for ref in context['references']])}
272
+
273
+ ## 验收标准
274
+ {chr(10).join([f"- {criterion}" for criterion in context['acceptance_criteria']])}
275
+
276
+ 请根据上述信息,完成这个子任务。首先分析任务需求,然后编写代码实现。如果需要,请修改或创建必要的文件。
277
+ 在实现过程中,请遵循代码最佳实践,保持代码清晰、可维护。
278
+ """
279
+
280
+ # 创建coding命令
281
+ return prompt
282
+
283
+
284
+ async def update_task_status(todo_id: str, task_index: int, new_status: str, event_file_id: Optional[str] = None):
285
+ """
286
+ 更新任务状态
287
+
288
+ Args:
289
+ todo_id: 待办事项ID
290
+ task_index: 任务索引
291
+ new_status: 新状态 (pending/executing/completed/failed)
292
+ event_file_id: 关联的事件文件ID
293
+ """
294
+ try:
295
+ # 加载所有待办事项
296
+ todos = await load_todos()
297
+
298
+ # 查找指定的待办事项
299
+ todo_index = next(
300
+ (i for i, t in enumerate(todos) if t.id == todo_id), None)
301
+ if todo_index is None:
302
+ logger.error(f"Todo {todo_id} not found for status update")
303
+ return
304
+
305
+ # 更新任务状态
306
+ if 0 <= task_index < len(todos[todo_index].tasks):
307
+ todos[todo_index].tasks[task_index].status = new_status
308
+ if event_file_id:
309
+ todos[todo_index].tasks[task_index].event_file_id = event_file_id
310
+
311
+ # 如果当前任务完成,且有下一个任务,则自动开始下一个任务
312
+ if new_status == "completed" and task_index + 1 < len(todos[todo_index].tasks):
313
+ next_task = todos[todo_index].tasks[task_index + 1]
314
+ if next_task.status == "pending":
315
+ # 任务完成后,启动下一个任务(通过API)
316
+ # 注意:这里不直接执行,而是记录一个标志,由前端轮询检测并触发
317
+ todos[todo_index].tasks[task_index].next_task_ready = True
318
+
319
+ # 检查所有任务状态,更新整体状态
320
+ all_completed = all(
321
+ task.status == "completed" for task in todos[todo_index].tasks)
322
+ if all_completed:
323
+ todos[todo_index].status = "done"
324
+
325
+ # 保存更新后的待办事项
326
+ await save_todos(todos)
327
+
328
+ logger.info(
329
+ f"Updated task {task_index} status to {new_status} for todo {todo_id}")
330
+ else:
331
+ logger.error(
332
+ f"Task index {task_index} out of range for todo {todo_id}")
333
+ except Exception as e:
334
+ logger.error(f"Error updating task status: {str(e)}")
335
+
336
+
337
+ async def update_todo_status(todo_id: str, new_status: str):
338
+ """
339
+ 更新待办事项的状态
340
+
341
+ Args:
342
+ todo_id: 待办事项ID
343
+ new_status: 新状态
344
+ """
345
+ try:
346
+ # 加载所有待办事项
347
+ todos = await load_todos()
348
+
349
+ # 查找指定的待办事项
350
+ todo_index = next(
351
+ (i for i, t in enumerate(todos) if t.id == todo_id), None)
352
+ if todo_index is None:
353
+ logger.error(f"Todo {todo_id} not found when updating todo status")
354
+ return
355
+
356
+ # 更新待办事项状态
357
+ todos[todo_index].status = new_status
358
+
359
+ # 保存更新后的待办事项
360
+ await save_todos(todos)
361
+
362
+ logger.info(f"Updated todo {todo_id} status to {new_status}")
363
+ except Exception as e:
364
+ logger.error(f"Error updating todo status: {str(e)}")
365
+
366
+
367
+ async def mark_next_task_ready(todo_id: str, current_task_index: int):
368
+ """
369
+ 标记下一个任务准备好执行
370
+
371
+ Args:
372
+ todo_id: 待办事项ID
373
+ current_task_index: 当前任务索引
374
+ """
375
+ try:
376
+ # 加载所有待办事项
377
+ todos = await load_todos()
378
+
379
+ # 查找指定的待办事项
380
+ todo_index = next(
381
+ (i for i, t in enumerate(todos) if t.id == todo_id), None)
382
+ if todo_index is None:
383
+ logger.error(
384
+ f"Todo {todo_id} not found when marking next task ready")
385
+ return
386
+
387
+ # 验证任务索引
388
+ if not todos[todo_index].tasks or current_task_index < 0 or current_task_index >= len(todos[todo_index].tasks) - 1:
389
+ logger.error(
390
+ f"Invalid task index {current_task_index} for todo {todo_id} or no next task available")
391
+ return
392
+
393
+ # 标记当前任务的next_task_ready为True
394
+ todos[todo_index].tasks[current_task_index].next_task_ready = True
395
+
396
+ # 保存更新后的待办事项
397
+ await save_todos(todos)
398
+
399
+ logger.info(
400
+ f"Marked next task ready after task {current_task_index} for todo {todo_id}")
401
+ except Exception as e:
402
+ logger.error(f"Error marking next task ready: {str(e)}")
403
+
404
+
405
+ @router.get("/api/todos/{todo_id}/tasks/status")
406
+ async def get_tasks_status(todo_id: str):
407
+ """
408
+ 获取待办事项的所有任务状态
409
+
410
+ Args:
411
+ todo_id: 待办事项ID
412
+
413
+ Returns:
414
+ 任务状态列表
415
+ """
416
+ todos = await load_todos()
417
+
418
+ # 查找指定的待办事项
419
+ todo = next((t for t in todos if t.id == todo_id), None)
420
+ if not todo:
421
+ raise HTTPException(status_code=404, detail="Todo not found")
422
+
423
+ # 如果没有任务,返回空列表
424
+ if not todo.tasks:
425
+ return {"tasks": []}
426
+
427
+ # 准备任务状态数据
428
+ tasks_status = []
429
+ for i, task in enumerate(todo.tasks):
430
+ status_data = {
431
+ "index": i,
432
+ "title": task.title,
433
+ "status": task.status,
434
+ "event_file_id": task.event_file_id,
435
+ "next_task_ready": task.next_task_ready
436
+ }
437
+ tasks_status.append(status_data)
438
+
439
+ # 检查是否有下一个准备执行的任务
440
+ next_task_index = next((i for i, task in enumerate(
441
+ todo.tasks) if task.next_task_ready), None)
442
+
443
+ return {
444
+ "tasks": tasks_status,
445
+ "next_task_index": next_task_index
446
+ }
447
+
448
+
449
+ @router.post("/api/todos/{todo_id}/execute-tasks")
450
+ async def execute_todo_tasks(todo_id: str, project_path: str = Depends(get_project_path)):
451
+ """
452
+ 按顺序执行待办事项的所有任务
453
+
454
+ Args:
455
+ todo_id: 待办事项ID
456
+
457
+ Returns:
458
+ 执行状态
459
+ """
460
+ todos = await load_todos()
461
+
462
+ # 查找指定的待办事项
463
+ todo = next((t for t in todos if t.id == todo_id), None)
464
+ if not todo:
465
+ raise HTTPException(status_code=404, detail="Todo not found")
466
+
467
+ # 检查是否有任务
468
+ if not todo.tasks or len(todo.tasks) == 0:
469
+ raise HTTPException(
470
+ status_code=400, detail="No tasks found in this todo item")
471
+
472
+ # 更新待办事项状态为正在执行
473
+ todo_index = next(
474
+ (i for i, t in enumerate(todos) if t.id == todo_id), None)
475
+ if todo_index is not None:
476
+ todos[todo_index].status = "developing"
477
+ await save_todos(todos)
478
+
479
+ # 创建一个列表来存储所有任务的执行状态
480
+ task_execution_results = []
481
+
482
+ # 定义执行单个任务的函数
483
+ async def execute_single_task(task_index: int):
484
+ task = todo.tasks[task_index]
485
+
486
+ # 构建执行命令
487
+ command = generate_command_from_task(task, todo)
488
+
489
+ # 生成事件文件路径
490
+ event_file, file_id = gengerate_event_file_path()
491
+
492
+ # 更新任务状态
493
+ todo.tasks[task_index].status = "executing"
494
+ todo.tasks[task_index].event_file_id = file_id
495
+
496
+ # 保存更新后的待办事项
497
+ await save_todos(todos)
498
+
499
+ return task, event_file, file_id
500
+
501
+ # 定义线程中运行的函数
502
+ def run_tasks_in_thread():
503
+ try:
504
+ for i, task in enumerate(todo.tasks):
505
+ try:
506
+ # 获取当前任务的信息
507
+ current_task, event_file, file_id = asyncio.run(
508
+ execute_single_task(i))
509
+
510
+ # 创建AutoCoderRunnerWrapper实例
511
+ wrapper = AutoCoderRunnerWrapper(project_path)
512
+ wrapper.configure_wrapper(f"event_file:{event_file}")
513
+
514
+ # 调用coding方法执行任务
515
+ command = generate_command_from_task(current_task, todo)
516
+ result = wrapper.coding_wapper(command)
517
+
518
+ # 标记任务完成
519
+ get_event_manager(event_file).write_completion(
520
+ EventContentCreator.create_completion(
521
+ "200", "completed", result).to_dict()
522
+ )
523
+
524
+ # 更新任务状态
525
+ asyncio.run(update_task_status(
526
+ todo_id, i, "completed", file_id))
527
+
528
+ # 如果还有下一个任务,标记它准备好执行
529
+ if i < len(todo.tasks) - 1:
530
+ asyncio.run(mark_next_task_ready(todo_id, i))
531
+
532
+ logger.info(
533
+ f"Task {i+1}/{len(todo.tasks)} (ID: {file_id}) for todo {todo_id} completed successfully")
534
+
535
+ # 添加到结果列表
536
+ task_execution_results.append({
537
+ "task_index": i,
538
+ "task_id": file_id,
539
+ "status": "completed",
540
+ "title": current_task.title
541
+ })
542
+
543
+ except Exception as e:
544
+ logger.error(
545
+ f"Error executing task {i+1}/{len(todo.tasks)} for todo {todo_id}: {str(e)}")
546
+
547
+ # 标记任务失败
548
+ if 'event_file' in locals():
549
+ get_event_manager(event_file).write_error(
550
+ EventContentCreator.create_error(
551
+ "500", "error", str(e)).to_dict()
552
+ )
553
+
554
+ # 更新任务状态为失败
555
+ if 'file_id' in locals():
556
+ asyncio.run(update_task_status(
557
+ todo_id, i, "failed", file_id))
558
+
559
+ # 添加到结果列表
560
+ task_execution_results.append({
561
+ "task_index": i,
562
+ "status": "failed",
563
+ "error": str(e),
564
+ "title": task.title
565
+ })
566
+
567
+ # 如果一个任务失败,停止执行后续任务
568
+ break
569
+
570
+ # 所有任务执行完成后,更新todo状态
571
+ all_completed = all(result.get("status") ==
572
+ "completed" for result in task_execution_results)
573
+ final_status = "testing" if all_completed else "pending"
574
+ asyncio.run(update_todo_status(todo_id, final_status))
575
+
576
+ # 记录状态变更
577
+ logger.info(
578
+ f"Updated todo {todo_id} status to {final_status} after task execution")
579
+
580
+ except Exception as e:
581
+ logger.error(
582
+ f"Error in task execution thread for todo {todo_id}: {str(e)}")
583
+
584
+ # 创建并启动线程
585
+ thread = Thread(target=run_tasks_in_thread)
586
+ thread.daemon = True
587
+ thread.start()
588
+
589
+ logger.info(
590
+ f"Started sequential task execution in background thread for todo {todo_id}")
591
+
592
+ # 返回响应
593
+ return ExecuteTaskResponse(
594
+ status="success",
595
+ task_id=todo_id,
596
+ message=f"Executing all tasks for todo: {todo.title}",
597
+ current_task_index=0, # 从第一个任务开始
598
+ event_file_id=None # 不返回单个事件ID,因为有多个任务
599
+ )
auto_coder_web/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.24"
1
+ __version__ = "0.1.25"
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "files": {
3
- "main.css": "/static/css/main.770925e5.css",
4
- "main.js": "/static/js/main.470202a1.js",
3
+ "main.css": "/static/css/main.95277c5f.css",
4
+ "main.js": "/static/js/main.66c37ccf.js",
5
5
  "static/js/453.d855a71b.chunk.js": "/static/js/453.d855a71b.chunk.js",
6
6
  "index.html": "/index.html",
7
- "main.770925e5.css.map": "/static/css/main.770925e5.css.map",
8
- "main.470202a1.js.map": "/static/js/main.470202a1.js.map",
7
+ "main.95277c5f.css.map": "/static/css/main.95277c5f.css.map",
8
+ "main.66c37ccf.js.map": "/static/js/main.66c37ccf.js.map",
9
9
  "453.d855a71b.chunk.js.map": "/static/js/453.d855a71b.chunk.js.map"
10
10
  },
11
11
  "entrypoints": [
12
- "static/css/main.770925e5.css",
13
- "static/js/main.470202a1.js"
12
+ "static/css/main.95277c5f.css",
13
+ "static/js/main.66c37ccf.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.470202a1.js"></script><link href="/static/css/main.770925e5.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.66c37ccf.js"></script><link href="/static/css/main.95277c5f.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>