@researai/deepscientist 1.5.15 → 1.5.17

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 (202) hide show
  1. package/README.md +385 -104
  2. package/bin/ds.js +1241 -110
  3. package/docs/en/00_QUICK_START.md +100 -19
  4. package/docs/en/01_SETTINGS_REFERENCE.md +34 -1
  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 +25 -8
  9. package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +63 -13
  10. package/docs/en/15_CODEX_PROVIDER_SETUP.md +37 -11
  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/21_LOCAL_MODEL_BACKENDS_GUIDE.md +283 -0
  15. package/docs/en/91_DEVELOPMENT.md +237 -0
  16. package/docs/en/README.md +24 -2
  17. package/docs/zh/00_QUICK_START.md +89 -19
  18. package/docs/zh/01_SETTINGS_REFERENCE.md +34 -1
  19. package/docs/zh/02_START_RESEARCH_GUIDE.md +7 -0
  20. package/docs/zh/05_TUI_GUIDE.md +6 -0
  21. package/docs/zh/09_DOCTOR.md +26 -9
  22. package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +63 -13
  23. package/docs/zh/15_CODEX_PROVIDER_SETUP.md +37 -11
  24. package/docs/zh/19_EXTERNAL_CONTROLLER_GUIDE.md +226 -0
  25. package/docs/zh/19_LOCAL_BROWSER_AUTH.md +68 -0
  26. package/docs/zh/20_WORKSPACE_MODES_GUIDE.md +251 -0
  27. package/docs/zh/21_LOCAL_MODEL_BACKENDS_GUIDE.md +281 -0
  28. package/docs/zh/README.md +24 -2
  29. package/install.sh +46 -4
  30. package/package.json +2 -1
  31. package/pyproject.toml +1 -1
  32. package/src/deepscientist/__init__.py +1 -1
  33. package/src/deepscientist/acp/envelope.py +6 -0
  34. package/src/deepscientist/artifact/service.py +647 -22
  35. package/src/deepscientist/bash_exec/service.py +234 -9
  36. package/src/deepscientist/bridges/connectors.py +8 -2
  37. package/src/deepscientist/cli.py +115 -19
  38. package/src/deepscientist/codex_cli_compat.py +367 -22
  39. package/src/deepscientist/config/models.py +2 -1
  40. package/src/deepscientist/config/service.py +183 -13
  41. package/src/deepscientist/daemon/api/handlers.py +255 -31
  42. package/src/deepscientist/daemon/api/router.py +9 -0
  43. package/src/deepscientist/daemon/app.py +1146 -105
  44. package/src/deepscientist/diagnostics/__init__.py +6 -0
  45. package/src/deepscientist/diagnostics/runner_failures.py +130 -0
  46. package/src/deepscientist/doctor.py +207 -3
  47. package/src/deepscientist/gitops/__init__.py +10 -1
  48. package/src/deepscientist/gitops/diff.py +129 -0
  49. package/src/deepscientist/gitops/service.py +4 -1
  50. package/src/deepscientist/mcp/server.py +39 -0
  51. package/src/deepscientist/prompts/builder.py +275 -34
  52. package/src/deepscientist/quest/layout.py +15 -2
  53. package/src/deepscientist/quest/service.py +707 -55
  54. package/src/deepscientist/quest/stage_views.py +6 -1
  55. package/src/deepscientist/runners/codex.py +143 -43
  56. package/src/deepscientist/shared.py +19 -0
  57. package/src/deepscientist/skills/__init__.py +2 -2
  58. package/src/deepscientist/skills/installer.py +196 -5
  59. package/src/deepscientist/skills/registry.py +66 -0
  60. package/src/prompts/connectors/qq.md +18 -8
  61. package/src/prompts/connectors/weixin.md +16 -6
  62. package/src/prompts/contracts/shared_interaction.md +14 -2
  63. package/src/prompts/system.md +23 -5
  64. package/src/prompts/system_copilot.md +56 -0
  65. package/src/skills/analysis-campaign/SKILL.md +1 -0
  66. package/src/skills/baseline/SKILL.md +8 -0
  67. package/src/skills/decision/SKILL.md +8 -0
  68. package/src/skills/experiment/SKILL.md +8 -0
  69. package/src/skills/figure-polish/SKILL.md +1 -0
  70. package/src/skills/finalize/SKILL.md +1 -0
  71. package/src/skills/idea/SKILL.md +1 -0
  72. package/src/skills/intake-audit/SKILL.md +8 -0
  73. package/src/skills/mentor/SKILL.md +217 -0
  74. package/src/skills/mentor/references/correction-rules.md +210 -0
  75. package/src/skills/mentor/references/knowledge-profile.md +91 -0
  76. package/src/skills/mentor/references/persona-profile.md +138 -0
  77. package/src/skills/mentor/references/taste-profile.md +128 -0
  78. package/src/skills/mentor/references/thought-style-profile.md +138 -0
  79. package/src/skills/mentor/references/work-profile.md +289 -0
  80. package/src/skills/mentor/references/workflow-profile.md +240 -0
  81. package/src/skills/optimize/SKILL.md +1 -0
  82. package/src/skills/rebuttal/SKILL.md +1 -0
  83. package/src/skills/review/SKILL.md +1 -0
  84. package/src/skills/scout/SKILL.md +8 -0
  85. package/src/skills/write/SKILL.md +1 -0
  86. package/src/tui/dist/app/AppContainer.js +19 -11
  87. package/src/tui/dist/index.js +4 -1
  88. package/src/tui/dist/lib/api.js +33 -3
  89. package/src/tui/package.json +1 -1
  90. package/src/ui/dist/assets/AiManusChatView-Bv-Z8YpU.js +204 -0
  91. package/src/ui/dist/assets/AnalysisPlugin-BCKAfjba.js +1 -0
  92. package/src/ui/dist/assets/CliPlugin-BCKcpc35.js +109 -0
  93. package/src/ui/dist/assets/CodeEditorPlugin-DbOfSJ8K.js +2 -0
  94. package/src/ui/dist/assets/CodeViewerPlugin-CbaFRrUU.js +270 -0
  95. package/src/ui/dist/assets/DocViewerPlugin-DAjLVeQD.js +7 -0
  96. package/src/ui/dist/assets/GitCommitViewerPlugin-CIUqbUDO.js +1 -0
  97. package/src/ui/dist/assets/GitDiffViewerPlugin-CQACjoAA.js +6 -0
  98. package/src/ui/dist/assets/GitSnapshotViewer-0r4nLPke.js +30 -0
  99. package/src/ui/dist/assets/ImageViewerPlugin-nBOmI2v_.js +26 -0
  100. package/src/ui/dist/assets/LabCopilotPanel-BHxOxF4z.js +14 -0
  101. package/src/ui/dist/assets/LabPlugin-BKoZGs95.js +22 -0
  102. package/src/ui/dist/assets/LatexPlugin-ZwtV8pIp.js +25 -0
  103. package/src/ui/dist/assets/MarkdownViewerPlugin-DKqVfKyW.js +128 -0
  104. package/src/ui/dist/assets/MarketplacePlugin-BwxStZ9D.js +13 -0
  105. package/src/ui/dist/assets/NotebookEditor-BEQhaQbt.js +81 -0
  106. package/src/ui/dist/assets/{NotebookEditor-CccQYZjX.css → NotebookEditor-BHH8rdGj.css} +1 -1
  107. package/src/ui/dist/assets/NotebookEditor-BOr3x3Ej.css +1 -0
  108. package/src/ui/dist/assets/NotebookEditor-DB9N_T9q.js +361 -0
  109. package/src/ui/dist/assets/PdfLoader-Cy5jtWrr.css +1 -0
  110. package/src/ui/dist/assets/PdfLoader-eWBONbQP.js +16 -0
  111. package/src/ui/dist/assets/PdfMarkdownPlugin-D22YOZL3.js +1 -0
  112. package/src/ui/dist/assets/PdfViewerPlugin-c-RK9DLM.js +17 -0
  113. package/src/ui/dist/assets/PdfViewerPlugin-nwwE-fjJ.css +1 -0
  114. package/src/ui/dist/assets/SearchPlugin-CxF9ytAx.js +16 -0
  115. package/src/ui/dist/assets/SearchPlugin-DA4en4hK.css +1 -0
  116. package/src/ui/dist/assets/TextViewerPlugin-C5xqeeUH.js +54 -0
  117. package/src/ui/dist/assets/VNCViewer-BoLGLnHz.js +11 -0
  118. package/src/ui/dist/assets/bot-DREQOxzP.js +6 -0
  119. package/src/ui/dist/assets/browser-CTB2jwNe.js +8 -0
  120. package/src/ui/dist/assets/chevron-up-C9Qpx4DE.js +6 -0
  121. package/src/ui/dist/assets/code-WlFHE7z_.js +6 -0
  122. package/src/ui/dist/assets/file-content-BZMz3RYp.js +1 -0
  123. package/src/ui/dist/assets/file-diff-panel-CQhw0jS2.js +1 -0
  124. package/src/ui/dist/assets/file-jump-queue-DA-SdG__.js +1 -0
  125. package/src/ui/dist/assets/file-socket-CfQPKQKj.js +1 -0
  126. package/src/ui/dist/assets/git-commit-horizontal-DxZ8DCZh.js +6 -0
  127. package/src/ui/dist/assets/image-Bgl4VIyx.js +6 -0
  128. package/src/ui/dist/assets/index-BpV6lusQ.css +33 -0
  129. package/src/ui/dist/assets/index-CBNVuWcP.js +2496 -0
  130. package/src/ui/dist/assets/index-CwNu1aH4.js +11 -0
  131. package/src/ui/dist/assets/index-DrUnlf6K.js +1 -0
  132. package/src/ui/dist/assets/index-NW-h8VzN.js +1 -0
  133. package/src/ui/dist/assets/monaco-CiHMMNH_.js +1 -0
  134. package/src/ui/dist/assets/pdf-effect-queue-J8OnM0jE.js +6 -0
  135. package/src/ui/dist/assets/plugin-monaco-C8UgLomw.js +19 -0
  136. package/src/ui/dist/assets/plugin-notebook-HbW2K-1c.js +169 -0
  137. package/src/ui/dist/assets/plugin-pdf-CR8hgQBV.js +357 -0
  138. package/src/ui/dist/assets/plugin-terminal-MXFIPun8.js +227 -0
  139. package/src/ui/dist/assets/popover-CLc0pPP8.js +1 -0
  140. package/src/ui/dist/assets/project-sync-C9IdzdZW.js +1 -0
  141. package/src/ui/dist/assets/select-Cs2PmzwL.js +11 -0
  142. package/src/ui/dist/assets/sigma-ClKcHAXm.js +6 -0
  143. package/src/ui/dist/assets/trash-DwpbFr3w.js +11 -0
  144. package/src/ui/dist/assets/useCliAccess-NQ8m0Let.js +1 -0
  145. package/src/ui/dist/assets/useFileDiffOverlay-FuhcnKiw.js +1 -0
  146. package/src/ui/dist/assets/wrap-text-BC-Hltpd.js +11 -0
  147. package/src/ui/dist/assets/zoom-out-E_gaeAxL.js +11 -0
  148. package/src/ui/dist/index.html +5 -2
  149. package/src/ui/dist/assets/AiManusChatView-DDjbFnbt.js +0 -26597
  150. package/src/ui/dist/assets/AnalysisPlugin-Yb5IdmaU.js +0 -123
  151. package/src/ui/dist/assets/CliPlugin-e64sreyu.js +0 -31037
  152. package/src/ui/dist/assets/CodeEditorPlugin-C4D2TIkU.js +0 -427
  153. package/src/ui/dist/assets/CodeViewerPlugin-BVoNZIvC.js +0 -905
  154. package/src/ui/dist/assets/DocViewerPlugin-CLChbllo.js +0 -278
  155. package/src/ui/dist/assets/GitDiffViewerPlugin-C4xeFyFQ.js +0 -2661
  156. package/src/ui/dist/assets/ImageViewerPlugin-OiMUAcLi.js +0 -500
  157. package/src/ui/dist/assets/LabCopilotPanel-BjD2ThQF.js +0 -4104
  158. package/src/ui/dist/assets/LabPlugin-DQPg-NrB.js +0 -2677
  159. package/src/ui/dist/assets/LatexPlugin-CI05XAV9.js +0 -1792
  160. package/src/ui/dist/assets/MarkdownViewerPlugin-DpeBLYZf.js +0 -308
  161. package/src/ui/dist/assets/MarketplacePlugin-DolE58Q2.js +0 -413
  162. package/src/ui/dist/assets/NotebookEditor-7Qm2rSWD.js +0 -4214
  163. package/src/ui/dist/assets/NotebookEditor-C1kWaxKi.js +0 -84873
  164. package/src/ui/dist/assets/NotebookEditor-C3VQ7ylN.css +0 -1405
  165. package/src/ui/dist/assets/PdfLoader-BfOHw8Zw.js +0 -25468
  166. package/src/ui/dist/assets/PdfLoader-C-Y707R3.css +0 -49
  167. package/src/ui/dist/assets/PdfMarkdownPlugin-BulDREv1.js +0 -409
  168. package/src/ui/dist/assets/PdfViewerPlugin-C-daaOaL.js +0 -3095
  169. package/src/ui/dist/assets/PdfViewerPlugin-DQ11QcSf.css +0 -3627
  170. package/src/ui/dist/assets/SearchPlugin-CjpaiJ3A.js +0 -741
  171. package/src/ui/dist/assets/SearchPlugin-DDMrGDkh.css +0 -379
  172. package/src/ui/dist/assets/TextViewerPlugin-BxIyqPQC.js +0 -472
  173. package/src/ui/dist/assets/VNCViewer-HAg9mF7M.js +0 -18821
  174. package/src/ui/dist/assets/awareness-C0NPR2Dj.js +0 -292
  175. package/src/ui/dist/assets/bot-0DYntytV.js +0 -21
  176. package/src/ui/dist/assets/browser-BAcuE0Xj.js +0 -2895
  177. package/src/ui/dist/assets/code-B20Slj_w.js +0 -17
  178. package/src/ui/dist/assets/file-content-DT24KFma.js +0 -377
  179. package/src/ui/dist/assets/file-diff-panel-DK13YPql.js +0 -92
  180. package/src/ui/dist/assets/file-jump-queue-r5XKgJEV.js +0 -16
  181. package/src/ui/dist/assets/file-socket-B4T2o4nR.js +0 -58
  182. package/src/ui/dist/assets/function-B5QZkkHC.js +0 -1895
  183. package/src/ui/dist/assets/image-DSeR_sDS.js +0 -18
  184. package/src/ui/dist/assets/index-BrFje2Uk.js +0 -120
  185. package/src/ui/dist/assets/index-BwRJaoTl.js +0 -25
  186. package/src/ui/dist/assets/index-D_E4281X.js +0 -221322
  187. package/src/ui/dist/assets/index-DnYB3xb1.js +0 -159
  188. package/src/ui/dist/assets/index-G7AcWcMu.css +0 -12594
  189. package/src/ui/dist/assets/monaco-LExaAN3Y.js +0 -623
  190. package/src/ui/dist/assets/pdf-effect-queue-BJk5okWJ.js +0 -47
  191. package/src/ui/dist/assets/pdf_viewer-e0g1is2C.js +0 -8206
  192. package/src/ui/dist/assets/popover-D3Gg_FoV.js +0 -476
  193. package/src/ui/dist/assets/project-sync-C_ygLlVU.js +0 -297
  194. package/src/ui/dist/assets/select-CpAK6uWm.js +0 -1690
  195. package/src/ui/dist/assets/sigma-DEccaSgk.js +0 -22
  196. package/src/ui/dist/assets/square-check-big-uUfyVsbD.js +0 -17
  197. package/src/ui/dist/assets/trash-CXvwwSe8.js +0 -32
  198. package/src/ui/dist/assets/useCliAccess-Bnop4mgR.js +0 -957
  199. package/src/ui/dist/assets/useFileDiffOverlay-B8eUAX0I.js +0 -53
  200. package/src/ui/dist/assets/wrap-text-9vbOBpkW.js +0 -35
  201. package/src/ui/dist/assets/yjs-DncrqiZ8.js +0 -11243
  202. 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 };