@neuralis/brain-core 0.3.1 → 0.4.0

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 (371) hide show
  1. package/README.md +88 -1417
  2. package/app/README.md +4 -4
  3. package/app/cards/FilesystemCardShell.tsx +42 -4
  4. package/app/cards/FilesystemChangeCard.tsx +34 -11
  5. package/app/cards/README.md +6 -5
  6. package/app/cards/diffUtils.ts +99 -1
  7. package/app/filesystem/FilesystemHost.tsx +24 -2
  8. package/app/filesystem/README.md +1 -1
  9. package/app/filesystem/api/README.md +3 -3
  10. package/app/filesystem/api/index.ts +38 -14
  11. package/app/filesystem/api/projectPackages.ts +13 -102
  12. package/app/filesystem/domain/types.ts +30 -10
  13. package/app/filesystem/hooks/README.md +4 -4
  14. package/app/filesystem/hooks/useDiscoverableSources.ts +19 -30
  15. package/app/filesystem/hooks/useFilesystemSSE.ts +42 -2
  16. package/app/filesystem/host/README.md +6 -4
  17. package/app/filesystem/host/buildFilesystemHostValue.ts +28 -2
  18. package/app/filesystem/host/installFilesystemHostComponents.tsx +1 -1
  19. package/app/filesystem/lib/sourceKindForm.ts +210 -27
  20. package/app/filesystem/lib/treeVisualState.tsx +98 -4
  21. package/app/filesystem/store/README.md +1 -0
  22. package/app/filesystem/store/filesystemStore.ts +99 -8
  23. package/app/filesystem/store/gitSlice.ts +5 -0
  24. package/app/filesystem/store/helpers.ts +17 -0
  25. package/app/filesystem/store/listSlice.ts +8 -0
  26. package/app/filesystem/ui/CodeEditor.tsx +18 -3
  27. package/app/filesystem/ui/DiscoverDock.tsx +5 -1
  28. package/app/filesystem/ui/FileEditor.tsx +15 -10
  29. package/app/filesystem/ui/FileTree.tsx +75 -24
  30. package/app/filesystem/ui/FilesystemWidget.tsx +10 -2
  31. package/app/filesystem/ui/FolderPicker.tsx +251 -0
  32. package/app/filesystem/ui/GitControlPanel.tsx +7 -2
  33. package/app/filesystem/ui/PackagesPanel.tsx +52 -374
  34. package/app/filesystem/ui/PendingChangesPanel.tsx +1 -1
  35. package/app/filesystem/ui/PolicyEditor.tsx +109 -24
  36. package/app/filesystem/ui/README.md +30 -23
  37. package/app/filesystem/ui/RawMediaPreview.tsx +58 -0
  38. package/app/filesystem/ui/SourceBranchHeader.tsx +4 -4
  39. package/app/filesystem/ui/SourcesPanel.tsx +502 -342
  40. package/app/filesystem/ui/Toolbar.tsx +1 -2
  41. package/app/filesystem/ui/VectorHealthPanel.tsx +2 -2
  42. package/app/shared/filesystem.png +0 -0
  43. package/dist/app/host.js +58 -46
  44. package/dist/scripts/sourceRootPairV1.d.ts +47 -0
  45. package/dist/scripts/sourceRootPairV1.d.ts.map +1 -0
  46. package/dist/scripts/sourceRootPairV1.js +147 -0
  47. package/dist/scripts/sourceRootPairV1.js.map +1 -0
  48. package/dist/scripts/sourceToFolderV1.d.ts +56 -0
  49. package/dist/scripts/sourceToFolderV1.d.ts.map +1 -0
  50. package/dist/scripts/sourceToFolderV1.js +152 -0
  51. package/dist/scripts/sourceToFolderV1.js.map +1 -0
  52. package/dist/scripts/sourceToHostV1.d.ts +56 -0
  53. package/dist/scripts/sourceToHostV1.d.ts.map +1 -0
  54. package/dist/scripts/sourceToHostV1.js +132 -0
  55. package/dist/scripts/sourceToHostV1.js.map +1 -0
  56. package/dist/src/channels/filesystem.d.ts +1 -1
  57. package/dist/src/channels/filesystem.js +1 -1
  58. package/dist/src/connectors/AppSourceConfigStore.d.ts +17 -3
  59. package/dist/src/connectors/AppSourceConfigStore.d.ts.map +1 -1
  60. package/dist/src/connectors/AppSourceConfigStore.js +46 -6
  61. package/dist/src/connectors/AppSourceConfigStore.js.map +1 -1
  62. package/dist/src/connectors/HostConnector.d.ts +201 -0
  63. package/dist/src/connectors/HostConnector.d.ts.map +1 -0
  64. package/dist/src/connectors/HostConnector.js +903 -0
  65. package/dist/src/connectors/HostConnector.js.map +1 -0
  66. package/dist/src/connectors/inProcessTransport.d.ts +131 -0
  67. package/dist/src/connectors/inProcessTransport.d.ts.map +1 -0
  68. package/dist/src/connectors/inProcessTransport.js +447 -0
  69. package/dist/src/connectors/inProcessTransport.js.map +1 -0
  70. package/dist/src/domain/access/callerPermissions.d.ts +29 -0
  71. package/dist/src/domain/access/callerPermissions.d.ts.map +1 -1
  72. package/dist/src/domain/access/callerPermissions.js +85 -5
  73. package/dist/src/domain/access/callerPermissions.js.map +1 -1
  74. package/dist/src/domain/access/nativeLocalFence.d.ts +65 -0
  75. package/dist/src/domain/access/nativeLocalFence.d.ts.map +1 -0
  76. package/dist/src/domain/access/nativeLocalFence.js +171 -0
  77. package/dist/src/domain/access/nativeLocalFence.js.map +1 -0
  78. package/dist/src/domain/access/uriPermission.js +3 -3
  79. package/dist/src/domain/access/uriPermission.js.map +1 -1
  80. package/dist/src/domain/byteRange.d.ts +15 -0
  81. package/dist/src/domain/byteRange.d.ts.map +1 -0
  82. package/dist/src/domain/byteRange.js +30 -0
  83. package/dist/src/domain/byteRange.js.map +1 -0
  84. package/dist/src/domain/defaultPermissions.d.ts.map +1 -1
  85. package/dist/src/domain/defaultPermissions.js +29 -0
  86. package/dist/src/domain/defaultPermissions.js.map +1 -1
  87. package/dist/src/domain/mime.d.ts +11 -19
  88. package/dist/src/domain/mime.d.ts.map +1 -1
  89. package/dist/src/domain/mime.js +13 -102
  90. package/dist/src/domain/mime.js.map +1 -1
  91. package/dist/src/domain/paths.d.ts.map +1 -1
  92. package/dist/src/domain/paths.js +5 -3
  93. package/dist/src/domain/paths.js.map +1 -1
  94. package/dist/src/domain/scopeAccessCtx.d.ts +2 -2
  95. package/dist/src/domain/scopeAccessCtx.js +2 -2
  96. package/dist/src/domain/sourceConfig.d.ts +52 -19
  97. package/dist/src/domain/sourceConfig.d.ts.map +1 -1
  98. package/dist/src/domain/sourceConfig.js +103 -19
  99. package/dist/src/domain/sourceConfig.js.map +1 -1
  100. package/dist/src/domain/sourcePackages.d.ts +8 -8
  101. package/dist/src/domain/sourcePackages.d.ts.map +1 -1
  102. package/dist/src/domain/sourceRootPair.d.ts +88 -0
  103. package/dist/src/domain/sourceRootPair.d.ts.map +1 -0
  104. package/dist/src/domain/sourceRootPair.js +108 -0
  105. package/dist/src/domain/sourceRootPair.js.map +1 -0
  106. package/dist/src/domain/syncTypes.d.ts +8 -1
  107. package/dist/src/domain/syncTypes.d.ts.map +1 -1
  108. package/dist/src/domain/syncTypes.js +1 -0
  109. package/dist/src/domain/syncTypes.js.map +1 -1
  110. package/dist/src/domain/types.d.ts +32 -2
  111. package/dist/src/domain/types.d.ts.map +1 -1
  112. package/dist/src/domain/uri.d.ts.map +1 -1
  113. package/dist/src/domain/uri.js +3 -2
  114. package/dist/src/domain/uri.js.map +1 -1
  115. package/dist/src/embeddings/clients/GeminiEmbedder.d.ts.map +1 -1
  116. package/dist/src/embeddings/clients/GeminiEmbedder.js +2 -5
  117. package/dist/src/embeddings/clients/GeminiEmbedder.js.map +1 -1
  118. package/dist/src/embeddings/clients/OpenAIEmbedder.d.ts.map +1 -1
  119. package/dist/src/embeddings/clients/OpenAIEmbedder.js +2 -3
  120. package/dist/src/embeddings/clients/OpenAIEmbedder.js.map +1 -1
  121. package/dist/src/embeddings/clients/QwenEmbedder.d.ts +2 -0
  122. package/dist/src/embeddings/clients/QwenEmbedder.d.ts.map +1 -1
  123. package/dist/src/embeddings/clients/QwenEmbedder.js +10 -2
  124. package/dist/src/embeddings/clients/QwenEmbedder.js.map +1 -1
  125. package/dist/src/embeddings/clients/VoyageEmbedder.d.ts +2 -0
  126. package/dist/src/embeddings/clients/VoyageEmbedder.d.ts.map +1 -1
  127. package/dist/src/embeddings/clients/VoyageEmbedder.js +8 -1
  128. package/dist/src/embeddings/clients/VoyageEmbedder.js.map +1 -1
  129. package/dist/src/embeddings/factory.d.ts +5 -3
  130. package/dist/src/embeddings/factory.d.ts.map +1 -1
  131. package/dist/src/embeddings/factory.js +7 -3
  132. package/dist/src/embeddings/factory.js.map +1 -1
  133. package/dist/src/embeddings/models.d.ts +1 -1
  134. package/dist/src/embeddings/models.d.ts.map +1 -1
  135. package/dist/src/embeddings/retry.js +1 -1
  136. package/dist/src/embeddings/retry.js.map +1 -1
  137. package/dist/src/embeddings/types.d.ts +6 -0
  138. package/dist/src/embeddings/types.d.ts.map +1 -1
  139. package/dist/src/embeddings/types.js +11 -0
  140. package/dist/src/embeddings/types.js.map +1 -1
  141. package/dist/src/events/pending.d.ts +1 -1
  142. package/dist/src/events/pending.js +1 -1
  143. package/dist/src/git/GitRunner.d.ts +110 -30
  144. package/dist/src/git/GitRunner.d.ts.map +1 -1
  145. package/dist/src/git/GitRunner.js +511 -199
  146. package/dist/src/git/GitRunner.js.map +1 -1
  147. package/dist/src/git/GitWatchRegistry.d.ts +41 -35
  148. package/dist/src/git/GitWatchRegistry.d.ts.map +1 -1
  149. package/dist/src/git/GitWatchRegistry.js +61 -79
  150. package/dist/src/git/GitWatchRegistry.js.map +1 -1
  151. package/dist/src/git/gitPlace.d.ts +61 -0
  152. package/dist/src/git/gitPlace.d.ts.map +1 -0
  153. package/dist/src/git/gitPlace.js +74 -0
  154. package/dist/src/git/gitPlace.js.map +1 -0
  155. package/dist/src/git/sourceGitControl.d.ts +33 -21
  156. package/dist/src/git/sourceGitControl.d.ts.map +1 -1
  157. package/dist/src/git/sourceGitControl.js +211 -95
  158. package/dist/src/git/sourceGitControl.js.map +1 -1
  159. package/dist/src/git/sourceGitStatus.js +1 -1
  160. package/dist/src/git/sourceGitStatus.js.map +1 -1
  161. package/dist/src/git/untrackedStats.js +1 -1
  162. package/dist/src/git/untrackedStats.js.map +1 -1
  163. package/dist/src/index.d.ts +2 -1
  164. package/dist/src/index.d.ts.map +1 -1
  165. package/dist/src/index.js +2 -1
  166. package/dist/src/index.js.map +1 -1
  167. package/dist/src/lifecycle.d.ts +9 -12
  168. package/dist/src/lifecycle.d.ts.map +1 -1
  169. package/dist/src/lifecycle.js +2 -1
  170. package/dist/src/lifecycle.js.map +1 -1
  171. package/dist/src/routes/approve.d.ts +1 -1
  172. package/dist/src/routes/approve.js +1 -1
  173. package/dist/src/routes/events.d.ts +1 -1
  174. package/dist/src/routes/events.js +1 -1
  175. package/dist/src/routes/git.d.ts +7 -7
  176. package/dist/src/routes/git.d.ts.map +1 -1
  177. package/dist/src/routes/git.js +201 -72
  178. package/dist/src/routes/git.js.map +1 -1
  179. package/dist/src/routes/health.d.ts +6 -6
  180. package/dist/src/routes/health.js +12 -12
  181. package/dist/src/routes/helpers/sourceNotConfigured.d.ts +1 -1
  182. package/dist/src/routes/helpers/sourceNotConfigured.js +1 -1
  183. package/dist/src/routes/helpers/uriGuard.d.ts +1 -1
  184. package/dist/src/routes/helpers/uriGuard.d.ts.map +1 -1
  185. package/dist/src/routes/helpers/uriGuard.js +3 -2
  186. package/dist/src/routes/helpers/uriGuard.js.map +1 -1
  187. package/dist/src/routes/helpers.d.ts +11 -4
  188. package/dist/src/routes/helpers.d.ts.map +1 -1
  189. package/dist/src/routes/helpers.js +13 -6
  190. package/dist/src/routes/helpers.js.map +1 -1
  191. package/dist/src/routes/list.d.ts +1 -1
  192. package/dist/src/routes/list.d.ts.map +1 -1
  193. package/dist/src/routes/list.js +3 -4
  194. package/dist/src/routes/list.js.map +1 -1
  195. package/dist/src/routes/pending.d.ts +4 -4
  196. package/dist/src/routes/pending.js +9 -9
  197. package/dist/src/routes/policies.d.ts +10 -8
  198. package/dist/src/routes/policies.d.ts.map +1 -1
  199. package/dist/src/routes/policies.js +31 -25
  200. package/dist/src/routes/policies.js.map +1 -1
  201. package/dist/src/routes/raw.d.ts +1 -1
  202. package/dist/src/routes/raw.d.ts.map +1 -1
  203. package/dist/src/routes/raw.js +66 -12
  204. package/dist/src/routes/raw.js.map +1 -1
  205. package/dist/src/routes/read.d.ts +1 -1
  206. package/dist/src/routes/read.js +1 -1
  207. package/dist/src/routes/search.d.ts +1 -1
  208. package/dist/src/routes/search.js +1 -1
  209. package/dist/src/routes/sources.d.ts +63 -6
  210. package/dist/src/routes/sources.d.ts.map +1 -1
  211. package/dist/src/routes/sources.js +494 -382
  212. package/dist/src/routes/sources.js.map +1 -1
  213. package/dist/src/routes/upload.d.ts +1 -1
  214. package/dist/src/routes/upload.js +1 -1
  215. package/dist/src/routes/write.d.ts +2 -2
  216. package/dist/src/routes/write.js +2 -2
  217. package/dist/src/services/BridgeService.d.ts +21 -35
  218. package/dist/src/services/BridgeService.d.ts.map +1 -1
  219. package/dist/src/services/BridgeService.js +42 -88
  220. package/dist/src/services/BridgeService.js.map +1 -1
  221. package/dist/src/services/FilesystemService.d.ts +4 -3
  222. package/dist/src/services/FilesystemService.d.ts.map +1 -1
  223. package/dist/src/services/FilesystemService.js +112 -34
  224. package/dist/src/services/FilesystemService.js.map +1 -1
  225. package/dist/src/services/FilesystemUiService.d.ts +4 -1
  226. package/dist/src/services/FilesystemUiService.d.ts.map +1 -1
  227. package/dist/src/services/FilesystemUiService.js +66 -25
  228. package/dist/src/services/FilesystemUiService.js.map +1 -1
  229. package/dist/src/services/SyncScheduler.d.ts +12 -4
  230. package/dist/src/services/SyncScheduler.d.ts.map +1 -1
  231. package/dist/src/services/SyncScheduler.js +37 -8
  232. package/dist/src/services/SyncScheduler.js.map +1 -1
  233. package/dist/src/services/baselineRepair.d.ts +13 -3
  234. package/dist/src/services/baselineRepair.d.ts.map +1 -1
  235. package/dist/src/services/baselineRepair.js +13 -3
  236. package/dist/src/services/baselineRepair.js.map +1 -1
  237. package/dist/src/services/declaredSources.d.ts +132 -43
  238. package/dist/src/services/declaredSources.d.ts.map +1 -1
  239. package/dist/src/services/declaredSources.js +118 -45
  240. package/dist/src/services/declaredSources.js.map +1 -1
  241. package/dist/src/store/dataFormats.d.ts +17 -2
  242. package/dist/src/store/dataFormats.d.ts.map +1 -1
  243. package/dist/src/store/dataFormats.js +18 -3
  244. package/dist/src/store/dataFormats.js.map +1 -1
  245. package/dist/src/sync/DeltaSyncRunner.d.ts.map +1 -1
  246. package/dist/src/sync/DeltaSyncRunner.js +144 -4
  247. package/dist/src/sync/DeltaSyncRunner.js.map +1 -1
  248. package/dist/src/sync/SyncJobQueue.d.ts +7 -2
  249. package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
  250. package/dist/src/sync/SyncJobQueue.js +16 -10
  251. package/dist/src/sync/SyncJobQueue.js.map +1 -1
  252. package/dist/src/sync/SyncWatchService.d.ts +21 -4
  253. package/dist/src/sync/SyncWatchService.d.ts.map +1 -1
  254. package/dist/src/sync/SyncWatchService.js +115 -10
  255. package/dist/src/sync/SyncWatchService.js.map +1 -1
  256. package/dist/src/sync/categoryInference.d.ts +1 -1
  257. package/dist/src/sync/categoryInference.js +1 -1
  258. package/dist/src/tools/execCtx.d.ts +2 -2
  259. package/dist/src/tools/execCtx.js +2 -2
  260. package/dist/src/tools/fs_read.d.ts.map +1 -1
  261. package/dist/src/tools/fs_read.js +5 -0
  262. package/dist/src/tools/fs_read.js.map +1 -1
  263. package/dist/src/usecases/admitSourceRoot.d.ts +65 -0
  264. package/dist/src/usecases/admitSourceRoot.d.ts.map +1 -0
  265. package/dist/src/usecases/admitSourceRoot.js +85 -0
  266. package/dist/src/usecases/admitSourceRoot.js.map +1 -0
  267. package/dist/src/usecases/browseSourceFolders.d.ts +85 -0
  268. package/dist/src/usecases/browseSourceFolders.d.ts.map +1 -0
  269. package/dist/src/usecases/browseSourceFolders.js +210 -0
  270. package/dist/src/usecases/browseSourceFolders.js.map +1 -0
  271. package/dist/src/usecases/createDeclaredSources.d.ts +13 -2
  272. package/dist/src/usecases/createDeclaredSources.d.ts.map +1 -1
  273. package/dist/src/usecases/createDeclaredSources.js +39 -0
  274. package/dist/src/usecases/createDeclaredSources.js.map +1 -1
  275. package/dist/src/usecases/embeddingBacklog.js +1 -1
  276. package/dist/src/usecases/embeddingBacklog.js.map +1 -1
  277. package/dist/src/usecases/list.d.ts.map +1 -1
  278. package/dist/src/usecases/list.js +83 -26
  279. package/dist/src/usecases/list.js.map +1 -1
  280. package/dist/src/usecases/listAttachableDevices.d.ts +13 -0
  281. package/dist/src/usecases/listAttachableDevices.d.ts.map +1 -0
  282. package/dist/src/usecases/listAttachableDevices.js +10 -0
  283. package/dist/src/usecases/listAttachableDevices.js.map +1 -0
  284. package/dist/src/usecases/listSourcePackages.d.ts.map +1 -1
  285. package/dist/src/usecases/listSourcePackages.js +2 -5
  286. package/dist/src/usecases/listSourcePackages.js.map +1 -1
  287. package/dist/src/usecases/purgeExcludedPoints.d.ts.map +1 -1
  288. package/dist/src/usecases/purgeExcludedPoints.js +3 -2
  289. package/dist/src/usecases/purgeExcludedPoints.js.map +1 -1
  290. package/dist/src/usecases/readFiles.d.ts.map +1 -1
  291. package/dist/src/usecases/readFiles.js +99 -1
  292. package/dist/src/usecases/readFiles.js.map +1 -1
  293. package/dist/src/usecases/reconcileSourcePackageRoots.d.ts +1 -1
  294. package/dist/src/usecases/reconcileSourcePackageRoots.d.ts.map +1 -1
  295. package/dist/src/usecases/reconcileSourcePackageRoots.js +2 -1
  296. package/dist/src/usecases/reconcileSourcePackageRoots.js.map +1 -1
  297. package/dist/src/usecases/revokePrincipal.d.ts +7 -5
  298. package/dist/src/usecases/revokePrincipal.d.ts.map +1 -1
  299. package/dist/src/usecases/revokePrincipal.js +29 -7
  300. package/dist/src/usecases/revokePrincipal.js.map +1 -1
  301. package/dist/src/usecases/scheduleSourceSync.d.ts +7 -0
  302. package/dist/src/usecases/scheduleSourceSync.d.ts.map +1 -1
  303. package/dist/src/usecases/scheduleSourceSync.js +6 -5
  304. package/dist/src/usecases/scheduleSourceSync.js.map +1 -1
  305. package/dist/src/usecases/syncPointWrites.d.ts +2 -0
  306. package/dist/src/usecases/syncPointWrites.d.ts.map +1 -1
  307. package/dist/src/usecases/syncPointWrites.js +5 -1
  308. package/dist/src/usecases/syncPointWrites.js.map +1 -1
  309. package/dist/src/usecases/triggerSourceSync.d.ts +46 -0
  310. package/dist/src/usecases/triggerSourceSync.d.ts.map +1 -0
  311. package/dist/src/usecases/triggerSourceSync.js +75 -0
  312. package/dist/src/usecases/triggerSourceSync.js.map +1 -0
  313. package/dist/src/usecases/uploadBinary.d.ts +2 -1
  314. package/dist/src/usecases/uploadBinary.d.ts.map +1 -1
  315. package/dist/src/usecases/uploadBinary.js +2 -2
  316. package/dist/src/usecases/uploadBinary.js.map +1 -1
  317. package/dist/src/usecases/vector/endpointGuard.d.ts +1 -1
  318. package/dist/src/usecases/vector/endpointGuard.js +1 -1
  319. package/dist/src/usecases/vectorMaintenance.js +1 -1
  320. package/dist/src/usecases/vectorMaintenance.js.map +1 -1
  321. package/dist/src/usecases/write/content.js +1 -1
  322. package/dist/src/vector/qdrantClient.d.ts +1 -1
  323. package/dist/src/vector/qdrantClient.js +1 -1
  324. package/dist/src/wiring.d.ts +3 -0
  325. package/dist/src/wiring.d.ts.map +1 -1
  326. package/dist/src/wiring.js +72 -6
  327. package/dist/src/wiring.js.map +1 -1
  328. package/dist/tools/fs_list.json +1 -1
  329. package/dist/tools/fs_read.json +1 -1
  330. package/dist/tools/fs_search.json +1 -1
  331. package/dist/tools/fs_write.json +1 -1
  332. package/instructions/brain-model.md +1 -1
  333. package/package.json +212 -114
  334. package/rules/brain-rules.md +2 -2
  335. package/skills/brain-start/SKILL.md +1 -1
  336. package/skills/connect-business-data/SKILL.md +3 -3
  337. package/skills/create-package/SKILL.md +26 -26
  338. package/skills/create-package/references/config-and-credentials.md +16 -13
  339. package/skills/create-package/references/connectors-and-uri-policies.md +39 -25
  340. package/skills/create-package/references/manifest-and-discovery.md +12 -12
  341. package/skills/create-package/references/runtime-and-build.md +19 -19
  342. package/skills/create-package/references/skills-and-context.md +36 -20
  343. package/skills/create-package/references/surfaces-and-design.md +16 -16
  344. package/skills/create-package/references/team-and-workflows.md +2 -2
  345. package/skills/create-package/references/test-and-ship.md +21 -21
  346. package/skills/create-package/references/tools-and-schemas.md +5 -5
  347. package/skills/create-package/scripts/{check-package.sh → check-package.mjs} +79 -65
  348. package/skills/create-package/scripts/{verify-loaded.sh → verify-loaded.mjs} +156 -162
  349. package/skills/git/SKILL.md +53 -51
  350. package/skills/manage-files/SKILL.md +22 -25
  351. package/skills/manage-sources/SKILL.md +128 -87
  352. package/skills/manage-uri-policy/SKILL.md +18 -15
  353. package/skills/organize/SKILL.md +1 -1
  354. package/skills/sync/SKILL.md +3 -3
  355. package/tools/fs_list.json +1 -1
  356. package/tools/fs_read.json +1 -1
  357. package/tools/fs_search.json +1 -1
  358. package/tools/fs_write.json +1 -1
  359. package/workflows/sources-digest.json +1 -1
  360. package/dist/src/connectors/LocalDiskConnector.d.ts +0 -171
  361. package/dist/src/connectors/LocalDiskConnector.d.ts.map +0 -1
  362. package/dist/src/connectors/LocalDiskConnector.js +0 -1233
  363. package/dist/src/connectors/LocalDiskConnector.js.map +0 -1
  364. package/docs/drive-overview.md +0 -59
  365. package/skills/manage-files/scripts/copy.sh +0 -7
  366. package/skills/manage-files/scripts/create.sh +0 -7
  367. package/skills/manage-files/scripts/mkdir.sh +0 -7
  368. package/skills/manage-files/scripts/modify.sh +0 -7
  369. package/skills/manage-files/scripts/upload.sh +0 -16
  370. package/skills/manage-files/scripts/write.sh +0 -29
  371. package/skills/manage-sources/scripts/reembed.sh +0 -23
