@researai/deepscientist 1.5.16 → 1.5.17
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.
- package/README.md +66 -23
- package/bin/ds.js +550 -19
- package/docs/en/00_QUICK_START.md +65 -5
- package/docs/en/01_SETTINGS_REFERENCE.md +1 -1
- package/docs/en/09_DOCTOR.md +14 -3
- package/docs/en/15_CODEX_PROVIDER_SETUP.md +12 -3
- package/docs/en/21_LOCAL_MODEL_BACKENDS_GUIDE.md +283 -0
- package/docs/en/91_DEVELOPMENT.md +237 -0
- package/docs/en/README.md +7 -3
- package/docs/zh/00_QUICK_START.md +54 -5
- package/docs/zh/01_SETTINGS_REFERENCE.md +1 -1
- package/docs/zh/09_DOCTOR.md +15 -4
- package/docs/zh/15_CODEX_PROVIDER_SETUP.md +12 -3
- package/docs/zh/21_LOCAL_MODEL_BACKENDS_GUIDE.md +281 -0
- package/docs/zh/README.md +7 -3
- package/install.sh +46 -4
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/src/deepscientist/__init__.py +1 -1
- package/src/deepscientist/bridges/connectors.py +8 -2
- package/src/deepscientist/codex_cli_compat.py +185 -72
- package/src/deepscientist/config/service.py +154 -6
- package/src/deepscientist/daemon/api/handlers.py +130 -25
- package/src/deepscientist/daemon/api/router.py +5 -0
- package/src/deepscientist/daemon/app.py +446 -22
- package/src/deepscientist/diagnostics/__init__.py +6 -0
- package/src/deepscientist/diagnostics/runner_failures.py +130 -0
- package/src/deepscientist/doctor.py +207 -3
- package/src/deepscientist/prompts/builder.py +22 -4
- package/src/deepscientist/quest/service.py +413 -13
- package/src/deepscientist/runners/codex.py +59 -14
- package/src/deepscientist/shared.py +19 -0
- package/src/prompts/contracts/shared_interaction.md +3 -2
- package/src/prompts/system.md +13 -0
- package/src/prompts/system_copilot.md +13 -0
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-COFACy7V.js → AiManusChatView-Bv-Z8YpU.js} +44 -44
- package/src/ui/dist/assets/{AnalysisPlugin-DnSm0GZn.js → AnalysisPlugin-BCKAfjba.js} +1 -1
- package/src/ui/dist/assets/{CliPlugin-CvwCmDQ5.js → CliPlugin-BCKcpc35.js} +4 -4
- package/src/ui/dist/assets/{CodeEditorPlugin-cOqSa0xq.js → CodeEditorPlugin-DbOfSJ8K.js} +1 -1
- package/src/ui/dist/assets/{CodeViewerPlugin-itb0tltR.js → CodeViewerPlugin-CbaFRrUU.js} +3 -3
- package/src/ui/dist/assets/{DocViewerPlugin-DqKkiCI6.js → DocViewerPlugin-DAjLVeQD.js} +3 -3
- package/src/ui/dist/assets/{GitCommitViewerPlugin-DVgNHBCS.js → GitCommitViewerPlugin-CIUqbUDO.js} +1 -1
- package/src/ui/dist/assets/{GitDiffViewerPlugin-DxL2ezFG.js → GitDiffViewerPlugin-CQACjoAA.js} +1 -1
- package/src/ui/dist/assets/{GitSnapshotViewer-B_RQm1YZ.js → GitSnapshotViewer-0r4nLPke.js} +1 -1
- package/src/ui/dist/assets/{ImageViewerPlugin-tHqlXY3n.js → ImageViewerPlugin-nBOmI2v_.js} +3 -3
- package/src/ui/dist/assets/{LabCopilotPanel-ClMbq5Yu.js → LabCopilotPanel-BHxOxF4z.js} +1 -1
- package/src/ui/dist/assets/{LabPlugin-L_SuE8ow.js → LabPlugin-BKoZGs95.js} +1 -1
- package/src/ui/dist/assets/{LatexPlugin-B495DTXC.js → LatexPlugin-ZwtV8pIp.js} +1 -1
- package/src/ui/dist/assets/{MarkdownViewerPlugin-DG28-61B.js → MarkdownViewerPlugin-DKqVfKyW.js} +3 -3
- package/src/ui/dist/assets/{MarketplacePlugin-BiOGT-Kj.js → MarketplacePlugin-BwxStZ9D.js} +1 -1
- package/src/ui/dist/assets/{NotebookEditor-C-4Kt1p9.js → NotebookEditor-BEQhaQbt.js} +1 -1
- package/src/ui/dist/assets/{NotebookEditor-CVsj8h_T.js → NotebookEditor-DB9N_T9q.js} +23 -23
- package/src/ui/dist/assets/{PdfLoader-CASDQmxJ.js → PdfLoader-eWBONbQP.js} +1 -1
- package/src/ui/dist/assets/{PdfMarkdownPlugin-BFhwoKsY.js → PdfMarkdownPlugin-D22YOZL3.js} +1 -1
- package/src/ui/dist/assets/{PdfViewerPlugin-DcOzU9vd.js → PdfViewerPlugin-c-RK9DLM.js} +3 -3
- package/src/ui/dist/assets/{SearchPlugin-CHj7M58O.js → SearchPlugin-CxF9ytAx.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-CB4DYfWO.js → TextViewerPlugin-C5xqeeUH.js} +2 -2
- package/src/ui/dist/assets/{VNCViewer-CjlbyCB3.js → VNCViewer-BoLGLnHz.js} +1 -1
- package/src/ui/dist/assets/{bot-CFkZY-JP.js → bot-DREQOxzP.js} +1 -1
- package/src/ui/dist/assets/{chevron-up-Dq5ofbht.js → chevron-up-C9Qpx4DE.js} +1 -1
- package/src/ui/dist/assets/{code-DLC6G24T.js → code-WlFHE7z_.js} +1 -1
- package/src/ui/dist/assets/{file-content-Dv4LoZec.js → file-content-BZMz3RYp.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-Denq-lC3.js → file-diff-panel-CQhw0jS2.js} +1 -1
- package/src/ui/dist/assets/{file-socket-Cu4Qln7Y.js → file-socket-CfQPKQKj.js} +1 -1
- package/src/ui/dist/assets/{git-commit-horizontal-BUh6G52n.js → git-commit-horizontal-DxZ8DCZh.js} +1 -1
- package/src/ui/dist/assets/{image-B9HUUddG.js → image-Bgl4VIyx.js} +1 -1
- package/src/ui/dist/assets/{index-Cgla8biy.css → index-BpV6lusQ.css} +1 -1
- package/src/ui/dist/assets/{index-Gbl53BNp.js → index-CBNVuWcP.js} +363 -363
- package/src/ui/dist/assets/{index-wQ7RIIRd.js → index-CwNu1aH4.js} +1 -1
- package/src/ui/dist/assets/{index-B2B1sg-M.js → index-DrUnlf6K.js} +1 -1
- package/src/ui/dist/assets/{index-DRyx7vAc.js → index-NW-h8VzN.js} +1 -1
- package/src/ui/dist/assets/{pdf-effect-queue-ZtnHFCAi.js → pdf-effect-queue-J8OnM0jE.js} +1 -1
- package/src/ui/dist/assets/{popover-DL6h35vr.js → popover-CLc0pPP8.js} +1 -1
- package/src/ui/dist/assets/{project-sync-CsX08Qno.js → project-sync-C9IdzdZW.js} +1 -1
- package/src/ui/dist/assets/{select-DvmXt1yY.js → select-Cs2PmzwL.js} +1 -1
- package/src/ui/dist/assets/{sigma-7jpXazui.js → sigma-ClKcHAXm.js} +1 -1
- package/src/ui/dist/assets/{trash-xA7kFt8i.js → trash-DwpbFr3w.js} +1 -1
- package/src/ui/dist/assets/{useCliAccess-DsMwDjOp.js → useCliAccess-NQ8m0Let.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-CwMn-iqb.js → wrap-text-BC-Hltpd.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-R-GWEhzS.js → zoom-out-E_gaeAxL.js} +1 -1
- package/src/ui/dist/index.html +2 -2
|
@@ -523,7 +523,10 @@ npm --prefix src/ui run build</pre>
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
def quest(self, quest_id: str) -> dict:
|
|
526
|
-
|
|
526
|
+
try:
|
|
527
|
+
return self.app.quest_service.snapshot(quest_id)
|
|
528
|
+
except FileNotFoundError:
|
|
529
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
527
530
|
|
|
528
531
|
def quest_delete(self, quest_id: str, body: dict | None = None) -> dict | tuple[int, dict]:
|
|
529
532
|
source = "web"
|
|
@@ -536,6 +539,7 @@ npm --prefix src/ui run build</pre>
|
|
|
536
539
|
"title": body.get("title") if "title" in body else None,
|
|
537
540
|
"active_anchor": body.get("active_anchor") if "active_anchor" in body else None,
|
|
538
541
|
"default_runner": body.get("default_runner") if "default_runner" in body else None,
|
|
542
|
+
"workspace_mode": body.get("workspace_mode") if "workspace_mode" in body else None,
|
|
539
543
|
}
|
|
540
544
|
if all(value is None for value in updates.values()):
|
|
541
545
|
return {
|
|
@@ -585,7 +589,10 @@ npm --prefix src/ui run build</pre>
|
|
|
585
589
|
}
|
|
586
590
|
|
|
587
591
|
def quest_session(self, quest_id: str) -> dict:
|
|
588
|
-
|
|
592
|
+
try:
|
|
593
|
+
snapshot = self.app.quest_service.snapshot_fast(quest_id)
|
|
594
|
+
except FileNotFoundError:
|
|
595
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
589
596
|
for kind in ("details", "canvas", "git_canvas"):
|
|
590
597
|
try:
|
|
591
598
|
self.app.quest_service.prime_projection(quest_id, kind)
|
|
@@ -1474,19 +1481,25 @@ npm --prefix src/ui run build</pre>
|
|
|
1474
1481
|
)
|
|
1475
1482
|
|
|
1476
1483
|
def documents(self, quest_id: str) -> list[dict]:
|
|
1477
|
-
|
|
1484
|
+
try:
|
|
1485
|
+
return self.app.quest_service.list_documents(quest_id)
|
|
1486
|
+
except FileNotFoundError:
|
|
1487
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
1478
1488
|
|
|
1479
1489
|
def explorer(self, quest_id: str, path: str) -> dict:
|
|
1480
1490
|
query = self.parse_query(path)
|
|
1481
1491
|
revision = ((query.get("revision") or [""])[0] or "").strip() or None
|
|
1482
1492
|
mode = ((query.get("mode") or [""])[0] or "").strip() or None
|
|
1483
1493
|
profile = ((query.get("profile") or [""])[0] or "").strip() or None
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1494
|
+
try:
|
|
1495
|
+
return self.app.quest_service.explorer(
|
|
1496
|
+
quest_id,
|
|
1497
|
+
revision=revision,
|
|
1498
|
+
mode=mode,
|
|
1499
|
+
profile=profile,
|
|
1500
|
+
)
|
|
1501
|
+
except FileNotFoundError:
|
|
1502
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
1490
1503
|
|
|
1491
1504
|
def quest_search(self, quest_id: str, path: str) -> dict:
|
|
1492
1505
|
query = self.parse_query(path)
|
|
@@ -1495,7 +1508,90 @@ npm --prefix src/ui run build</pre>
|
|
|
1495
1508
|
limit = int(((query.get("limit") or ["50"])[0] or "50").strip())
|
|
1496
1509
|
except ValueError:
|
|
1497
1510
|
limit = 50
|
|
1498
|
-
|
|
1511
|
+
try:
|
|
1512
|
+
return self.app.quest_service.search_files(quest_id, term=term, limit=limit)
|
|
1513
|
+
except FileNotFoundError:
|
|
1514
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
1515
|
+
|
|
1516
|
+
def quest_file_create_folder(self, quest_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
1517
|
+
try:
|
|
1518
|
+
return self._fresh_quest_service().create_workspace_folder(
|
|
1519
|
+
quest_id,
|
|
1520
|
+
name=body.get("name"),
|
|
1521
|
+
parent_path=body.get("parent_path"),
|
|
1522
|
+
)
|
|
1523
|
+
except FileNotFoundError as exc:
|
|
1524
|
+
return 404, {"ok": False, "message": str(exc)}
|
|
1525
|
+
except FileExistsError as exc:
|
|
1526
|
+
return 409, {"ok": False, "message": str(exc)}
|
|
1527
|
+
except ValueError as exc:
|
|
1528
|
+
return 400, {"ok": False, "message": str(exc)}
|
|
1529
|
+
|
|
1530
|
+
def quest_file_upload(self, quest_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
1531
|
+
file_name = str(body.get("file_name") or "").strip()
|
|
1532
|
+
content_base64 = str(body.get("content_base64") or "").strip()
|
|
1533
|
+
mime_type = str(body.get("mime_type") or "").strip() or None
|
|
1534
|
+
if not file_name:
|
|
1535
|
+
return 400, {"ok": False, "message": "`file_name` is required."}
|
|
1536
|
+
if not content_base64:
|
|
1537
|
+
return 400, {"ok": False, "message": "`content_base64` is required."}
|
|
1538
|
+
try:
|
|
1539
|
+
content = base64.b64decode(content_base64, validate=True)
|
|
1540
|
+
except (ValueError, TypeError):
|
|
1541
|
+
return 400, {"ok": False, "message": "Invalid `content_base64` payload."}
|
|
1542
|
+
try:
|
|
1543
|
+
return self._fresh_quest_service().upload_workspace_file(
|
|
1544
|
+
quest_id,
|
|
1545
|
+
file_name=file_name,
|
|
1546
|
+
content=content,
|
|
1547
|
+
mime_type=mime_type,
|
|
1548
|
+
parent_path=body.get("parent_path"),
|
|
1549
|
+
)
|
|
1550
|
+
except FileNotFoundError as exc:
|
|
1551
|
+
return 404, {"ok": False, "message": str(exc)}
|
|
1552
|
+
except FileExistsError as exc:
|
|
1553
|
+
return 409, {"ok": False, "message": str(exc)}
|
|
1554
|
+
except ValueError as exc:
|
|
1555
|
+
return 400, {"ok": False, "message": str(exc)}
|
|
1556
|
+
|
|
1557
|
+
def quest_file_rename(self, quest_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
1558
|
+
try:
|
|
1559
|
+
return self._fresh_quest_service().rename_workspace_entry(
|
|
1560
|
+
quest_id,
|
|
1561
|
+
path=body.get("path"),
|
|
1562
|
+
new_name=body.get("new_name"),
|
|
1563
|
+
)
|
|
1564
|
+
except FileNotFoundError as exc:
|
|
1565
|
+
return 404, {"ok": False, "message": str(exc)}
|
|
1566
|
+
except FileExistsError as exc:
|
|
1567
|
+
return 409, {"ok": False, "message": str(exc)}
|
|
1568
|
+
except ValueError as exc:
|
|
1569
|
+
return 400, {"ok": False, "message": str(exc)}
|
|
1570
|
+
|
|
1571
|
+
def quest_file_move(self, quest_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
1572
|
+
try:
|
|
1573
|
+
return self._fresh_quest_service().move_workspace_entries(
|
|
1574
|
+
quest_id,
|
|
1575
|
+
paths=body.get("paths"),
|
|
1576
|
+
target_parent_path=body.get("target_parent_path"),
|
|
1577
|
+
)
|
|
1578
|
+
except FileNotFoundError as exc:
|
|
1579
|
+
return 404, {"ok": False, "message": str(exc)}
|
|
1580
|
+
except FileExistsError as exc:
|
|
1581
|
+
return 409, {"ok": False, "message": str(exc)}
|
|
1582
|
+
except ValueError as exc:
|
|
1583
|
+
return 400, {"ok": False, "message": str(exc)}
|
|
1584
|
+
|
|
1585
|
+
def quest_file_delete(self, quest_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
1586
|
+
try:
|
|
1587
|
+
return self._fresh_quest_service().delete_workspace_entries(
|
|
1588
|
+
quest_id,
|
|
1589
|
+
paths=body.get("paths"),
|
|
1590
|
+
)
|
|
1591
|
+
except FileNotFoundError as exc:
|
|
1592
|
+
return 404, {"ok": False, "message": str(exc)}
|
|
1593
|
+
except ValueError as exc:
|
|
1594
|
+
return 400, {"ok": False, "message": str(exc)}
|
|
1499
1595
|
|
|
1500
1596
|
def document_asset(self, quest_id: str, path: str) -> tuple[int, dict, bytes]:
|
|
1501
1597
|
quest_service = self._fresh_quest_service()
|
|
@@ -1519,7 +1615,10 @@ npm --prefix src/ui run build</pre>
|
|
|
1519
1615
|
return 200, self._asset_headers(mime_type), path.read_bytes()
|
|
1520
1616
|
|
|
1521
1617
|
def document_open(self, quest_id: str, body: dict) -> dict:
|
|
1522
|
-
|
|
1618
|
+
try:
|
|
1619
|
+
return self._fresh_quest_service().open_document(quest_id, body["document_id"])
|
|
1620
|
+
except FileNotFoundError:
|
|
1621
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
1523
1622
|
|
|
1524
1623
|
def document_asset_upload(self, quest_id: str, body: dict) -> dict:
|
|
1525
1624
|
document_id = str(body.get("document_id") or "").strip()
|
|
@@ -1537,22 +1636,28 @@ npm --prefix src/ui run build</pre>
|
|
|
1537
1636
|
content = base64.b64decode(content_base64, validate=True)
|
|
1538
1637
|
except (ValueError, TypeError):
|
|
1539
1638
|
return {"ok": False, "message": "Invalid `content_base64` payload."}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1639
|
+
try:
|
|
1640
|
+
return self.app.quest_service.save_document_asset(
|
|
1641
|
+
quest_id,
|
|
1642
|
+
document_id,
|
|
1643
|
+
file_name=file_name,
|
|
1644
|
+
mime_type=mime_type or None,
|
|
1645
|
+
content=content,
|
|
1646
|
+
kind=kind,
|
|
1647
|
+
)
|
|
1648
|
+
except FileNotFoundError:
|
|
1649
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
1548
1650
|
|
|
1549
1651
|
def document_save(self, quest_id: str, document_id: str, body: dict) -> dict:
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1652
|
+
try:
|
|
1653
|
+
return self.app.quest_service.save_document(
|
|
1654
|
+
quest_id,
|
|
1655
|
+
document_id,
|
|
1656
|
+
body["content"],
|
|
1657
|
+
previous_revision=body.get("revision"),
|
|
1658
|
+
)
|
|
1659
|
+
except FileNotFoundError:
|
|
1660
|
+
return 404, {"ok": False, "message": f"Unknown quest `{quest_id}`."}
|
|
1556
1661
|
|
|
1557
1662
|
def latex_init(self, project_id: str, body: dict) -> dict:
|
|
1558
1663
|
return self.app.latex_service.init_project(
|
|
@@ -78,6 +78,11 @@ ROUTES: list[tuple[str, re.Pattern[str], str]] = [
|
|
|
78
78
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/documents$"), "documents"),
|
|
79
79
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/explorer$"), "explorer"),
|
|
80
80
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/search$"), "quest_search"),
|
|
81
|
+
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/files/folder$"), "quest_file_create_folder"),
|
|
82
|
+
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/files/upload$"), "quest_file_upload"),
|
|
83
|
+
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/files/rename$"), "quest_file_rename"),
|
|
84
|
+
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/files/move$"), "quest_file_move"),
|
|
85
|
+
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/files/delete$"), "quest_file_delete"),
|
|
81
86
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/documents/asset$"), "document_asset"),
|
|
82
87
|
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/documents/open$"), "document_open"),
|
|
83
88
|
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/documents/assets$"), "document_asset_upload"),
|