@researai/deepscientist 1.5.14 → 1.5.16

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 (225) hide show
  1. package/README.md +336 -90
  2. package/assets/branding/logo-raster.png +0 -0
  3. package/bin/ds.js +816 -131
  4. package/docs/en/00_QUICK_START.md +36 -15
  5. package/docs/en/01_SETTINGS_REFERENCE.md +53 -4
  6. package/docs/en/02_START_RESEARCH_GUIDE.md +7 -0
  7. package/docs/en/03_QQ_CONNECTOR_GUIDE.md +19 -0
  8. package/docs/en/05_TUI_GUIDE.md +6 -0
  9. package/docs/en/06_RUNTIME_AND_CANVAS.md +4 -3
  10. package/docs/en/09_DOCTOR.md +11 -5
  11. package/docs/en/10_WEIXIN_CONNECTOR_GUIDE.md +20 -0
  12. package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +65 -13
  13. package/docs/en/15_CODEX_PROVIDER_SETUP.md +25 -8
  14. package/docs/en/16_TELEGRAM_CONNECTOR_GUIDE.md +134 -0
  15. package/docs/en/17_WHATSAPP_CONNECTOR_GUIDE.md +126 -0
  16. package/docs/en/18_FEISHU_CONNECTOR_GUIDE.md +136 -0
  17. package/docs/en/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
  18. package/docs/en/19_LOCAL_BROWSER_AUTH.md +70 -0
  19. package/docs/en/20_WORKSPACE_MODES_GUIDE.md +250 -0
  20. package/docs/en/README.md +24 -0
  21. package/docs/zh/00_QUICK_START.md +36 -15
  22. package/docs/zh/01_SETTINGS_REFERENCE.md +53 -4
  23. package/docs/zh/02_START_RESEARCH_GUIDE.md +7 -0
  24. package/docs/zh/03_QQ_CONNECTOR_GUIDE.md +19 -0
  25. package/docs/zh/05_TUI_GUIDE.md +6 -0
  26. package/docs/zh/09_DOCTOR.md +11 -5
  27. package/docs/zh/10_WEIXIN_CONNECTOR_GUIDE.md +20 -0
  28. package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +65 -13
  29. package/docs/zh/15_CODEX_PROVIDER_SETUP.md +25 -8
  30. package/docs/zh/16_TELEGRAM_CONNECTOR_GUIDE.md +134 -0
  31. package/docs/zh/17_WHATSAPP_CONNECTOR_GUIDE.md +126 -0
  32. package/docs/zh/18_FEISHU_CONNECTOR_GUIDE.md +136 -0
  33. package/docs/zh/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
  34. package/docs/zh/19_LOCAL_BROWSER_AUTH.md +68 -0
  35. package/docs/zh/20_WORKSPACE_MODES_GUIDE.md +251 -0
  36. package/docs/zh/README.md +24 -0
  37. package/install.sh +2 -0
  38. package/package.json +1 -1
  39. package/pyproject.toml +1 -1
  40. package/src/deepscientist/__init__.py +1 -1
  41. package/src/deepscientist/acp/envelope.py +6 -0
  42. package/src/deepscientist/artifact/charts.py +567 -0
  43. package/src/deepscientist/artifact/guidance.py +50 -10
  44. package/src/deepscientist/artifact/metrics.py +228 -5
  45. package/src/deepscientist/artifact/schemas.py +3 -0
  46. package/src/deepscientist/artifact/service.py +4276 -308
  47. package/src/deepscientist/bash_exec/models.py +23 -0
  48. package/src/deepscientist/bash_exec/monitor.py +147 -67
  49. package/src/deepscientist/bash_exec/runtime.py +218 -156
  50. package/src/deepscientist/bash_exec/service.py +309 -69
  51. package/src/deepscientist/bash_exec/shells.py +87 -0
  52. package/src/deepscientist/bridges/connectors.py +51 -2
  53. package/src/deepscientist/cli.py +115 -19
  54. package/src/deepscientist/codex_cli_compat.py +232 -0
  55. package/src/deepscientist/config/models.py +8 -4
  56. package/src/deepscientist/config/service.py +38 -11
  57. package/src/deepscientist/connector/weixin_support.py +122 -1
  58. package/src/deepscientist/daemon/api/handlers.py +199 -9
  59. package/src/deepscientist/daemon/api/router.py +5 -0
  60. package/src/deepscientist/daemon/app.py +1458 -289
  61. package/src/deepscientist/doctor.py +51 -0
  62. package/src/deepscientist/file_lock.py +48 -0
  63. package/src/deepscientist/gitops/__init__.py +10 -1
  64. package/src/deepscientist/gitops/diff.py +296 -1
  65. package/src/deepscientist/gitops/service.py +4 -1
  66. package/src/deepscientist/mcp/server.py +212 -5
  67. package/src/deepscientist/process_control.py +161 -0
  68. package/src/deepscientist/prompts/builder.py +501 -453
  69. package/src/deepscientist/quest/layout.py +15 -2
  70. package/src/deepscientist/quest/service.py +2539 -195
  71. package/src/deepscientist/quest/stage_views.py +177 -1
  72. package/src/deepscientist/runners/base.py +2 -0
  73. package/src/deepscientist/runners/codex.py +169 -31
  74. package/src/deepscientist/runners/runtime_overrides.py +17 -1
  75. package/src/deepscientist/skills/__init__.py +2 -2
  76. package/src/deepscientist/skills/installer.py +196 -5
  77. package/src/deepscientist/skills/registry.py +66 -0
  78. package/src/prompts/connectors/qq.md +18 -8
  79. package/src/prompts/connectors/weixin.md +16 -6
  80. package/src/prompts/contracts/shared_interaction.md +24 -4
  81. package/src/prompts/system.md +921 -72
  82. package/src/prompts/system_copilot.md +43 -0
  83. package/src/skills/analysis-campaign/SKILL.md +32 -2
  84. package/src/skills/analysis-campaign/references/artifact-orchestration.md +1 -1
  85. package/src/skills/analysis-campaign/references/writing-facing-slice-examples.md +65 -0
  86. package/src/skills/baseline/SKILL.md +10 -0
  87. package/src/skills/decision/SKILL.md +27 -2
  88. package/src/skills/experiment/SKILL.md +16 -2
  89. package/src/skills/figure-polish/SKILL.md +1 -0
  90. package/src/skills/finalize/SKILL.md +19 -0
  91. package/src/skills/idea/SKILL.md +79 -0
  92. package/src/skills/idea/references/idea-generation-playbook.md +100 -0
  93. package/src/skills/idea/references/outline-seeding-example.md +60 -0
  94. package/src/skills/intake-audit/SKILL.md +9 -1
  95. package/src/skills/mentor/SKILL.md +217 -0
  96. package/src/skills/mentor/references/correction-rules.md +210 -0
  97. package/src/skills/mentor/references/knowledge-profile.md +91 -0
  98. package/src/skills/mentor/references/persona-profile.md +138 -0
  99. package/src/skills/mentor/references/taste-profile.md +128 -0
  100. package/src/skills/mentor/references/thought-style-profile.md +138 -0
  101. package/src/skills/mentor/references/work-profile.md +289 -0
  102. package/src/skills/mentor/references/workflow-profile.md +240 -0
  103. package/src/skills/optimize/SKILL.md +1645 -0
  104. package/src/skills/rebuttal/SKILL.md +3 -1
  105. package/src/skills/review/SKILL.md +3 -1
  106. package/src/skills/scout/SKILL.md +8 -0
  107. package/src/skills/write/SKILL.md +81 -12
  108. package/src/skills/write/references/outline-evidence-contract-example.md +107 -0
  109. package/src/tui/dist/app/AppContainer.js +22 -11
  110. package/src/tui/dist/index.js +4 -1
  111. package/src/tui/dist/lib/api.js +33 -3
  112. package/src/tui/package.json +1 -1
  113. package/src/ui/dist/assets/AiManusChatView-COFACy7V.js +204 -0
  114. package/src/ui/dist/assets/AnalysisPlugin-DnSm0GZn.js +1 -0
  115. package/src/ui/dist/assets/CliPlugin-CvwCmDQ5.js +109 -0
  116. package/src/ui/dist/assets/CodeEditorPlugin-cOqSa0xq.js +2 -0
  117. package/src/ui/dist/assets/CodeViewerPlugin-itb0tltR.js +270 -0
  118. package/src/ui/dist/assets/DocViewerPlugin-DqKkiCI6.js +7 -0
  119. package/src/ui/dist/assets/GitCommitViewerPlugin-DVgNHBCS.js +1 -0
  120. package/src/ui/dist/assets/GitDiffViewerPlugin-DxL2ezFG.js +6 -0
  121. package/src/ui/dist/assets/GitSnapshotViewer-B_RQm1YZ.js +30 -0
  122. package/src/ui/dist/assets/ImageViewerPlugin-tHqlXY3n.js +26 -0
  123. package/src/ui/dist/assets/LabCopilotPanel-ClMbq5Yu.js +14 -0
  124. package/src/ui/dist/assets/LabPlugin-L_SuE8ow.js +22 -0
  125. package/src/ui/dist/assets/LatexPlugin-B495DTXC.js +25 -0
  126. package/src/ui/dist/assets/MarkdownViewerPlugin-DG28-61B.js +128 -0
  127. package/src/ui/dist/assets/MarketplacePlugin-BiOGT-Kj.js +13 -0
  128. package/src/ui/dist/assets/{NotebookEditor-CccQYZjX.css → NotebookEditor-BHH8rdGj.css} +1 -1
  129. package/src/ui/dist/assets/NotebookEditor-BOr3x3Ej.css +1 -0
  130. package/src/ui/dist/assets/NotebookEditor-C-4Kt1p9.js +81 -0
  131. package/src/ui/dist/assets/NotebookEditor-CVsj8h_T.js +361 -0
  132. package/src/ui/dist/assets/PdfLoader-CASDQmxJ.js +16 -0
  133. package/src/ui/dist/assets/PdfLoader-Cy5jtWrr.css +1 -0
  134. package/src/ui/dist/assets/PdfMarkdownPlugin-BFhwoKsY.js +1 -0
  135. package/src/ui/dist/assets/PdfViewerPlugin-DcOzU9vd.js +17 -0
  136. package/src/ui/dist/assets/PdfViewerPlugin-nwwE-fjJ.css +1 -0
  137. package/src/ui/dist/assets/SearchPlugin-CHj7M58O.js +16 -0
  138. package/src/ui/dist/assets/SearchPlugin-DA4en4hK.css +1 -0
  139. package/src/ui/dist/assets/TextViewerPlugin-CB4DYfWO.js +54 -0
  140. package/src/ui/dist/assets/VNCViewer-CjlbyCB3.js +11 -0
  141. package/src/ui/dist/assets/bot-CFkZY-JP.js +6 -0
  142. package/src/ui/dist/assets/browser-CTB2jwNe.js +8 -0
  143. package/src/ui/dist/assets/chevron-up-Dq5ofbht.js +6 -0
  144. package/src/ui/dist/assets/code-DLC6G24T.js +6 -0
  145. package/src/ui/dist/assets/file-content-Dv4LoZec.js +1 -0
  146. package/src/ui/dist/assets/file-diff-panel-Denq-lC3.js +1 -0
  147. package/src/ui/dist/assets/file-jump-queue-DA-SdG__.js +1 -0
  148. package/src/ui/dist/assets/file-socket-Cu4Qln7Y.js +1 -0
  149. package/src/ui/dist/assets/git-commit-horizontal-BUh6G52n.js +6 -0
  150. package/src/ui/dist/assets/image-B9HUUddG.js +6 -0
  151. package/src/ui/dist/assets/index-B2B1sg-M.js +1 -0
  152. package/src/ui/dist/assets/index-Cgla8biy.css +33 -0
  153. package/src/ui/dist/assets/index-DRyx7vAc.js +1 -0
  154. package/src/ui/dist/assets/index-Gbl53BNp.js +2496 -0
  155. package/src/ui/dist/assets/index-wQ7RIIRd.js +11 -0
  156. package/src/ui/dist/assets/monaco-CiHMMNH_.js +1 -0
  157. package/src/ui/dist/assets/pdf-effect-queue-ZtnHFCAi.js +6 -0
  158. package/src/ui/dist/assets/plugin-monaco-C8UgLomw.js +19 -0
  159. package/src/ui/dist/assets/plugin-notebook-HbW2K-1c.js +169 -0
  160. package/src/ui/dist/assets/plugin-pdf-CR8hgQBV.js +357 -0
  161. package/src/ui/dist/assets/plugin-terminal-MXFIPun8.js +227 -0
  162. package/src/ui/dist/assets/popover-DL6h35vr.js +1 -0
  163. package/src/ui/dist/assets/project-sync-CsX08Qno.js +1 -0
  164. package/src/ui/dist/assets/select-DvmXt1yY.js +11 -0
  165. package/src/ui/dist/assets/sigma-7jpXazui.js +6 -0
  166. package/src/ui/dist/assets/trash-xA7kFt8i.js +11 -0
  167. package/src/ui/dist/assets/useCliAccess-DsMwDjOp.js +1 -0
  168. package/src/ui/dist/assets/useFileDiffOverlay-FuhcnKiw.js +1 -0
  169. package/src/ui/dist/assets/wrap-text-CwMn-iqb.js +11 -0
  170. package/src/ui/dist/assets/zoom-out-R-GWEhzS.js +11 -0
  171. package/src/ui/dist/index.html +5 -2
  172. package/src/ui/dist/assets/AiManusChatView-DaF9Nge_.js +0 -26597
  173. package/src/ui/dist/assets/AnalysisPlugin-BSVx6dXE.js +0 -123
  174. package/src/ui/dist/assets/CliPlugin-C9gzJX41.js +0 -5905
  175. package/src/ui/dist/assets/CodeEditorPlugin-DU9G0Tox.js +0 -427
  176. package/src/ui/dist/assets/CodeViewerPlugin-DoX_fI9l.js +0 -905
  177. package/src/ui/dist/assets/DocViewerPlugin-C4FWIXuU.js +0 -278
  178. package/src/ui/dist/assets/GitDiffViewerPlugin-BgfFMgtf.js +0 -2661
  179. package/src/ui/dist/assets/ImageViewerPlugin-tcPkfY_x.js +0 -500
  180. package/src/ui/dist/assets/LabCopilotPanel-_dKV60Bf.js +0 -4104
  181. package/src/ui/dist/assets/LabPlugin-Bje0ayoC.js +0 -2677
  182. package/src/ui/dist/assets/LatexPlugin-CVsBzAln.js +0 -1792
  183. package/src/ui/dist/assets/MarkdownViewerPlugin-xjmrqv_8.js +0 -308
  184. package/src/ui/dist/assets/MarketplacePlugin-mMM2A8wP.js +0 -413
  185. package/src/ui/dist/assets/NotebookEditor-3kVDSOBo.js +0 -4214
  186. package/src/ui/dist/assets/NotebookEditor-C3VQ7ylN.css +0 -1405
  187. package/src/ui/dist/assets/NotebookEditor-SoJ8X-MO.js +0 -84873
  188. package/src/ui/dist/assets/PdfLoader-C-Y707R3.css +0 -49
  189. package/src/ui/dist/assets/PdfLoader-DElVuHl9.js +0 -25468
  190. package/src/ui/dist/assets/PdfMarkdownPlugin-Bq88XT4G.js +0 -409
  191. package/src/ui/dist/assets/PdfViewerPlugin-CsCXMo9S.js +0 -3095
  192. package/src/ui/dist/assets/PdfViewerPlugin-DQ11QcSf.css +0 -3627
  193. package/src/ui/dist/assets/SearchPlugin-DDMrGDkh.css +0 -379
  194. package/src/ui/dist/assets/SearchPlugin-oUPvy19k.js +0 -741
  195. package/src/ui/dist/assets/TextViewerPlugin-CRkT9yNy.js +0 -472
  196. package/src/ui/dist/assets/VNCViewer-BgbuvWhR.js +0 -18821
  197. package/src/ui/dist/assets/awareness-C0NPR2Dj.js +0 -292
  198. package/src/ui/dist/assets/bot-v_RASACv.js +0 -21
  199. package/src/ui/dist/assets/browser-BAcuE0Xj.js +0 -2895
  200. package/src/ui/dist/assets/code-5hC9d0VH.js +0 -17
  201. package/src/ui/dist/assets/file-content-D1PxfOrp.js +0 -377
  202. package/src/ui/dist/assets/file-diff-panel-DG1oT_Hj.js +0 -92
  203. package/src/ui/dist/assets/file-jump-queue-r5XKgJEV.js +0 -16
  204. package/src/ui/dist/assets/file-socket-BmdFYQlk.js +0 -58
  205. package/src/ui/dist/assets/function-B5QZkkHC.js +0 -1895
  206. package/src/ui/dist/assets/image-Dqe2X2tW.js +0 -18
  207. package/src/ui/dist/assets/index-BQG-1s2o.css +0 -12553
  208. package/src/ui/dist/assets/index-DVsMKK_y.js +0 -25
  209. package/src/ui/dist/assets/index-Duvz8Ip0.js +0 -159
  210. package/src/ui/dist/assets/index-Nt9hS4ck.js +0 -244829
  211. package/src/ui/dist/assets/index-RDlNXXx1.js +0 -120
  212. package/src/ui/dist/assets/monaco-DIXge1CP.js +0 -623
  213. package/src/ui/dist/assets/pdf-effect-queue-BBTTQaO-.js +0 -47
  214. package/src/ui/dist/assets/pdf_viewer-e0g1is2C.js +0 -8206
  215. package/src/ui/dist/assets/popover-BWlolyxo.js +0 -476
  216. package/src/ui/dist/assets/project-sync-BM5PkFH4.js +0 -297
  217. package/src/ui/dist/assets/select-D4dAtrA8.js +0 -1690
  218. package/src/ui/dist/assets/sigma-CKbE5jJT.js +0 -22
  219. package/src/ui/dist/assets/square-check-big-CZNGMgiB.js +0 -17
  220. package/src/ui/dist/assets/trash-DaB37xAz.js +0 -32
  221. package/src/ui/dist/assets/useCliAccess-C2OmAcWe.js +0 -957
  222. package/src/ui/dist/assets/useFileDiffOverlay-Dowd1Ij4.js +0 -53
  223. package/src/ui/dist/assets/wrap-text-BGjAhAUq.js +0 -35
  224. package/src/ui/dist/assets/yjs-DncrqiZ8.js +0 -11243
  225. package/src/ui/dist/assets/zoom-out-dMZQMXzc.js +0 -34
