@researai/deepscientist 1.5.8 → 1.5.11

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 (148) hide show
  1. package/LICENSE +186 -21
  2. package/README.md +108 -95
  3. package/assets/branding/connector-qq.png +0 -0
  4. package/assets/branding/connector-rokid.png +0 -0
  5. package/assets/branding/connector-weixin.png +0 -0
  6. package/assets/branding/projects.png +0 -0
  7. package/bin/ds.js +172 -13
  8. package/docs/assets/branding/projects.png +0 -0
  9. package/docs/en/00_QUICK_START.md +308 -70
  10. package/docs/en/01_SETTINGS_REFERENCE.md +3 -0
  11. package/docs/en/02_START_RESEARCH_GUIDE.md +112 -0
  12. package/docs/en/04_LINGZHU_CONNECTOR_GUIDE.md +62 -179
  13. package/docs/en/09_DOCTOR.md +41 -5
  14. package/docs/en/10_WEIXIN_CONNECTOR_GUIDE.md +137 -0
  15. package/docs/en/11_LICENSE_AND_RISK.md +256 -0
  16. package/docs/en/12_GUIDED_WORKFLOW_TOUR.md +427 -0
  17. package/docs/en/13_CORE_ARCHITECTURE_GUIDE.md +297 -0
  18. package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +506 -0
  19. package/docs/en/99_ACKNOWLEDGEMENTS.md +4 -1
  20. package/docs/en/README.md +79 -0
  21. package/docs/images/lingzhu/rokid-agent-platform-create.png +0 -0
  22. package/docs/images/weixin/weixin-plugin-entry.png +0 -0
  23. package/docs/images/weixin/weixin-plugin-entry.svg +33 -0
  24. package/docs/images/weixin/weixin-qr-confirm.svg +30 -0
  25. package/docs/images/weixin/weixin-quest-media-flow.svg +44 -0
  26. package/docs/images/weixin/weixin-settings-bind.svg +57 -0
  27. package/docs/zh/00_QUICK_START.md +315 -74
  28. package/docs/zh/01_SETTINGS_REFERENCE.md +3 -0
  29. package/docs/zh/02_START_RESEARCH_GUIDE.md +112 -0
  30. package/docs/zh/04_LINGZHU_CONNECTOR_GUIDE.md +62 -193
  31. package/docs/zh/09_DOCTOR.md +41 -5
  32. package/docs/zh/10_WEIXIN_CONNECTOR_GUIDE.md +144 -0
  33. package/docs/zh/11_LICENSE_AND_RISK.md +256 -0
  34. package/docs/zh/12_GUIDED_WORKFLOW_TOUR.md +423 -0
  35. package/docs/zh/13_CORE_ARCHITECTURE_GUIDE.md +296 -0
  36. package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +506 -0
  37. package/docs/zh/99_ACKNOWLEDGEMENTS.md +4 -1
  38. package/docs/zh/README.md +126 -0
  39. package/install.sh +0 -34
  40. package/package.json +3 -3
  41. package/pyproject.toml +2 -2
  42. package/src/deepscientist/__init__.py +1 -1
  43. package/src/deepscientist/annotations.py +343 -0
  44. package/src/deepscientist/artifact/arxiv.py +484 -37
  45. package/src/deepscientist/artifact/metrics.py +1 -3
  46. package/src/deepscientist/artifact/service.py +1347 -111
  47. package/src/deepscientist/arxiv_library.py +275 -0
  48. package/src/deepscientist/bash_exec/service.py +9 -0
  49. package/src/deepscientist/bridges/builtins.py +2 -0
  50. package/src/deepscientist/bridges/connectors.py +447 -0
  51. package/src/deepscientist/channels/__init__.py +2 -0
  52. package/src/deepscientist/channels/builtins.py +3 -1
  53. package/src/deepscientist/channels/qq.py +1 -1
  54. package/src/deepscientist/channels/qq_gateway.py +1 -1
  55. package/src/deepscientist/channels/relay.py +7 -1
  56. package/src/deepscientist/channels/weixin.py +59 -0
  57. package/src/deepscientist/channels/weixin_ilink.py +317 -0
  58. package/src/deepscientist/config/models.py +22 -2
  59. package/src/deepscientist/config/service.py +431 -60
  60. package/src/deepscientist/connector/__init__.py +4 -0
  61. package/src/deepscientist/connector/connector_profiles.py +481 -0
  62. package/src/deepscientist/connector/lingzhu_support.py +668 -0
  63. package/src/deepscientist/connector/qq_profiles.py +206 -0
  64. package/src/deepscientist/connector/weixin_support.py +663 -0
  65. package/src/deepscientist/connector_profiles.py +1 -374
  66. package/src/deepscientist/connector_runtime.py +2 -0
  67. package/src/deepscientist/daemon/api/handlers.py +295 -5
  68. package/src/deepscientist/daemon/api/router.py +16 -1
  69. package/src/deepscientist/daemon/app.py +1130 -61
  70. package/src/deepscientist/doctor.py +5 -2
  71. package/src/deepscientist/gitops/diff.py +120 -29
  72. package/src/deepscientist/lingzhu_support.py +1 -182
  73. package/src/deepscientist/mcp/server.py +14 -5
  74. package/src/deepscientist/prompts/builder.py +29 -1
  75. package/src/deepscientist/qq_profiles.py +1 -196
  76. package/src/deepscientist/quest/node_traces.py +152 -2
  77. package/src/deepscientist/quest/service.py +169 -43
  78. package/src/deepscientist/quest/stage_views.py +172 -9
  79. package/src/deepscientist/registries/baseline.py +56 -4
  80. package/src/deepscientist/runners/codex.py +55 -3
  81. package/src/deepscientist/weixin_support.py +1 -0
  82. package/src/prompts/connectors/lingzhu.md +3 -1
  83. package/src/prompts/connectors/weixin.md +230 -0
  84. package/src/prompts/system.md +9 -0
  85. package/src/skills/idea/SKILL.md +16 -0
  86. package/src/skills/idea/references/literature-survey-template.md +24 -0
  87. package/src/skills/idea/references/related-work-playbook.md +4 -0
  88. package/src/skills/idea/references/selection-gate.md +9 -0
  89. package/src/skills/write/SKILL.md +1 -1
  90. package/src/tui/package.json +1 -1
  91. package/src/ui/dist/assets/{AiManusChatView-m2FNtwbn.js → AiManusChatView-D0mTXG4-.js} +156 -48
  92. package/src/ui/dist/assets/{AnalysisPlugin-BMTF8EGL.js → AnalysisPlugin-Db0cTXxm.js} +1 -1
  93. package/src/ui/dist/assets/{CliPlugin-BEOWgxCI.js → CliPlugin-DrV8je02.js} +164 -9
  94. package/src/ui/dist/assets/{CodeEditorPlugin-BCXvjqmb.js → CodeEditorPlugin-QXMSCH71.js} +8 -8
  95. package/src/ui/dist/assets/{CodeViewerPlugin-DaJcy3nD.js → CodeViewerPlugin-7hhtWj_E.js} +5 -5
  96. package/src/ui/dist/assets/{DocViewerPlugin-ByfeIq4K.js → DocViewerPlugin-BWMSnRJe.js} +3 -3
  97. package/src/ui/dist/assets/{GitDiffViewerPlugin-Cksf3VZ-.js → GitDiffViewerPlugin-7J9h9Vy_.js} +20 -21
  98. package/src/ui/dist/assets/{ImageViewerPlugin-CFz-OsTS.js → ImageViewerPlugin-CHJl_0lr.js} +5 -5
  99. package/src/ui/dist/assets/{LabCopilotPanel-CJ1cJzoX.js → LabCopilotPanel-1qSow1es.js} +11 -11
  100. package/src/ui/dist/assets/{LabPlugin-BF3dVJwa.js → LabPlugin-eQpPPCEp.js} +2 -1
  101. package/src/ui/dist/assets/{LatexPlugin-DDkwZ6Sj.js → LatexPlugin-BwRfi89Z.js} +7 -7
  102. package/src/ui/dist/assets/{MarkdownViewerPlugin-HAuvurcT.js → MarkdownViewerPlugin-836PVQWV.js} +4 -4
  103. package/src/ui/dist/assets/{MarketplacePlugin-BtoTYy2C.js → MarketplacePlugin-C2y_556i.js} +3 -3
  104. package/src/ui/dist/assets/{NotebookEditor-CSJYx7b-.js → NotebookEditor-BRzJbGsn.js} +12 -12
  105. package/src/ui/dist/assets/{NotebookEditor-DQgRezm_.js → NotebookEditor-DIX7Mlzu.js} +1 -1
  106. package/src/ui/dist/assets/{PdfLoader-DPa_-fv6.js → PdfLoader-DzRaTAlq.js} +14 -7
  107. package/src/ui/dist/assets/{PdfMarkdownPlugin-BZpXOEjm.js → PdfMarkdownPlugin-DZUfIUnp.js} +73 -6
  108. package/src/ui/dist/assets/{PdfViewerPlugin-BT8a6wGR.js → PdfViewerPlugin-BwtICzue.js} +103 -34
  109. package/src/ui/dist/assets/PdfViewerPlugin-DQ11QcSf.css +3627 -0
  110. package/src/ui/dist/assets/{SearchPlugin-D_blveZi.js → SearchPlugin-DHeIAMsx.js} +1 -1
  111. package/src/ui/dist/assets/{TextViewerPlugin-Btx0M3hX.js → TextViewerPlugin-C3tCmFox.js} +5 -4
  112. package/src/ui/dist/assets/{VNCViewer-DImJO4rO.js → VNCViewer-CQsKVm3t.js} +10 -10
  113. package/src/ui/dist/assets/bot-BEA2vWuK.js +21 -0
  114. package/src/ui/dist/assets/branding/logo-rokid.png +0 -0
  115. package/src/ui/dist/assets/browser-BAcuE0Xj.js +2895 -0
  116. package/src/ui/dist/assets/{code-BUfXGJSl.js → code-XfbSR8K2.js} +1 -1
  117. package/src/ui/dist/assets/{file-content-VqamwI3X.js → file-content-BjxNaIfy.js} +1 -1
  118. package/src/ui/dist/assets/{file-diff-panel-C_wOoS7a.js → file-diff-panel-D_lLVQk0.js} +1 -1
  119. package/src/ui/dist/assets/{file-socket-D2bTuMVP.js → file-socket-D9x_5vlY.js} +1 -1
  120. package/src/ui/dist/assets/{image-BZkGJ4mM.js → image-BhWT33W1.js} +1 -1
  121. package/src/ui/dist/assets/{index-DdRW6RMJ.js → index--c4iXtuy.js} +12 -12
  122. package/src/ui/dist/assets/{index-CxkvSeKw.js → index-BDxipwrC.js} +2 -2
  123. package/src/ui/dist/assets/{index-DjggJovS.js → index-DZTZ8mWP.js} +14934 -9613
  124. package/src/ui/dist/assets/{index-DXZ1daiJ.css → index-Dqj-Mjb4.css} +2 -13
  125. package/src/ui/dist/assets/index-PJbSbPTy.js +25 -0
  126. package/src/ui/dist/assets/{monaco-DHMc7kKM.js → monaco-K8izTGgo.js} +1 -1
  127. package/src/ui/dist/assets/{pdf-effect-queue-DSw_D3RV.js → pdf-effect-queue-DfBors6y.js} +16 -1
  128. package/src/ui/dist/assets/pdf.worker.min-yatZIOMy.mjs +21 -0
  129. package/src/ui/dist/assets/{popover-B85oCgCS.js → popover-yFK1J4fL.js} +1 -1
  130. package/src/ui/dist/assets/{project-sync-DOMCcPac.js → project-sync-PENr2zcz.js} +1 -74
  131. package/src/ui/dist/assets/select-CAbJDfYv.js +1690 -0
  132. package/src/ui/dist/assets/{sigma-BO2rQrl3.js → sigma-DEuYJqTl.js} +1 -1
  133. package/src/ui/dist/assets/{index-D9QIGcmc.js → square-check-big-omoSUmcd.js} +2 -13
  134. package/src/ui/dist/assets/{trash-BsVEH_dV.js → trash--F119N47.js} +1 -1
  135. package/src/ui/dist/assets/{useCliAccess-b8L6JuZm.js → useCliAccess-D31UR23I.js} +1 -1
  136. package/src/ui/dist/assets/{useFileDiffOverlay-BY7uA9hV.js → useFileDiffOverlay-BH6KcMzq.js} +1 -1
  137. package/src/ui/dist/assets/{wrap-text-BwyVuUIK.js → wrap-text-CZ613PM5.js} +1 -1
  138. package/src/ui/dist/assets/{zoom-out-RDpLugQP.js → zoom-out-BgDLAv3z.js} +1 -1
  139. package/src/ui/dist/index.html +2 -2
  140. package/src/ui/dist/assets/AutoFigurePlugin-BGxN8Umr.css +0 -3056
  141. package/src/ui/dist/assets/AutoFigurePlugin-DxPdMUNb.js +0 -8149
  142. package/src/ui/dist/assets/PdfViewerPlugin-BJXtIwj_.css +0 -260
  143. package/src/ui/dist/assets/Stepper-DH2k75Vo.js +0 -158
  144. package/src/ui/dist/assets/bibtex-B-Hqu0Sg.js +0 -189
  145. package/src/ui/dist/assets/file-utils--zJCPN1i.js +0 -109
  146. package/src/ui/dist/assets/message-square-FUIPIhU2.js +0 -16
  147. package/src/ui/dist/assets/pdfjs-DU1YE8WO.js +0 -3
  148. package/src/ui/dist/assets/tooltip-B1OspAkx.js +0 -108
