@researai/deepscientist 1.5.2 → 1.5.3
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 +22 -0
- package/bin/ds.js +384 -0
- package/docs/en/00_QUICK_START.md +22 -0
- package/docs/zh/00_QUICK_START.md +22 -0
- package/install.sh +120 -4
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/deepscientist/__init__.py +1 -1
- package/src/deepscientist/artifact/service.py +1 -1
- package/src/deepscientist/bash_exec/monitor.py +23 -4
- package/src/deepscientist/bash_exec/runtime.py +3 -0
- package/src/deepscientist/bash_exec/service.py +132 -4
- package/src/deepscientist/bridges/base.py +10 -19
- package/src/deepscientist/channels/discord_gateway.py +25 -2
- package/src/deepscientist/channels/feishu_long_connection.py +41 -3
- package/src/deepscientist/channels/qq.py +524 -64
- package/src/deepscientist/channels/qq_gateway.py +22 -3
- package/src/deepscientist/channels/relay.py +429 -90
- package/src/deepscientist/channels/slack_socket.py +29 -5
- package/src/deepscientist/channels/telegram_polling.py +25 -2
- package/src/deepscientist/channels/whatsapp_local_session.py +32 -4
- package/src/deepscientist/cli.py +27 -0
- package/src/deepscientist/config/models.py +6 -40
- package/src/deepscientist/config/service.py +164 -155
- package/src/deepscientist/connector_profiles.py +346 -0
- package/src/deepscientist/connector_runtime.py +88 -43
- package/src/deepscientist/daemon/api/handlers.py +47 -10
- package/src/deepscientist/daemon/api/router.py +2 -2
- package/src/deepscientist/daemon/app.py +682 -218
- package/src/deepscientist/mcp/server.py +60 -7
- package/src/deepscientist/migration.py +114 -0
- package/src/deepscientist/prompts/builder.py +30 -3
- package/src/deepscientist/qq_profiles.py +186 -0
- package/src/prompts/connectors/qq.md +42 -2
- package/src/prompts/system.md +85 -5
- package/src/skills/analysis-campaign/SKILL.md +11 -5
- package/src/skills/baseline/SKILL.md +66 -31
- package/src/skills/decision/SKILL.md +1 -1
- package/src/skills/experiment/SKILL.md +11 -5
- package/src/skills/finalize/SKILL.md +1 -1
- package/src/skills/idea/SKILL.md +1 -1
- package/src/skills/intake-audit/SKILL.md +1 -1
- package/src/skills/rebuttal/SKILL.md +1 -1
- package/src/skills/review/SKILL.md +1 -1
- package/src/skills/scout/SKILL.md +1 -1
- package/src/skills/write/SKILL.md +1 -1
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-CZpg376x.js → AiManusChatView-qzChi9uh.js} +14 -37
- package/src/ui/dist/assets/{AnalysisPlugin-CtHA22g3.js → AnalysisPlugin-CcC_-UqN.js} +1 -1
- package/src/ui/dist/assets/{AutoFigurePlugin-BSWmLMmF.js → AutoFigurePlugin-DD8LkJLe.js} +5 -5
- package/src/ui/dist/assets/{CliPlugin-CJ7jdm_s.js → CliPlugin-DJJFfVmW.js} +17 -110
- package/src/ui/dist/assets/{CodeEditorPlugin-DhInVGFf.js → CodeEditorPlugin-CrjkHNLh.js} +8 -8
- package/src/ui/dist/assets/{CodeViewerPlugin-D1n8S9r5.js → CodeViewerPlugin-obnD6G5R.js} +5 -5
- package/src/ui/dist/assets/{DocViewerPlugin-C4XM_kqk.js → DocViewerPlugin-DB9SUQVd.js} +3 -3
- package/src/ui/dist/assets/{GitDiffViewerPlugin-W6kS9r6v.js → GitDiffViewerPlugin-DZLlNlD2.js} +1 -1
- package/src/ui/dist/assets/{ImageViewerPlugin-DPeUx_Oz.js → ImageViewerPlugin-BGwfDZ0Y.js} +5 -5
- package/src/ui/dist/assets/{LabCopilotPanel-eAelUaub.js → LabCopilotPanel-dfLptQcR.js} +10 -10
- package/src/ui/dist/assets/{LabPlugin-BbOrBxKY.js → LabPlugin-CeGjAl3A.js} +1 -1
- package/src/ui/dist/assets/{LatexPlugin-C-HhkVXY.js → LatexPlugin-BBJ7kd1V.js} +7 -7
- package/src/ui/dist/assets/{MarkdownViewerPlugin-BDIzIBfh.js → MarkdownViewerPlugin-DKZi7BcB.js} +4 -4
- package/src/ui/dist/assets/{MarketplacePlugin-DAOJphwr.js → MarketplacePlugin-C_k-9jD0.js} +3 -3
- package/src/ui/dist/assets/{NotebookEditor-BsoMvDoU.js → NotebookEditor-4R88_BMO.js} +1 -1
- package/src/ui/dist/assets/{PdfLoader-fiC7RtHf.js → PdfLoader-DwEFQLrw.js} +1 -1
- package/src/ui/dist/assets/{PdfMarkdownPlugin-C5OxZBFK.js → PdfMarkdownPlugin-D-jdsqF8.js} +3 -3
- package/src/ui/dist/assets/{PdfViewerPlugin-CAbxQebk.js → PdfViewerPlugin-CmeBGDY0.js} +10 -10
- package/src/ui/dist/assets/{SearchPlugin-SE33Lb9B.js → SearchPlugin-Dlz2WKJ4.js} +1 -1
- package/src/ui/dist/assets/{Stepper-0Av7GfV7.js → Stepper-ClOgzWM3.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-Daf2gJDI.js → TextViewerPlugin-DDQWxibk.js} +4 -4
- package/src/ui/dist/assets/{VNCViewer-BKrMUIOX.js → VNCViewer-CJXT0Nm8.js} +9 -9
- package/src/ui/dist/assets/{bibtex-JBdOEe45.js → bibtex-DLr4Rtk4.js} +1 -1
- package/src/ui/dist/assets/{code-B0TDFCZz.js → code-DgKK408Y.js} +1 -1
- package/src/ui/dist/assets/{file-content-3YtrSacz.js → file-content-6HBqQnvQ.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-CJEg5OG1.js → file-diff-panel-Dhu0TbBM.js} +1 -1
- package/src/ui/dist/assets/{file-socket-CYQYdmB1.js → file-socket-CP3iwVZG.js} +1 -1
- package/src/ui/dist/assets/{file-utils-Cd1C9Ppl.js → file-utils-BsS-Aw68.js} +1 -1
- package/src/ui/dist/assets/{image-B33ctrvC.js → image-ByeK-Zcv.js} +1 -1
- package/src/ui/dist/assets/{index-BVXsmS7V.js → index-BLjo5--a.js} +9499 -8688
- package/src/ui/dist/assets/{index-BNQWqmJ2.js → index-BdsE0uRz.js} +11 -11
- package/src/ui/dist/assets/{index-9CLPVeZh.js → index-C-eX-N6A.js} +1 -1
- package/src/ui/dist/assets/{index-SwmFAld3.css → index-CuQhlrR-.css} +49 -2
- package/src/ui/dist/assets/{index-Buw_N1VQ.js → index-DyremSIv.js} +2 -2
- package/src/ui/dist/assets/{message-square-D0cUJ9yU.js → message-square-DnagiLnc.js} +1 -1
- package/src/ui/dist/assets/{monaco-UZLYkp2n.js → monaco-4kBFeprs.js} +1 -1
- package/src/ui/dist/assets/{popover-CTeiY-dK.js → popover-hRCXZzs2.js} +1 -1
- package/src/ui/dist/assets/{project-sync-Dbs01Xky.js → project-sync-O_85YuP6.js} +1 -1
- package/src/ui/dist/assets/{sigma-CM08S-xT.js → sigma-DvKopSnL.js} +1 -1
- package/src/ui/dist/assets/{tooltip-pDtzvU9p.js → tooltip-BmlPc6kc.js} +1 -1
- package/src/ui/dist/assets/{trash-YvPCP-da.js → trash-n-UvdZFR.js} +1 -1
- package/src/ui/dist/assets/{useCliAccess-Bavi74Ac.js → useCliAccess-WDd3_wIh.js} +1 -1
- package/src/ui/dist/assets/{useFileDiffOverlay-CVXY6oeg.js → useFileDiffOverlay-rXLIL2NF.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-Cf4flRW7.js → wrap-text-qIYQ4a_W.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-Hb0Z1YpT.js → zoom-out-fZXCEFsy.js} +1 -1
- package/src/ui/dist/index.html +2 -2
|
@@ -10,6 +10,7 @@ from urllib.request import Request, urlopen
|
|
|
10
10
|
from websockets.exceptions import ConnectionClosed
|
|
11
11
|
from websockets.sync.client import connect as websocket_connect
|
|
12
12
|
|
|
13
|
+
from ..connector_runtime import format_conversation_id
|
|
13
14
|
from ..shared import read_json, utc_now, write_json
|
|
14
15
|
|
|
15
16
|
|
|
@@ -24,11 +25,17 @@ class DiscordGatewayService:
|
|
|
24
25
|
config: dict[str, Any],
|
|
25
26
|
on_event: Callable[[dict[str, Any]], None],
|
|
26
27
|
log: Callable[[str, str], None] | None = None,
|
|
28
|
+
profile_id: str | None = None,
|
|
29
|
+
profile_label: str | None = None,
|
|
30
|
+
encode_profile_id: bool = False,
|
|
27
31
|
) -> None:
|
|
28
32
|
self.home = home
|
|
29
33
|
self.config = config
|
|
30
34
|
self.on_event = on_event
|
|
31
35
|
self.log = log or self._default_log
|
|
36
|
+
self.profile_id = str(profile_id or "").strip() or None
|
|
37
|
+
self.profile_label = str(profile_label or "").strip() or None
|
|
38
|
+
self._encode_profile_id = bool(encode_profile_id and self.profile_id)
|
|
32
39
|
self._thread: threading.Thread | None = None
|
|
33
40
|
self._stop_event = threading.Event()
|
|
34
41
|
self._heartbeat_stop = threading.Event()
|
|
@@ -37,6 +44,8 @@ class DiscordGatewayService:
|
|
|
37
44
|
self._seq: int | None = None
|
|
38
45
|
self._bot_user_id: str | None = None
|
|
39
46
|
self._root = home / "logs" / "connectors" / "discord"
|
|
47
|
+
if self.profile_id:
|
|
48
|
+
self._root = self._root / "profiles" / self.profile_id
|
|
40
49
|
self._runtime_path = self._root / "runtime.json"
|
|
41
50
|
|
|
42
51
|
def start(self) -> bool:
|
|
@@ -71,7 +80,7 @@ class DiscordGatewayService:
|
|
|
71
80
|
self._thread = threading.Thread(
|
|
72
81
|
target=self._run,
|
|
73
82
|
daemon=True,
|
|
74
|
-
name="deepscientist-discord-gateway",
|
|
83
|
+
name=f"deepscientist-discord-gateway-{self.profile_id or 'default'}",
|
|
75
84
|
)
|
|
76
85
|
self._thread.start()
|
|
77
86
|
return True
|
|
@@ -288,12 +297,22 @@ class DiscordGatewayService:
|
|
|
288
297
|
"sender_id": sender_id,
|
|
289
298
|
"sender_name": str(author.get("global_name") or author.get("username") or sender_id).strip(),
|
|
290
299
|
"message_id": str(data.get("id") or "").strip(),
|
|
291
|
-
"conversation_id":
|
|
300
|
+
"conversation_id": self._conversation_id(chat_type, channel_id),
|
|
301
|
+
"profile_id": self.profile_id,
|
|
302
|
+
"profile_label": self.profile_label,
|
|
292
303
|
"text": normalized_text,
|
|
293
304
|
"mentioned": mentioned,
|
|
294
305
|
"raw_event": data,
|
|
295
306
|
}
|
|
296
307
|
|
|
308
|
+
def _conversation_id(self, chat_type: str, chat_id: str) -> str:
|
|
309
|
+
return format_conversation_id(
|
|
310
|
+
"discord",
|
|
311
|
+
chat_type,
|
|
312
|
+
chat_id,
|
|
313
|
+
profile_id=self.profile_id if self._encode_profile_id else None,
|
|
314
|
+
)
|
|
315
|
+
|
|
297
316
|
@staticmethod
|
|
298
317
|
def _strip_bot_mention(text: str, bot_user_id: str) -> str:
|
|
299
318
|
cleaned = str(text or "").strip()
|
|
@@ -354,6 +373,10 @@ class DiscordGatewayService:
|
|
|
354
373
|
state = read_json(self._runtime_path, {}) or {}
|
|
355
374
|
if not isinstance(state, dict):
|
|
356
375
|
state = {}
|
|
376
|
+
if self.profile_id:
|
|
377
|
+
state["profile_id"] = self.profile_id
|
|
378
|
+
if self.profile_label:
|
|
379
|
+
state["profile_label"] = self.profile_label
|
|
357
380
|
state.update(patch)
|
|
358
381
|
write_json(self._runtime_path, state)
|
|
359
382
|
|
|
@@ -9,6 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
from typing import Any, Callable
|
|
10
10
|
|
|
11
11
|
from ..bridges.connectors import FeishuConnectorBridge
|
|
12
|
+
from ..connector_runtime import format_conversation_id, parse_conversation_id
|
|
12
13
|
from ..shared import read_json, utc_now, write_json
|
|
13
14
|
|
|
14
15
|
|
|
@@ -29,17 +30,25 @@ class FeishuLongConnectionService:
|
|
|
29
30
|
config: dict[str, Any],
|
|
30
31
|
on_event: Callable[[dict[str, Any]], None],
|
|
31
32
|
log: Callable[[str, str], None] | None = None,
|
|
33
|
+
profile_id: str | None = None,
|
|
34
|
+
profile_label: str | None = None,
|
|
35
|
+
encode_profile_id: bool = False,
|
|
32
36
|
) -> None:
|
|
33
37
|
self.home = home
|
|
34
38
|
self.config = config
|
|
35
39
|
self.on_event = on_event
|
|
36
40
|
self.log = log or self._default_log
|
|
41
|
+
self.profile_id = str(profile_id or "").strip() or None
|
|
42
|
+
self.profile_label = str(profile_label or "").strip() or None
|
|
43
|
+
self._encode_profile_id = bool(encode_profile_id and self.profile_id)
|
|
37
44
|
self._thread: threading.Thread | None = None
|
|
38
45
|
self._stop_event = threading.Event()
|
|
39
46
|
self._loop: asyncio.AbstractEventLoop | None = None
|
|
40
47
|
self._async_stop: asyncio.Event | None = None
|
|
41
48
|
self._client: Any = None
|
|
42
49
|
self._root = home / "logs" / "connectors" / "feishu"
|
|
50
|
+
if self.profile_id:
|
|
51
|
+
self._root = self._root / "profiles" / self.profile_id
|
|
43
52
|
self._runtime_path = self._root / "runtime.json"
|
|
44
53
|
|
|
45
54
|
def start(self) -> bool:
|
|
@@ -85,7 +94,7 @@ class FeishuLongConnectionService:
|
|
|
85
94
|
self._thread = threading.Thread(
|
|
86
95
|
target=self._run,
|
|
87
96
|
daemon=True,
|
|
88
|
-
name="deepscientist-feishu-long-connection",
|
|
97
|
+
name=f"deepscientist-feishu-long-connection-{self.profile_id or 'default'}",
|
|
89
98
|
)
|
|
90
99
|
self._thread.start()
|
|
91
100
|
return True
|
|
@@ -201,16 +210,41 @@ class FeishuLongConnectionService:
|
|
|
201
210
|
config=self.config,
|
|
202
211
|
)
|
|
203
212
|
for event in result.events:
|
|
204
|
-
self.
|
|
213
|
+
normalized = self._normalize_event(event)
|
|
214
|
+
self.on_event(normalized)
|
|
205
215
|
self._write_state(
|
|
206
216
|
connected=True,
|
|
207
217
|
connection_state="connected",
|
|
208
218
|
auth_state="ready",
|
|
209
219
|
last_event_at=utc_now(),
|
|
210
|
-
last_conversation_id=
|
|
220
|
+
last_conversation_id=normalized.get("conversation_id"),
|
|
211
221
|
updated_at=utc_now(),
|
|
212
222
|
)
|
|
213
223
|
|
|
224
|
+
def _normalize_event(self, event: dict[str, Any]) -> dict[str, Any]:
|
|
225
|
+
normalized = dict(event)
|
|
226
|
+
chat_type = str(normalized.get("chat_type") or "direct").strip().lower() or "direct"
|
|
227
|
+
group_id = str(normalized.get("group_id") or "").strip()
|
|
228
|
+
direct_id = str(normalized.get("direct_id") or "").strip()
|
|
229
|
+
chat_id = group_id if chat_type == "group" else direct_id
|
|
230
|
+
if not chat_id:
|
|
231
|
+
parsed = parse_conversation_id(normalized.get("conversation_id"))
|
|
232
|
+
if parsed is not None:
|
|
233
|
+
chat_type = str(parsed.get("chat_type") or chat_type).strip().lower() or chat_type
|
|
234
|
+
chat_id = str(parsed.get("chat_id") or "").strip()
|
|
235
|
+
normalized["conversation_id"] = self._conversation_id(chat_type, chat_id or "unknown")
|
|
236
|
+
normalized["profile_id"] = self.profile_id
|
|
237
|
+
normalized["profile_label"] = self.profile_label
|
|
238
|
+
return normalized
|
|
239
|
+
|
|
240
|
+
def _conversation_id(self, chat_type: str, chat_id: str) -> str:
|
|
241
|
+
return format_conversation_id(
|
|
242
|
+
"feishu",
|
|
243
|
+
chat_type,
|
|
244
|
+
chat_id,
|
|
245
|
+
profile_id=self.profile_id if self._encode_profile_id else None,
|
|
246
|
+
)
|
|
247
|
+
|
|
214
248
|
@staticmethod
|
|
215
249
|
def _sdk_bundle() -> dict[str, Any] | None:
|
|
216
250
|
try:
|
|
@@ -239,6 +273,10 @@ class FeishuLongConnectionService:
|
|
|
239
273
|
state = read_json(self._runtime_path, {}) or {}
|
|
240
274
|
if not isinstance(state, dict):
|
|
241
275
|
state = {}
|
|
276
|
+
if self.profile_id:
|
|
277
|
+
state["profile_id"] = self.profile_id
|
|
278
|
+
if self.profile_label:
|
|
279
|
+
state["profile_label"] = self.profile_label
|
|
242
280
|
state.update(patch)
|
|
243
281
|
write_json(self._runtime_path, state)
|
|
244
282
|
|