@marktrue/dsh-mobile-remote 3.2.1-alpha.2 → 3.2.1-alpha.3-app

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 (349) hide show
  1. package/DSH-Remote-v3.2.1.apk +4 -0
  2. package/README.md +6 -253
  3. package/manifest.json +21 -0
  4. package/package.json +10 -65
  5. package/CHANGELOG.md +0 -803
  6. package/CONTRIBUTING.md +0 -59
  7. package/FAQ.md +0 -111
  8. package/cordis.patch.yml +0 -14
  9. package/docs/00-/345/274/200/345/217/221/346/200/273/347/272/262.md +0 -122
  10. package/docs/01-PRD.md +0 -148
  11. package/docs/02-architecture.md +0 -249
  12. package/docs/03-api.md +0 -816
  13. package/docs/04-security.md +0 -96
  14. package/docs/05-test-cases.md +0 -326
  15. package/docs/06-install-run.md +0 -308
  16. package/docs/07-user-manual.md +0 -65
  17. package/docs/08-/346/211/251/345/261/225/345/274/200/345/217/221/346/214/207/345/215/227.md +0 -86
  18. package/docs/09-compatibility.md +0 -195
  19. package/docs/10-release.md +0 -927
  20. package/docs/screenshots/01-home.png +0 -0
  21. package/docs/screenshots/02-notifications.png +0 -0
  22. package/docs/screenshots/03-sessions.png +0 -0
  23. package/docs/screenshots/04-chat.png +0 -0
  24. package/docs/screenshots/05-settings.png +0 -0
  25. package/docs/screenshots/06-new-session.png +0 -0
  26. package/docs/screenshots/pgy-appstore.jpg +0 -0
  27. package/docs/screenshots/pgy-mobile-app.jpg +0 -0
  28. package/docs/screenshots/pgy-pc-client.jpg +0 -0
  29. package/lib/account-usage.js +0 -145
  30. package/lib/app-alignment.js +0 -112
  31. package/lib/app-carrier-store.js +0 -1972
  32. package/lib/app-carrier.js +0 -602
  33. package/lib/client.js +0 -706
  34. package/lib/desktop-form.js +0 -738
  35. package/lib/endpoint-registry.js +0 -162
  36. package/lib/git-read-bundled-provider.js +0 -255
  37. package/lib/git-read-service.js +0 -322
  38. package/lib/index.js +0 -9292
  39. package/lib/plugin-content-digest.js +0 -80
  40. package/lib/plugin-self-update.js +0 -758
  41. package/lib/plugin-update-controller.js +0 -95
  42. package/lib/plugin-update-transaction.js +0 -322
  43. package/lib/plugin-update.js +0 -309
  44. package/lib/runtime-dependency-snapshot.js +0 -345
  45. package/lib/session-title-cache.js +0 -123
  46. package/lib/session-title-refresh.js +0 -261
  47. package/lib/update-fetch.js +0 -24
  48. package/lib/update-lock-arbiter.js +0 -158
  49. package/lib/update-supervisor.js +0 -312
  50. package/node_modules/ansi-regex/index.d.ts +0 -37
  51. package/node_modules/ansi-regex/index.js +0 -10
  52. package/node_modules/ansi-regex/license +0 -9
  53. package/node_modules/ansi-regex/package.json +0 -55
  54. package/node_modules/ansi-regex/readme.md +0 -78
  55. package/node_modules/ansi-styles/index.d.ts +0 -345
  56. package/node_modules/ansi-styles/index.js +0 -163
  57. package/node_modules/ansi-styles/license +0 -9
  58. package/node_modules/ansi-styles/package.json +0 -56
  59. package/node_modules/ansi-styles/readme.md +0 -152
  60. package/node_modules/camelcase/index.d.ts +0 -63
  61. package/node_modules/camelcase/index.js +0 -76
  62. package/node_modules/camelcase/license +0 -9
  63. package/node_modules/camelcase/package.json +0 -43
  64. package/node_modules/camelcase/readme.md +0 -99
  65. package/node_modules/cliui/CHANGELOG.md +0 -76
  66. package/node_modules/cliui/LICENSE.txt +0 -14
  67. package/node_modules/cliui/README.md +0 -115
  68. package/node_modules/cliui/index.js +0 -354
  69. package/node_modules/cliui/package.json +0 -65
  70. package/node_modules/color-convert/CHANGELOG.md +0 -54
  71. package/node_modules/color-convert/LICENSE +0 -21
  72. package/node_modules/color-convert/README.md +0 -68
  73. package/node_modules/color-convert/conversions.js +0 -839
  74. package/node_modules/color-convert/index.js +0 -81
  75. package/node_modules/color-convert/package.json +0 -48
  76. package/node_modules/color-convert/route.js +0 -97
  77. package/node_modules/color-name/LICENSE +0 -8
  78. package/node_modules/color-name/README.md +0 -11
  79. package/node_modules/color-name/index.js +0 -152
  80. package/node_modules/color-name/package.json +0 -28
  81. package/node_modules/decamelize/index.js +0 -13
  82. package/node_modules/decamelize/license +0 -21
  83. package/node_modules/decamelize/package.json +0 -38
  84. package/node_modules/decamelize/readme.md +0 -48
  85. package/node_modules/dijkstrajs/.travis.yml +0 -4
  86. package/node_modules/dijkstrajs/CONTRIBUTING.md +0 -8
  87. package/node_modules/dijkstrajs/LICENSE.md +0 -19
  88. package/node_modules/dijkstrajs/README.md +0 -18
  89. package/node_modules/dijkstrajs/dijkstra.js +0 -165
  90. package/node_modules/dijkstrajs/package.json +0 -60
  91. package/node_modules/dijkstrajs/test/dijkstra.test.js +0 -96
  92. package/node_modules/emoji-regex/LICENSE-MIT.txt +0 -20
  93. package/node_modules/emoji-regex/README.md +0 -73
  94. package/node_modules/emoji-regex/es2015/index.js +0 -6
  95. package/node_modules/emoji-regex/es2015/text.js +0 -6
  96. package/node_modules/emoji-regex/index.d.ts +0 -23
  97. package/node_modules/emoji-regex/index.js +0 -6
  98. package/node_modules/emoji-regex/package.json +0 -50
  99. package/node_modules/emoji-regex/text.js +0 -6
  100. package/node_modules/find-up/index.d.ts +0 -137
  101. package/node_modules/find-up/index.js +0 -89
  102. package/node_modules/find-up/license +0 -9
  103. package/node_modules/find-up/package.json +0 -53
  104. package/node_modules/find-up/readme.md +0 -156
  105. package/node_modules/get-caller-file/LICENSE.md +0 -6
  106. package/node_modules/get-caller-file/README.md +0 -41
  107. package/node_modules/get-caller-file/index.d.ts +0 -2
  108. package/node_modules/get-caller-file/index.js +0 -22
  109. package/node_modules/get-caller-file/index.js.map +0 -1
  110. package/node_modules/get-caller-file/package.json +0 -42
  111. package/node_modules/is-fullwidth-code-point/index.d.ts +0 -17
  112. package/node_modules/is-fullwidth-code-point/index.js +0 -50
  113. package/node_modules/is-fullwidth-code-point/license +0 -9
  114. package/node_modules/is-fullwidth-code-point/package.json +0 -42
  115. package/node_modules/is-fullwidth-code-point/readme.md +0 -39
  116. package/node_modules/locate-path/index.d.ts +0 -83
  117. package/node_modules/locate-path/index.js +0 -65
  118. package/node_modules/locate-path/license +0 -9
  119. package/node_modules/locate-path/package.json +0 -45
  120. package/node_modules/locate-path/readme.md +0 -122
  121. package/node_modules/p-limit/index.d.ts +0 -38
  122. package/node_modules/p-limit/index.js +0 -57
  123. package/node_modules/p-limit/license +0 -9
  124. package/node_modules/p-limit/package.json +0 -52
  125. package/node_modules/p-limit/readme.md +0 -101
  126. package/node_modules/p-locate/index.d.ts +0 -64
  127. package/node_modules/p-locate/index.js +0 -52
  128. package/node_modules/p-locate/license +0 -9
  129. package/node_modules/p-locate/package.json +0 -53
  130. package/node_modules/p-locate/readme.md +0 -90
  131. package/node_modules/p-try/index.d.ts +0 -39
  132. package/node_modules/p-try/index.js +0 -9
  133. package/node_modules/p-try/license +0 -9
  134. package/node_modules/p-try/package.json +0 -42
  135. package/node_modules/p-try/readme.md +0 -58
  136. package/node_modules/path-exists/index.d.ts +0 -28
  137. package/node_modules/path-exists/index.js +0 -23
  138. package/node_modules/path-exists/license +0 -9
  139. package/node_modules/path-exists/package.json +0 -39
  140. package/node_modules/path-exists/readme.md +0 -52
  141. package/node_modules/pngjs/.eslintignore +0 -2
  142. package/node_modules/pngjs/.eslintrc.json +0 -19
  143. package/node_modules/pngjs/.prettierignore +0 -3
  144. package/node_modules/pngjs/LICENSE +0 -20
  145. package/node_modules/pngjs/README.md +0 -429
  146. package/node_modules/pngjs/browser.js +0 -16096
  147. package/node_modules/pngjs/coverage/lcov-report/base.css +0 -354
  148. package/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html +0 -881
  149. package/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html +0 -554
  150. package/node_modules/pngjs/coverage/lcov-report/block-navigation.js +0 -77
  151. package/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html +0 -647
  152. package/node_modules/pngjs/coverage/lcov-report/constants.js.html +0 -176
  153. package/node_modules/pngjs/coverage/lcov-report/crc.js.html +0 -200
  154. package/node_modules/pngjs/coverage/lcov-report/favicon.png +0 -0
  155. package/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html +0 -593
  156. package/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html +0 -152
  157. package/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html +0 -143
  158. package/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html +0 -611
  159. package/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html +0 -359
  160. package/node_modules/pngjs/coverage/lcov-report/index.html +0 -426
  161. package/node_modules/pngjs/coverage/lcov-report/interlace.js.html +0 -365
  162. package/node_modules/pngjs/coverage/lcov-report/packer-async.js.html +0 -230
  163. package/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html +0 -248
  164. package/node_modules/pngjs/coverage/lcov-report/packer.js.html +0 -467
  165. package/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html +0 -128
  166. package/node_modules/pngjs/coverage/lcov-report/parser-async.js.html +0 -575
  167. package/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html +0 -404
  168. package/node_modules/pngjs/coverage/lcov-report/parser.js.html +0 -950
  169. package/node_modules/pngjs/coverage/lcov-report/png-sync.js.html +0 -116
  170. package/node_modules/pngjs/coverage/lcov-report/png.js.html +0 -662
  171. package/node_modules/pngjs/coverage/lcov-report/prettify.css +0 -101
  172. package/node_modules/pngjs/coverage/lcov-report/prettify.js +0 -1007
  173. package/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  174. package/node_modules/pngjs/coverage/lcov-report/sorter.js +0 -169
  175. package/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html +0 -584
  176. package/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html +0 -215
  177. package/node_modules/pngjs/coverage/lcov.info +0 -2177
  178. package/node_modules/pngjs/lib/bitmapper.js +0 -267
  179. package/node_modules/pngjs/lib/bitpacker.js +0 -158
  180. package/node_modules/pngjs/lib/chunkstream.js +0 -189
  181. package/node_modules/pngjs/lib/constants.js +0 -32
  182. package/node_modules/pngjs/lib/crc.js +0 -40
  183. package/node_modules/pngjs/lib/filter-pack.js +0 -171
  184. package/node_modules/pngjs/lib/filter-parse-async.js +0 -24
  185. package/node_modules/pngjs/lib/filter-parse-sync.js +0 -21
  186. package/node_modules/pngjs/lib/filter-parse.js +0 -177
  187. package/node_modules/pngjs/lib/format-normaliser.js +0 -93
  188. package/node_modules/pngjs/lib/interlace.js +0 -95
  189. package/node_modules/pngjs/lib/packer-async.js +0 -50
  190. package/node_modules/pngjs/lib/packer-sync.js +0 -56
  191. package/node_modules/pngjs/lib/packer.js +0 -129
  192. package/node_modules/pngjs/lib/paeth-predictor.js +0 -16
  193. package/node_modules/pngjs/lib/parser-async.js +0 -165
  194. package/node_modules/pngjs/lib/parser-sync.js +0 -108
  195. package/node_modules/pngjs/lib/parser.js +0 -290
  196. package/node_modules/pngjs/lib/png-sync.js +0 -12
  197. package/node_modules/pngjs/lib/png.js +0 -194
  198. package/node_modules/pngjs/lib/sync-inflate.js +0 -168
  199. package/node_modules/pngjs/lib/sync-reader.js +0 -45
  200. package/node_modules/pngjs/package.json +0 -73
  201. package/node_modules/qrcode/README.md +0 -770
  202. package/node_modules/qrcode/bin/qrcode +0 -159
  203. package/node_modules/qrcode/helper/to-sjis-browser.js +0 -2
  204. package/node_modules/qrcode/helper/to-sjis.js +0 -105
  205. package/node_modules/qrcode/lib/browser.js +0 -76
  206. package/node_modules/qrcode/lib/can-promise.js +0 -7
  207. package/node_modules/qrcode/lib/core/alignment-pattern.js +0 -83
  208. package/node_modules/qrcode/lib/core/alphanumeric-data.js +0 -59
  209. package/node_modules/qrcode/lib/core/bit-buffer.js +0 -37
  210. package/node_modules/qrcode/lib/core/bit-matrix.js +0 -65
  211. package/node_modules/qrcode/lib/core/byte-data.js +0 -30
  212. package/node_modules/qrcode/lib/core/error-correction-code.js +0 -135
  213. package/node_modules/qrcode/lib/core/error-correction-level.js +0 -50
  214. package/node_modules/qrcode/lib/core/finder-pattern.js +0 -22
  215. package/node_modules/qrcode/lib/core/format-info.js +0 -29
  216. package/node_modules/qrcode/lib/core/galois-field.js +0 -69
  217. package/node_modules/qrcode/lib/core/kanji-data.js +0 -54
  218. package/node_modules/qrcode/lib/core/mask-pattern.js +0 -234
  219. package/node_modules/qrcode/lib/core/mode.js +0 -167
  220. package/node_modules/qrcode/lib/core/numeric-data.js +0 -43
  221. package/node_modules/qrcode/lib/core/polynomial.js +0 -62
  222. package/node_modules/qrcode/lib/core/qrcode.js +0 -495
  223. package/node_modules/qrcode/lib/core/reed-solomon-encoder.js +0 -56
  224. package/node_modules/qrcode/lib/core/regex.js +0 -31
  225. package/node_modules/qrcode/lib/core/segments.js +0 -330
  226. package/node_modules/qrcode/lib/core/utils.js +0 -63
  227. package/node_modules/qrcode/lib/core/version-check.js +0 -9
  228. package/node_modules/qrcode/lib/core/version.js +0 -163
  229. package/node_modules/qrcode/lib/index.js +0 -12
  230. package/node_modules/qrcode/lib/renderer/canvas.js +0 -63
  231. package/node_modules/qrcode/lib/renderer/png.js +0 -78
  232. package/node_modules/qrcode/lib/renderer/svg-tag.js +0 -81
  233. package/node_modules/qrcode/lib/renderer/svg.js +0 -19
  234. package/node_modules/qrcode/lib/renderer/terminal/terminal-small.js +0 -85
  235. package/node_modules/qrcode/lib/renderer/terminal/terminal.js +0 -49
  236. package/node_modules/qrcode/lib/renderer/terminal.js +0 -9
  237. package/node_modules/qrcode/lib/renderer/utf8.js +0 -71
  238. package/node_modules/qrcode/lib/renderer/utils.js +0 -99
  239. package/node_modules/qrcode/lib/server.js +0 -138
  240. package/node_modules/qrcode/license +0 -10
  241. package/node_modules/qrcode/package.json +0 -77
  242. package/node_modules/require-directory/.jshintrc +0 -67
  243. package/node_modules/require-directory/.npmignore +0 -1
  244. package/node_modules/require-directory/.travis.yml +0 -3
  245. package/node_modules/require-directory/LICENSE +0 -22
  246. package/node_modules/require-directory/README.markdown +0 -184
  247. package/node_modules/require-directory/index.js +0 -86
  248. package/node_modules/require-directory/package.json +0 -40
  249. package/node_modules/require-main-filename/CHANGELOG.md +0 -26
  250. package/node_modules/require-main-filename/LICENSE.txt +0 -14
  251. package/node_modules/require-main-filename/README.md +0 -26
  252. package/node_modules/require-main-filename/index.js +0 -18
  253. package/node_modules/require-main-filename/package.json +0 -35
  254. package/node_modules/set-blocking/CHANGELOG.md +0 -26
  255. package/node_modules/set-blocking/LICENSE.txt +0 -14
  256. package/node_modules/set-blocking/README.md +0 -31
  257. package/node_modules/set-blocking/index.js +0 -7
  258. package/node_modules/set-blocking/package.json +0 -42
  259. package/node_modules/string-width/index.d.ts +0 -29
  260. package/node_modules/string-width/index.js +0 -47
  261. package/node_modules/string-width/license +0 -9
  262. package/node_modules/string-width/package.json +0 -56
  263. package/node_modules/string-width/readme.md +0 -50
  264. package/node_modules/strip-ansi/index.d.ts +0 -17
  265. package/node_modules/strip-ansi/index.js +0 -4
  266. package/node_modules/strip-ansi/license +0 -9
  267. package/node_modules/strip-ansi/package.json +0 -54
  268. package/node_modules/strip-ansi/readme.md +0 -46
  269. package/node_modules/which-module/LICENSE +0 -13
  270. package/node_modules/which-module/README.md +0 -58
  271. package/node_modules/which-module/index.js +0 -9
  272. package/node_modules/which-module/package.json +0 -41
  273. package/node_modules/wrap-ansi/index.js +0 -186
  274. package/node_modules/wrap-ansi/license +0 -9
  275. package/node_modules/wrap-ansi/package.json +0 -61
  276. package/node_modules/wrap-ansi/readme.md +0 -97
  277. package/node_modules/y18n/CHANGELOG.md +0 -35
  278. package/node_modules/y18n/LICENSE +0 -13
  279. package/node_modules/y18n/README.md +0 -109
  280. package/node_modules/y18n/index.js +0 -188
  281. package/node_modules/y18n/package.json +0 -39
  282. package/node_modules/yargs/CHANGELOG.md +0 -420
  283. package/node_modules/yargs/LICENSE +0 -21
  284. package/node_modules/yargs/README.md +0 -140
  285. package/node_modules/yargs/build/lib/apply-extends.d.ts +0 -2
  286. package/node_modules/yargs/build/lib/apply-extends.js +0 -65
  287. package/node_modules/yargs/build/lib/argsert.d.ts +0 -2
  288. package/node_modules/yargs/build/lib/argsert.js +0 -65
  289. package/node_modules/yargs/build/lib/command.d.ts +0 -64
  290. package/node_modules/yargs/build/lib/command.js +0 -416
  291. package/node_modules/yargs/build/lib/common-types.d.ts +0 -36
  292. package/node_modules/yargs/build/lib/common-types.js +0 -25
  293. package/node_modules/yargs/build/lib/completion-templates.d.ts +0 -2
  294. package/node_modules/yargs/build/lib/completion-templates.js +0 -50
  295. package/node_modules/yargs/build/lib/completion.d.ts +0 -21
  296. package/node_modules/yargs/build/lib/completion.js +0 -135
  297. package/node_modules/yargs/build/lib/is-promise.d.ts +0 -1
  298. package/node_modules/yargs/build/lib/is-promise.js +0 -9
  299. package/node_modules/yargs/build/lib/levenshtein.d.ts +0 -1
  300. package/node_modules/yargs/build/lib/levenshtein.js +0 -58
  301. package/node_modules/yargs/build/lib/middleware.d.ts +0 -10
  302. package/node_modules/yargs/build/lib/middleware.js +0 -57
  303. package/node_modules/yargs/build/lib/obj-filter.d.ts +0 -1
  304. package/node_modules/yargs/build/lib/obj-filter.js +0 -14
  305. package/node_modules/yargs/build/lib/parse-command.d.ts +0 -11
  306. package/node_modules/yargs/build/lib/parse-command.js +0 -36
  307. package/node_modules/yargs/build/lib/process-argv.d.ts +0 -2
  308. package/node_modules/yargs/build/lib/process-argv.js +0 -31
  309. package/node_modules/yargs/build/lib/usage.d.ts +0 -49
  310. package/node_modules/yargs/build/lib/usage.js +0 -540
  311. package/node_modules/yargs/build/lib/validation.d.ts +0 -34
  312. package/node_modules/yargs/build/lib/validation.js +0 -330
  313. package/node_modules/yargs/build/lib/yargs.d.ts +0 -274
  314. package/node_modules/yargs/build/lib/yargs.js +0 -1190
  315. package/node_modules/yargs/build/lib/yerror.d.ts +0 -4
  316. package/node_modules/yargs/build/lib/yerror.js +0 -11
  317. package/node_modules/yargs/index.js +0 -40
  318. package/node_modules/yargs/locales/be.json +0 -46
  319. package/node_modules/yargs/locales/de.json +0 -46
  320. package/node_modules/yargs/locales/en.json +0 -51
  321. package/node_modules/yargs/locales/es.json +0 -46
  322. package/node_modules/yargs/locales/fi.json +0 -49
  323. package/node_modules/yargs/locales/fr.json +0 -53
  324. package/node_modules/yargs/locales/hi.json +0 -49
  325. package/node_modules/yargs/locales/hu.json +0 -46
  326. package/node_modules/yargs/locales/id.json +0 -50
  327. package/node_modules/yargs/locales/it.json +0 -46
  328. package/node_modules/yargs/locales/ja.json +0 -51
  329. package/node_modules/yargs/locales/ko.json +0 -49
  330. package/node_modules/yargs/locales/nb.json +0 -44
  331. package/node_modules/yargs/locales/nl.json +0 -49
  332. package/node_modules/yargs/locales/nn.json +0 -44
  333. package/node_modules/yargs/locales/pirate.json +0 -13
  334. package/node_modules/yargs/locales/pl.json +0 -49
  335. package/node_modules/yargs/locales/pt.json +0 -45
  336. package/node_modules/yargs/locales/pt_BR.json +0 -48
  337. package/node_modules/yargs/locales/ru.json +0 -46
  338. package/node_modules/yargs/locales/th.json +0 -46
  339. package/node_modules/yargs/locales/tr.json +0 -48
  340. package/node_modules/yargs/locales/zh_CN.json +0 -48
  341. package/node_modules/yargs/locales/zh_TW.json +0 -47
  342. package/node_modules/yargs/package.json +0 -92
  343. package/node_modules/yargs/yargs.js +0 -14
  344. package/node_modules/yargs-parser/CHANGELOG.md +0 -601
  345. package/node_modules/yargs-parser/LICENSE.txt +0 -14
  346. package/node_modules/yargs-parser/README.md +0 -449
  347. package/node_modules/yargs-parser/index.js +0 -1032
  348. package/node_modules/yargs-parser/lib/tokenize-arg-string.js +0 -40
  349. package/node_modules/yargs-parser/package.json +0 -46
