dsh-remote-vs 0.0.0-stage → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +385 -0
  3. package/README.md +347 -2
  4. package/cordis.patch.yml +259 -0
  5. package/icon.svg +7 -0
  6. package/lib/client.js +62602 -0
  7. package/lib/index.js +4287 -0
  8. package/lib/p2-bridge-refs.js +10 -0
  9. package/lib/p2-bridge.js +16 -0
  10. package/lib/p2-router-fs.js +252 -0
  11. package/lib/p2-router-refs.js +466 -0
  12. package/lib/p2-router-spill.js +62 -0
  13. package/lib/p2-router-subprocess.js +64 -0
  14. package/lib/p2-shell-bash.js +24 -0
  15. package/lib/ssh-proc-arI5lm4W.js +632 -0
  16. package/lib/types/changes/recorder.d.ts +240 -0
  17. package/lib/types/changes/status.d.ts +201 -0
  18. package/lib/types/changes/text-diff.d.ts +65 -0
  19. package/lib/types/client/CodeEditor.d.ts +125 -0
  20. package/lib/types/client/Dialog.d.ts +14 -0
  21. package/lib/types/client/DirectoryFlow.d.ts +30 -0
  22. package/lib/types/client/EditorPane.d.ts +30 -0
  23. package/lib/types/client/HostsView.d.ts +10 -0
  24. package/lib/types/client/NativeExplorer.d.ts +39 -0
  25. package/lib/types/client/RemoteDirectoryPicker.d.ts +16 -0
  26. package/lib/types/client/RemoteEditorView.d.ts +20 -0
  27. package/lib/types/client/RemoteExplorer.d.ts +18 -0
  28. package/lib/types/client/RemoteRoot.d.ts +16 -0
  29. package/lib/types/client/SearchView.d.ts +14 -0
  30. package/lib/types/client/SettingsHosts.d.ts +15 -0
  31. package/lib/types/client/TerminalView.d.ts +16 -0
  32. package/lib/types/client/WorkspaceWizard.d.ts +16 -0
  33. package/lib/types/client/WorkspacesView.d.ts +14 -0
  34. package/lib/types/client/XTerm.d.ts +15 -0
  35. package/lib/types/client/api.d.ts +162 -0
  36. package/lib/types/client/changes/ChangesDock.d.ts +35 -0
  37. package/lib/types/client/changes/model.d.ts +36 -0
  38. package/lib/types/client/changes/undo-affordance.d.ts +48 -0
  39. package/lib/types/client/changes/undo-context.d.ts +25 -0
  40. package/lib/types/client/composer.d.ts +165 -0
  41. package/lib/types/client/i18n.d.ts +17 -0
  42. package/lib/types/client/index.d.ts +14 -0
  43. package/lib/types/client/remote-file-open-target.d.ts +247 -0
  44. package/lib/types/client/remote-file-open.d.ts +35 -0
  45. package/lib/types/client/reveal.d.ts +15 -0
  46. package/lib/types/client/scm/DiffView.d.ts +24 -0
  47. package/lib/types/client/scm/HistoryPanel.d.ts +12 -0
  48. package/lib/types/client/scm/RepoPicker.d.ts +24 -0
  49. package/lib/types/client/scm/ScmPanel.d.ts +15 -0
  50. package/lib/types/client/scm/actions.d.ts +170 -0
  51. package/lib/types/client/scm/diff-model.d.ts +29 -0
  52. package/lib/types/client/scm/stage-queue.d.ts +99 -0
  53. package/lib/types/client/scm/status-map.d.ts +157 -0
  54. package/lib/types/client/scm/untracked-dirs.d.ts +72 -0
  55. package/lib/types/client/selection-popup.d.ts +61 -0
  56. package/lib/types/client/store.d.ts +437 -0
  57. package/lib/types/client/theme.d.ts +15 -0
  58. package/lib/types/client/ui.d.ts +46 -0
  59. package/lib/types/client/upload-plan.d.ts +78 -0
  60. package/lib/types/client/upload-source.d.ts +46 -0
  61. package/lib/types/client/use-remote-chat-target.d.ts +17 -0
  62. package/lib/types/client/vsc/FindWidget.d.ts +81 -0
  63. package/lib/types/client/vsc/change-marks.d.ts +150 -0
  64. package/lib/types/client/vsc/editor-langs.d.ts +5 -0
  65. package/lib/types/client/vsc/editor-palette.d.ts +37 -0
  66. package/lib/types/client/vsc/editor-theme.d.ts +32 -0
  67. package/lib/types/client/vsc/fallback-highlight.d.ts +26 -0
  68. package/lib/types/client/vsc/kit.d.ts +195 -0
  69. package/lib/types/client/vsc/markdown.d.ts +11 -0
  70. package/lib/types/client/vsc/reveal-line.d.ts +38 -0
  71. package/lib/types/client/vsc/tokenize.d.ts +104 -0
  72. package/lib/types/deploy.d.ts +94 -0
  73. package/lib/types/fs-ops.d.ts +8 -0
  74. package/lib/types/git-format.d.ts +34 -0
  75. package/lib/types/git-ops.d.ts +183 -0
  76. package/lib/types/http.d.ts +14 -0
  77. package/lib/types/importers.d.ts +20 -0
  78. package/lib/types/index.d.ts +87 -0
  79. package/lib/types/keygen.d.ts +19 -0
  80. package/lib/types/loopback.d.ts +7 -0
  81. package/lib/types/p2/bridge-refs.d.ts +21 -0
  82. package/lib/types/p2/bridge.d.ts +24 -0
  83. package/lib/types/p2/file-refs.d.ts +73 -0
  84. package/lib/types/p2/helper-rpc.d.ts +63 -0
  85. package/lib/types/p2/in-flight-gate.d.ts +25 -0
  86. package/lib/types/p2/router-fs.d.ts +92 -0
  87. package/lib/types/p2/router-refs.d.ts +45 -0
  88. package/lib/types/p2/router-spill.d.ts +11 -0
  89. package/lib/types/p2/router-subprocess.d.ts +23 -0
  90. package/lib/types/p2/shell-bash.d.ts +16 -0
  91. package/lib/types/p2/ssh-proc.d.ts +22 -0
  92. package/lib/types/p2/worlds.d.ts +179 -0
  93. package/lib/types/paths.d.ts +12 -0
  94. package/lib/types/pool.d.ts +105 -0
  95. package/lib/types/protocol.d.ts +452 -0
  96. package/lib/types/routes.d.ts +27 -0
  97. package/lib/types/search-ops.d.ts +68 -0
  98. package/lib/types/sftp.d.ts +90 -0
  99. package/lib/types/store.d.ts +66 -0
  100. package/lib/types/terminal.d.ts +51 -0
  101. package/lib/types/timeouts.d.ts +83 -0
  102. package/lib/types/tools.d.ts +41 -0
  103. package/lib/worlds-PUumRIh7.js +18765 -0
  104. package/locale/en.json +6 -0
  105. package/locale/zh.json +6 -0
  106. package/package.json +189 -4
  107. package/src/changes/recorder.ts +902 -0
  108. package/src/changes/status.ts +448 -0
  109. package/src/changes/text-diff.ts +377 -0
  110. package/src/client/CodeEditor.tsx +923 -0
  111. package/src/client/Dialog.tsx +76 -0
  112. package/src/client/DirectoryFlow.tsx +431 -0
  113. package/src/client/EditorPane.tsx +512 -0
  114. package/src/client/HostsView.tsx +312 -0
  115. package/src/client/NativeExplorer.tsx +121 -0
  116. package/src/client/RemoteDirectoryPicker.tsx +157 -0
  117. package/src/client/RemoteEditorView.tsx +54 -0
  118. package/src/client/RemoteExplorer.tsx +1398 -0
  119. package/src/client/RemoteRoot.tsx +389 -0
  120. package/src/client/SearchView.tsx +407 -0
  121. package/src/client/SettingsHosts.tsx +136 -0
  122. package/src/client/TerminalView.tsx +308 -0
  123. package/src/client/WorkspaceWizard.tsx +199 -0
  124. package/src/client/WorkspacesView.tsx +93 -0
  125. package/src/client/XTerm.tsx +308 -0
  126. package/src/client/api.ts +331 -0
  127. package/src/client/changes/ChangesDock.tsx +348 -0
  128. package/src/client/changes/changes.css +230 -0
  129. package/src/client/changes/model.ts +347 -0
  130. package/src/client/changes/undo-affordance.ts +389 -0
  131. package/src/client/changes/undo-context.ts +34 -0
  132. package/src/client/composer.ts +436 -0
  133. package/src/client/css.d.ts +7 -0
  134. package/src/client/i18n.ts +702 -0
  135. package/src/client/index.tsx +286 -0
  136. package/src/client/remote-file-open-target.ts +553 -0
  137. package/src/client/remote-file-open.ts +261 -0
  138. package/src/client/reveal.ts +33 -0
  139. package/src/client/scm/DiffView.tsx +570 -0
  140. package/src/client/scm/HistoryPanel.tsx +353 -0
  141. package/src/client/scm/RepoPicker.tsx +238 -0
  142. package/src/client/scm/ScmPanel.tsx +857 -0
  143. package/src/client/scm/actions.ts +460 -0
  144. package/src/client/scm/diff-model.ts +206 -0
  145. package/src/client/scm/stage-queue.ts +264 -0
  146. package/src/client/scm/status-map.ts +381 -0
  147. package/src/client/scm/untracked-dirs.ts +139 -0
  148. package/src/client/selection-popup.ts +157 -0
  149. package/src/client/store.tsx +1670 -0
  150. package/src/client/theme.ts +54 -0
  151. package/src/client/ui.tsx +136 -0
  152. package/src/client/upload-plan.ts +153 -0
  153. package/src/client/upload-source.ts +145 -0
  154. package/src/client/use-remote-chat-target.ts +153 -0
  155. package/src/client/vsc/FindWidget.tsx +446 -0
  156. package/src/client/vsc/change-marks.ts +586 -0
  157. package/src/client/vsc/editor-langs.ts +137 -0
  158. package/src/client/vsc/editor-palette.ts +107 -0
  159. package/src/client/vsc/editor-theme.ts +93 -0
  160. package/src/client/vsc/fallback-highlight.ts +145 -0
  161. package/src/client/vsc/kit.tsx +777 -0
  162. package/src/client/vsc/markdown.tsx +172 -0
  163. package/src/client/vsc/reveal-line.ts +142 -0
  164. package/src/client/vsc/tokenize.ts +569 -0
  165. package/src/client/vsc/vsc.css +2669 -0
  166. package/src/deploy.ts +481 -0
  167. package/src/fs-ops.ts +57 -0
  168. package/src/git-format.ts +205 -0
  169. package/src/git-ops.ts +693 -0
  170. package/src/http.ts +55 -0
  171. package/src/importers.ts +141 -0
  172. package/src/index.ts +442 -0
  173. package/src/keygen.ts +77 -0
  174. package/src/loopback.ts +47 -0
  175. package/src/p2/bridge-refs.ts +27 -0
  176. package/src/p2/bridge.ts +32 -0
  177. package/src/p2/file-refs.ts +392 -0
  178. package/src/p2/helper-rpc.ts +394 -0
  179. package/src/p2/in-flight-gate.ts +63 -0
  180. package/src/p2/router-fs.ts +327 -0
  181. package/src/p2/router-refs.ts +166 -0
  182. package/src/p2/router-spill.ts +75 -0
  183. package/src/p2/router-subprocess.ts +92 -0
  184. package/src/p2/shell-bash.ts +30 -0
  185. package/src/p2/ssh-proc.ts +802 -0
  186. package/src/p2/worlds.ts +735 -0
  187. package/src/paths.ts +50 -0
  188. package/src/pool.ts +811 -0
  189. package/src/protocol.ts +460 -0
  190. package/src/routes.ts +802 -0
  191. package/src/search-ops.ts +220 -0
  192. package/src/sftp.ts +677 -0
  193. package/src/store.ts +364 -0
  194. package/src/terminal.ts +291 -0
  195. package/src/timeouts.ts +122 -0
  196. package/src/tools.ts +320 -0
  197. package/vendor/dsh-remote-helpers/dsh-ssh-helper-0.2.1-alpha.2-linux-x64.helper.json +16 -0
  198. package/vendor/dsh-remote-helpers/dsh-ssh-helper-0.2.1-alpha.2-linux-x64.tar.gz +4 -0
  199. package/vendor/dsh-remote-helpers/dsh-ssh-helper-0.2.1-alpha.2-linux-x64.tar.gz.sha256 +1 -0
  200. package/vendor/dsh-remote-helpers/glibc-ceiling.patch +31 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Remote CONTENT search: command builder + output parser for a recursive
