@researai/deepscientist 1.5.1 → 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 +69 -1
- package/bin/ds.js +2239 -153
- package/docs/en/00_QUICK_START.md +60 -20
- package/docs/en/01_SETTINGS_REFERENCE.md +20 -20
- package/docs/en/02_START_RESEARCH_GUIDE.md +11 -11
- package/docs/en/03_QQ_CONNECTOR_GUIDE.md +10 -10
- package/docs/en/05_TUI_GUIDE.md +1 -1
- package/docs/en/09_DOCTOR.md +48 -4
- package/docs/en/90_ARCHITECTURE.md +4 -2
- package/docs/zh/00_QUICK_START.md +60 -20
- package/docs/zh/01_SETTINGS_REFERENCE.md +21 -21
- package/docs/zh/02_START_RESEARCH_GUIDE.md +19 -19
- package/docs/zh/03_QQ_CONNECTOR_GUIDE.md +10 -10
- package/docs/zh/05_TUI_GUIDE.md +1 -1
- package/docs/zh/09_DOCTOR.md +46 -4
- package/install.sh +125 -8
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/src/deepscientist/__init__.py +6 -1
- package/src/deepscientist/artifact/service.py +553 -26
- 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 +165 -156
- package/src/deepscientist/connector_profiles.py +346 -0
- package/src/deepscientist/connector_runtime.py +88 -43
- package/src/deepscientist/daemon/api/handlers.py +65 -11
- package/src/deepscientist/daemon/api/router.py +4 -2
- package/src/deepscientist/daemon/app.py +772 -219
- package/src/deepscientist/doctor.py +69 -2
- package/src/deepscientist/gitops/diff.py +3 -0
- package/src/deepscientist/home.py +25 -2
- package/src/deepscientist/mcp/context.py +3 -1
- package/src/deepscientist/mcp/server.py +66 -7
- package/src/deepscientist/migration.py +114 -0
- package/src/deepscientist/prompts/builder.py +71 -3
- package/src/deepscientist/qq_profiles.py +186 -0
- package/src/deepscientist/quest/layout.py +1 -0
- package/src/deepscientist/quest/service.py +70 -12
- package/src/deepscientist/quest/stage_views.py +46 -0
- package/src/deepscientist/runners/codex.py +2 -0
- package/src/deepscientist/shared.py +44 -17
- package/src/prompts/connectors/lingzhu.md +3 -0
- package/src/prompts/connectors/qq.md +42 -2
- package/src/prompts/system.md +123 -10
- package/src/skills/analysis-campaign/SKILL.md +35 -6
- package/src/skills/baseline/SKILL.md +73 -32
- package/src/skills/decision/SKILL.md +4 -3
- package/src/skills/experiment/SKILL.md +28 -6
- package/src/skills/finalize/SKILL.md +5 -2
- package/src/skills/idea/SKILL.md +2 -2
- package/src/skills/intake-audit/SKILL.md +2 -2
- package/src/skills/rebuttal/SKILL.md +4 -2
- package/src/skills/review/SKILL.md +4 -2
- package/src/skills/scout/SKILL.md +2 -2
- package/src/skills/write/SKILL.md +2 -2
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AiManusChatView-w5lF2Ttt.js → AiManusChatView-qzChi9uh.js} +67 -94
- package/src/ui/dist/assets/{AnalysisPlugin-DJOED79I.js → AnalysisPlugin-CcC_-UqN.js} +1 -1
- package/src/ui/dist/assets/{AutoFigurePlugin-DaG61Y0M.js → AutoFigurePlugin-DD8LkJLe.js} +5 -5
- package/src/ui/dist/assets/{CliPlugin-CV4LqUB_.js → CliPlugin-DJJFfVmW.js} +17 -110
- package/src/ui/dist/assets/{CodeEditorPlugin-DylfAea4.js → CodeEditorPlugin-CrjkHNLh.js} +8 -8
- package/src/ui/dist/assets/{CodeViewerPlugin-F7saY0LM.js → CodeViewerPlugin-obnD6G5R.js} +5 -5
- package/src/ui/dist/assets/{DocViewerPlugin-COP0c7jf.js → DocViewerPlugin-DB9SUQVd.js} +3 -3
- package/src/ui/dist/assets/{GitDiffViewerPlugin-CAS05pT9.js → GitDiffViewerPlugin-DZLlNlD2.js} +1 -1
- package/src/ui/dist/assets/{ImageViewerPlugin-Bco1CN_w.js → ImageViewerPlugin-BGwfDZ0Y.js} +5 -5
- package/src/ui/dist/assets/{LabCopilotPanel-CvMlCD99.js → LabCopilotPanel-dfLptQcR.js} +10 -10
- package/src/ui/dist/assets/{LabPlugin-BYankkE4.js → LabPlugin-CeGjAl3A.js} +1 -1
- package/src/ui/dist/assets/{LatexPlugin-LDSMR-t-.js → LatexPlugin-BBJ7kd1V.js} +7 -7
- package/src/ui/dist/assets/{MarkdownViewerPlugin-B7o80jgm.js → MarkdownViewerPlugin-DKZi7BcB.js} +4 -4
- package/src/ui/dist/assets/{MarketplacePlugin-CM6ZOcpC.js → MarketplacePlugin-C_k-9jD0.js} +3 -3
- package/src/ui/dist/assets/{NotebookEditor-Dc61cXmK.js → NotebookEditor-4R88_BMO.js} +1 -1
- package/src/ui/dist/assets/{PdfLoader-DWowuQwx.js → PdfLoader-DwEFQLrw.js} +1 -1
- package/src/ui/dist/assets/{PdfMarkdownPlugin-BsJM1q_a.js → PdfMarkdownPlugin-D-jdsqF8.js} +3 -3
- package/src/ui/dist/assets/{PdfViewerPlugin-DB2eEEFQ.js → PdfViewerPlugin-CmeBGDY0.js} +10 -10
- package/src/ui/dist/assets/{SearchPlugin-CraThSvt.js → SearchPlugin-Dlz2WKJ4.js} +1 -1
- package/src/ui/dist/assets/{Stepper-CgocRTPq.js → Stepper-ClOgzWM3.js} +1 -1
- package/src/ui/dist/assets/{TextViewerPlugin-B1JGhKtd.js → TextViewerPlugin-DDQWxibk.js} +4 -4
- package/src/ui/dist/assets/{VNCViewer-CclFC7FM.js → VNCViewer-CJXT0Nm8.js} +9 -9
- package/src/ui/dist/assets/{bibtex-D3IKsMl7.js → bibtex-DLr4Rtk4.js} +1 -1
- package/src/ui/dist/assets/{code-BP37Xx0p.js → code-DgKK408Y.js} +1 -1
- package/src/ui/dist/assets/{file-content-BAJSu-9r.js → file-content-6HBqQnvQ.js} +1 -1
- package/src/ui/dist/assets/{file-diff-panel-DUGeCTuy.js → file-diff-panel-Dhu0TbBM.js} +1 -1
- package/src/ui/dist/assets/{file-socket-CXc1Ojf7.js → file-socket-CP3iwVZG.js} +1 -1
- package/src/ui/dist/assets/{file-utils-2J21jt7M.js → file-utils-BsS-Aw68.js} +1 -1
- package/src/ui/dist/assets/{image-CMMmgvcn.js → image-ByeK-Zcv.js} +1 -1
- package/src/ui/dist/assets/{index-DmwmJmbW.js → index-BLjo5--a.js} +33610 -31016
- package/src/ui/dist/assets/{index-CWgMgpow.js → index-BdsE0uRz.js} +11 -11
- package/src/ui/dist/assets/{index-s7aHnNQ4.js → index-C-eX-N6A.js} +1 -1
- package/src/ui/dist/assets/{index-KGt-z-dD.css → index-CuQhlrR-.css} +2747 -2
- package/src/ui/dist/assets/{index-BaVumsQT.js → index-DyremSIv.js} +2 -2
- package/src/ui/dist/assets/{message-square-CQRfX0Am.js → message-square-DnagiLnc.js} +1 -1
- package/src/ui/dist/assets/{monaco-B4TbdsrF.js → monaco-4kBFeprs.js} +1 -1
- package/src/ui/dist/assets/{popover-B8Rokodk.js → popover-hRCXZzs2.js} +1 -1
- package/src/ui/dist/assets/{project-sync-D_i96KH4.js → project-sync-O_85YuP6.js} +1 -1
- package/src/ui/dist/assets/{sigma-D12PnzCN.js → sigma-DvKopSnL.js} +1 -1
- package/src/ui/dist/assets/{tooltip-B6YrI4aJ.js → tooltip-BmlPc6kc.js} +1 -1
- package/src/ui/dist/assets/{trash-Bc8jGp0V.js → trash-n-UvdZFR.js} +1 -1
- package/src/ui/dist/assets/{useCliAccess-mXVCYSZ-.js → useCliAccess-WDd3_wIh.js} +1 -1
- package/src/ui/dist/assets/{useFileDiffOverlay-Bg6b9H9K.js → useFileDiffOverlay-rXLIL2NF.js} +1 -1
- package/src/ui/dist/assets/{wrap-text-Drh5GEnL.js → wrap-text-qIYQ4a_W.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-CJj9DZLn.js → zoom-out-fZXCEFsy.js} +1 -1
- package/src/ui/dist/index.html +2 -2
- package/uv.lock +1155 -0
- package/src/ui/dist/assets/LabPlugin-D9jVIo0A.css +0 -2698
|
@@ -10,6 +10,7 @@ from urllib.parse import parse_qs, unquote
|
|
|
10
10
|
|
|
11
11
|
from ...acp import OptionalACPBridge, build_session_descriptor, build_session_update, get_acp_bridge_status
|
|
12
12
|
from ...bash_exec.service import DEFAULT_TERMINAL_SESSION_ID
|
|
13
|
+
from ... import __version__ as DEEPSCIENTIST_VERSION
|
|
13
14
|
from ...gitops import commit_detail, compare_refs, diff_file_between_refs, diff_file_for_commit, export_git_graph, list_branch_canvas, log_ref_history
|
|
14
15
|
from ...memory import MemoryService
|
|
15
16
|
from ...quest import QuestService
|
|
@@ -71,6 +72,7 @@ class ApiHandlers:
|
|
|
71
72
|
def _inject_ui_runtime(self, payload: str) -> str:
|
|
72
73
|
runtime_payload = {
|
|
73
74
|
"surface": "quest",
|
|
75
|
+
"version": DEEPSCIENTIST_VERSION,
|
|
74
76
|
"supports": {
|
|
75
77
|
"productApis": False,
|
|
76
78
|
"socketIo": False,
|
|
@@ -160,6 +162,13 @@ npm --prefix src/ui run build</pre>
|
|
|
160
162
|
"sessions": self.app.sessions.snapshot(),
|
|
161
163
|
}
|
|
162
164
|
|
|
165
|
+
def system_update(self) -> dict:
|
|
166
|
+
return self.app.system_update_status()
|
|
167
|
+
|
|
168
|
+
def system_update_action(self, body: dict) -> dict:
|
|
169
|
+
action = str(body.get("action") or "").strip().lower()
|
|
170
|
+
return self.app.request_system_update(action=action)
|
|
171
|
+
|
|
163
172
|
def cli_health(self) -> dict:
|
|
164
173
|
online_channels = [
|
|
165
174
|
channel.status()
|
|
@@ -196,19 +205,12 @@ npm --prefix src/ui run build</pre>
|
|
|
196
205
|
def connectors(self) -> list[dict]:
|
|
197
206
|
return self.app.list_connector_statuses()
|
|
198
207
|
|
|
208
|
+
def connectors_availability(self) -> dict:
|
|
209
|
+
return self.app.connector_availability_summary()
|
|
210
|
+
|
|
199
211
|
def baselines(self) -> list[dict]:
|
|
200
212
|
return self.app.artifact_service.baselines.list_entries()
|
|
201
213
|
|
|
202
|
-
def bridge_webhook(self, connector: str, *, method: str, path: str, raw_body: bytes, headers: dict[str, str], body: dict) -> tuple[int, dict, bytes | str] | dict:
|
|
203
|
-
return self.app.handle_bridge_webhook(
|
|
204
|
-
connector,
|
|
205
|
-
method=method,
|
|
206
|
-
path=path,
|
|
207
|
-
raw_body=raw_body,
|
|
208
|
-
headers=headers,
|
|
209
|
-
body=body,
|
|
210
|
-
)
|
|
211
|
-
|
|
212
214
|
def qq_bindings(self) -> list[dict]:
|
|
213
215
|
return self.app.list_qq_bindings()
|
|
214
216
|
|
|
@@ -237,12 +239,33 @@ npm --prefix src/ui run build</pre>
|
|
|
237
239
|
preferred_connector_conversation_id = (
|
|
238
240
|
str(body.get("preferred_connector_conversation_id") or "").strip() or None
|
|
239
241
|
)
|
|
242
|
+
requested_connector_bindings = (
|
|
243
|
+
[dict(item) for item in body.get("requested_connector_bindings") if isinstance(item, dict)]
|
|
244
|
+
if isinstance(body.get("requested_connector_bindings"), list)
|
|
245
|
+
else []
|
|
246
|
+
)
|
|
247
|
+
force_connector_rebind_raw = body.get("force_connector_rebind")
|
|
248
|
+
force_connector_rebind = bool(force_connector_rebind_raw) and str(force_connector_rebind_raw).strip().lower() not in {
|
|
249
|
+
"0",
|
|
250
|
+
"false",
|
|
251
|
+
"no",
|
|
252
|
+
"off",
|
|
253
|
+
}
|
|
240
254
|
requested_baseline_ref = body.get("requested_baseline_ref")
|
|
241
255
|
startup_contract = body.get("startup_contract")
|
|
242
256
|
auto_start = body.get("auto_start") is True
|
|
243
257
|
initial_message = str(body.get("initial_message") or "").strip()
|
|
244
258
|
if not goal:
|
|
245
259
|
return {"ok": False, "message": "Quest goal is required."}
|
|
260
|
+
if requested_connector_bindings and not force_connector_rebind:
|
|
261
|
+
conflicts = self.app.preview_connector_binding_conflicts(requested_connector_bindings)
|
|
262
|
+
if conflicts:
|
|
263
|
+
return 409, {
|
|
264
|
+
"ok": False,
|
|
265
|
+
"conflict": True,
|
|
266
|
+
"message": "One or more selected connector targets are already bound to another quest.",
|
|
267
|
+
"conflicts": conflicts,
|
|
268
|
+
}
|
|
246
269
|
try:
|
|
247
270
|
snapshot = self.app.create_quest(
|
|
248
271
|
goal=goal,
|
|
@@ -250,6 +273,8 @@ npm --prefix src/ui run build</pre>
|
|
|
250
273
|
quest_id=quest_id,
|
|
251
274
|
source=source,
|
|
252
275
|
preferred_connector_conversation_id=preferred_connector_conversation_id,
|
|
276
|
+
requested_connector_bindings=requested_connector_bindings,
|
|
277
|
+
force_connector_rebind=force_connector_rebind,
|
|
253
278
|
requested_baseline_ref=requested_baseline_ref if isinstance(requested_baseline_ref, dict) else None,
|
|
254
279
|
startup_contract=startup_contract if isinstance(startup_contract, dict) else None,
|
|
255
280
|
)
|
|
@@ -377,9 +402,19 @@ npm --prefix src/ui run build</pre>
|
|
|
377
402
|
}
|
|
378
403
|
|
|
379
404
|
def quest_bindings(self, quest_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
405
|
+
requested_bindings = (
|
|
406
|
+
[dict(item) for item in body.get("bindings") if isinstance(item, dict)]
|
|
407
|
+
if isinstance(body.get("bindings"), list)
|
|
408
|
+
else []
|
|
409
|
+
)
|
|
380
410
|
conversation_id = str(body.get("conversation_id") or body.get("source") or "").strip() or None
|
|
411
|
+
connector_name = str(body.get("connector") or "").strip() or None
|
|
381
412
|
force_raw = body.get("force")
|
|
382
413
|
force = bool(force_raw) and str(force_raw).strip().lower() not in {"0", "false", "no", "off"}
|
|
414
|
+
if requested_bindings:
|
|
415
|
+
return self.app.update_quest_bindings(quest_id, requested_bindings, force=force)
|
|
416
|
+
if connector_name:
|
|
417
|
+
return self.app.update_quest_connector_binding(quest_id, connector_name, conversation_id, force=force)
|
|
383
418
|
return self.app.update_quest_binding(quest_id, conversation_id, force=force)
|
|
384
419
|
|
|
385
420
|
def quest_session(self, quest_id: str) -> dict:
|
|
@@ -394,12 +429,20 @@ npm --prefix src/ui run build</pre>
|
|
|
394
429
|
def quest_events(self, quest_id: str, path: str) -> dict:
|
|
395
430
|
query = self.parse_query(path)
|
|
396
431
|
after = int((query.get("after") or ["0"])[0] or "0")
|
|
432
|
+
before_raw = ((query.get("before") or [""])[0] or "").strip()
|
|
433
|
+
before = int(before_raw) if before_raw.isdigit() else None
|
|
397
434
|
limit = int((query.get("limit") or ["200"])[0] or "200")
|
|
398
435
|
tail_raw = ((query.get("tail") or ["0"])[0] or "0").strip().lower()
|
|
399
436
|
tail = tail_raw in {"1", "true", "yes", "on"}
|
|
400
437
|
format_name = ((query.get("format") or ["both"])[0] or "both").lower()
|
|
401
438
|
session_id = ((query.get("session_id") or [f"quest:{quest_id}"])[0] or f"quest:{quest_id}")
|
|
402
|
-
payload = self._fresh_quest_service().events(
|
|
439
|
+
payload = self._fresh_quest_service().events(
|
|
440
|
+
quest_id,
|
|
441
|
+
after=after,
|
|
442
|
+
before=before,
|
|
443
|
+
limit=limit,
|
|
444
|
+
tail=tail,
|
|
445
|
+
)
|
|
403
446
|
if format_name in {"acp", "both"}:
|
|
404
447
|
payload["acp_updates"] = [
|
|
405
448
|
build_session_update(
|
|
@@ -438,6 +481,7 @@ npm --prefix src/ui run build</pre>
|
|
|
438
481
|
def bash_sessions(self, quest_id: str, path: str) -> list[dict]:
|
|
439
482
|
query = self.parse_query(path)
|
|
440
483
|
status = ((query.get("status") or [""])[0] or "").strip() or None
|
|
484
|
+
kind = ((query.get("kind") or [""])[0] or "").strip() or None
|
|
441
485
|
chat_session_id = ((query.get("chat_session_id") or [""])[0] or "").strip() or None
|
|
442
486
|
limit_raw = ((query.get("limit") or ["200"])[0] or "200").strip()
|
|
443
487
|
try:
|
|
@@ -458,6 +502,7 @@ npm --prefix src/ui run build</pre>
|
|
|
458
502
|
return self.app.bash_exec_service.list_sessions(
|
|
459
503
|
quest_root,
|
|
460
504
|
status=status,
|
|
505
|
+
kind=kind,
|
|
461
506
|
agent_ids=agent_ids or None,
|
|
462
507
|
agent_instance_ids=agent_instance_ids or None,
|
|
463
508
|
chat_session_id=chat_session_id,
|
|
@@ -475,12 +520,14 @@ npm --prefix src/ui run build</pre>
|
|
|
475
520
|
query = self.parse_query(path)
|
|
476
521
|
limit_raw = ((query.get("limit") or ["200"])[0] or "200").strip()
|
|
477
522
|
before_seq_raw = ((query.get("before_seq") or [""])[0] or "").strip()
|
|
523
|
+
after_seq_raw = ((query.get("after_seq") or [""])[0] or "").strip()
|
|
478
524
|
order = ((query.get("order") or ["asc"])[0] or "asc").strip().lower()
|
|
479
525
|
try:
|
|
480
526
|
limit = max(1, min(int(limit_raw), 1000))
|
|
481
527
|
except ValueError:
|
|
482
528
|
limit = 200
|
|
483
529
|
before_seq = int(before_seq_raw) if before_seq_raw.isdigit() else None
|
|
530
|
+
after_seq = int(after_seq_raw) if after_seq_raw.isdigit() else None
|
|
484
531
|
quest_root = self.app.quest_service._quest_root(quest_id)
|
|
485
532
|
try:
|
|
486
533
|
entries, meta = self.app.bash_exec_service.read_log_entries(
|
|
@@ -488,6 +535,7 @@ npm --prefix src/ui run build</pre>
|
|
|
488
535
|
bash_id,
|
|
489
536
|
limit=limit,
|
|
490
537
|
before_seq=before_seq,
|
|
538
|
+
after_seq=after_seq,
|
|
491
539
|
order=order,
|
|
492
540
|
)
|
|
493
541
|
except FileNotFoundError:
|
|
@@ -504,15 +552,21 @@ npm --prefix src/ui run build</pre>
|
|
|
504
552
|
|
|
505
553
|
def bash_stop(self, quest_id: str, bash_id: str, body: dict) -> dict | tuple[int, dict]:
|
|
506
554
|
quest_root = self.app.quest_service._quest_root(quest_id)
|
|
555
|
+
wait = bool(body.get("wait"))
|
|
556
|
+
timeout_seconds_raw = body.get("timeout_seconds")
|
|
557
|
+
timeout_seconds = timeout_seconds_raw if isinstance(timeout_seconds_raw, int) and timeout_seconds_raw > 0 else None
|
|
507
558
|
try:
|
|
508
559
|
session = self.app.bash_exec_service.request_stop(
|
|
509
560
|
quest_root,
|
|
510
561
|
bash_id,
|
|
511
562
|
reason=str(body.get("reason") or "").strip() or None,
|
|
512
563
|
user_id="web-react",
|
|
564
|
+
force=bool(body.get("force")),
|
|
513
565
|
)
|
|
514
566
|
except FileNotFoundError:
|
|
515
567
|
return 404, {"success": False, "status": "not_found"}
|
|
568
|
+
if wait:
|
|
569
|
+
session = self.app.bash_exec_service.wait_for_session(quest_root, bash_id, timeout_seconds=timeout_seconds)
|
|
516
570
|
return {
|
|
517
571
|
"success": True,
|
|
518
572
|
"status": session.get("status"),
|
|
@@ -8,12 +8,13 @@ ROUTES: list[tuple[str, re.Pattern[str], str]] = [
|
|
|
8
8
|
("GET", re.compile(r"^/ui/(?P<ui_path>.+)$"), "ui_asset"),
|
|
9
9
|
("GET", re.compile(r"^/(?P<spa_path>(?!api(?:/|$)|ui(?:/|$)|assets(?:/|$)).+)$"), "spa_root"),
|
|
10
10
|
("GET", re.compile(r"^/api/health$"), "health"),
|
|
11
|
+
("GET", re.compile(r"^/api/system/update$"), "system_update"),
|
|
12
|
+
("POST", re.compile(r"^/api/system/update$"), "system_update_action"),
|
|
11
13
|
("GET", re.compile(r"^/api/v1/health/cli$"), "cli_health"),
|
|
12
14
|
("POST", re.compile(r"^/api/admin/shutdown$"), "admin_shutdown"),
|
|
13
15
|
("GET", re.compile(r"^/api/acp/status$"), "acp_status"),
|
|
14
16
|
("GET", re.compile(r"^/api/connectors$"), "connectors"),
|
|
15
|
-
("GET", re.compile(r"^/api/
|
|
16
|
-
("POST", re.compile(r"^/api/bridges/(?P<connector>[^/]+)/webhook$"), "bridge_webhook"),
|
|
17
|
+
("GET", re.compile(r"^/api/connectors/availability$"), "connectors_availability"),
|
|
17
18
|
("GET", re.compile(r"^/api/connectors/qq/bindings$"), "qq_bindings"),
|
|
18
19
|
("POST", re.compile(r"^/api/connectors/qq/inbound$"), "qq_inbound"),
|
|
19
20
|
("GET", re.compile(r"^/api/connectors/(?P<connector>[^/]+)/bindings$"), "connector_bindings"),
|
|
@@ -28,6 +29,7 @@ ROUTES: list[tuple[str, re.Pattern[str], str]] = [
|
|
|
28
29
|
("DELETE", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/baseline-binding$"), "quest_baseline_unbind"),
|
|
29
30
|
("PATCH", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/settings$"), "quest_settings"),
|
|
30
31
|
("POST", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/bindings$"), "quest_bindings"),
|
|
32
|
+
("PUT", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/bindings$"), "quest_bindings"),
|
|
31
33
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/session$"), "quest_session"),
|
|
32
34
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/events$"), "quest_events"),
|
|
33
35
|
("GET", re.compile(r"^/api/quests/(?P<quest_id>[^/]+)/artifacts$"), "quest_artifacts"),
|