@@ -1,162 +0,0 @@
1
- // 端点登记表(ADR 0019「能力登记强制化」;评审 #32 note 1286 的 W2)。
2
- //
3
- // 三条判据里「能力能不能用」看的是**能力声明**;而声明要成立,前提是"新增端点时必须有人
4
- // 登记它"。此前这件事只写在 CONTRIBUTING 的文字要求里,没有机制兜底——于是必然漏。
5
- //
6
- // 这里把登记变成**可被测试检出**的东西:
7
- // - 从 `lib/index.js` 抽取所有正向分派(`rest === "..."`、`new Set([...]).has(rest)`),
8
- // 与登记表**双向**比对:漏登记、陈旧登记、**方法不符**都会失败;
9
- // - 抽取正则容忍引号与空白差异(`rest === '/x'`、`rest==="/x"` 同样会被抓到);
10
- // - 每条登记项都必须显式写出 `capability`(能力键或 `null`);写了键就必须真的在
11
- // bootstrap 的 capabilities 里声明过,否则失败。
12
- //
13
- // 已知边界(不假装更强):`methods` 由源码按分派段落推导,是**契约快照**而非运行期保证;
14
- // 端点自身仍靠 `requireGet`/`method` 检查在运行时兜底。
15
-
16
- /** 抽取正向分派所用的源码文件(相对仓库根)。 */
17
- export const ENDPOINT_DISPATCH_SOURCE = "lib/index.js";
18
-
19
- /** 从源码抽取"正向分派"及其方法(按分派段落判定,不看固定窗口)。 */
20
- export function extractEndpointDetails(source) {
21
- const lines = source.split("\n");
22
- const marks = [];
23
- lines.forEach((line, index) => {
24
- for (const m of line.matchAll(/rest\s*===\s*['"]([^'"]+)['"]/g)) marks.push({ index, path: m[1] });
25
- for (const group of line.matchAll(/new Set\(\[([^\]]+)\]\)\s*\.has\(rest\)/g)) {
26
- for (const m of group[1].matchAll(/['"]([^'"]+)['"]/g)) marks.push({ index, path: m[1] });
27
- }
28
- });
29
- marks.sort((a, b) => a.index - b.index);
30
- const markLines = [...new Set(marks.map((m) => m.index))].sort((a, b) => a - b);
31
- const out = new Map();
32
- for (const { index, path } of marks) {
33
- if (out.has(path)) continue;
34
- const next = markLines.find((l) => l > index);
35
- const segment = lines.slice(index, next ?? Math.min(lines.length, index + 400)).join("\n");
36
- let methods = "GET/POST";
37
- if (/requireGet\(method,\s*res\)/.test(segment)) methods = "GET";
38
- else if (/method\s*!==\s*['"]POST['"]/.test(segment)) methods = "POST";
39
- out.set(path, methods);
40
- }
41
- return out;
42
- }
43
-
44
- /**
45
- * 抽取 **bootstrap 响应**里实际声明的能力键(G2)。
46
- * 只认 `/bootstrap` 处理器里的那个 `capabilities: {...}` 块——SSE hello 里也有
47
- * `capabilities`,按"源码里第一个"抽取会误判(那样负向变异根本测不出来)。
48
- */
49
- export function extractDeclaredCapabilities(source) {
50
- const lines = source.split("\n");
51
- const bootstrapAt = lines.findIndex((l) => /rest\s*===\s*['"]\/bootstrap['"]/.test(l));
52
- const from = bootstrapAt >= 0 ? bootstrapAt : 0;
53
- const tail = lines.slice(from).join("\n");
54
- const m = /capabilities:\s*\{/.exec(tail);
55
- if (!m) return new Set();
56
- // 从 `{` 起做花括号配平,取出完整块
57
- const open = tail.indexOf("{", m.index);
58
- let depth = 0;
59
- let end = -1;
60
- for (let i = open; i < tail.length; i++) {
61
- if (tail[i] === "{") depth++;
62
- else if (tail[i] === "}") {
63
- depth--;
64
- if (depth === 0) {
65
- end = i;
66
- break;
67
- }
68
- }
69
- }
70
- if (end < 0) return new Set();
71
- const block = tail.slice(open + 1, end);
72
- return new Set([...block.matchAll(/([A-Za-z_][A-Za-z0-9_]*)\s*:/g)].map((x) => x[1]));
73
- }
74
-
75
- /** 未声明能力时的显式豁免理由(登记表要求二者必居其一)。 */
76
- export const NO_CAPABILITY_NEEDED = "端点级能力由 App 按 404/缺字段降级;能力声明机制覆盖的是帧/字段级特性";
77
-
78
- /**
79
- * 双向比对。返回 `missing`(源码有、表里没有)、`stale`(表里有、源码没有)、
80
- * `methodMismatch`(方法不符)与 `undeclaredCapabilities`(登记了未声明的能力键)。
81
- */
82
- export function diffRegisteredEndpoints(source, registered = REGISTERED_ENDPOINTS) {
83
- const dispatched = extractEndpointDetails(source);
84
- const known = new Map(registered.map((e) => [e.path, e]));
85
- const declared = extractDeclaredCapabilities(source);
86
- const missing = [...dispatched.keys()].filter((p) => !known.has(p)).sort();
87
- const stale = [...known.keys()].filter((p) => !dispatched.has(p)).sort();
88
- const methodMismatch = [...dispatched.entries()]
89
- .filter(([p, methods]) => known.has(p) && known.get(p).methods && known.get(p).methods !== methods)
90
- .map(([p, methods]) => ({ path: p, registered: known.get(p).methods, source: methods }))
91
- .sort((a, b) => a.path.localeCompare(b.path));
92
- const undeclaredCapabilities = [...new Set(
93
- registered.map((e) => e.capability).filter((c) => typeof c === "string" && c !== "" && !declared.has(c)),
94
- )].sort();
95
- const missingCapabilityField = registered.filter((e) => !("capability" in e)).map((e) => e.path).sort();
96
- // 没关联能力键的必须给出**显式豁免理由**(G2:不允许"忘了写"和"确实不需要"长得一样)
97
- const missingExemption = registered
98
- .filter((e) => (e.capability === null || e.capability === undefined) && !(typeof e.why === "string" && e.why.trim() !== ""))
99
- .map((e) => e.path)
100
- .sort();
101
- return { missing, stale, methodMismatch, undeclaredCapabilities, missingCapabilityField, missingExemption, dispatched, declared };
102
- }
103
-
104
- /** 已登记的 `/m/api/*` 端点(`path` 是去掉 `/m/api` 前缀后的部分)。 */
105
- export const REGISTERED_ENDPOINTS = Object.freeze([
106
- { path: "/account-usage", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
107
- { path: "/actions", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
108
- { path: "/attachment", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
109
- { path: "/balance", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
110
- { path: "/bootstrap", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
111
- { path: "/catalog", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
112
- { path: "/commands", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
113
- { path: "/defaults", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
114
- { path: "/dev/approval-test", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
115
- { path: "/diagnostics", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
116
- { path: "/directories", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
117
- { path: "/event-detail", methods: "GET", capability: "eventTimeline" },
118
- { path: "/events", methods: "GET/POST", capability: "eventTimeline" },
119
- { path: "/feedback", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
120
- { path: "/files", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
121
- { path: "/files/upload", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
122
- { path: "/git/branches", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
123
- { path: "/git/capabilities", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
124
- { path: "/git/commit", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
125
- { path: "/git/graph", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
126
- { path: "/git/preview", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
127
- { path: "/git/repository", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
128
- { path: "/git/worktree", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
129
- { path: "/goal", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
130
- { path: "/history", methods: "GET", capability: "eventTimeline" },
131
- { path: "/jobs", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
132
- { path: "/jobs/kill", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
133
- { path: "/llm-providers", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
134
- { path: "/llm-providers/probe", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
135
- { path: "/messages", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
136
- { path: "/notifications", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
137
- { path: "/notifications/delete", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
138
- { path: "/notifications/read", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
139
- { path: "/plugin-update", methods: "POST", capability: null, why: NO_CAPABILITY_NEEDED },
140
- { path: "/push-test", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
141
- { path: "/qr-config", methods: "GET", capability: null, auth: "local-privileged", why: NO_CAPABILITY_NEEDED },
142
- { path: "/queue", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
143
- { path: "/respond", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
144
- { path: "/send", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
145
- { path: "/send-receipt", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
146
- { path: "/session-config", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
147
- { path: "/sessions", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
148
- { path: "/sessions/archive", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
149
- { path: "/sessions/fork", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
150
- { path: "/sessions/stop", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
151
- { path: "/sessions/touch", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
152
- { path: "/sessions/unarchive", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
153
- { path: "/subagents", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
154
- { path: "/subagents/interrupt", methods: "GET/POST", capability: null, why: NO_CAPABILITY_NEEDED },
155
- { path: "/todos", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
156
- { path: "/turn-outline", methods: "GET", capability: "turnOutline" },
157
- { path: "/update/apk", methods: "GET", capability: null, auth: "anonymous", why: NO_CAPABILITY_NEEDED },
158
- { path: "/update/manifest", methods: "GET", capability: null, auth: "required", why: NO_CAPABILITY_NEEDED },
159
- { path: "/update/plugin", methods: "GET", capability: null, auth: "required", why: NO_CAPABILITY_NEEDED },
160
- { path: "/usage", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
161
- { path: "/workspaces", methods: "GET", capability: null, why: NO_CAPABILITY_NEEDED },
162
- ]);
@@ -1,255 +0,0 @@
1
- import { constants as fsConstants } from "node:fs";
2
- import { realpath, open, lstat } from "node:fs/promises";
3
- import { isAbsolute, relative, resolve, sep } from "node:path";
4
- import { createHash } from "node:crypto";
5
-
6
- const UNTRACKED_PREVIEW_MAX = 512 * 1024;
7
- const SIGNATURE_SAMPLE_BYTES = 4096;
8
- const readOnlyNoFollow = fsConstants.O_RDONLY | (fsConstants.O_NOFOLLOW ?? 0);
9
- function sameRegularFile(expected, opened) {
10
- return expected.isFile() && opened.isFile() && expected.dev === opened.dev && expected.ino === opened.ino;
11
- }
12
- async function readPrefix(path, maximum, expected) {
13
- const handle = await open(path, readOnlyNoFollow);
14
- try {
15
- if (!sameRegularFile(expected, await handle.stat())) throw new Error("file changed while opening preview");
16
- const buffer = Buffer.alloc(maximum + 1);
17
- const { bytesRead } = await handle.read(buffer, 0, maximum + 1, 0);
18
- return { bytes: buffer.subarray(0, bytesRead), truncated: bytesRead > maximum };
19
- } finally { await handle.close(); }
20
- }
21
- async function sampledFileSignature(path, info) {
22
- const handle = await open(path, readOnlyNoFollow);
23
- try {
24
- if (!sameRegularFile(info, await handle.stat())) throw new Error("file changed while sampling worktree");
25
- const first = Buffer.alloc(Math.min(SIGNATURE_SAMPLE_BYTES, info.size));
26
- const firstRead = await handle.read(first, 0, first.length, 0);
27
- let last = Buffer.alloc(0);
28
- if (info.size > SIGNATURE_SAMPLE_BYTES) {
29
- last = Buffer.alloc(SIGNATURE_SAMPLE_BYTES);
30
- const read = await handle.read(last, 0, last.length, Math.max(0, info.size - last.length));
31
- last = last.subarray(0, read.bytesRead);
32
- }
33
- return createHash("sha256").update(`${info.dev}:${info.ino}:${info.size}:${info.mtimeMs}:${info.ctimeMs}:`).update(first.subarray(0, firstRead.bytesRead)).update(last).digest("hex");
34
- } finally { await handle.close(); }
35
- }
36
-
37
- function gitError(code, status, message = code) {
38
- const error = new Error(message);
39
- error.code = code;
40
- error.status = status;
41
- return error;
42
- }
43
-
44
- /** Bundled, read-only Git provider. Every command uses the host subprocess service. */
45
- export function createBundledGitReadProvider(ctx) {
46
- const get = (name) => {
47
- try { return ctx.get?.(name); } catch { return undefined; }
48
- };
49
- const subprocess = () => get("subprocess") ?? ctx.subprocess;
50
- const workspaces = () => (get("workspaceRegistry")?.list?.() ?? [])
51
- .map((entry) => entry?.path).filter((path) => typeof path === "string" && path !== "");
52
- const inside = (child, parent) => {
53
- const value = relative(resolve(parent), resolve(child));
54
- return value === "" || (value !== ".." && !value.startsWith(`..${sep}`) && !isAbsolute(value));
55
- };
56
- const assertWorkspace = async (path) => {
57
- if (typeof path !== "string" || path === "") throw gitError("workspace-not-allowed", 403);
58
- let canonical;
59
- try { canonical = await realpath(path); } catch { throw gitError("workspace-not-allowed", 403); }
60
- const roots = await Promise.all(workspaces().map((root) => realpath(root).catch(() => null)));
61
- if (!roots.some((root) => root && inside(canonical, root))) throw gitError("workspace-not-allowed", 403);
62
- return canonical;
63
- };
64
- const run = async (root, args, disableFilters = false, allowNoMatches = false) => {
65
- root = await assertWorkspace(root);
66
- const executor = subprocess();
67
- if (!executor?.spawn) throw gitError("git-provider-unavailable", 503);
68
- const noHooksPath = process.platform === "win32" ? "NUL" : "/dev/null";
69
- let filterOverrides = [];
70
- if (disableFilters) {
71
- const names = await run(root, ["config", "--null", "--name-only", "--get-regexp", "^filter\\..*\\.(clean|process)$"], false, true);
72
- filterOverrides = names.split("\0").filter(Boolean).flatMap((name) => ["-c", `${name}=`]);
73
- }
74
- const child = executor.spawn({
75
- argv: [
76
- process.platform === "win32" ? "git.exe" : "git",
77
- "-c", "core.fsmonitor=false",
78
- "-c", `core.hooksPath=${noHooksPath}`,
79
- ...filterOverrides,
80
- "-C", root,
81
- "--no-optional-locks",
82
- ...args,
83
- ],
84
- cwd: root,
85
- // Prevent ambient Git repository/config overrides from redirecting a
86
- // session-authorized read. Undefined values are seam tombstones.
87
- env: {
88
- GIT_TERMINAL_PROMPT: "0",
89
- GCM_INTERACTIVE: "never",
90
- GIT_DIR: undefined,
91
- GIT_WORK_TREE: undefined,
92
- GIT_INDEX_FILE: undefined,
93
- GIT_COMMON_DIR: undefined,
94
- GIT_OBJECT_DIRECTORY: undefined,
95
- GIT_ALTERNATE_OBJECT_DIRECTORIES: undefined,
96
- GIT_CONFIG: undefined,
97
- GIT_CONFIG_PARAMETERS: undefined,
98
- GIT_CONFIG_COUNT: "0",
99
- // Trace destinations open files even for otherwise read-only Git commands.
100
- ...Object.fromEntries(Object.keys(process.env).filter((key) => /^GIT_TRACE(?:2)?(?:_|$)/.test(key)).map((key) => [key, undefined])),
101
- GIT_TRACE: undefined,
102
- GIT_TRACE2: undefined,
103
- GIT_TRACE2_EVENT: undefined,
104
- GIT_TRACE2_PERF: undefined,
105
- },
106
- stdio: { stdin: "ignore", stdout: { maxBytes: 8 * 1024 * 1024 }, stderr: { maxBytes: 1024 * 1024 } },
107
- graceMs: 10_000,
108
- });
109
- const done = await child.done;
110
- const stdoutResult = await child.collected?.stdout?.readFrom?.(0);
111
- const stderrResult = await child.collected?.stderr?.readFrom?.(0);
112
- if (stdoutResult?.lossy || stderrResult?.lossy) {
113
- throw gitError("git-output-too-large", 413);
114
- }
115
- const stdout = stdoutResult?.text ?? "";
116
- const stderr = stderrResult?.text ?? "";
117
- if (done?.exitCode !== 0) {
118
- if (allowNoMatches && done?.exitCode === 1) return "";
119
- if (/not a git repository/i.test(stderr)) throw gitError("not-git-repository", 404);
120
- throw gitError("git-command-failed", 400);
121
- }
122
- return stdout;
123
- };
124
- const repositoryRoot = async (cwd) => {
125
- const allowed = await assertWorkspace(cwd);
126
- const root = (await run(allowed, ["rev-parse", "--show-toplevel"])).trim();
127
- return assertWorkspace(root);
128
- };
129
- return {
130
- contractVersion: "1.0.0",
131
- capabilities() {
132
- const available = Boolean(subprocess()?.spawn) && workspaces().length > 0;
133
- return { available, reason: available ? null : !subprocess()?.spawn ? "git-provider-unavailable" : "workspace-registry-unavailable" };
134
- },
135
- repositoryRoot,
136
- async refSignature(root) {
137
- let refs = "";
138
- try { refs = await run(root, ["show-ref", "--head", "--dereference"]); } catch (error) { if (error?.code !== "git-command-failed") throw error; }
139
- return createHash("sha256").update(refs).digest("hex");
140
- },
141
- async repositoryInfo(root) {
142
- let currentBranch = null, headOid = null;
143
- try { currentBranch = (await run(root, ["symbolic-ref", "--quiet", "HEAD"])).trim() || null; } catch (error) { if (error?.code !== "git-command-failed") throw error; }
144
- try { headOid = (await run(root, ["rev-parse", "--verify", "HEAD"])).trim() || null; } catch (error) { if (error?.code !== "git-command-failed") throw error; }
145
- return { ...(headOid ? { headOid } : {}), ...(currentBranch ? { currentBranch } : {}), detached: Boolean(headOid && !currentBranch), empty: !headOid };
146
- },
147
- async resolveTip(root, ref) {
148
- return (await run(root, ["rev-parse", "--verify", `${ref}^{commit}`])).trim();
149
- },
150
- async graph(root, { refs, offset, limit }) {
151
- if (refs.length === 0) return [];
152
- const text = await run(root, ["log", "--topo-order", "--date-order", `--skip=${offset}`, `--max-count=${limit}`, "--decorate=full", "--format=%H%x1f%P%x1f%an%x1f%at%x1f%s%x1f%D%x00", ...refs]);
153
- return text.split("\0").map((record) => record.replace(/^[\r\n]+|[\r\n]+$/g, "")).filter(Boolean).map((record) => {
154
- const [oid, parents, author, timestamp, subject, decorations] = record.split("\x1f");
155
- return { oid, parents: parents ? parents.split(" ") : [], author, timestamp: Number(timestamp) || 0, subject, refs: decorations ? decorations.split(",").map((value) => value.trim()).filter(Boolean) : [] };
156
- });
157
- },
158
- async commit(root, oid) {
159
- if (typeof oid !== "string" || !/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i.test(oid)) throw gitError("invalid-oid", 400);
160
- const metadata = (await run(root, ["show", "-s", "--format=%H%x1f%P%x1f%an%x1f%at%x1f%B%x00", oid])).split("\0")[0].split("\x1f");
161
- const [hash, parentText, author, timestamp, ...messageParts] = metadata;
162
- const diffBase = parentText ? [parentText.split(" ")[0], hash] : ["--root", hash];
163
- const statusParts = (await run(root, ["diff-tree", "--no-commit-id", "-r", "-M", "--name-status", "-z", ...diffBase])).split("\0");
164
- const files = [];
165
- for (let index = 0; index < statusParts.length;) {
166
- const code = statusParts[index++];
167
- if (!code) continue;
168
- const renamed = code.startsWith("R") || code.startsWith("C");
169
- const oldPath = renamed ? statusParts[index++] : undefined;
170
- const path = statusParts[index++];
171
- if (!path) break;
172
- const statuses = { A: "added", M: "modified", D: "deleted", R: "renamed", C: "copied", T: "type-changed" };
173
- files.push({ path, ...(oldPath ? { oldPath } : {}), status: statuses[code[0]] ?? "modified" });
174
- }
175
- const statParts = (await run(root, ["diff-tree", "--no-commit-id", "-r", "-M", "--numstat", "-z", ...diffBase])).split("\0");
176
- const stats = new Map();
177
- for (let index = 0; index < statParts.length;) {
178
- const record = statParts[index++];
179
- if (!record) continue;
180
- const firstTab = record.indexOf("\t");
181
- const secondTab = record.indexOf("\t", firstTab + 1);
182
- if (firstTab < 0 || secondTab < 0) continue;
183
- const added = record.slice(0, firstTab);
184
- const deleted = record.slice(firstTab + 1, secondTab);
185
- let path = record.slice(secondTab + 1);
186
- if (!path) { index++; path = statParts[index++] ?? ""; }
187
- stats.set(path, { binary: added === "-" || deleted === "-", additions: added === "-" ? null : Number(added), deletions: deleted === "-" ? null : Number(deleted) });
188
- }
189
- for (const file of files) Object.assign(file, stats.get(file.path) ?? { binary: false, additions: 0, deletions: 0 });
190
- return { oid: hash, parents: parentText ? parentText.split(" ") : [], author, timestamp: Number(timestamp) || 0, message: messageParts.join("\x1f").trim(), files };
191
- },
192
- async worktree(root) {
193
- const text = await run(root, ["status", "--porcelain=v1", "-z", "--untracked-files=all"], true);
194
- const parts = text.split("\0"); const entries = [];
195
- for (let i = 0; i < parts.length;) {
196
- const record = parts[i++]; if (!record) continue;
197
- const code = record.slice(0, 2); let path = record.slice(3); let oldPath;
198
- if (/[RC]/.test(code)) { oldPath = parts[i++] ?? ""; }
199
- const status = code.includes("U") || code === "AA" || code === "DD" ? "conflicted" : code === "??" ? "untracked" : "modified";
200
- entries.push({ path, ...(oldPath ? { oldPath } : {}), status, conflicted: status === "conflicted", index: code[0] !== " " && code !== "??", worktree: code[1] !== " " && code !== "??" });
201
- }
202
- let signatureMaterial = text;
203
- for (const entry of entries) {
204
- if (entry.status !== "untracked" && !entry.worktree) continue;
205
- try { const target = resolve(root, entry.path); const info = await lstat(target); signatureMaterial += `\\0${entry.path}:${info.isSymbolicLink() ? "symlink" : info.isFile() ? await sampledFileSignature(target, info) : "special"}`; } catch { signatureMaterial += `\\0${entry.path}:missing`; }
206
- }
207
- try { signatureMaterial += await run(root, ["--literal-pathspecs", "diff", "--raw", "-z", "--no-abbrev", "HEAD"], true); } catch (error) { if (error?.code !== "git-command-failed") throw error; }
208
- try { signatureMaterial += await run(root, ["--literal-pathspecs", "diff", "--raw", "-z", "--no-abbrev", "--cached"], true); } catch (error) { if (error?.code !== "git-command-failed") throw error; }
209
- const signature = createHash("sha256").update(signatureMaterial).digest("hex");
210
- return { entries, signature };
211
- },
212
- async worktreePreview(root, kind, path) {
213
- const args = ["--literal-pathspecs", "diff", "--unified=999999", "--no-ext-diff", "--no-textconv", "--no-color", "--binary"];
214
- if (kind === "staged") args.push("--cached");
215
- args.push("--", path);
216
- if (kind === "untracked") {
217
- try {
218
- const target = resolve(root, path); const info = await lstat(target);
219
- if (info.isSymbolicLink()) return { diff: "", binary: false, additions: null, deletions: null, notice: "symlink preview omitted" };
220
- if (!info.isFile()) return { diff: "", binary: false, additions: null, deletions: null, notice: "special file preview omitted" };
221
- const { bytes, truncated } = await readPrefix(target, UNTRACKED_PREVIEW_MAX, info);
222
- const binary = bytes.includes(0);
223
- return { diff: binary ? "" : bytes.toString("utf8"), binary, truncated, additions: null, deletions: null, ...(binary ? { notice: "binary preview omitted" } : {}) };
224
- } catch { return { diff: "", binary: false, additions: 0, deletions: 0, notice: "unavailable" }; }
225
- }
226
- return { diff: await run(root, args, true), binary: false, additions: null, deletions: null };
227
- },
228
- async commitPreview(root, oid, path) {
229
- const commit = await this.commit(root, oid);
230
- if (!commit.parents.length) return { diff: await run(root, ["--literal-pathspecs", "diff-tree", "--root", "--no-commit-id", "-p", "-r", "--unified=999999", "--no-ext-diff", "--no-textconv", "--no-color", "--binary", oid, "--", path]), binary: false };
231
- return { diff: await run(root, ["--literal-pathspecs", "diff", "--unified=999999", "--no-ext-diff", "--no-textconv", "--no-color", "--binary", `${oid}^1`, oid, "--", path]), binary: false };
232
- },
233
- async branches(root) {
234
- const text = await run(root, ["for-each-ref", "--format=%(HEAD)%09%(refname)%09%(objectname)%09%(upstream:short)%00", "refs/heads", "refs/remotes"]);
235
- const rows = text.split("\0").map((record) => record.replace(/^[\r\n]+|[\r\n]+$/g, "")).filter(Boolean);
236
- const branches = [];
237
- for (const row of rows) {
238
- const [head, ref, oid, upstream = ""] = row.split("\t");
239
- if (ref.endsWith("/HEAD")) continue;
240
- const local = ref.startsWith("refs/heads/");
241
- let ahead = 0, behind = 0;
242
- if (local && upstream) {
243
- const counts = (await run(root, ["rev-list", "--left-right", "--count", `${ref}...${upstream}`])).trim().split(/\s+/).map(Number);
244
- [ahead, behind] = counts;
245
- }
246
- branches.push({
247
- name: ref, displayName: ref.replace(/^refs\/(?:heads|remotes)\//, ""), oid,
248
- kind: local ? "local" : "remote", current: local && head === "*",
249
- tracking: local && upstream ? `refs/remotes/${upstream}` : null, ahead, behind,
250
- });
251
- }
252
- return branches;
253
- },
254
- };
255
- }