3
+ * `grep` over the workspace (the file-NAME search lives in
4
+ * `client/scm/actions.ts`).
5
+ *
6
+ * Pure string work — the command runs through the existing exec route, so no
7
+ * host change is needed. The query never reaches the shell unquoted, output is
8
+ * bounded twice (per line, and per result count), and binary files are skipped
9
+ * so a kernel tree full of `.ko` files cannot flood the wire.
10
+ */
11
+ import { assertRemoteDir, shQuote } from './git-format.ts'
12
+
13
+ /** Directory names always pruned from a recursive search. */
14
+ const PRUNE_DIRS = [
15
+ '.git',
16
+ 'node_modules',
17
+ '.venv',
18
+ 'venv',
19
+ '__pycache__',
20
+ '.cache',
21
+ 'dist',
22
+ 'build',
23
+ 'out',
24
+ 'target',
25
+ '.next',
26
+ '.idea',
27
+ '.gradle',
28
+ ]
29
+
30
+ export interface ContentSearchOptions {
31
+ /** Regex (ERE) instead of a literal substring. */
32
+ regex: boolean
33
+ /** Case-sensitive match (grep defaults to sensitive; the UI defaults to off). */
34
+ caseSensitive: boolean
35
+ /** Match whole words only. */
36
+ wholeWord: boolean
37
+ /** Maximum result lines returned (a `head` cap, plus a truncation marker). */
38
+ maxResults: number
39
+ /** Per-line character cap: a minified file must not carry megabytes of one line. */
40
+ maxLineChars: number
41
+ /** Extra directory names to prune. */
42
+ prune?: readonly string[]
43
+ }
44
+
45
+ export const DEFAULT_CONTENT_OPTIONS: ContentSearchOptions = {
46
+ regex: false,
47
+ caseSensitive: false,
48
+ wholeWord: false,
49
+ maxResults: 400,
50
+ maxLineChars: 500,
51
+ }
52
+
53
+ /** Assert a search query (printable, bounded, no NUL/newline). */
54
+ export function assertQuery(query: string): string {
55
+ if (typeof query !== 'string') throw new Error('invalid query')
56
+ if (/[\0\n\r]/.test(query)) throw new Error('query contains control characters')
57
+ const trimmed = query.trim()
58
+ if (trimmed === '') throw new Error('empty query')
59
+ if (trimmed.length > 256) throw new Error('query too long')
60
+ return trimmed
61
+ }
62
+
63
+ /**
64
+ * Recursive content search under one absolute remote directory.
65
+ *
66
+ * `--null` puts a NUL between the path and the `line:text` half so a path
67
+ * containing `:` still parses; `cut` bounds each line and `head` bounds the
68
+ * result count (asked for one more than the cap so "truncated" is detectable).
69
+ */
70
+ export function contentSearchCommand(dir: string, query: string, options: ContentSearchOptions = DEFAULT_CONTENT_OPTIONS): string {
71
+ const pattern = assertQuery(query)
72
+ const max = Math.min(Math.max(Math.floor(options.maxResults), 1), 2000)
73
+ const lineChars = Math.min(Math.max(Math.floor(options.maxLineChars), 80), 4000)
74
+ const prune = [...PRUNE_DIRS, ...(options.prune ?? [])]
75
+ const parts = [
76
+ 'grep -rIn --null --binary-files=without-match',
77
+ ...prune.map(name => `--exclude-dir=${shQuote(name)}`),
78
+ options.caseSensitive ? '' : '-i',
79
+ options.wholeWord ? '-w' : '',
80
+ options.regex ? '-E' : '-F',
81
+ `-e ${shQuote(pattern)}`,
82
+ '--',
83
+ shQuote(assertRemoteDir(dir)),
84
+ ].filter(part => part !== '')
85
+ return `${parts.join(' ')} 2>/dev/null | cut -c1-${lineChars} | head -n ${max + 1}`
86
+ }
87
+
88
+ /** One content-search hit. */
89
+ export interface ContentHit {
90
+ /** Absolute remote path. */
91
+ path: string
92
+ /** 1-based line number. */
93
+ line: number
94
+ /** The matching line (possibly truncated by the per-line cap). */
95
+ text: string
96
+ }
97
+
98
+ export interface ContentSearchResult {
99
+ hits: ContentHit[]
100
+ /** True when the result cap cut the listing short. */
101
+ truncated: boolean
102
+ /** True when the per-line cap truncated at least one line. */
103
+ linesClipped: boolean
104
+ }
105
+
106
+ /**
107
+ * Parse the NUL-separated grep output (tolerating a fallback colon format).
108
+ *
109
+ * `maxLineChars` must be the cap the COMMAND was built with, not the default:
110
+ * the parser cannot otherwise know where the `cut` happened, and comparing
111
+ * against the default reports "line clipped" on lines of the wrong length.
112
+ */
113
+ export function parseContentHits(
114
+ stdout: string,
115
+ maxResults = DEFAULT_CONTENT_OPTIONS.maxResults,
116
+ maxLineChars = DEFAULT_CONTENT_OPTIONS.maxLineChars,
117
+ ): ContentSearchResult {
118
+ const hits: ContentHit[] = []
119
+ const max = Math.max(1, Math.floor(maxResults))
120
+ const charCap = Math.max(1, Math.floor(maxLineChars))
121
+ let truncated = false
122
+ let linesClipped = false
123
+ for (const raw of stdout.split('\n')) {
124
+ if (raw === '') continue
125
+ if (raw.length > 4000) break
126
+ let path = ''
127
+ let rest = ''
128
+ const nul = raw.indexOf('\0')
129
+ if (nul >= 0) {
130
+ path = raw.slice(0, nul)
131
+ rest = raw.slice(nul + 1)
132
+ } else {
133
+ // Fallback (a grep without --null): split on the first `:<digits>:`.
134
+ const match = /^(.*?):(\d+):(.*)$/.exec(raw)
135
+ if (match === null) continue
136
+ path = match[1] as string
137
+ rest = `${match[2]}:${match[3]}`
138
+ }
139
+ const colon = rest.indexOf(':')
140
+ if (colon <= 0) continue
141
+ const line = Number(rest.slice(0, colon))
142
+ if (!Number.isFinite(line) || line <= 0) continue
143
+ const text = rest.slice(colon + 1)
144
+ // Compare against the cap the command used. `cut -c1-N` keeps N characters,
145
+ // so a line of exactly N is only "possibly clipped" when it is the LAST
146
+ // field (there is nothing after it to prove otherwise); flag at N-1 to stay
147
+ // conservative, but against the CALLER's N.
148
+ if (text.length >= charCap - 1) linesClipped = true
149
+ if (hits.length >= max) {
150
+ truncated = true
151
+ break
152
+ }
153
+ hits.push({ path, line, text })
154
+ }
155
+ return { hits, truncated, linesClipped }
156
+ }
157
+
158
+ /** Group hits by file for display (keeps hit order). */
159
+ export function groupHits(hits: readonly ContentHit[]): { path: string; hits: ContentHit[] }[] {
160
+ const groups: { path: string; hits: ContentHit[] }[] = []
161
+ const index = new Map<string, number>()
162
+ for (const hit of hits) {
163
+ const at = index.get(hit.path)
164
+ if (at === undefined) {
165
+ index.set(hit.path, groups.length)
166
+ groups.push({ path: hit.path, hits: [hit] })
167
+ } else {
168
+ (groups[at] as { path: string; hits: ContentHit[] }).hits.push(hit)
169
+ }
170
+ }
171
+ return groups
172
+ }
173
+
174
+ /**
175
+ * Split a line around every match of the query, for highlighting.
176
+ * A regex that does not compile degrades to a literal match.
177
+ *
178
+ * `compiled` is for callers that split MANY lines with one query: compiling a
179
+ * `RegExp` per call costs a few microseconds, which is invisible for one line
180
+ * and adds up to milliseconds for the up-to-400 result rows a content search
181
+ * renders. Pass the same pattern the flags describe (`g`/`gi`, regex mode); a
182
+ * caller that passes nothing keeps the old behaviour.
183
+ */
184
+ export function splitMatches(
185
+ text: string,
186
+ query: string,
187
+ regex: boolean,
188
+ caseSensitive: boolean,
189
+ compiled?: RegExp | null,
190
+ ): { text: string; hit: boolean }[] {
191
+ const trimmed = query
192
+ if (trimmed === '') return [{ text, hit: false }]
193
+ let pattern: RegExp
194
+ try {
195
+ pattern = compiled ?? (regex
196
+ ? new RegExp(trimmed, caseSensitive ? 'g' : 'gi')
197
+ : new RegExp(trimmed.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), caseSensitive ? 'g' : 'gi'))
198
+ } catch {
199
+ pattern = new RegExp(trimmed.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), caseSensitive ? 'g' : 'gi')
200
+ }
201
+ // A shared pattern carries `lastIndex` between calls, and this loop leaves it
202
+ // wherever the last match ended — so a reused regex would start mid-line on
203
+ // the next row and silently drop that row's earlier matches.
204
+ pattern.lastIndex = 0
205
+ const out: { text: string; hit: boolean }[] = []
206
+ let last = 0
207
+ let guard = 0
208
+ for (let match = pattern.exec(text); match !== null; match = pattern.exec(text)) {
209
+ if (match[0] === '') {
210
+ pattern.lastIndex += 1
211
+ continue
212
+ }
213
+ if (guard++ > 200) break
214
+ if (match.index > last) out.push({ text: text.slice(last, match.index), hit: false })
215
+ out.push({ text: match[0], hit: true })
216
+ last = match.index + match[0].length
217
+ }
218
+ if (last < text.length) out.push({ text: text.slice(last), hit: false })
219
+ return out.length === 0 ? [{ text, hit: false }] : out
220
+ }