@@ -1,472 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-Nt9hS4ck.js","assets/index-BQG-1s2o.css"])))=>i.map(i=>d[i]);
2
- import { r as reactExports, c as copyToClipboard, j as jsxRuntimeExports, L as LoaderCircle, T as TriangleAlert, k as FileText, l as Search, b as cn, d as Check, e as Copy, m as ChevronDown, X, _ as __vitePreload } from './index-Nt9hS4ck.js';
3
- import { c as consumeFileJumpEffects } from './file-jump-queue-r5XKgJEV.js';
4
- import { H as Hash, W as WrapText } from './wrap-text-BGjAhAUq.js';
5
- import { C as ChevronUp } from './index-DVsMKK_y.js';
6
-
7
- const LARGE_FILE_THRESHOLD = 1024 * 1024;
8
- const MAX_RENDERED_LINES = 1e4;
9
- function TextViewerPlugin({
10
- context,
11
- tabId,
12
- setDirty,
13
- setTitle
14
- }) {
15
- const [content, setContent] = reactExports.useState("");
16
- const [loading, setLoading] = reactExports.useState(true);
17
- const [error, setError] = reactExports.useState(null);
18
- const [copied, setCopied] = reactExports.useState(false);
19
- const [showLineNumbers, setShowLineNumbers] = reactExports.useState(true);
20
- const [wordWrap, setWordWrap] = reactExports.useState(true);
21
- const [fileSize, setFileSize] = reactExports.useState(0);
22
- const [showLargeFileWarning, setShowLargeFileWarning] = reactExports.useState(false);
23
- const [showSearch, setShowSearch] = reactExports.useState(false);
24
- const [searchQuery, setSearchQuery] = reactExports.useState("");
25
- const [currentMatchIndex, setCurrentMatchIndex] = reactExports.useState(0);
26
- const [matchPositions, setMatchPositions] = reactExports.useState([]);
27
- const [highlightRange, setHighlightRange] = reactExports.useState(
28
- null
29
- );
30
- const highlightTimerRef = reactExports.useRef(null);
31
- const fileId = context.resourceId;
32
- const fileName = context.resourceName || context.resourcePath || "Untitled";
33
- reactExports.useEffect(() => {
34
- setTitle(fileName);
35
- }, [fileName, setTitle]);
36
- reactExports.useEffect(() => {
37
- const loadContent = async () => {
38
- setLoading(true);
39
- setError(null);
40
- setShowLargeFileWarning(false);
41
- try {
42
- if (!context.resourceId) {
43
- setContent(DEMO_TEXT);
44
- setFileSize(DEMO_TEXT.length);
45
- setLoading(false);
46
- return;
47
- }
48
- const { getFileContent } = await __vitePreload(async () => { const { getFileContent } = await import('./index-Nt9hS4ck.js').then(n => n.el);return { getFileContent }},true?__vite__mapDeps([0,1]):void 0);
49
- const text = await getFileContent(context.resourceId);
50
- setContent(text);
51
- setFileSize(text.length);
52
- if (text.length > LARGE_FILE_THRESHOLD) {
53
- setShowLargeFileWarning(true);
54
- }
55
- } catch (err) {
56
- setError(err instanceof Error ? err.message : "Failed to load file");
57
- } finally {
58
- setLoading(false);
59
- }
60
- };
61
- loadContent();
62
- }, [context.resourceId]);
63
- const lines = reactExports.useMemo(() => content.split("\n"), [content]);
64
- const renderedLines = reactExports.useMemo(() => {
65
- if (lines.length > MAX_RENDERED_LINES) {
66
- return lines.slice(0, MAX_RENDERED_LINES);
67
- }
68
- return lines;
69
- }, [lines]);
70
- const isTruncated = lines.length > MAX_RENDERED_LINES;
71
- const applyJump = reactExports.useCallback(
72
- (detail) => {
73
- if (!fileId || detail.fileId !== fileId) return;
74
- const startValue = detail.lineStart ?? detail.line ?? detail.lineEnd;
75
- if (!startValue) return;
76
- const endValue = detail.lineEnd ?? detail.line ?? detail.lineStart ?? startValue;
77
- const maxLine = Math.max(1, lines.length);
78
- const start = Math.min(Math.max(startValue, 1), maxLine);
79
- const end = Math.min(Math.max(endValue, start), maxLine);
80
- setHighlightRange({ start, end });
81
- const lineElement = document.getElementById(`line-${start - 1}`);
82
- if (lineElement) {
83
- lineElement.scrollIntoView({ behavior: "smooth", block: "center" });
84
- }
85
- if (highlightTimerRef.current) {
86
- window.clearTimeout(highlightTimerRef.current);
87
- }
88
- highlightTimerRef.current = window.setTimeout(() => {
89
- setHighlightRange(null);
90
- }, 2500);
91
- },
92
- [fileId, lines.length]
93
- );
94
- reactExports.useEffect(() => {
95
- if (!fileId) return;
96
- const processQueue = () => {
97
- const queued = consumeFileJumpEffects(fileId);
98
- queued.forEach((entry) => applyJump(entry.data));
99
- };
100
- processQueue();
101
- const handleJump = (event) => {
102
- const detail = event.detail;
103
- applyJump(detail);
104
- };
105
- const handleQueue = (event) => {
106
- const detail = event.detail;
107
- if (!detail || detail.fileId !== fileId) return;
108
- processQueue();
109
- };
110
- window.addEventListener("ds:file:jump", handleJump);
111
- window.addEventListener("ds:file:queue", handleQueue);
112
- return () => {
113
- window.removeEventListener("ds:file:jump", handleJump);
114
- window.removeEventListener("ds:file:queue", handleQueue);
115
- if (highlightTimerRef.current) {
116
- window.clearTimeout(highlightTimerRef.current);
117
- highlightTimerRef.current = null;
118
- }
119
- };
120
- }, [applyJump, fileId]);
121
- reactExports.useEffect(() => {
122
- if (!searchQuery.trim()) {
123
- setMatchPositions([]);
124
- setCurrentMatchIndex(0);
125
- return;
126
- }
127
- const query = searchQuery.toLowerCase();
128
- const positions = [];
129
- lines.forEach((line, index) => {
130
- if (line.toLowerCase().includes(query)) {
131
- positions.push(index);
132
- }
133
- });
134
- setMatchPositions(positions);
135
- setCurrentMatchIndex(0);
136
- }, [searchQuery, lines]);
137
- const goToMatch = reactExports.useCallback(
138
- (direction) => {
139
- if (matchPositions.length === 0) return;
140
- let newIndex = currentMatchIndex;
141
- if (direction === "next") {
142
- newIndex = (currentMatchIndex + 1) % matchPositions.length;
143
- } else {
144
- newIndex = (currentMatchIndex - 1 + matchPositions.length) % matchPositions.length;
145
- }
146
- setCurrentMatchIndex(newIndex);
147
- const lineElement = document.getElementById(`line-${matchPositions[newIndex]}`);
148
- if (lineElement) {
149
- lineElement.scrollIntoView({ behavior: "smooth", block: "center" });
150
- }
151
- },
152
- [currentMatchIndex, matchPositions]
153
- );
154
- const handleCopy = reactExports.useCallback(async () => {
155
- const ok = await copyToClipboard(content);
156
- if (ok) {
157
- setCopied(true);
158
- setTimeout(() => setCopied(false), 2e3);
159
- }
160
- }, [content]);
161
- const formattedSize = reactExports.useMemo(() => {
162
- if (fileSize < 1024) return `${fileSize} B`;
163
- if (fileSize < 1024 * 1024) return `${(fileSize / 1024).toFixed(1)} KB`;
164
- return `${(fileSize / (1024 * 1024)).toFixed(1)} MB`;
165
- }, [fileSize]);
166
- reactExports.useEffect(() => {
167
- const handleKeyDown = (e) => {
168
- if ((e.ctrlKey || e.metaKey) && e.key === "f") {
169
- e.preventDefault();
170
- setShowSearch(true);
171
- }
172
- if (e.key === "Escape" && showSearch) {
173
- setShowSearch(false);
174
- setSearchQuery("");
175
- }
176
- if (showSearch && (e.key === "F3" || e.key === "Enter" && !e.shiftKey)) {
177
- e.preventDefault();
178
- goToMatch("next");
179
- }
180
- if (showSearch && (e.key === "F3" && e.shiftKey || e.key === "Enter" && e.shiftKey)) {
181
- e.preventDefault();
182
- goToMatch("prev");
183
- }
184
- };
185
- window.addEventListener("keydown", handleKeyDown);
186
- return () => window.removeEventListener("keydown", handleKeyDown);
187
- }, [showSearch, goToMatch]);
188
- if (loading) {
189
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full bg-background", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-muted-foreground", children: [
190
- /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "w-8 h-8 animate-spin" }),
191
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Loading file..." })
192
- ] }) });
193
- }
194
- if (error) {
195
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full bg-background", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3 text-destructive", children: [
196
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "w-8 h-8" }),
197
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: error }),
198
- /* @__PURE__ */ jsxRuntimeExports.jsx(
199
- "button",
200
- {
201
- className: "px-4 py-2 text-sm bg-destructive/10 hover:bg-destructive/20 rounded-lg transition-colors",
202
- onClick: () => window.location.reload(),
203
- children: "Retry"
204
- }
205
- )
206
- ] }) });
207
- }
208
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full bg-background text-foreground", children: [
209
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-4 py-2 border-b border-border bg-muted/30", children: [
210
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
211
- /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "w-4 h-4 text-muted-foreground" }),
212
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-foreground", children: fileName }),
213
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-muted-foreground", children: [
214
- lines.length,
215
- " ",
216
- lines.length === 1 ? "line" : "lines",
217
- " | ",
218
- formattedSize
219
- ] })
220
- ] }),
221
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
222
- /* @__PURE__ */ jsxRuntimeExports.jsx(
223
- "button",
224
- {
225
- onClick: () => setShowSearch(!showSearch),
226
- className: cn(
227
- "p-2 rounded hover:bg-accent transition-colors",
228
- showSearch ? "text-primary bg-accent" : "text-muted-foreground"
229
- ),
230
- title: "Search (Ctrl+F)",
231
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "w-4 h-4" })
232
- }
233
- ),
234
- /* @__PURE__ */ jsxRuntimeExports.jsx(
235
- "button",
236
- {
237
- onClick: () => setShowLineNumbers(!showLineNumbers),
238
- className: cn(
239
- "p-2 rounded hover:bg-accent transition-colors",
240
- showLineNumbers ? "text-primary" : "text-muted-foreground"
241
- ),
242
- title: "Toggle line numbers",
243
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Hash, { className: "w-4 h-4" })
244
- }
245
- ),
246
- /* @__PURE__ */ jsxRuntimeExports.jsx(
247
- "button",
248
- {
249
- onClick: () => setWordWrap(!wordWrap),
250
- className: cn(
251
- "p-2 rounded hover:bg-accent transition-colors",
252
- wordWrap ? "text-primary" : "text-muted-foreground"
253
- ),
254
- title: "Toggle word wrap",
255
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(WrapText, { className: "w-4 h-4" })
256
- }
257
- ),
258
- /* @__PURE__ */ jsxRuntimeExports.jsx(
259
- "button",
260
- {
261
- onClick: handleCopy,
262
- className: "p-2 rounded hover:bg-accent transition-colors text-muted-foreground hover:text-foreground",
263
- title: "Copy to clipboard",
264
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "w-4 h-4 text-green-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "w-4 h-4" })
265
- }
266
- )
267
- ] })
268
- ] }),
269
- showSearch && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-4 py-2 border-b border-border bg-muted/20", children: [
270
- /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "w-4 h-4 text-muted-foreground flex-shrink-0" }),
271
- /* @__PURE__ */ jsxRuntimeExports.jsx(
272
- "input",
273
- {
274
- type: "text",
275
- value: searchQuery,
276
- onChange: (e) => setSearchQuery(e.target.value),
277
- placeholder: "Search...",
278
- className: "flex-1 bg-transparent border-none outline-none text-sm placeholder:text-muted-foreground",
279
- autoFocus: true
280
- }
281
- ),
282
- matchPositions.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-muted-foreground flex-shrink-0", children: [
283
- currentMatchIndex + 1,
284
- " of ",
285
- matchPositions.length
286
- ] }),
287
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 flex-shrink-0", children: [
288
- /* @__PURE__ */ jsxRuntimeExports.jsx(
289
- "button",
290
- {
291
- onClick: () => goToMatch("prev"),
292
- disabled: matchPositions.length === 0,
293
- className: "p-1 rounded hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed",
294
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" })
295
- }
296
- ),
297
- /* @__PURE__ */ jsxRuntimeExports.jsx(
298
- "button",
299
- {
300
- onClick: () => goToMatch("next"),
301
- disabled: matchPositions.length === 0,
302
- className: "p-1 rounded hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed",
303
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" })
304
- }
305
- ),
306
- /* @__PURE__ */ jsxRuntimeExports.jsx(
307
- "button",
308
- {
309
- onClick: () => {
310
- setShowSearch(false);
311
- setSearchQuery("");
312
- },
313
- className: "p-1 rounded hover:bg-accent",
314
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-4 h-4" })
315
- }
316
- )
317
- ] })
318
- ] }),
319
- showLargeFileWarning && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-4 py-2 bg-yellow-500/10 border-b border-yellow-500/30 text-yellow-600 dark:text-yellow-400", children: [
320
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }),
321
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm", children: [
322
- "Large file (",
323
- formattedSize,
324
- "). Performance may be affected."
325
- ] }),
326
- /* @__PURE__ */ jsxRuntimeExports.jsx(
327
- "button",
328
- {
329
- onClick: () => setShowLargeFileWarning(false),
330
- className: "ml-auto p-1 hover:bg-yellow-500/20 rounded",
331
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-4 h-4" })
332
- }
333
- )
334
- ] }),
335
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-h-full", children: [
336
- showLineNumbers && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 py-4 pr-4 text-right bg-muted/20 border-r border-border select-none sticky left-0", children: renderedLines.map((_, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
337
- "div",
338
- {
339
- id: `line-num-${index}`,
340
- className: cn(
341
- "px-4 text-xs leading-6 font-mono",
342
- matchPositions.includes(index) && matchPositions[currentMatchIndex] === index ? "text-primary font-bold" : matchPositions.includes(index) ? "text-primary/60" : "text-muted-foreground"
343
- ),
344
- children: index + 1
345
- },
346
- index
347
- )) }),
348
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
349
- "pre",
350
- {
351
- className: cn(
352
- "flex-1 py-4 px-4 font-mono text-sm leading-6 overflow-x-auto",
353
- wordWrap && "whitespace-pre-wrap break-all"
354
- ),
355
- children: [
356
- renderedLines.map((line, index) => {
357
- const isCurrentMatch = matchPositions.length > 0 && matchPositions[currentMatchIndex] === index;
358
- const hasMatch = searchQuery.trim() && line.toLowerCase().includes(searchQuery.toLowerCase());
359
- const isCitationLine = highlightRange && index + 1 >= highlightRange.start && index + 1 <= highlightRange.end;
360
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
361
- "div",
362
- {
363
- id: `line-${index}`,
364
- className: cn(
365
- "min-h-[1.5rem]",
366
- isCitationLine && "ds-citation-line-highlight",
367
- isCurrentMatch && "bg-primary/20",
368
- hasMatch && !isCurrentMatch && "bg-primary/10"
369
- ),
370
- children: hasMatch ? highlightMatches(line, searchQuery) : line || " "
371
- },
372
- index
373
- );
374
- }),
375
- isTruncated && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-4 text-center text-muted-foreground border-t border-border mt-4", children: [
376
- /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "w-4 h-4 inline-block mr-2" }),
377
- "File truncated. Showing first ",
378
- MAX_RENDERED_LINES.toLocaleString(),
379
- " ",
380
- "of ",
381
- lines.length.toLocaleString(),
382
- " lines."
383
- ] })
384
- ]
385
- }
386
- )
387
- ] }) })
388
- ] });
389
- }
390
- function highlightMatches(text, query) {
391
- if (!query.trim()) return text;
392
- const parts = [];
393
- const lowerText = text.toLowerCase();
394
- const lowerQuery = query.toLowerCase();
395
- let lastIndex = 0;
396
- let index = lowerText.indexOf(lowerQuery);
397
- while (index !== -1) {
398
- if (index > lastIndex) {
399
- parts.push(text.slice(lastIndex, index));
400
- }
401
- parts.push(
402
- /* @__PURE__ */ jsxRuntimeExports.jsx(
403
- "mark",
404
- {
405
- className: "bg-yellow-300 dark:bg-yellow-500/50 text-foreground px-0.5 rounded",
406
- children: text.slice(index, index + query.length)
407
- },
408
- index
409
- )
410
- );
411
- lastIndex = index + query.length;
412
- index = lowerText.indexOf(lowerQuery, lastIndex);
413
- }
414
- if (lastIndex < text.length) {
415
- parts.push(text.slice(lastIndex));
416
- }
417
- return parts;
418
- }
419
- const DEMO_TEXT = `DeepScientist - Text Viewer Demo
420
- ================================
421
-
422
- This is a demonstration of the Text Viewer plugin.
423
- It displays plain text files with optional features:
424
-
425
- Features:
426
- ---------
427
- 1. Line numbers (toggle with # button)
428
- 2. Word wrap (toggle with wrap button)
429
- 3. Search functionality (Ctrl+F)
430
- 4. Copy to clipboard
431
- 5. Large file warning (> 1MB)
432
-
433
- Keyboard Shortcuts:
434
- ------------------
435
- - Ctrl+F: Open search
436
- - Escape: Close search
437
- - Enter: Next match
438
- - Shift+Enter: Previous match
439
- - F3: Next match
440
- - Shift+F3: Previous match
441
-
442
- Sample Log Output:
443
- -----------------
444
- [2025-12-18 10:30:15] INFO: Application started
445
- [2025-12-18 10:30:16] DEBUG: Loading configuration from config.yaml
446
- [2025-12-18 10:30:16] INFO: Database connection established
447
- [2025-12-18 10:30:17] DEBUG: Cache initialized with 256MB limit
448
- [2025-12-18 10:30:18] INFO: API server listening on port 8080
449
- [2025-12-18 10:30:20] INFO: Worker pool started with 4 workers
450
- [2025-12-18 10:30:22] DEBUG: Health check endpoint registered
451
- [2025-12-18 10:30:25] INFO: Ready to accept connections
452
-
453
- Environment Variables:
454
- ---------------------
455
- NODE_ENV=production
456
- DATABASE_URL=postgresql://localhost/deepscientist
457
- REDIS_URL=redis://localhost:6379
458
- API_KEY=sk-...
459
- LOG_LEVEL=debug
460
-
461
- This text viewer is designed as a fallback for files
462
- that don't have a specialized viewer, such as:
463
- - Plain text files (.txt)
464
- - Log files (.log)
465
- - Configuration files
466
- - README files without markdown rendering
467
-
468
- The viewer prioritizes readability and performance,
469
- even for large files with thousands of lines.
470
- `;
471
-
472
- export { TextViewerPlugin as default };