@@ -1,374 +1 @@
1
- from __future__ import annotations
2
-
3
- from copy import deepcopy
4
- from typing import Any
5
-
6
- from .connector_runtime import infer_connector_transport
7
- from .shared import slugify
8
-
9
-
10
- PROFILEABLE_CONNECTOR_NAMES = ("telegram", "discord", "slack", "feishu", "whatsapp")
11
-
12
-
13
- def _normalize_secret_pair(payload: dict[str, Any], direct_key: str, env_key: str) -> None:
14
- direct = _as_text(payload.get(direct_key))
15
- env_name = _as_text(payload.get(env_key))
16
- payload[direct_key] = direct
17
- payload[env_key] = None if direct else env_name
18
-
19
-
20
- CONNECTOR_PROFILE_SPECS: dict[str, dict[str, Any]] = {
21
- "telegram": {
22
- "profile_id_prefix": "telegram-profile",
23
- "shared_fields": (
24
- "enabled",
25
- "profiles",
26
- "transport",
27
- "bot_name",
28
- "bot_token",
29
- "bot_token_env",
30
- "command_prefix",
31
- "dm_policy",
32
- "allow_from",
33
- "group_policy",
34
- "group_allow_from",
35
- "groups",
36
- "require_mention_in_groups",
37
- "auto_bind_dm_to_active_quest",
38
- ),
39
- "profile_defaults": {
40
- "profile_id": None,
41
- "enabled": True,
42
- "transport": "polling",
43
- "bot_name": "DeepScientist",
44
- "bot_token": None,
45
- "bot_token_env": None,
46
- },
47
- "profile_fields": (
48
- "enabled",
49
- "transport",
50
- "bot_name",
51
- "bot_token",
52
- "bot_token_env",
53
- ),
54
- "migration_keys": ("bot_token",),
55
- "label_fields": ("bot_name",),
56
- "id_fields": ("bot_name",),
57
- "secret_pairs": (("bot_token", "bot_token_env"),),
58
- },
59
- "discord": {
60
- "profile_id_prefix": "discord-profile",
61
- "shared_fields": (
62
- "enabled",
63
- "profiles",
64
- "transport",
65
- "bot_name",
66
- "bot_token",
67
- "bot_token_env",
68
- "command_prefix",
69
- "application_id",
70
- "dm_policy",
71
- "allow_from",
72
- "group_policy",
73
- "group_allow_from",
74
- "groups",
75
- "require_mention_in_groups",
76
- "auto_bind_dm_to_active_quest",
77
- "guild_allowlist",
78
- ),
79
- "profile_defaults": {
80
- "profile_id": None,
81
- "enabled": True,
82
- "transport": "gateway",
83
- "bot_name": "DeepScientist",
84
- "bot_token": None,
85
- "bot_token_env": None,
86
- "application_id": None,
87
- },
88
- "profile_fields": (
89
- "enabled",
90
- "transport",
91
- "bot_name",
92
- "bot_token",
93
- "bot_token_env",
94
- "application_id",
95
- ),
96
- "migration_keys": ("bot_token", "application_id"),
97
- "label_fields": ("bot_name", "application_id"),
98
- "id_fields": ("application_id", "bot_name"),
99
- "secret_pairs": (("bot_token", "bot_token_env"),),
100
- },
101
- "slack": {
102
- "profile_id_prefix": "slack-profile",
103
- "shared_fields": (
104
- "enabled",
105
- "profiles",
106
- "transport",
107
- "bot_name",
108
- "bot_token",
109
- "bot_token_env",
110
- "bot_user_id",
111
- "app_token",
112
- "app_token_env",
113
- "command_prefix",
114
- "dm_policy",
115
- "allow_from",
116
- "group_policy",
117
- "group_allow_from",
118
- "groups",
119
- "require_mention_in_groups",
120
- "auto_bind_dm_to_active_quest",
121
- ),
122
- "profile_defaults": {
123
- "profile_id": None,
124
- "enabled": True,
125
- "transport": "socket_mode",
126
- "bot_name": "DeepScientist",
127
- "bot_token": None,
128
- "bot_token_env": None,
129
- "bot_user_id": None,
130
- "app_token": None,
131
- "app_token_env": None,
132
- },
133
- "profile_fields": (
134
- "enabled",
135
- "transport",
136
- "bot_name",
137
- "bot_token",
138
- "bot_token_env",
139
- "bot_user_id",
140
- "app_token",
141
- "app_token_env",
142
- ),
143
- "migration_keys": ("bot_token", "bot_user_id", "app_token"),
144
- "label_fields": ("bot_name", "bot_user_id"),
145
- "id_fields": ("bot_user_id", "bot_name"),
146
- "secret_pairs": (
147
- ("bot_token", "bot_token_env"),
148
- ("app_token", "app_token_env"),
149
- ),
150
- },
151
- "feishu": {
152
- "profile_id_prefix": "feishu-profile",
153
- "shared_fields": (
154
- "enabled",
155
- "profiles",
156
- "transport",
157
- "bot_name",
158
- "app_id",
159
- "app_secret",
160
- "app_secret_env",
161
- "api_base_url",
162
- "command_prefix",
163
- "dm_policy",
164
- "allow_from",
165
- "group_policy",
166
- "group_allow_from",
167
- "groups",
168
- "require_mention_in_groups",
169
- "auto_bind_dm_to_active_quest",
170
- ),
171
- "profile_defaults": {
172
- "profile_id": None,
173
- "enabled": True,
174
- "transport": "long_connection",
175
- "bot_name": "DeepScientist",
176
- "app_id": None,
177
- "app_secret": None,
178
- "app_secret_env": None,
179
- "api_base_url": "https://open.feishu.cn",
180
- },
181
- "profile_fields": (
182
- "enabled",
183
- "transport",
184
- "bot_name",
185
- "app_id",
186
- "app_secret",
187
- "app_secret_env",
188
- "api_base_url",
189
- ),
190
- "migration_keys": ("app_id", "app_secret"),
191
- "label_fields": ("bot_name", "app_id"),
192
- "id_fields": ("app_id", "bot_name"),
193
- "secret_pairs": (("app_secret", "app_secret_env"),),
194
- },
195
- "whatsapp": {
196
- "profile_id_prefix": "whatsapp-profile",
197
- "shared_fields": (
198
- "enabled",
199
- "profiles",
200
- "transport",
201
- "bot_name",
202
- "auth_method",
203
- "session_dir",
204
- "command_prefix",
205
- "dm_policy",
206
- "allow_from",
207
- "group_policy",
208
- "group_allow_from",
209
- "groups",
210
- "auto_bind_dm_to_active_quest",
211
- ),
212
- "profile_defaults": {
213
- "profile_id": None,
214
- "enabled": True,
215
- "transport": "local_session",
216
- "bot_name": "DeepScientist",
217
- "auth_method": "qr_browser",
218
- "session_dir": "~/.deepscientist/connectors/whatsapp",
219
- },
220
- "profile_fields": (
221
- "enabled",
222
- "transport",
223
- "bot_name",
224
- "auth_method",
225
- "session_dir",
226
- ),
227
- "migration_keys": ("session_dir",),
228
- "label_fields": ("bot_name",),
229
- "id_fields": ("bot_name",),
230
- "secret_pairs": (),
231
- },
232
- }
233
-
234
-
235
- def _as_text(value: Any) -> str | None:
236
- text = str(value or "").strip()
237
- return text or None
238
-
239
-
240
- def _profile_seed(connector_name: str, raw: dict[str, Any], *, index: int) -> str:
241
- spec = CONNECTOR_PROFILE_SPECS[connector_name]
242
- explicit = _as_text(raw.get("profile_id"))
243
- if explicit:
244
- return explicit
245
- for key in spec["id_fields"]:
246
- candidate = _as_text(raw.get(key))
247
- if candidate:
248
- return f"{connector_name}-{candidate}"
249
- return f"{spec['profile_id_prefix']}-{index:03d}"
250
-
251
-
252
- def _unique_profile_id(seed: str, *, prefix: str, used: set[str]) -> str:
253
- base = slugify(seed, default=prefix)
254
- candidate = base
255
- suffix = 2
256
- while candidate in used:
257
- candidate = f"{base}-{suffix}"
258
- suffix += 1
259
- used.add(candidate)
260
- return candidate
261
-
262
-
263
- def default_connector_profile(connector_name: str) -> dict[str, Any]:
264
- spec = CONNECTOR_PROFILE_SPECS[connector_name]
265
- return deepcopy(spec["profile_defaults"])
266
-
267
-
268
- def connector_profile_label(connector_name: str, profile: dict[str, Any] | None) -> str:
269
- if not isinstance(profile, dict):
270
- return connector_name.capitalize()
271
- spec = CONNECTOR_PROFILE_SPECS[connector_name]
272
- parts = [_as_text(profile.get(key)) for key in spec["label_fields"]]
273
- filtered = [item for item in parts if item]
274
- return " · ".join(filtered) if filtered else connector_name.capitalize()
275
-
276
-
277
- def normalize_connector_config(connector_name: str, config: dict[str, Any] | None) -> dict[str, Any]:
278
- if connector_name not in CONNECTOR_PROFILE_SPECS:
279
- raise KeyError(f"Connector `{connector_name}` does not support generic profile normalization.")
280
- spec = CONNECTOR_PROFILE_SPECS[connector_name]
281
- payload = deepcopy(config or {})
282
- shared = {
283
- key: deepcopy(payload.get(key))
284
- for key in spec["shared_fields"]
285
- if key in payload
286
- }
287
- shared["profiles"] = []
288
- for direct_key, env_key in spec.get("secret_pairs", ()):
289
- _normalize_secret_pair(shared, direct_key, env_key)
290
-
291
- raw_profiles = payload.get("profiles")
292
- items = list(raw_profiles) if isinstance(raw_profiles, list) else []
293
- has_direct_migration_value = any(_as_text(payload.get(key)) for key in spec["migration_keys"])
294
- has_env_only_secret = bool(payload.get("enabled")) and any(
295
- _as_text(payload.get(env_key))
296
- for _, env_key in spec.get("secret_pairs", ())
297
- )
298
- if not items and (has_direct_migration_value or has_env_only_secret):
299
- items = [{key: payload.get(key) for key in spec["profile_fields"]}]
300
-
301
- used_ids: set[str] = set()
302
- profiles: list[dict[str, Any]] = []
303
- for index, raw in enumerate(items, start=1):
304
- if not isinstance(raw, dict):
305
- continue
306
- current = default_connector_profile(connector_name)
307
- for key in ("profile_id", *spec["profile_fields"]):
308
- if key in raw:
309
- current[key] = deepcopy(raw.get(key))
310
- current["enabled"] = bool(current.get("enabled", True))
311
- for key in spec["profile_fields"]:
312
- if key in {"enabled", "transport", "mode"}:
313
- continue
314
- if isinstance(current.get(key), list):
315
- continue
316
- if current.get(key) is None:
317
- continue
318
- current[key] = _as_text(current.get(key))
319
- current["transport"] = infer_connector_transport(connector_name, current)
320
- if "mode" in spec["profile_defaults"] or current.get("mode") is not None:
321
- current["mode"] = _as_text(current.get("mode")) or str(spec["profile_defaults"].get("mode") or "")
322
- for direct_key, env_key in spec.get("secret_pairs", ()):
323
- _normalize_secret_pair(current, direct_key, env_key)
324
- current["profile_id"] = _unique_profile_id(
325
- _profile_seed(connector_name, current, index=index),
326
- prefix=str(spec["profile_id_prefix"]),
327
- used=used_ids,
328
- )
329
- profiles.append(current)
330
-
331
- shared["transport"] = infer_connector_transport(connector_name, shared)
332
- shared["profiles"] = profiles
333
- if len(profiles) == 1:
334
- for key in spec["profile_fields"]:
335
- shared[key] = profiles[0].get(key)
336
- elif len(profiles) > 1:
337
- for direct_key, env_key in spec.get("secret_pairs", ()):
338
- shared[direct_key] = None
339
- shared[env_key] = None
340
- return shared
341
-
342
-
343
- def list_connector_profiles(connector_name: str, config: dict[str, Any] | None) -> list[dict[str, Any]]:
344
- normalized = normalize_connector_config(connector_name, config)
345
- profiles = normalized.get("profiles")
346
- return [dict(item) for item in profiles] if isinstance(profiles, list) else []
347
-
348
-
349
- def find_connector_profile(
350
- connector_name: str,
351
- config: dict[str, Any] | None,
352
- *,
353
- profile_id: str | None = None,
354
- ) -> dict[str, Any] | None:
355
- normalized_profile_id = _as_text(profile_id)
356
- for profile in list_connector_profiles(connector_name, config):
357
- if normalized_profile_id and str(profile.get("profile_id") or "").strip() == normalized_profile_id:
358
- return profile
359
- return None
360
-
361
-
362
- def merge_connector_profile_config(
363
- connector_name: str,
364
- shared_config: dict[str, Any] | None,
365
- profile: dict[str, Any],
366
- ) -> dict[str, Any]:
367
- normalized = normalize_connector_config(connector_name, shared_config)
368
- merged = deepcopy(normalized)
369
- merged.pop("profiles", None)
370
- for key in CONNECTOR_PROFILE_SPECS[connector_name]["profile_fields"]:
371
- merged[key] = profile.get(key)
372
- merged["profile_id"] = str(profile.get("profile_id") or "").strip() or None
373
- merged["enabled"] = bool(normalized.get("enabled", False)) and bool(profile.get("enabled", True))
374
- return merged
1
+ from .connector.connector_profiles import * # noqa: F401,F403
@@ -22,6 +22,8 @@ def infer_connector_transport(name: str, config: dict[str, Any] | None) -> str:
22
22
 
23
23
  if normalized == "qq":
24
24
  return "gateway_direct"
25
+ if normalized == "weixin":
26
+ return "ilink_long_poll"
25
27
  if normalized == "telegram":
26
28
  return "polling"
27
29
  if normalized == "discord":