@@ -0,0 +1,251 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { CheckCircle2, ChevronUp, Folder, FolderOpen, Loader2, Send } from 'lucide-react';
5
+ import type { PackageApi } from '@neuralis/package-system/client';
6
+ import { browseDirectories, type BrowseFoldersResult } from '../api';
7
+ import { useFilesystemHost } from '../FilesystemHost';
8
+
9
+ /** A folder the picker offers without a request — the discoverable mount roots on this server. */
10
+ export type FolderSuggestion = { name: string; path: string };
11
+
12
+ type Props = {
13
+ agentId: string;
14
+ projectId: string | null;
15
+ client: PackageApi;
16
+ /** The paired device the folder lives on (`dev_…`), or `null` for this server. */
17
+ device: string | null;
18
+ /** This server runs in a container: the browsable zone is `/mounts` (an empty path opens it). */
19
+ isDocker: boolean;
20
+ /** The folder the picker opens at (the typed path); empty = the plane's start. */
21
+ startPath: string;
22
+ /** This server only: discoverable folders shown first, picked with no listing. */
23
+ suggestions: readonly FolderSuggestion[];
24
+ /** The access the form asks for — an "ask on that device" requests the write list when set. */
25
+ wantWrite: boolean;
26
+ onSelect(path: string): void;
27
+ onClose(): void;
28
+ };
29
+
30
+ /** The parent of a server or device path, in that path's own separators (`C:\x` → `C:\`). */
31
+ function parentOf(path: string): string {
32
+ const up = path.replace(/[/\\][^/\\]+[/\\]?$/, '');
33
+ if (/^[A-Za-z]:$/.test(up)) return `${up}\\`;
34
+ return up || '/';
35
+ }
36
+
37
+ /** What a device's fixed state code tells a person — never a path. */
38
+ function deviceStateLine(state: string): string {
39
+ switch (state) {
40
+ case 'ceiling_denied': return 'This folder is not allowed on that device yet.';
41
+ case 'device_offline': return 'The device is offline. Type the folder — it attaches now and serves when the device is back.';
42
+ case 'broker_outdated': return 'That device runs an older Neuralis CLI. Update it there (neuralis device install) to browse; a typed folder still attaches.';
43
+ case 'devices_disabled': return 'Paired devices are switched off on this server.';
44
+ case 'not_found': return 'That folder does not exist on the device.';
45
+ case 'not_a_directory': return 'That path is not a folder.';
46
+ case 'os_denied': return 'The device cannot read that folder.';
47
+ default: return 'The device did not answer. Type the folder, or try again.';
48
+ }
49
+ }
50
+
51
+ /** The line a device folder outside its allowed ones reads — the picker's state and the Create guard say it the same way. */
52
+ export const DEVICE_FOLDER_NOT_ALLOWED = deviceStateLine('ceiling_denied');
53
+
54
+ /**
55
+ * Ask on the caller's OWN device for a folder it does not allow yet: the ask
56
+ * button, the answer, the pending count and the grant command to run there.
57
+ * ONE owner for the picker's `ceiling_denied` state and the Create guard. Key
58
+ * it by `path` so a new folder starts a new ask. Cost: one ask + one count per
59
+ * click, nothing on render.
60
+ */
61
+ export function DeviceFolderAsk({ device, projectId, agentId, path, wantWrite }: {
62
+ device: string; projectId: string | null; agentId: string; path: string; wantWrite: boolean;
63
+ }) {
64
+ const host = useFilesystemHost();
65
+ const [ask, setAsk] = useState<{ busy: boolean; line: string | null; pending: number | null }>({ busy: false, line: null, pending: null });
66
+ const askOnDevice = async () => {
67
+ if (!projectId || !host.requestDeviceFolder) return;
68
+ setAsk((a) => ({ ...a, busy: true }));
69
+ try {
70
+ const answer = await host.requestDeviceFolder({ deviceId: device, path, list: wantWrite ? 'write' : 'read', projectId, agentId });
71
+ const pending = host.countDeviceFolderRequests ? await host.countDeviceFolderRequests({ deviceId: device, projectId, agentId }) : null;
72
+ setAsk({
73
+ busy: false,
74
+ pending,
75
+ line: answer.recorded
76
+ ? 'Asked. On that device: tray → Allow a folder…, or run the command below.'
77
+ : answer.reason === 'inside_ceiling'
78
+ ? 'That folder is already allowed — open it again.'
79
+ : 'The device did not record the ask. Run the command below on it.',
80
+ });
81
+ } catch (err) {
82
+ setAsk({ busy: false, pending: null, line: err instanceof Error && err.message ? err.message : 'The ask could not be sent.' });
83
+ }
84
+ };
85
+ return (
86
+ <>
87
+ {host.requestDeviceFolder && projectId && (
88
+ <button type="button" disabled={ask.busy} onClick={() => void askOnDevice()}
89
+ className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[8px] font-semibold text-cyan-300/80 bg-cyan-500/10 hover:bg-cyan-500/20 border border-cyan-400/20 transition disabled:opacity-40">
90
+ {ask.busy ? <Loader2 className="h-2.5 w-2.5 animate-spin" /> : <Send className="h-2.5 w-2.5" />}
91
+ Ask on that device
92
+ </button>
93
+ )}
94
+ {ask.line && <div className="text-[9px] text-white/55">{ask.line}</div>}
95
+ {ask.pending !== null && <div className="text-[9px] text-white/40">{ask.pending} pending on that device for this project</div>}
96
+ <code className="block text-[9px] text-white/45 font-mono break-all">neuralis device grant {path}{wantWrite ? ' --write' : ''}</code>
97
+ </>
98
+ );
99
+ }
100
+
101
+ /**
102
+ * The Add-Source folder picker: one level at a time, folders only, "Select
103
+ * this folder". On this server it reads `sources/browse` (the gates are the
104
+ * route's: you browse what you could attach; in Docker the `/mounts` zone and
105
+ * below) and shows the discoverable suggestions first. On the caller's OWN
106
+ * device it starts at the typed folder, or else from the folders that device
107
+ * allows this host, lists through the device's broker, and for a folder
108
+ * outside them offers to ASK on that device — the grant stays the owner's act on the machine (the tray's
109
+ * "Allow a folder…", `neuralis device grant`). UX only: the create re-checks
110
+ * every gate. Cost: one request per opened level, one ask per click; nothing
111
+ * on open of the form, no timer, no listener.
112
+ */
113
+ export function FolderPicker({ agentId, projectId, client, device, isDocker, startPath, suggestions, wantWrite, onSelect, onClose }: Props) {
114
+ const [listing, setListing] = useState<BrowseFoldersResult | null>(null);
115
+ const [path, setPath] = useState('');
116
+ const [loading, setLoading] = useState(false);
117
+ const [error, setError] = useState<string | null>(null);
118
+ // The device's allowed folders: "up" from one of them returns to that list.
119
+ const rootsRef = useRef<Set<string>>(new Set());
120
+ // Liveness: a reply that lands after the picker closed (or a newer open) is dropped.
121
+ const seqRef = useRef(0);
122
+ // Where the picker first opens — read once per open, never a reason to re-list as the field changes.
123
+ const startRef = useRef(startPath);
124
+ startRef.current = startPath;
125
+
126
+ const open = useCallback(async (target: string) => {
127
+ const seq = ++seqRef.current;
128
+ // Natively an empty path is the suggestions alone: there is no "start" folder to list.
129
+ if (!device && !isDocker && target === '') {
130
+ setListing(null);
131
+ setPath('');
132
+ setError(null);
133
+ setLoading(false);
134
+ return;
135
+ }
136
+ setLoading(true);
137
+ setError(null);
138
+ try {
139
+ const result = await browseDirectories({ path: target, agentId, ...(projectId ? { projectId } : {}), ...(device ? { device } : {}) }, client);
140
+ if (seq !== seqRef.current) return;
141
+ if (result.roots) rootsRef.current = new Set(result.entries.map((e) => e.path));
142
+ setListing(result);
143
+ setPath(target);
144
+ } catch (err) {
145
+ if (seq !== seqRef.current) return;
146
+ // One stable sentence per plane — the server never returns a path or an errno.
147
+ setError(device && err instanceof Error && err.message ? err.message : 'That path is not available.');
148
+ setListing(null);
149
+ setPath(target);
150
+ } finally {
151
+ if (seq === seqRef.current) setLoading(false);
152
+ }
153
+ }, [agentId, projectId, client, device, isDocker]);
154
+
155
+ const hasSuggestions = suggestions.length > 0;
156
+ useEffect(() => {
157
+ // A typed folder opens where it is — on a device too, where a folder outside
158
+ // the allowed ones answers `ceiling_denied` (existence-independent) and offers the ask.
159
+ void open(startRef.current || (device || hasSuggestions || isDocker ? '' : '/'));
160
+ return () => { seqRef.current += 1; };
161
+ }, [open, device, isDocker, hasSuggestions]);
162
+
163
+ const state = listing?.state ?? 'ok';
164
+ const inRoots = Boolean(device && listing?.roots);
165
+ // On this server the suggestions are the start (in Docker above the zone's own listing).
166
+ const listed = new Set(listing?.entries.map((e) => e.path) ?? []);
167
+ const shownSuggestions = !device && path === '' ? suggestions.filter((s) => !listed.has(s.path)) : [];
168
+ const canSelectHere = Boolean(path) && !inRoots && state === 'ok' && !error;
169
+ const canGoUp = Boolean(path) && !loading && (device ? true : listing ? listing.atRoot !== true : path !== '/');
170
+
171
+ const goUp = () => {
172
+ if (device && (rootsRef.current.has(path) || listing?.atRoot || parentOf(path) === path)) { void open(''); return; }
173
+ void open(parentOf(path));
174
+ };
175
+
176
+ return (
177
+ <div className="rounded-md bg-white/[0.03] border border-white/[0.1] overflow-hidden">
178
+ <div className="flex items-center gap-1.5 px-2 py-1.5 bg-white/[0.02] border-b border-white/[0.06]">
179
+ <FolderOpen className="h-3 w-3 text-cyan-400 shrink-0" />
180
+ <span className="text-[9px] font-mono text-white/60 truncate flex-1">
181
+ {inRoots ? 'Folders this device allows' : path || 'Suggested'}
182
+ </span>
183
+ <button type="button" onClick={onClose} className="text-[9px] text-white/40 hover:text-white/70 px-1">Close</button>
184
+ </div>
185
+ {error && <div className="px-2 py-1 text-[9px] text-red-300/80">{error}</div>}
186
+ {loading ? (
187
+ <div className="flex items-center justify-center py-3">
188
+ <Loader2 className="h-3 w-3 animate-spin text-white/30" />
189
+ </div>
190
+ ) : (
191
+ <div className="max-h-[180px] overflow-y-auto">
192
+ {shownSuggestions.map((s) => (
193
+ <div key={`s:${s.path}`} className="flex items-center gap-0.5 hover:bg-white/[0.04] transition">
194
+ <button type="button" onClick={() => void open(s.path)} className="flex items-center gap-1.5 px-2 py-1 flex-1 text-left min-w-0">
195
+ <Folder className="h-3 w-3 text-emerald-300/70 shrink-0" />
196
+ <span className="text-[10px] text-white/75 truncate">{s.name}</span>
197
+ <span className="text-[8px] text-white/30 font-mono truncate">{s.path}</span>
198
+ </button>
199
+ <button type="button" onClick={() => onSelect(s.path)} className="px-2 py-1 text-[8px] font-medium text-cyan-300/70 hover:text-cyan-200 shrink-0">Select</button>
200
+ </div>
201
+ ))}
202
+ {canGoUp && (
203
+ <button type="button" onClick={goUp} className="w-full flex items-center gap-1.5 px-2 py-1 text-left hover:bg-white/[0.04] transition">
204
+ <ChevronUp className="h-3 w-3 text-white/30" />
205
+ <span className="text-[10px] text-white/50">..</span>
206
+ </button>
207
+ )}
208
+ {device && state !== 'ok' && (
209
+ <div className="px-2 py-1.5 space-y-1">
210
+ <div className="text-[9px] text-amber-300/80">{deviceStateLine(state)}</div>
211
+ {state === 'ceiling_denied' && path && (
212
+ <DeviceFolderAsk key={path} device={device} projectId={projectId} agentId={agentId} path={path} wantWrite={wantWrite} />
213
+ )}
214
+ </div>
215
+ )}
216
+ {state === 'ok' && !error && listing && listing.entries.length === 0 && (
217
+ <div className="px-2 py-2 text-[9px] text-white/30 italic">
218
+ {inRoots ? 'This device allows no folder to this server yet — type one and ask, or run neuralis device grant <dir> there.' : 'No subfolders'}
219
+ </div>
220
+ )}
221
+ {state === 'ok' && listing?.entries.map((entry) => (
222
+ <div key={entry.path} className="flex items-center gap-0.5 hover:bg-white/[0.04] transition">
223
+ <button type="button" onClick={() => void open(entry.path)} className="flex items-center gap-1.5 px-2 py-1 flex-1 text-left min-w-0">
224
+ <Folder className="h-3 w-3 text-cyan-400/70 shrink-0" />
225
+ <span className="text-[10px] text-white/75 truncate">{entry.name}</span>
226
+ {entry.access && <span className="text-[8px] text-white/30 shrink-0">{entry.access === 'write' ? 'read · write' : 'read'}</span>}
227
+ </button>
228
+ <button type="button" onClick={() => onSelect(entry.path)} className="px-2 py-1 text-[8px] font-medium text-cyan-300/70 hover:text-cyan-200 shrink-0">Select</button>
229
+ </div>
230
+ ))}
231
+ {state === 'ok' && (listing?.symlinks ?? 0) > 0 && (
232
+ <div className="px-2 py-1 text-[8px] text-white/30 italic">
233
+ {listing!.symlinks} linked {listing!.symlinks === 1 ? 'folder is' : 'folders are'} not shown — links are not followed; type the path to attach one.
234
+ </div>
235
+ )}
236
+ {state === 'ok' && listing?.truncated && (
237
+ <div className="px-2 py-1 text-[8px] text-white/30 italic">Only the first entries are listed — type the path for one further down.</div>
238
+ )}
239
+ {canSelectHere && (
240
+ <button type="button" onClick={() => onSelect(path)}
241
+ className="w-full flex items-center gap-1.5 px-2 py-1.5 text-left bg-cyan-500/5 hover:bg-cyan-500/10 border-t border-white/[0.06] transition">
242
+ <CheckCircle2 className="h-3 w-3 text-cyan-400 shrink-0" />
243
+ <span className="text-[10px] font-medium text-cyan-300/80">Select this folder</span>
244
+ <span className="text-[9px] text-white/30 font-mono truncate ml-auto">{path}</span>
245
+ </button>
246
+ )}
247
+ </div>
248
+ )}
249
+ </div>
250
+ );
251
+ }
@@ -84,7 +84,7 @@ import {
84
84
  * Stage / Unstage / Discard, a commit box (message + optional amend), and a
85
85
  * branch-switcher quick-pick (checkout / create / delete). Each write is the
86
86
  * HUMAN face of the git engine — the click IS the consent (server gates
87
- * `drive.write` + uri-policy `write` + audits); a DESTRUCTIVE op (discard,
87
+ * `files.write` + uri-policy `write` + audits); a DESTRUCTIVE op (discard,
88
88
  * branch delete) is behind a CONFIRM dialog AND the server unconditionally
89
89
  * auto-snapshots (Q6) — the returned rescue ref powers a best-effort recovery
90
90
  * notice. On success the N3 badge SSE refreshes the panel; we ALSO
@@ -592,7 +592,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
592
592
  );
