@neuralis/brain-core 0.3.2 → 0.4.1

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 (388) hide show
  1. package/README.md +80 -1410
  2. package/app/README.md +1 -1
  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 +17 -2
  8. package/app/filesystem/api/README.md +3 -3
  9. package/app/filesystem/api/index.ts +35 -11
  10. package/app/filesystem/api/projectPackages.ts +13 -102
  11. package/app/filesystem/domain/types.ts +30 -10
  12. package/app/filesystem/hooks/README.md +3 -3
  13. package/app/filesystem/hooks/useDiscoverableSources.ts +19 -30
  14. package/app/filesystem/hooks/useFilesystemSSE.ts +1 -1
  15. package/app/filesystem/host/README.md +5 -3
  16. package/app/filesystem/host/buildFilesystemHostValue.ts +19 -0
  17. package/app/filesystem/host/installFilesystemHostComponents.tsx +1 -1
  18. package/app/filesystem/lib/sourceKindForm.ts +118 -39
  19. package/app/filesystem/lib/treeVisualState.tsx +98 -4
  20. package/app/filesystem/store/README.md +1 -0
  21. package/app/filesystem/store/filesystemStore.ts +86 -5
  22. package/app/filesystem/store/gitSlice.ts +5 -0
  23. package/app/filesystem/store/helpers.ts +17 -0
  24. package/app/filesystem/store/listSlice.ts +8 -0
  25. package/app/filesystem/ui/CodeEditor.tsx +18 -3
  26. package/app/filesystem/ui/FileEditor.tsx +15 -10
  27. package/app/filesystem/ui/FileTree.tsx +41 -16
  28. package/app/filesystem/ui/FolderPicker.tsx +251 -0
  29. package/app/filesystem/ui/GitControlPanel.tsx +5 -0
  30. package/app/filesystem/ui/PackagesPanel.tsx +52 -374
  31. package/app/filesystem/ui/PolicyEditor.tsx +109 -24
  32. package/app/filesystem/ui/README.md +17 -11
  33. package/app/filesystem/ui/RawMediaPreview.tsx +58 -0
  34. package/app/filesystem/ui/SourceBranchHeader.tsx +4 -4
  35. package/app/filesystem/ui/SourcesPanel.tsx +420 -360
  36. package/app/filesystem/ui/Toolbar.tsx +1 -2
  37. package/app/shared/filesystem.png +0 -0
  38. package/dist/app/host.js +53 -48
  39. package/dist/scripts/sourceRootPairV1.d.ts +47 -0
  40. package/dist/scripts/sourceRootPairV1.d.ts.map +1 -0
  41. package/dist/scripts/sourceRootPairV1.js +147 -0
  42. package/dist/scripts/sourceRootPairV1.js.map +1 -0
  43. package/dist/scripts/sourceToFolderV1.d.ts +56 -0
  44. package/dist/scripts/sourceToFolderV1.d.ts.map +1 -0
  45. package/dist/scripts/sourceToFolderV1.js +152 -0
  46. package/dist/scripts/sourceToFolderV1.js.map +1 -0
  47. package/dist/scripts/sourceToHostV1.d.ts +56 -0
  48. package/dist/scripts/sourceToHostV1.d.ts.map +1 -0
  49. package/dist/scripts/sourceToHostV1.js +132 -0
  50. package/dist/scripts/sourceToHostV1.js.map +1 -0
  51. package/dist/src/config/env.d.ts +8 -0
  52. package/dist/src/config/env.d.ts.map +1 -1
  53. package/dist/src/config/env.js +17 -6
  54. package/dist/src/config/env.js.map +1 -1
  55. package/dist/src/connectors/AppSourceConfigStore.d.ts +17 -3
  56. package/dist/src/connectors/AppSourceConfigStore.d.ts.map +1 -1
  57. package/dist/src/connectors/AppSourceConfigStore.js +46 -6
  58. package/dist/src/connectors/AppSourceConfigStore.js.map +1 -1
  59. package/dist/src/connectors/HostConnector.d.ts +201 -0
  60. package/dist/src/connectors/HostConnector.d.ts.map +1 -0
  61. package/dist/src/connectors/HostConnector.js +903 -0
  62. package/dist/src/connectors/HostConnector.js.map +1 -0
  63. package/dist/src/connectors/inProcessTransport.d.ts +131 -0
  64. package/dist/src/connectors/inProcessTransport.d.ts.map +1 -0
  65. package/dist/src/connectors/inProcessTransport.js +447 -0
  66. package/dist/src/connectors/inProcessTransport.js.map +1 -0
  67. package/dist/src/domain/BrainError.d.ts +14 -0
  68. package/dist/src/domain/BrainError.d.ts.map +1 -1
  69. package/dist/src/domain/BrainError.js +21 -0
  70. package/dist/src/domain/BrainError.js.map +1 -1
  71. package/dist/src/domain/access/callerPermissions.d.ts +29 -0
  72. package/dist/src/domain/access/callerPermissions.d.ts.map +1 -1
  73. package/dist/src/domain/access/callerPermissions.js +85 -5
  74. package/dist/src/domain/access/callerPermissions.js.map +1 -1
  75. package/dist/src/domain/access/nativeLocalFence.d.ts +65 -0
  76. package/dist/src/domain/access/nativeLocalFence.d.ts.map +1 -0
  77. package/dist/src/domain/access/nativeLocalFence.js +171 -0
  78. package/dist/src/domain/access/nativeLocalFence.js.map +1 -0
  79. package/dist/src/domain/access/uriPermission.js +3 -3
  80. package/dist/src/domain/access/uriPermission.js.map +1 -1
  81. package/dist/src/domain/byteRange.d.ts +15 -0
  82. package/dist/src/domain/byteRange.d.ts.map +1 -0
  83. package/dist/src/domain/byteRange.js +30 -0
  84. package/dist/src/domain/byteRange.js.map +1 -0
  85. package/dist/src/domain/defaultPermissions.d.ts.map +1 -1
  86. package/dist/src/domain/defaultPermissions.js +29 -0
  87. package/dist/src/domain/defaultPermissions.js.map +1 -1
  88. package/dist/src/domain/mime.d.ts +8 -16
  89. package/dist/src/domain/mime.d.ts.map +1 -1
  90. package/dist/src/domain/mime.js +10 -99
  91. package/dist/src/domain/mime.js.map +1 -1
  92. package/dist/src/domain/paths.d.ts.map +1 -1
  93. package/dist/src/domain/paths.js +5 -3
  94. package/dist/src/domain/paths.js.map +1 -1
  95. package/dist/src/domain/sourceConfig.d.ts +52 -19
  96. package/dist/src/domain/sourceConfig.d.ts.map +1 -1
  97. package/dist/src/domain/sourceConfig.js +103 -19
  98. package/dist/src/domain/sourceConfig.js.map +1 -1
  99. package/dist/src/domain/sourcePackages.d.ts +8 -8
  100. package/dist/src/domain/sourcePackages.d.ts.map +1 -1
  101. package/dist/src/domain/sourceRootPair.d.ts +88 -0
  102. package/dist/src/domain/sourceRootPair.d.ts.map +1 -0
  103. package/dist/src/domain/sourceRootPair.js +108 -0
  104. package/dist/src/domain/sourceRootPair.js.map +1 -0
  105. package/dist/src/domain/syncTypes.d.ts +8 -1
  106. package/dist/src/domain/syncTypes.d.ts.map +1 -1
  107. package/dist/src/domain/syncTypes.js +1 -0
  108. package/dist/src/domain/syncTypes.js.map +1 -1
  109. package/dist/src/domain/types.d.ts +29 -1
  110. package/dist/src/domain/types.d.ts.map +1 -1
  111. package/dist/src/domain/uri.d.ts.map +1 -1
  112. package/dist/src/domain/uri.js +3 -2
  113. package/dist/src/domain/uri.js.map +1 -1
  114. package/dist/src/embeddings/clients/GeminiEmbedder.d.ts.map +1 -1
  115. package/dist/src/embeddings/clients/GeminiEmbedder.js +2 -5
  116. package/dist/src/embeddings/clients/GeminiEmbedder.js.map +1 -1
  117. package/dist/src/embeddings/clients/OpenAIEmbedder.d.ts.map +1 -1
  118. package/dist/src/embeddings/clients/OpenAIEmbedder.js +2 -3
  119. package/dist/src/embeddings/clients/OpenAIEmbedder.js.map +1 -1
  120. package/dist/src/embeddings/clients/QwenEmbedder.d.ts +2 -0
  121. package/dist/src/embeddings/clients/QwenEmbedder.d.ts.map +1 -1
  122. package/dist/src/embeddings/clients/QwenEmbedder.js +10 -2
  123. package/dist/src/embeddings/clients/QwenEmbedder.js.map +1 -1
  124. package/dist/src/embeddings/clients/VoyageEmbedder.d.ts +2 -0
  125. package/dist/src/embeddings/clients/VoyageEmbedder.d.ts.map +1 -1
  126. package/dist/src/embeddings/clients/VoyageEmbedder.js +8 -1
  127. package/dist/src/embeddings/clients/VoyageEmbedder.js.map +1 -1
  128. package/dist/src/embeddings/factory.d.ts +5 -3
  129. package/dist/src/embeddings/factory.d.ts.map +1 -1
  130. package/dist/src/embeddings/factory.js +7 -3
  131. package/dist/src/embeddings/factory.js.map +1 -1
  132. package/dist/src/embeddings/models.d.ts +2 -3
  133. package/dist/src/embeddings/models.d.ts.map +1 -1
  134. package/dist/src/embeddings/models.js +1 -2
  135. package/dist/src/embeddings/models.js.map +1 -1
  136. package/dist/src/embeddings/retry.js +1 -1
  137. package/dist/src/embeddings/retry.js.map +1 -1
  138. package/dist/src/embeddings/types.d.ts +6 -0
  139. package/dist/src/embeddings/types.d.ts.map +1 -1
  140. package/dist/src/embeddings/types.js +11 -0
  141. package/dist/src/embeddings/types.js.map +1 -1
  142. package/dist/src/git/GitRunner.d.ts +110 -30
  143. package/dist/src/git/GitRunner.d.ts.map +1 -1
  144. package/dist/src/git/GitRunner.js +511 -199
  145. package/dist/src/git/GitRunner.js.map +1 -1
  146. package/dist/src/git/GitWatchRegistry.d.ts +41 -35
  147. package/dist/src/git/GitWatchRegistry.d.ts.map +1 -1
  148. package/dist/src/git/GitWatchRegistry.js +61 -79
  149. package/dist/src/git/GitWatchRegistry.js.map +1 -1
  150. package/dist/src/git/gitPlace.d.ts +61 -0
  151. package/dist/src/git/gitPlace.d.ts.map +1 -0
  152. package/dist/src/git/gitPlace.js +74 -0
  153. package/dist/src/git/gitPlace.js.map +1 -0
  154. package/dist/src/git/sourceGitControl.d.ts +31 -19
  155. package/dist/src/git/sourceGitControl.d.ts.map +1 -1
  156. package/dist/src/git/sourceGitControl.js +208 -92
  157. package/dist/src/git/sourceGitControl.js.map +1 -1
  158. package/dist/src/git/sourceGitStatus.js +1 -1
  159. package/dist/src/git/sourceGitStatus.js.map +1 -1
  160. package/dist/src/git/untrackedStats.js +1 -1
  161. package/dist/src/git/untrackedStats.js.map +1 -1
  162. package/dist/src/index.d.ts +2 -1
  163. package/dist/src/index.d.ts.map +1 -1
  164. package/dist/src/index.js +2 -1
  165. package/dist/src/index.js.map +1 -1
  166. package/dist/src/lifecycle.d.ts +12 -16
  167. package/dist/src/lifecycle.d.ts.map +1 -1
  168. package/dist/src/lifecycle.js +2 -1
  169. package/dist/src/lifecycle.js.map +1 -1
  170. package/dist/src/routes/approve.d.ts.map +1 -1
  171. package/dist/src/routes/approve.js +3 -3
  172. package/dist/src/routes/approve.js.map +1 -1
  173. package/dist/src/routes/git.d.ts.map +1 -1
  174. package/dist/src/routes/git.js +183 -54
  175. package/dist/src/routes/git.js.map +1 -1
  176. package/dist/src/routes/health.d.ts.map +1 -1
  177. package/dist/src/routes/health.js +8 -5
  178. package/dist/src/routes/health.js.map +1 -1
  179. package/dist/src/routes/helpers/uriGuard.d.ts +1 -1
  180. package/dist/src/routes/helpers/uriGuard.d.ts.map +1 -1
  181. package/dist/src/routes/helpers/uriGuard.js +3 -2
  182. package/dist/src/routes/helpers/uriGuard.js.map +1 -1
  183. package/dist/src/routes/helpers.d.ts +20 -4
  184. package/dist/src/routes/helpers.d.ts.map +1 -1
  185. package/dist/src/routes/helpers.js +38 -5
  186. package/dist/src/routes/helpers.js.map +1 -1
  187. package/dist/src/routes/list.d.ts.map +1 -1
  188. package/dist/src/routes/list.js +5 -6
  189. package/dist/src/routes/list.js.map +1 -1
  190. package/dist/src/routes/pending.d.ts.map +1 -1
  191. package/dist/src/routes/pending.js +5 -5
  192. package/dist/src/routes/pending.js.map +1 -1
  193. package/dist/src/routes/policies.d.ts +6 -4
  194. package/dist/src/routes/policies.d.ts.map +1 -1
  195. package/dist/src/routes/policies.js +22 -16
  196. package/dist/src/routes/policies.js.map +1 -1
  197. package/dist/src/routes/raw.d.ts.map +1 -1
  198. package/dist/src/routes/raw.js +68 -14
  199. package/dist/src/routes/raw.js.map +1 -1
  200. package/dist/src/routes/read.d.ts.map +1 -1
  201. package/dist/src/routes/read.js +3 -3
  202. package/dist/src/routes/read.js.map +1 -1
  203. package/dist/src/routes/search.d.ts.map +1 -1
  204. package/dist/src/routes/search.js +3 -3
  205. package/dist/src/routes/search.js.map +1 -1
  206. package/dist/src/routes/sources.d.ts +60 -18
  207. package/dist/src/routes/sources.d.ts.map +1 -1
  208. package/dist/src/routes/sources.js +420 -308
  209. package/dist/src/routes/sources.js.map +1 -1
  210. package/dist/src/routes/upload.d.ts.map +1 -1
  211. package/dist/src/routes/upload.js +3 -3
  212. package/dist/src/routes/upload.js.map +1 -1
  213. package/dist/src/services/BridgeService.d.ts +15 -35
  214. package/dist/src/services/BridgeService.d.ts.map +1 -1
  215. package/dist/src/services/BridgeService.js +30 -88
  216. package/dist/src/services/BridgeService.js.map +1 -1
  217. package/dist/src/services/FilesystemService.d.ts +3 -2
  218. package/dist/src/services/FilesystemService.d.ts.map +1 -1
  219. package/dist/src/services/FilesystemService.js +116 -32
  220. package/dist/src/services/FilesystemService.js.map +1 -1
  221. package/dist/src/services/FilesystemUiService.d.ts +4 -1
  222. package/dist/src/services/FilesystemUiService.d.ts.map +1 -1
  223. package/dist/src/services/FilesystemUiService.js +71 -27
  224. package/dist/src/services/FilesystemUiService.js.map +1 -1
  225. package/dist/src/services/SyncScheduler.d.ts +12 -4
  226. package/dist/src/services/SyncScheduler.d.ts.map +1 -1
  227. package/dist/src/services/SyncScheduler.js +45 -10
  228. package/dist/src/services/SyncScheduler.js.map +1 -1
  229. package/dist/src/services/baselineRepair.d.ts +13 -3
  230. package/dist/src/services/baselineRepair.d.ts.map +1 -1
  231. package/dist/src/services/baselineRepair.js +13 -3
  232. package/dist/src/services/baselineRepair.js.map +1 -1
  233. package/dist/src/services/declaredSources.d.ts +125 -42
  234. package/dist/src/services/declaredSources.d.ts.map +1 -1
  235. package/dist/src/services/declaredSources.js +117 -45
  236. package/dist/src/services/declaredSources.js.map +1 -1
  237. package/dist/src/store/dataFormats.d.ts +17 -2
  238. package/dist/src/store/dataFormats.d.ts.map +1 -1
  239. package/dist/src/store/dataFormats.js +18 -3
  240. package/dist/src/store/dataFormats.js.map +1 -1
  241. package/dist/src/sync/DeltaSyncRunner.d.ts.map +1 -1
  242. package/dist/src/sync/DeltaSyncRunner.js +144 -4
  243. package/dist/src/sync/DeltaSyncRunner.js.map +1 -1
  244. package/dist/src/sync/SyncJobQueue.d.ts +14 -2
  245. package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
  246. package/dist/src/sync/SyncJobQueue.js +56 -10
  247. package/dist/src/sync/SyncJobQueue.js.map +1 -1
  248. package/dist/src/sync/SyncWatchService.d.ts +21 -4
  249. package/dist/src/sync/SyncWatchService.d.ts.map +1 -1
  250. package/dist/src/sync/SyncWatchService.js +115 -10
  251. package/dist/src/sync/SyncWatchService.js.map +1 -1
  252. package/dist/src/sync/categoryInference.d.ts +1 -1
  253. package/dist/src/sync/categoryInference.js +1 -1
  254. package/dist/src/tools/execCtx.d.ts +6 -0
  255. package/dist/src/tools/execCtx.d.ts.map +1 -1
  256. package/dist/src/tools/execCtx.js +11 -0
  257. package/dist/src/tools/execCtx.js.map +1 -1
  258. package/dist/src/tools/fs_list.js +2 -2
  259. package/dist/src/tools/fs_list.js.map +1 -1
  260. package/dist/src/tools/fs_read.js +2 -2
  261. package/dist/src/tools/fs_read.js.map +1 -1
  262. package/dist/src/tools/fs_search.js +2 -2
  263. package/dist/src/tools/fs_search.js.map +1 -1
  264. package/dist/src/tools/fs_write.js +2 -2
  265. package/dist/src/tools/fs_write.js.map +1 -1
  266. package/dist/src/usecases/admitSourceRoot.d.ts +65 -0
  267. package/dist/src/usecases/admitSourceRoot.d.ts.map +1 -0
  268. package/dist/src/usecases/admitSourceRoot.js +85 -0
  269. package/dist/src/usecases/admitSourceRoot.js.map +1 -0
  270. package/dist/src/usecases/browseSourceFolders.d.ts +85 -0
  271. package/dist/src/usecases/browseSourceFolders.d.ts.map +1 -0
  272. package/dist/src/usecases/browseSourceFolders.js +210 -0
  273. package/dist/src/usecases/browseSourceFolders.js.map +1 -0
  274. package/dist/src/usecases/createDeclaredSources.d.ts +13 -2
  275. package/dist/src/usecases/createDeclaredSources.d.ts.map +1 -1
  276. package/dist/src/usecases/createDeclaredSources.js +39 -0
  277. package/dist/src/usecases/createDeclaredSources.js.map +1 -1
  278. package/dist/src/usecases/deprovisionProject.d.ts +4 -5
  279. package/dist/src/usecases/deprovisionProject.d.ts.map +1 -1
  280. package/dist/src/usecases/deprovisionProject.js +3 -8
  281. package/dist/src/usecases/deprovisionProject.js.map +1 -1
  282. package/dist/src/usecases/list.d.ts.map +1 -1
  283. package/dist/src/usecases/list.js +83 -26
  284. package/dist/src/usecases/list.js.map +1 -1
  285. package/dist/src/usecases/listAttachableDevices.d.ts +13 -0
  286. package/dist/src/usecases/listAttachableDevices.d.ts.map +1 -0
  287. package/dist/src/usecases/listAttachableDevices.js +10 -0
  288. package/dist/src/usecases/listAttachableDevices.js.map +1 -0
  289. package/dist/src/usecases/listSourcePackages.d.ts.map +1 -1
  290. package/dist/src/usecases/listSourcePackages.js +95 -79
  291. package/dist/src/usecases/listSourcePackages.js.map +1 -1
  292. package/dist/src/usecases/purgeExcludedPoints.d.ts.map +1 -1
  293. package/dist/src/usecases/purgeExcludedPoints.js +3 -2
  294. package/dist/src/usecases/purgeExcludedPoints.js.map +1 -1
  295. package/dist/src/usecases/readFiles.d.ts.map +1 -1
  296. package/dist/src/usecases/readFiles.js +17 -1
  297. package/dist/src/usecases/readFiles.js.map +1 -1
  298. package/dist/src/usecases/reconcileSourcePackageRoots.d.ts +1 -1
  299. package/dist/src/usecases/reconcileSourcePackageRoots.d.ts.map +1 -1
  300. package/dist/src/usecases/reconcileSourcePackageRoots.js +2 -1
  301. package/dist/src/usecases/reconcileSourcePackageRoots.js.map +1 -1
  302. package/dist/src/usecases/revokePrincipal.d.ts +7 -5
  303. package/dist/src/usecases/revokePrincipal.d.ts.map +1 -1
  304. package/dist/src/usecases/revokePrincipal.js +29 -7
  305. package/dist/src/usecases/revokePrincipal.js.map +1 -1
  306. package/dist/src/usecases/scheduleSourceSync.d.ts +7 -0
  307. package/dist/src/usecases/scheduleSourceSync.d.ts.map +1 -1
  308. package/dist/src/usecases/scheduleSourceSync.js +6 -5
  309. package/dist/src/usecases/scheduleSourceSync.js.map +1 -1
  310. package/dist/src/usecases/searchFiles.d.ts.map +1 -1
  311. package/dist/src/usecases/searchFiles.js +13 -3
  312. package/dist/src/usecases/searchFiles.js.map +1 -1
  313. package/dist/src/usecases/sourcePackageInventory.d.ts +10 -2
  314. package/dist/src/usecases/sourcePackageInventory.d.ts.map +1 -1
  315. package/dist/src/usecases/sourcePackageInventory.js +24 -7
  316. package/dist/src/usecases/sourcePackageInventory.js.map +1 -1
  317. package/dist/src/usecases/triggerSourceSync.d.ts +46 -0
  318. package/dist/src/usecases/triggerSourceSync.d.ts.map +1 -0
  319. package/dist/src/usecases/triggerSourceSync.js +75 -0
  320. package/dist/src/usecases/triggerSourceSync.js.map +1 -0
  321. package/dist/src/usecases/uploadBinary.d.ts +2 -1
  322. package/dist/src/usecases/uploadBinary.d.ts.map +1 -1
  323. package/dist/src/usecases/uploadBinary.js +2 -2
  324. package/dist/src/usecases/uploadBinary.js.map +1 -1
  325. package/dist/src/usecases/vector/endpointGuard.d.ts +1 -1
  326. package/dist/src/usecases/vector/endpointGuard.js +1 -1
  327. package/dist/src/usecases/vectorActivityWatch.d.ts +20 -13
  328. package/dist/src/usecases/vectorActivityWatch.d.ts.map +1 -1
  329. package/dist/src/usecases/vectorActivityWatch.js +61 -36
  330. package/dist/src/usecases/vectorActivityWatch.js.map +1 -1
  331. package/dist/src/usecases/vectorMaintenance.d.ts.map +1 -1
  332. package/dist/src/usecases/vectorMaintenance.js +16 -1
  333. package/dist/src/usecases/vectorMaintenance.js.map +1 -1
  334. package/dist/src/usecases/write/index.d.ts.map +1 -1
  335. package/dist/src/usecases/write/index.js +17 -2
  336. package/dist/src/usecases/write/index.js.map +1 -1
  337. package/dist/src/usecases/write/occupancy.d.ts +5 -1
  338. package/dist/src/usecases/write/occupancy.d.ts.map +1 -1
  339. package/dist/src/usecases/write/occupancy.js +13 -4
  340. package/dist/src/usecases/write/occupancy.js.map +1 -1
  341. package/dist/src/usecases/write/structure.d.ts.map +1 -1
  342. package/dist/src/usecases/write/structure.js +20 -5
  343. package/dist/src/usecases/write/structure.js.map +1 -1
  344. package/dist/src/vector/FilesystemVectorIndex.d.ts +72 -2
  345. package/dist/src/vector/FilesystemVectorIndex.d.ts.map +1 -1
  346. package/dist/src/vector/FilesystemVectorIndex.js +211 -27
  347. package/dist/src/vector/FilesystemVectorIndex.js.map +1 -1
  348. package/dist/src/vector/InMemoryVectorIndex.d.ts.map +1 -1
  349. package/dist/src/vector/InMemoryVectorIndex.js +55 -7
  350. package/dist/src/vector/InMemoryVectorIndex.js.map +1 -1
  351. package/dist/src/vector/qdrantClient.d.ts +18 -1
  352. package/dist/src/vector/qdrantClient.d.ts.map +1 -1
  353. package/dist/src/vector/qdrantClient.js +48 -6
  354. package/dist/src/vector/qdrantClient.js.map +1 -1
  355. package/dist/src/wiring.d.ts +10 -12
  356. package/dist/src/wiring.d.ts.map +1 -1
  357. package/dist/src/wiring.js +101 -61
  358. package/dist/src/wiring.js.map +1 -1
  359. package/package.json +166 -54
  360. package/skills/connect-business-data/SKILL.md +2 -2
  361. package/skills/create-package/SKILL.md +18 -18
  362. package/skills/create-package/references/config-and-credentials.md +16 -13
  363. package/skills/create-package/references/connectors-and-uri-policies.md +36 -27
  364. package/skills/create-package/references/manifest-and-discovery.md +12 -12
  365. package/skills/create-package/references/runtime-and-build.md +18 -18
  366. package/skills/create-package/references/skills-and-context.md +35 -19
  367. package/skills/create-package/references/surfaces-and-design.md +16 -16
  368. package/skills/create-package/references/team-and-workflows.md +2 -2
  369. package/skills/create-package/references/test-and-ship.md +17 -17
  370. package/skills/create-package/references/tools-and-schemas.md +5 -5
  371. package/skills/create-package/scripts/{check-package.sh → check-package.mjs} +78 -64
  372. package/skills/create-package/scripts/{verify-loaded.sh → verify-loaded.mjs} +156 -162
  373. package/skills/git/SKILL.md +31 -29
  374. package/skills/manage-files/SKILL.md +11 -14
  375. package/skills/manage-sources/SKILL.md +85 -45
  376. package/skills/manage-uri-policy/SKILL.md +9 -6
  377. package/skills/sync/SKILL.md +2 -2
  378. package/dist/src/connectors/LocalDiskConnector.d.ts +0 -171
  379. package/dist/src/connectors/LocalDiskConnector.d.ts.map +0 -1
  380. package/dist/src/connectors/LocalDiskConnector.js +0 -1233
  381. package/dist/src/connectors/LocalDiskConnector.js.map +0 -1
  382. package/skills/manage-files/scripts/copy.sh +0 -7
  383. package/skills/manage-files/scripts/create.sh +0 -7
  384. package/skills/manage-files/scripts/mkdir.sh +0 -7
  385. package/skills/manage-files/scripts/modify.sh +0 -7
  386. package/skills/manage-files/scripts/upload.sh +0 -16
  387. package/skills/manage-files/scripts/write.sh +0 -29
  388. package/skills/manage-sources/scripts/reembed.sh +0 -23
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Client helpers for project-package operations exposed by the neuralis host
3
- * (NOT the brain-core package routes). Used by the filesystem panel Packages tab.
2
+ * Client reads for the Files → Packages panel: the packages an agent can use
3
+ * (the host's scoped snapshot) and the loader's diagnostics. The changes a
4
+ * package manager makes — trust, Build, the access feature — live in
5
+ * Admin → Packages.
4
6
  */
5
7
 
6
8
  import type {
@@ -27,15 +29,6 @@ export type ProjectPackageRow = {
27
29
  accessFeatureSource?: 'manifest' | 'override';
28
30
  };
29
31
 
30
- export type BuildResponse = {
31
- ok: boolean;
32
- slug: string;
33
- wasmPath?: string;
34
- logs: string[];
35
- durationMs: number;
36
- error?: string;
37
- };
38
-
39
32
  /**
40
33
  * W3F — diagnostics surfaced from the agent-core PackageLoader.
41
34
  * Each entry mirrors the loader's status with the captured init/manifest
@@ -59,8 +52,6 @@ export type PackagesDiagnosticsResponse = {
59
52
  summary: { total: number; loaded: number; partial: number; errors: number };
60
53
  };
61
54
 
62
- export type TrustValue = 'trusted' | 'untrusted' | null;
63
-
64
55
  async function parseJson<T>(res: Response): Promise<T> {
65
56
  const text = await res.text();
66
57
  try {
@@ -71,14 +62,17 @@ async function parseJson<T>(res: Response): Promise<T> {
71
62
  }
72
63
 
73
64
  /**
74
- * List installed packages for a project with their runtime status and
75
- * declarative contribution counts. Uses the host snapshot endpoint so the
76
- * panel reflects both first-party packages and project-installed packages.
65
+ * The packages an agent can use in this project — exactly what it gets: the
66
+ * host's scoped snapshot for this caller and THIS agent (`x-agent-id`, which
67
+ * the host verifies; an agent the caller cannot use resolves to none), so the
68
+ * agent's own packages show and another member's stay out. Native packages are
69
+ * left out (their trust is host-stamped, never a manifest claim): they belong
70
+ * to Admin → Packages. Each row carries its contribution counts.
77
71
  */
78
- export async function listProjectPackages(projectId: string): Promise<ProjectPackageRow[]> {
72
+ export async function listProjectPackages(projectId: string, agentId?: string): Promise<ProjectPackageRow[]> {
79
73
  const res = await fetch('/api/packages/runtime', {
80
74
  method: 'GET',
81
- headers: { 'x-project-id': projectId },
75
+ headers: { 'x-project-id': projectId, ...(agentId ? { 'x-agent-id': agentId } : {}) },
82
76
  credentials: 'same-origin',
83
77
  });
84
78
  if (!res.ok) throw new Error(`Failed to load packages snapshot: HTTP ${res.status}`);
@@ -102,6 +96,7 @@ export async function listProjectPackages(projectId: string): Promise<ProjectPac
102
96
  const commandsByPkg = groupCount(snapshot.commands, (c) => c.packageId);
103
97
 
104
98
  return snapshot.packages
99
+ .filter((pkg) => pkg.access?.trust !== 'native')
105
100
  .map<ProjectPackageRow>((pkg) => ({
106
101
  slug: pkg.id,
107
102
  packageId: pkg.id,
@@ -120,90 +115,6 @@ export async function listProjectPackages(projectId: string): Promise<ProjectPac
120
115
  }));
121
116
  }
122
117
 
123
- /**
124
- * Trigger a WASM build on the host. Returns once build + reload complete.
125
- * Use this against packages where the status is `partial` with reason
126
- * `build-missing`.
127
- */
128
- export async function buildPackage(projectId: string, slug: string): Promise<BuildResponse> {
129
- const res = await fetch(
130
- `/api/projects/${encodeURIComponent(projectId)}/packages/${encodeURIComponent(slug)}/build`,
131
- { method: 'POST', credentials: 'same-origin' },
132
- );
133
- return parseJson<BuildResponse>(res);
134
- }
135
-
136
- /**
137
- * Flip a package's trust. `null` clears the project-level override (package
138
- * reverts to its manifest-declared trust, typically `untrusted`).
139
- */
140
- export async function setPackageTrust(
141
- projectId: string,
142
- slug: string,
143
- trust: TrustValue,
144
- ): Promise<{ ok: boolean; trust: TrustValue }> {
145
- const res = await fetch(
146
- `/api/projects/${encodeURIComponent(projectId)}/packages/${encodeURIComponent(slug)}/trust`,
147
- {
148
- method: 'PUT',
149
- headers: { 'Content-Type': 'application/json' },
150
- credentials: 'same-origin',
151
- body: JSON.stringify({ trust }),
152
- },
153
- );
154
- if (!res.ok) {
155
- const body = await res.text();
156
- throw new Error(`Failed to set trust (HTTP ${res.status}): ${body.slice(0, 200)}`);
157
- }
158
- return parseJson<{ ok: boolean; trust: TrustValue }>(res);
159
- }
160
-
161
- /**
162
- * R2b — set or clear the base-access feature OVERRIDE for a package. `null`/empty
163
- * clears it (the package reverts to its manifest `requires.accessFeature`, if
164
- * any). Owner/admin-effective; restrict-only (can only attach a requirement).
165
- */
166
- export async function setPackageAccessFeature(
167
- projectId: string,
168
- packageId: string,
169
- featureId: string | null,
170
- ): Promise<{ ok: boolean; featureId: string | null }> {
171
- const res = await fetch(
172
- `/api/projects/${encodeURIComponent(projectId)}/packages/${encodeURIComponent(packageId)}/access-feature`,
173
- {
174
- method: 'PUT',
175
- headers: { 'Content-Type': 'application/json' },
176
- credentials: 'same-origin',
177
- body: JSON.stringify({ featureId }),
178
- },
179
- );
180
- if (!res.ok) {
181
- const body = await res.text();
182
- throw new Error(`Failed to set access feature (HTTP ${res.status}): ${body.slice(0, 200)}`);
183
- }
184
- return parseJson<{ ok: boolean; featureId: string | null }>(res);
185
- }
186
-
187
- /**
188
- * R2b — fetch the project's grantable feature catalog (the SAME source the admin
189
- * Roles UI uses), so the access-feature governance control can offer a picker of
190
- * real features instead of free-text. The endpoint is project-scoped
191
- * (`requireAdmin` gates `canInvite`), reachable by the owner via `x-project-id`.
192
- * Returns a flat sorted id list; callers degrade to free-text on failure.
193
- */
194
- export async function getGrantableFeatureIds(projectId: string): Promise<string[]> {
195
- const res = await fetch('/api/admin/feature-catalog', {
196
- method: 'GET',
197
- headers: { 'x-project-id': projectId },
198
- credentials: 'same-origin',
199
- });
200
- if (!res.ok) throw new Error(`Failed to load feature catalog: HTTP ${res.status}`);
201
- const body = await parseJson<{ groups?: Array<{ features?: string[] }> }>(res);
202
- const ids = new Set<string>();
203
- for (const g of body.groups ?? []) for (const id of g.features ?? []) ids.add(id);
204
- return Array.from(ids).sort();
205
- }
206
-
207
118
  /**
208
119
  * W3F — fetch per-package diagnostics. Reads
209
120
  * `GET /api/packages/agent-core/packages/diagnostics`, served by
@@ -1,4 +1,4 @@
1
- import type { SourceLiveReason } from '@neuralis/package-system/contracts';
1
+ import type { ConnectorWatchState, DeviceNotReadyCode, SourceLiveReason } from '@neuralis/package-system/contracts';
2
2
 
3
3
  export type FileType = 'file' | 'folder';
4
4
 
@@ -77,6 +77,12 @@ export interface SourceInfo {
77
77
  live?: boolean;
78
78
  /** Why `live === false` — fixed enum, mapped to a display string in the UI. */
79
79
  live_reason?: SourceLiveReason;
80
+ /** With `live_reason: 'device_not_ready'`: the device broker's own readiness codes. */
81
+ live_not_ready?: DeviceNotReadyCode[];
82
+ /** The scope of the source config this row comes from; absent for a runtime-observed source with no config. */
83
+ config_scope?: 'project' | 'user' | 'agent';
84
+ /** How much of the source the live watch covers (`partial`/`off` show as a badge). */
85
+ watch?: ConnectorWatchState;
80
86
  /**
81
87
  * Contract-backed owning package id (the package that DECLARES this source in
82
88
  * its manifest `sources[]`). `null`/absent for user-added mounts — the Sources
@@ -343,6 +349,9 @@ export interface SourceConfigRecord {
343
349
  * source that never authored its own. This is what the AGENT reads; the
344
350
  * field above is only what is on disk. */
345
351
  description_effective?: string | null;
352
+ /** The folder the server opens for a `local` source on its own plane — natively the
353
+ * pair's machine half, never the container spelling. Sent only with the paths. */
354
+ root_effective?: string;
346
355
  connection: {
347
356
  /** Open shape — any kind a package contributes via neuralis.connectors[]. */
348
357
  kind: string;
@@ -385,7 +394,7 @@ export interface SourceConfigRecord {
385
394
  updatedAt?: string;
386
395
  // Surfaced by the server-side sources route for UI badges.
387
396
  kind_label?: string;
388
- kind_trust?: 'first-party' | 'trusted' | 'untrusted' | null;
397
+ kind_trust?: 'native' | 'trusted' | 'untrusted' | null;
389
398
  orphan?: boolean;
390
399
  orphan_hint?: string | null;
391
400
  observed?: boolean;
@@ -405,12 +414,17 @@ export interface SourceConfigRecord {
405
414
  live?: boolean;
406
415
  /** Why `live === false` — fixed enum, mapped to a display string in the UI. */
407
416
  live_reason?: SourceLiveReason;
417
+ /** With `live_reason: 'device_not_ready'`: the device broker's own readiness codes. */
418
+ live_not_ready?: DeviceNotReadyCode[];
419
+ /** How much of the source the live watch covers (`partial`/`off` show as a badge). */
420
+ watch?: ConnectorWatchState;
408
421
  /**
409
- * R2b — local-kind source ALSO acts as a runtime package source (additive to the
410
- * default `_packages/` drop-zone). Owner/admin-effective to set; honored for
411
- * project AND user/agent scope (advertise isolation enforced downstream).
422
+ * R2b — the folders of this source that ALSO act as runtime package sources
423
+ * (additive to the default `_packages/` drop-zone), relative to the source root
424
+ * (`''` = the whole source). Owner/admin-effective to set; honored for project
425
+ * AND user/agent scope (advertise isolation enforced downstream).
412
426
  */
413
- recognizesPackages?: boolean;
427
+ packageFolders?: string[];
414
428
  /**
415
429
  * Contract-backed owning package id (manifest `sources[]`); `null`/absent for
416
430
  * user-added mounts. The Sources panel groups rows by this (per-package),
@@ -462,8 +476,8 @@ export interface UpdateSourceConfigRequest {
462
476
  * the existing config, so disabling sync needs this explicit flag.
463
477
  */
464
478
  clearSync?: boolean;
465
- /** R2b — toggle runtime package recognition (owner/admin-effective, local-only). */
466
- recognizesPackages?: boolean;
479
+ /** R2b — the source's package folders (owner/admin-effective, folder kind only); `[]` clears them. */
480
+ packageFolders?: string[];
467
481
  }
468
482
 
469
483
  export interface CreateSourceRequest {
@@ -484,8 +498,8 @@ export interface CreateSourceRequest {
484
498
  /** Per-source override of the platform `brainMaxScanFiles` scan cap. */
485
499
  maxScanFiles?: number;
486
500
  };
487
- /** R2b — create the (local-kind) source as a runtime package source (owner/admin). */
488
- recognizesPackages?: boolean;
501
+ /** R2b — the new folder's package folders (owner/admin-effective). */
502
+ packageFolders?: string[];
489
503
  }
490
504
 
491
505
  /**
@@ -731,8 +745,14 @@ export type FSReadResponse = {
731
745
  * caller may not read it (uri-policy deny / disabled source). A batch read
732
746
  * reports per-file outcomes inside a 200, so the HTTP status cannot carry
733
747
  * this — and a refusal must NEVER be read as an absence.
748
+ * `'source_unavailable'` / `'device_refused'` = a device folder could not
749
+ * serve the read (`reason` says why); the file very likely still exists.
734
750
  */
735
751
  code?: string;
752
+ /** With `source_unavailable` the folder's live reason; with `device_refused` the device's code. */
753
+ reason?: string;
754
+ /** With `reason: 'device_not_ready'`: the device broker's own readiness codes. */
755
+ not_ready?: DeviceNotReadyCode[];
736
756
  pinned?: boolean;
737
757
  status?: string;
738
758
  category?: string;
@@ -5,19 +5,19 @@ React hooks used by the Files widget: viewport diff loading and the filesystem S
5
5
  ## Responsibility
6
6
 
7
7
  - `GitFileDiff` and `FileEditor` import `useContainerWidth` from `@neuralis/package-system/client`. There is no package-local responsive hook.
8
- - `useFilesystemSSE(agentId, projectId)` — subscribe to the brain-core `filesystem` channel and dispatch the right store updates. Event types: `filesystem:created`/`updated`/`deleted`/`reverted` (per-file activity), `sync:completed` (source-scoped backstop — skipped when every change count, `filesMoved` and separate `chunksRemoved` included, says zero; a missing count is unknown and still re-lists, and a `purge` job never skips, because its removal count comes from a `deleteByFilter` and proves nothing), a `changeType:'badge'` git-state signal, and a `changeType:'structure'` + `external:true` EXTERNAL connector file change (brisk-kingfisher).
8
+ - `useFilesystemSSE(agentId, projectId)` — subscribe to the brain-core `filesystem` channel and dispatch the right store updates. Event types: `filesystem:created`/`updated`/`deleted`/`reverted` (per-file activity), `sync:completed` (source-scoped backstop — skipped when every change count, `filesMoved` and separate `chunksRemoved` included, says zero; a missing count is unknown and still re-lists, and a `purge` job never skips, because its removal count comes from a `deleteByFilter` and proves nothing), a `changeType:'badge'` git-state signal, and a `changeType:'structure'` + `external:true` EXTERNAL connector file change.
9
9
 
10
10
  - `useVisibleDiffCards(root)` — one viewport observer (cards within ~2 screens count as visible) and `CONTENT_LANES` (3) content lanes per Changes/history scroller, plus an LRU answer cache (200 entries / ~8 MB estimated) keyed by the caller — record or file, its `updatedAt`/mode and the source revision — so a card re-entering the viewport sends nothing and any change is a new key; `fresh` replaces an answer after a mutation. Pending previews defer to the observer; a git diff in the virtualized Changes list reads on mount (the virtualizer — overscan 4 — is that list's ONE mount bound) and paints its first frame from the synchronous `peek(key, family)` (the exact key, else the target's newest cached revision, shown as stale until its own answer lands — staging stays disabled meanwhile). The caller validates its current revision before queued work runs.
11
11
  - `useGitChangesInventory(...)` — the Git half of the Changes inventory: per-source repo discovery + status, re-read only when that source's change revision moved (or on a forced refresh), serial behind one tail and epoch-fenced; a source is marked read only once it COMPLETED.
12
12
 
13
- - `useDiscoverableSources({ agentId, projectId, enabled })` — the Discover dock's suggestion fetch (`GET /sources/discoverable`), lazily fired once the dock could actually render.
13
+ - `useDiscoverableSources({ agentId, projectId, enabled })` — the Discover dock's suggestion fetch (`GET /sources/discoverable`), lazily fired once the dock could actually render. It reads and fills the window store's ONE copy (`loadDiscoverable`, keyed by the (agent, project) pair, an in-flight read reused), which the Sources panel reads too — opening Files asks once; the panel's Refresh re-reads (pinned: `test/ui/discoverableOneOwner.test.tsx`).
14
14
 
15
15
  ## Public Surface
16
16
 
17
17
  - Responsive hook contracts live in the kernel client export map; existing Files callers retain their width thresholds and hysteresis.
18
18
  - `useFilesystemSSE(agentId: string | undefined, projectId: string | null): void` — side-effecting hook; returns nothing.
19
19
  - `useDiscoverableSources(params): readonly DiscoverableSourceSuggestion[]` — empty until the first response lands, and empty again immediately on a context change.
20
- - **The "already fetched" latch is a REF, never state.** As state it is a dependency of the effect it guards: committing it re-runs the effect, the first instance's cleanup cancels the in-flight request, and the second returns at the guard and never re-fetches. Live symptom: the request 200s with real data, there is no console error and no banner, and the dock renders nothing — invisible to any presentational test. Pinned by `test/ui/useDiscoverableSources.test.tsx` (5 of its 8 cases fail on the old shape).
20
+ - **The "already fetched" latch is never state of a hook.** (It now lives in the store's `loadDiscoverable`.) As state it is a dependency of the effect it guards: committing it re-runs the effect, the first instance's cleanup cancels the in-flight request, and the second returns at the guard and never re-fetches. Live symptom: the request 200s with real data, there is no console error and no banner, and the dock renders nothing — invisible to any presentational test. Pinned by `test/ui/useDiscoverableSources.test.tsx` (5 of its 8 cases fail on the old shape).
21
21
  - **Liveness is cleared on UNMOUNT ONLY**, never by dependency-change cleanup — otherwise a response is silently dropped when the user expands a branch mid-flight.
22
22
  - **A context change RE-ARMS the latch and clears the list.** The store can hydrate `agentId` and `projectId` out of step (a real run sent `projectId=main` under an `ecom` agent and took a correct cross-scope 403); without the re-arm that single racy render kills the dock for the whole page life.
23
23
  - Fail-soft: an error yields an empty list, no banner, and does NOT retry-loop.
@@ -36,11 +36,17 @@
36
36
  * got a correct cross-scope 403. With the latch reset on change, the corrected
37
37
  * pair simply re-fetches; without it, one racy first render killed the dock
38
38
  * for the whole page life.
39
+ *
40
+ * Both now hold by construction: the latch and the answer live in the window
41
+ * store's `loadDiscoverable` (keyed by the pair, an in-flight read reused), the
42
+ * ONE owner the Sources panel reads too — so opening Files asks once.
39
43
  */
40
44
 
41
- import { useEffect, useRef, useState } from 'react';
42
- import { listDiscoverableSources, type DiscoverableSourceSuggestion } from '../api';
43
- import { useFilesystemStore } from '../store/filesystemStore';
45
+ import { useEffect } from 'react';
46
+ import type { DiscoverableSourceSuggestion } from '../api';
47
+ import { discoverableKey, useFilesystemStore } from '../store/filesystemStore';
48
+
49
+ const NONE: readonly DiscoverableSourceSuggestion[] = [];
44
50
 
45
51
  export function useDiscoverableSources(params: {
46
52
  agentId: string | undefined;
@@ -48,36 +54,19 @@ export function useDiscoverableSources(params: {
48
54
  /** Only fetch once the caller could actually use the result. */
49
55
  enabled: boolean;
50
56
  }): readonly DiscoverableSourceSuggestion[] {
51
- const client = useFilesystemStore((s) => s.client);
52
57
  const { agentId, projectId, enabled } = params;
53
- const [suggestions, setSuggestions] = useState<readonly DiscoverableSourceSuggestion[]>([]);
54
-
55
- // Cleared on UNMOUNT ONLY — never on a dependency change, so a response that
56
- // lands while the caller is toggling `enabled` is still delivered.
57
- const aliveRef = useRef(true);
58
- useEffect(() => {
59
- aliveRef.current = true;
60
- return () => { aliveRef.current = false; };
61
- }, []);
62
-
63
- // The latch. A ref, not state: state would make it a dependency of the effect
64
- // it guards. Declared BEFORE the fetch effect so the reset runs first.
65
- const fetchedRef = useRef(false);
66
- useEffect(() => {
67
- fetchedRef.current = false;
68
- setSuggestions([]);
69
- }, [agentId, projectId]);
58
+ const loadDiscoverable = useFilesystemStore((s) => s.loadDiscoverable);
59
+ // The answer lives in the window STORE (its one owner, shared with the
60
+ // Sources panel), keyed by the pair: a reader on another pair sees nothing,
61
+ // and the store's held answer / in-flight read is the latch — never state of
62
+ // this hook, never a dependency of the effect below.
63
+ const key = agentId ? discoverableKey(agentId, projectId) : null;
64
+ const suggestions = useFilesystemStore((s) => (key && s.discoverable?.key === key ? s.discoverable.suggestions : NONE));
70
65
 
71
66
  useEffect(() => {
72
- if (!agentId || !enabled || fetchedRef.current) return;
73
- fetchedRef.current = true;
74
- listDiscoverableSources({ agentId, ...(projectId ? { projectId } : {}) }, client)
75
- .then((res) => { if (aliveRef.current) setSuggestions(res.suggestions ?? []); })
76
- // Fail-soft: no dock, no banner. It is an affordance, not a result. The
77
- // latch stays set, so a transient failure does not retry-loop; a context
78
- // change (the effect above) is what re-arms it.
79
- .catch(() => { if (aliveRef.current) setSuggestions([]); });
80
- }, [agentId, projectId, enabled, client]);
67
+ if (!agentId || !enabled) return;
68
+ void loadDiscoverable({ agentId, ...(projectId ? { projectId } : {}) });
69
+ }, [agentId, projectId, enabled, loadDiscoverable]);
81
70
 
82
71
  return suggestions;
83
72
  }
@@ -334,7 +334,7 @@ export function useFilesystemSSE(agentId: string | undefined, projectId: string
334
334
  return;
335
335
  }
336
336
 
337
- // External connector file change (brisk-kingfisher) — a SOURCE-SCOPED signal
337
+ // External connector file change — a SOURCE-SCOPED signal
338
338
  // (no acting user, `external:true`) that a file changed OUTSIDE the platform
339
339
  // (a shell / host edit / external program). Like the badge branch this MUST be
340
340
  // an EARLY short-circuit BEFORE the `uri` guard + `upsertFileNodeFromEvent`:
@@ -12,8 +12,10 @@ The host integration entry point — `installFilesystemHostComponents`, re-expor
12
12
 
13
13
  - `FilesystemPackageHost`, `FilesystemPackageHostProps` — `{ port: WorkspaceHostPort, children: ReactNode }`.
14
14
  - `useBuildFilesystemHostValue({ port })` — `FilesystemHostValue`. Includes the optional `usePackageIconBySlug()` hook (added 2026-05-07): fetches `/api/packages/agent-core/packages/overview` once per project and exposes `slug → lucide component` so the filetree can render package dock-icons on top-level `packages://<slug>/` and `data://<slug>/` folders. Empty map on miss → falls back to the plain Folder icon.
15
- - `FilesystemHostValue.currentRole` — `{ role?, priority? }` for the caller in the active project, derived from `WorkspaceHostPort.useCurrentUser()` (which now returns role + ordinal priority alongside name/email). Owner/admin-effective is `priority <= 2`. Used to HIDE owner-only Sources/Packages controls (the `recognizesPackages` toggle, the package access-feature override); UX-only — the server route stays the enforcement floor, so an absent signal hides the control (deny-by-default).
16
- - `FilesystemHostValue.grantedFeatures` — `readonly string[]`, the caller's granted feature ids in the active project, read from `WorkspaceHostPort.getGrantedFeatures(projectId, userId)`. **Evaluate it ONLY through `hasFeature` / `meetsRequires` from `@neuralis/package-system/access`** — never a hand-rolled `includes` (it would miss the `'*'` wildcard), and never `currentRole`: the role NAME is not an authority source, not even for a hide-only gate. It is `readonly` so no UI file can mutate the caller's grants; the kernel predicates take a mutable array, so copy at the call site rather than widening the contract. UX-only exactly like `currentRole` — it hides an affordance the caller could not use (the S2 "hidden means absent" discipline: hidden entirely, never a greyed-out or locked row), and the route re-checks every call regardless. Absent/empty ⇒ hide, deny-by-default. First consumer: the Explorer tree's **Discover dock**, gated on `sources.mount`.
15
+ - `FilesystemHostValue.currentRole` — `{ role?, priority? }` for the caller in the active project, derived from `WorkspaceHostPort.useCurrentUser()` (which now returns role + ordinal priority alongside name/email). Owner/admin-effective is the kernel `isOwnerOrAdminEffective` (`@neuralis/package-system/access`: `priority <= 2` or a `'*'` grant — the server gate's own predicate). Used to HIDE the owner-only package-folders field in Sources; UX-only — the server route stays the enforcement floor, so an absent signal hides the control (deny-by-default).
16
+ - `FilesystemHostValue.grantedFeatures` — `readonly string[]`, the caller's granted feature ids in the active project, read from `WorkspaceHostPort.getGrantedFeatures(projectId, userId)`. **Evaluate it ONLY through `hasFeature` / `meetsRequires` from `@neuralis/package-system/access`** — never a hand-rolled `includes` (it would miss the `'*'` wildcard), and never `currentRole`: the role NAME is not an authority source, not even for a hide-only gate. It is `readonly` so no UI file can mutate the caller's grants; the kernel predicates take a mutable array, so copy at the call site rather than widening the contract. UX-only exactly like `currentRole` — it hides an affordance the caller could not use (the S2 "hidden means absent" discipline: hidden entirely, never a greyed-out or locked row), and the route re-checks every call regardless. Absent/empty ⇒ hide, deny-by-default. Consumers: the Explorer tree's **Discover dock**, gated on `sources.mount`, and the Packages panel's Admin link, gated on `packages.manage`.
17
+ - `FilesystemHostValue.requestDeviceFolder` / `countDeviceFolderRequests` — optional; the folder picker's two device asks, agent-core's `POST`/`GET devices/:id/requests` through a `createPackageApi({slug:'agent-core'})` client built here (a component never fetches another package). The first records a folder on the caller's OWN device for its owner to allow there; the second counts that device's pending asks for this project (`null` = could not ask). Absent ⇒ the picker shows only the `neuralis device grant` line.
18
+ - `FilesystemHostValue.openAdminPackages(agentId)` — optional; opens the Admin widget on its project-scope Packages tab in that agent's window (`port.openWidget`), where trust, Build and the access feature are changed. Absent ⇒ the Packages panel shows no link.
17
19
  - The port returns a FRESH array on every call, so `buildFilesystemHostValue` memoises on a joined key rather than array identity — a raw pass-through would invalidate the whole host-value memo on every render.
18
20
  - `installFilesystemHostComponents({ registry: PackageHostRegistry, port: WorkspaceHostPort })` — side-effecting; registers widget + card + the provider fill (one component per install, closed over the port; it ignores the slot's `snapshot`/`assetScope` props), and subscribes ONCE to the host's optional `port.onClientStateReset` with `resetFilesClientState`, so the dock broom (instance / widget / agent / project level) reaches every mounted Files window it scopes and the one persisted record. A host without the method simply never resets.
19
21
  - `InstallFilesystemHostComponentsOptions`.
@@ -23,7 +25,7 @@ The host integration entry point — `installFilesystemHostComponents`, re-expor
23
25
  - `WorkspaceHostPort` (from `@neuralis/package-system/contracts`) is the single point of contact between the host and brain-core's UI. The host has exactly one implementation; brain-core consumes the port without knowing which host runs it.
24
26
  - `installFilesystemHostComponents` registers the widget under `componentImport: '@neuralis/brain-core/app/filesystem'` — the same string the package manifest declares for `app.surfaces[].component.import`. The host renderer resolves widgets by that import string at render time.
25
27
  - `FilesystemWidgetHost` is the window seam: it receives the window's `widgetId` and BOUND `agentId`, creates the window's own store (`useFilesWindowStore` — none, and nothing painted, until the live user and project are known) and mounts it under `FilesystemStoreProvider`, keyed on that identity so a different user or project remounts the whole Files tree instead of re-using callbacks of the previous one. The store's request `client` (`createPackageApi` over the window's project and bound agent) is what every API call passes; the surrounding `<PackageApiProvider slug="brain-core" projectId agentId userId>` keeps serving the kernel's own React consumers.
26
- - The card registration uses `registerCardComponent('filesystem.change', FilesystemChangeCard, { owner: { kind: 'package-direct', packageId: '@neuralis/brain-core' }, renderer: 'direct', mountPolicy: 'virtualized', estimateHeight: estimateFilesystemChangeCardHeight })` from `@neuralis/agent-core/app/chat` — the agent-core chat surface owns the card registry; brain-core contributes an OWNED first-party direct (React) card. The `virtualized` mount policy keeps it out of the iframe/keep-alive overscan bump. The registry rejects any OTHER owner touching `filesystem.change` (`OWNER_MISMATCH`) and never lets a package overwrite a builtin. `estimateHeight` is the card's own row-height model (see `app/cards/README.md`); it MUST stay a module-level reference — the registry compares estimator identity when deciding whether a re-registration is idempotent, so an inline arrow here would churn the registry (fingerprint bump + retained-View eviction) on every call.
28
+ - The card registration uses `registerCardComponent('filesystem.change', FilesystemChangeCard, { owner: { kind: 'package-direct', packageId: '@neuralis/brain-core' }, renderer: 'direct', mountPolicy: 'virtualized', estimateHeight: estimateFilesystemChangeCardHeight })` from `@neuralis/agent-core/app/chat` — the agent-core chat surface owns the card registry; brain-core contributes an OWNED native direct (React) card. The `virtualized` mount policy keeps it out of the iframe/keep-alive overscan bump. The registry rejects any OTHER owner touching `filesystem.change` (`OWNER_MISMATCH`) and never lets a package overwrite a builtin. `estimateHeight` is the card's own row-height model (see `app/cards/README.md`); it MUST stay a module-level reference — the registry compares estimator identity when deciding whether a re-registration is idempotent, so an inline arrow here would churn the registry (fingerprint bump + retained-View eviction) on every call.
27
29
 
28
30
  ## Security & scope
29
31
 
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { useEffect, useMemo, useState } from 'react';
9
9
  import type { WorkspaceHostPort } from '@neuralis/package-system/contracts';
10
+ import { createPackageApi } from '@neuralis/package-system/client';
10
11
  import type { FilesystemHostValue, PackageIconRecord } from '../FilesystemHost';
11
12
  import type { AgentInfo } from '../ports/types';
12
13
  import { resolveLucideIcon } from '../lib/iconResolver';
@@ -100,6 +101,24 @@ export function useBuildFilesystemHostValue({ port }: BuildFilesystemHostValueOp
100
101
  });
101
102
  },
102
103
  isDocker: port.isDocker,
104
+ openAdminPackages(agentId) {
105
+ port.openWidget({ agentId, type: 'admin', title: 'Admin', initialState: { scope: 'project', initialTab: 'packages' } });
106
+ },
107
+ // The folder picker's two device asks live on agent-core's devices route (the
108
+ // channel's owner); a component never fetches another package directly.
109
+ async requestDeviceFolder({ deviceId, path, list, projectId, agentId }) {
110
+ const api = createPackageApi({ slug: 'agent-core', getProjectId: () => projectId, getAgentId: () => agentId });
111
+ return api.post<{ recorded: boolean; reason?: string }>(`devices/${encodeURIComponent(deviceId)}/requests`, { path, list });
112
+ },
113
+ async countDeviceFolderRequests({ deviceId, projectId, agentId }) {
114
+ const api = createPackageApi({ slug: 'agent-core', getProjectId: () => projectId, getAgentId: () => agentId });
115
+ try {
116
+ const answer = await api.get<{ state?: string; requests?: unknown[] }>(`devices/${encodeURIComponent(deviceId)}/requests`);
117
+ return answer?.state === 'online' && Array.isArray(answer.requests) ? answer.requests.length : null;
118
+ } catch {
119
+ return null;
120
+ }
121
+ },
103
122
  /**
104
123
  * Fetches `/api/packages/agent-core/packages/overview` once per project
105
124
  * and exposes `slug → lucide icon component` so the filetree can render
@@ -123,7 +123,7 @@ export function installFilesystemHostComponents(
123
123
 
124
124
  // Card components live in agent-core's chat card registry; brain-core
125
125
  // registers its `filesystem.change` card there at install time, as an OWNED
126
- // first-party direct (React) card — `virtualized`, so it never raises the
126
+ // native direct (React) card — `virtualized`, so it never raises the
127
127
  // iframe/keep-alive overscan.
128
128
  // `estimateHeight` AND `composer` are MODULE-LEVEL references on purpose: the
129
129
  // registry compares them by identity to decide whether a re-registration is