@researai/deepscientist 1.5.15 → 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 (193) hide show
  1. package/README.md +336 -98
  2. package/bin/ds.js +691 -91
  3. package/docs/en/00_QUICK_START.md +36 -15
  4. package/docs/en/01_SETTINGS_REFERENCE.md +33 -0
  5. package/docs/en/02_START_RESEARCH_GUIDE.md +7 -0
  6. package/docs/en/05_TUI_GUIDE.md +6 -0
  7. package/docs/en/06_RUNTIME_AND_CANVAS.md +4 -3
  8. package/docs/en/09_DOCTOR.md +11 -5
  9. package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +63 -13
  10. package/docs/en/15_CODEX_PROVIDER_SETUP.md +25 -8
  11. package/docs/en/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
  12. package/docs/en/19_LOCAL_BROWSER_AUTH.md +70 -0
  13. package/docs/en/20_WORKSPACE_MODES_GUIDE.md +250 -0
  14. package/docs/en/README.md +18 -0
  15. package/docs/zh/00_QUICK_START.md +36 -15
  16. package/docs/zh/01_SETTINGS_REFERENCE.md +33 -0
  17. package/docs/zh/02_START_RESEARCH_GUIDE.md +7 -0
  18. package/docs/zh/05_TUI_GUIDE.md +6 -0
  19. package/docs/zh/09_DOCTOR.md +11 -5
  20. package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +63 -13
  21. package/docs/zh/15_CODEX_PROVIDER_SETUP.md +25 -8
  22. package/docs/zh/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
  23. package/docs/zh/19_LOCAL_BROWSER_AUTH.md +68 -0
  24. package/docs/zh/20_WORKSPACE_MODES_GUIDE.md +251 -0
  25. package/docs/zh/README.md +18 -0
  26. package/package.json +1 -1
  27. package/pyproject.toml +1 -1
  28. package/src/deepscientist/__init__.py +1 -1
  29. package/src/deepscientist/acp/envelope.py +6 -0
  30. package/src/deepscientist/artifact/service.py +647 -22
  31. package/src/deepscientist/bash_exec/service.py +234 -9
  32. package/src/deepscientist/cli.py +115 -19
  33. package/src/deepscientist/codex_cli_compat.py +232 -0
  34. package/src/deepscientist/config/models.py +2 -1
  35. package/src/deepscientist/config/service.py +31 -9
  36. package/src/deepscientist/daemon/api/handlers.py +125 -6
  37. package/src/deepscientist/daemon/api/router.py +4 -0
  38. package/src/deepscientist/daemon/app.py +715 -98
  39. package/src/deepscientist/gitops/__init__.py +10 -1
  40. package/src/deepscientist/gitops/diff.py +129 -0
  41. package/src/deepscientist/gitops/service.py +4 -1
  42. package/src/deepscientist/mcp/server.py +39 -0
  43. package/src/deepscientist/prompts/builder.py +255 -32
  44. package/src/deepscientist/quest/layout.py +15 -2
  45. package/src/deepscientist/quest/service.py +295 -43
  46. package/src/deepscientist/quest/stage_views.py +6 -1
  47. package/src/deepscientist/runners/codex.py +86 -31
  48. package/src/deepscientist/skills/__init__.py +2 -2
  49. package/src/deepscientist/skills/installer.py +196 -5
  50. package/src/deepscientist/skills/registry.py +66 -0
  51. package/src/prompts/connectors/qq.md +18 -8
  52. package/src/prompts/connectors/weixin.md +16 -6
  53. package/src/prompts/contracts/shared_interaction.md +12 -1
  54. package/src/prompts/system.md +10 -5
  55. package/src/prompts/system_copilot.md +43 -0
  56. package/src/skills/analysis-campaign/SKILL.md +1 -0
  57. package/src/skills/baseline/SKILL.md +8 -0
  58. package/src/skills/decision/SKILL.md +8 -0
  59. package/src/skills/experiment/SKILL.md +8 -0
  60. package/src/skills/figure-polish/SKILL.md +1 -0
  61. package/src/skills/finalize/SKILL.md +1 -0
  62. package/src/skills/idea/SKILL.md +1 -0
  63. package/src/skills/intake-audit/SKILL.md +8 -0
  64. package/src/skills/mentor/SKILL.md +217 -0
  65. package/src/skills/mentor/references/correction-rules.md +210 -0
  66. package/src/skills/mentor/references/knowledge-profile.md +91 -0
  67. package/src/skills/mentor/references/persona-profile.md +138 -0
  68. package/src/skills/mentor/references/taste-profile.md +128 -0
  69. package/src/skills/mentor/references/thought-style-profile.md +138 -0
  70. package/src/skills/mentor/references/work-profile.md +289 -0
  71. package/src/skills/mentor/references/workflow-profile.md +240 -0
  72. package/src/skills/optimize/SKILL.md +1 -0
  73. package/src/skills/rebuttal/SKILL.md +1 -0
  74. package/src/skills/review/SKILL.md +1 -0
  75. package/src/skills/scout/SKILL.md +8 -0
  76. package/src/skills/write/SKILL.md +1 -0
  77. package/src/tui/dist/app/AppContainer.js +19 -11
  78. package/src/tui/dist/index.js +4 -1
  79. package/src/tui/dist/lib/api.js +33 -3
  80. package/src/tui/package.json +1 -1
  81. package/src/ui/dist/assets/AiManusChatView-COFACy7V.js +204 -0
  82. package/src/ui/dist/assets/AnalysisPlugin-DnSm0GZn.js +1 -0
  83. package/src/ui/dist/assets/CliPlugin-CvwCmDQ5.js +109 -0
  84. package/src/ui/dist/assets/CodeEditorPlugin-cOqSa0xq.js +2 -0
  85. package/src/ui/dist/assets/CodeViewerPlugin-itb0tltR.js +270 -0
  86. package/src/ui/dist/assets/DocViewerPlugin-DqKkiCI6.js +7 -0
  87. package/src/ui/dist/assets/GitCommitViewerPlugin-DVgNHBCS.js +1 -0
  88. package/src/ui/dist/assets/GitDiffViewerPlugin-DxL2ezFG.js +6 -0
  89. package/src/ui/dist/assets/GitSnapshotViewer-B_RQm1YZ.js +30 -0
  90. package/src/ui/dist/assets/ImageViewerPlugin-tHqlXY3n.js +26 -0
  91. package/src/ui/dist/assets/LabCopilotPanel-ClMbq5Yu.js +14 -0
  92. package/src/ui/dist/assets/LabPlugin-L_SuE8ow.js +22 -0
  93. package/src/ui/dist/assets/LatexPlugin-B495DTXC.js +25 -0
  94. package/src/ui/dist/assets/MarkdownViewerPlugin-DG28-61B.js +128 -0
  95. package/src/ui/dist/assets/MarketplacePlugin-BiOGT-Kj.js +13 -0
  96. package/src/ui/dist/assets/{NotebookEditor-CccQYZjX.css → NotebookEditor-BHH8rdGj.css} +1 -1
  97. package/src/ui/dist/assets/NotebookEditor-BOr3x3Ej.css +1 -0
  98. package/src/ui/dist/assets/NotebookEditor-C-4Kt1p9.js +81 -0
  99. package/src/ui/dist/assets/NotebookEditor-CVsj8h_T.js +361 -0
  100. package/src/ui/dist/assets/PdfLoader-CASDQmxJ.js +16 -0
  101. package/src/ui/dist/assets/PdfLoader-Cy5jtWrr.css +1 -0
  102. package/src/ui/dist/assets/PdfMarkdownPlugin-BFhwoKsY.js +1 -0
  103. package/src/ui/dist/assets/PdfViewerPlugin-DcOzU9vd.js +17 -0
  104. package/src/ui/dist/assets/PdfViewerPlugin-nwwE-fjJ.css +1 -0
  105. package/src/ui/dist/assets/SearchPlugin-CHj7M58O.js +16 -0
  106. package/src/ui/dist/assets/SearchPlugin-DA4en4hK.css +1 -0
  107. package/src/ui/dist/assets/TextViewerPlugin-CB4DYfWO.js +54 -0
  108. package/src/ui/dist/assets/VNCViewer-CjlbyCB3.js +11 -0
  109. package/src/ui/dist/assets/bot-CFkZY-JP.js +6 -0
  110. package/src/ui/dist/assets/browser-CTB2jwNe.js +8 -0
  111. package/src/ui/dist/assets/chevron-up-Dq5ofbht.js +6 -0
  112. package/src/ui/dist/assets/code-DLC6G24T.js +6 -0
  113. package/src/ui/dist/assets/file-content-Dv4LoZec.js +1 -0
  114. package/src/ui/dist/assets/file-diff-panel-Denq-lC3.js +1 -0
  115. package/src/ui/dist/assets/file-jump-queue-DA-SdG__.js +1 -0
  116. package/src/ui/dist/assets/file-socket-Cu4Qln7Y.js +1 -0
  117. package/src/ui/dist/assets/git-commit-horizontal-BUh6G52n.js +6 -0
  118. package/src/ui/dist/assets/image-B9HUUddG.js +6 -0
  119. package/src/ui/dist/assets/index-B2B1sg-M.js +1 -0
  120. package/src/ui/dist/assets/index-Cgla8biy.css +33 -0
  121. package/src/ui/dist/assets/index-DRyx7vAc.js +1 -0
  122. package/src/ui/dist/assets/index-Gbl53BNp.js +2496 -0
  123. package/src/ui/dist/assets/index-wQ7RIIRd.js +11 -0
  124. package/src/ui/dist/assets/monaco-CiHMMNH_.js +1 -0
  125. package/src/ui/dist/assets/pdf-effect-queue-ZtnHFCAi.js +6 -0
  126. package/src/ui/dist/assets/plugin-monaco-C8UgLomw.js +19 -0
  127. package/src/ui/dist/assets/plugin-notebook-HbW2K-1c.js +169 -0
  128. package/src/ui/dist/assets/plugin-pdf-CR8hgQBV.js +357 -0
  129. package/src/ui/dist/assets/plugin-terminal-MXFIPun8.js +227 -0
  130. package/src/ui/dist/assets/popover-DL6h35vr.js +1 -0
  131. package/src/ui/dist/assets/project-sync-CsX08Qno.js +1 -0
  132. package/src/ui/dist/assets/select-DvmXt1yY.js +11 -0
  133. package/src/ui/dist/assets/sigma-7jpXazui.js +6 -0
  134. package/src/ui/dist/assets/trash-xA7kFt8i.js +11 -0
  135. package/src/ui/dist/assets/useCliAccess-DsMwDjOp.js +1 -0
  136. package/src/ui/dist/assets/useFileDiffOverlay-FuhcnKiw.js +1 -0
  137. package/src/ui/dist/assets/wrap-text-CwMn-iqb.js +11 -0
  138. package/src/ui/dist/assets/zoom-out-R-GWEhzS.js +11 -0
  139. package/src/ui/dist/index.html +5 -2
  140. package/src/ui/dist/assets/AiManusChatView-DDjbFnbt.js +0 -26597
  141. package/src/ui/dist/assets/AnalysisPlugin-Yb5IdmaU.js +0 -123
  142. package/src/ui/dist/assets/CliPlugin-e64sreyu.js +0 -31037
  143. package/src/ui/dist/assets/CodeEditorPlugin-C4D2TIkU.js +0 -427
  144. package/src/ui/dist/assets/CodeViewerPlugin-BVoNZIvC.js +0 -905
  145. package/src/ui/dist/assets/DocViewerPlugin-CLChbllo.js +0 -278
  146. package/src/ui/dist/assets/GitDiffViewerPlugin-C4xeFyFQ.js +0 -2661
  147. package/src/ui/dist/assets/ImageViewerPlugin-OiMUAcLi.js +0 -500
  148. package/src/ui/dist/assets/LabCopilotPanel-BjD2ThQF.js +0 -4104
  149. package/src/ui/dist/assets/LabPlugin-DQPg-NrB.js +0 -2677
  150. package/src/ui/dist/assets/LatexPlugin-CI05XAV9.js +0 -1792
  151. package/src/ui/dist/assets/MarkdownViewerPlugin-DpeBLYZf.js +0 -308
  152. package/src/ui/dist/assets/MarketplacePlugin-DolE58Q2.js +0 -413
  153. package/src/ui/dist/assets/NotebookEditor-7Qm2rSWD.js +0 -4214
  154. package/src/ui/dist/assets/NotebookEditor-C1kWaxKi.js +0 -84873
  155. package/src/ui/dist/assets/NotebookEditor-C3VQ7ylN.css +0 -1405
  156. package/src/ui/dist/assets/PdfLoader-BfOHw8Zw.js +0 -25468
  157. package/src/ui/dist/assets/PdfLoader-C-Y707R3.css +0 -49
  158. package/src/ui/dist/assets/PdfMarkdownPlugin-BulDREv1.js +0 -409
  159. package/src/ui/dist/assets/PdfViewerPlugin-C-daaOaL.js +0 -3095
  160. package/src/ui/dist/assets/PdfViewerPlugin-DQ11QcSf.css +0 -3627
  161. package/src/ui/dist/assets/SearchPlugin-CjpaiJ3A.js +0 -741
  162. package/src/ui/dist/assets/SearchPlugin-DDMrGDkh.css +0 -379
  163. package/src/ui/dist/assets/TextViewerPlugin-BxIyqPQC.js +0 -472
  164. package/src/ui/dist/assets/VNCViewer-HAg9mF7M.js +0 -18821
  165. package/src/ui/dist/assets/awareness-C0NPR2Dj.js +0 -292
  166. package/src/ui/dist/assets/bot-0DYntytV.js +0 -21
  167. package/src/ui/dist/assets/browser-BAcuE0Xj.js +0 -2895
  168. package/src/ui/dist/assets/code-B20Slj_w.js +0 -17
  169. package/src/ui/dist/assets/file-content-DT24KFma.js +0 -377
  170. package/src/ui/dist/assets/file-diff-panel-DK13YPql.js +0 -92
  171. package/src/ui/dist/assets/file-jump-queue-r5XKgJEV.js +0 -16
  172. package/src/ui/dist/assets/file-socket-B4T2o4nR.js +0 -58
  173. package/src/ui/dist/assets/function-B5QZkkHC.js +0 -1895
  174. package/src/ui/dist/assets/image-DSeR_sDS.js +0 -18
  175. package/src/ui/dist/assets/index-BrFje2Uk.js +0 -120
  176. package/src/ui/dist/assets/index-BwRJaoTl.js +0 -25
  177. package/src/ui/dist/assets/index-D_E4281X.js +0 -221322
  178. package/src/ui/dist/assets/index-DnYB3xb1.js +0 -159
  179. package/src/ui/dist/assets/index-G7AcWcMu.css +0 -12594
  180. package/src/ui/dist/assets/monaco-LExaAN3Y.js +0 -623
  181. package/src/ui/dist/assets/pdf-effect-queue-BJk5okWJ.js +0 -47
  182. package/src/ui/dist/assets/pdf_viewer-e0g1is2C.js +0 -8206
  183. package/src/ui/dist/assets/popover-D3Gg_FoV.js +0 -476
  184. package/src/ui/dist/assets/project-sync-C_ygLlVU.js +0 -297
  185. package/src/ui/dist/assets/select-CpAK6uWm.js +0 -1690
  186. package/src/ui/dist/assets/sigma-DEccaSgk.js +0 -22
  187. package/src/ui/dist/assets/square-check-big-uUfyVsbD.js +0 -17
  188. package/src/ui/dist/assets/trash-CXvwwSe8.js +0 -32
  189. package/src/ui/dist/assets/useCliAccess-Bnop4mgR.js +0 -957
  190. package/src/ui/dist/assets/useFileDiffOverlay-B8eUAX0I.js +0 -53
  191. package/src/ui/dist/assets/wrap-text-9vbOBpkW.js +0 -35
  192. package/src/ui/dist/assets/yjs-DncrqiZ8.js +0 -11243
  193. package/src/ui/dist/assets/zoom-out-BgVMmOW4.js +0 -34
@@ -1,472 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-D_E4281X.js","assets/index-G7AcWcMu.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-D_E4281X.js';
3
- import { c as consumeFileJumpEffects } from './file-jump-queue-r5XKgJEV.js';
4
- import { H as Hash, W as WrapText } from './wrap-text-9vbOBpkW.js';
5
- import { C as ChevronUp } from './index-BwRJaoTl.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-D_E4281X.js').then(n => n.ep);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 };