593
593
  // Show the write affordances (Stage/Unstage/Discard/Commit/branch-write) IFF the
594
594
  // caller can actually write — `git.canWrite` is computed SERVER-side per-caller as
595
- // the SAME two-plane gate the write routes enforce (the `drive.write` FEATURE ∧ the
595
+ // the SAME two-plane gate the write routes enforce (the `files.write` FEATURE ∧ the
596
596
  // caller's RESOLVED uri-policy `write` on the source root). This is authoritative:
597
597
  // it must NOT read `SourceInfo.permissions.write` (the source's DEFAULT block), which
598
598
  // hid the owner's write UI on a `default write:false` source where the owner gains
@@ -682,6 +682,11 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
682
682
  // shape symmetric with `source`).
683
683
  useEffect(() => {
684
684
  if (!selectedSlug) return;
685
+ // A folder that only CONTAINS checkouts has no change-set at its root: the
686
+ // effect above picks its first repo, and that pick loads the status. Asking
687
+ // the root would answer "unavailable" for a moment on every switch.
688
+ const git = selectedSource?.git;
689
+ if (!activeRepoRel && git && !git.isRepo && git.containsRepos) return;
685
690
  void loadGitStatus({ agentId, projectId: projectId ?? null, source: selectedSlug, repo: activeRepoRel });
686
691
  // eslint-disable-next-line react-hooks/exhaustive-deps
687
692
  }, [agentId, projectId, selectedSlug, activeRepoRel, repoKey]);