@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
@@ -133,14 +133,15 @@
133
133
  */
134
134
  import { realpath, stat } from 'node:fs/promises';
135
135
  import path from 'node:path';
136
- import { resolveUsername } from '@neuralis/package-system/contracts';
136
+ import { resolveUsername, sourcePlane } from '@neuralis/package-system/contracts';
137
137
  import { hasFeature } from '@neuralis/package-system/access';
138
138
  import { resolvePermissions } from '../domain/permissionResolver.js';
139
- import { LocalDiskConnector } from '../connectors/LocalDiskConnector.js';
139
+ import { HostConnector } from '../connectors/HostConnector.js';
140
140
  import { getSourceGitStatus, getSourceGitLogStats, getSourceBranches, getSourceGitDiff, getSourceGitLog, getSourceGitShow, getSourceGitCommitFiles, getSourceGitOutgoing, getSourceGitSummary, discoverSourceRepoRoots, resolveGitCanWrite, filterVisibleRepoNames, invalidateSourceGitCache, } from '../git/sourceGitControl.js';
141
141
  import { countUntrackedAdditions } from '../git/untrackedStats.js';
142
+ import { childPlace } from '../git/gitPlace.js';
142
143
  import { getBrainConfigNumber } from '../config/env.js';
143
- import { GitRunner, GitArgumentError, GitOutsideSourceError, GitUnavailableError, } from '../git/GitRunner.js';
144
+ import { GitRunner, GitArgumentError, GitDeviceUnavailableError, GitOutsideSourceError, GitUnavailableError, } from '../git/GitRunner.js';
144
145
  import { resolveGitToken } from '../git/tokenResolve.js';
145
146
  import { extractCtx, ensureAccess, getServices, toScopeAccessCtx, publishInAppGitBadge, } from './helpers.js';
146
147
  import { assertUriCapability, uriPolicyDeniedResponse, UriPolicyDeniedError, } from './helpers/uriGuard.js';
@@ -197,7 +198,17 @@ const MAX_SUBJECT_LEN = 500;
197
198
  * card shows the message, not a full diff). */
198
199
  const MAX_BODY_LEN = 4000;
199
200
  export const GET = async (req, raw) => {
200
- const state = raw;
201
+ try {
202
+ return await dispatchRead(req, raw);
203
+ }
204
+ catch (error) {
205
+ // A device that refused a read is named — never a clean repo's empty answer.
206
+ if (error instanceof GitDeviceUnavailableError)
207
+ return gitDeviceUnavailable(error.reason);
208
+ throw error;
209
+ }
210
+ };
211
+ async function dispatchRead(req, state) {
201
212
  const [sub] = req.path;
202
213
  if (sub === 'status')
203
214
  return handleGitStatus(req, state);
@@ -218,7 +229,7 @@ export const GET = async (req, raw) => {
218
229
  if (sub === 'repos')
219
230
  return handleGitRepos(req, state);
220
231
  return { status: 404, body: { error: `Unknown git route: ${sub ?? ''}` } };
221
- };
232
+ }
222
233
  /**
223
234
  * WRITE routes (G2.3) — the HUMAN face of the git engine. Dispatched on
224
235
  * `req.path[0]`. Each handler additionally gates `files.write` (the file-level
@@ -278,10 +289,11 @@ async function resolveGitSource(req, state, opts = {}) {
278
289
  if (!config) {
279
290
  return { ok: false, response: { status: 404, body: { error: `Source not found: ${source}` } } };
280
291
  }
281
- if (config.connection?.kind !== 'local') {
292
+ const plane = config.connection ? sourcePlane(config.connection.kind, config.connection.config) : 'connector';
293
+ if (plane !== 'local' && plane !== 'device') {
282
294
  return {
283
295
  ok: false,
284
- response: { status: 400, body: { error: `Source "${config.source}" is not a git-capable local source` } },
296
+ response: { status: 400, body: { error: `Source "${config.source}" is not a git-capable folder` } },
285
297
  };
286
298
  }
287
299
  // uri-policy gate (defense-in-depth beyond the scope check). `capability` is
@@ -313,13 +325,11 @@ async function resolveGitSource(req, state, opts = {}) {
313
325
  return { ok: false, response: uriPolicyDeniedResponse(error) };
314
326
  throw error;
315
327
  }
316
- const root = resolveLocalRootForSource(services, config.source);
317
- if (!root) {
318
- return {
319
- ok: false,
320
- response: { status: 400, body: { error: `Source "${config.source}" has no resolvable local checkout root` } },
321
- };
322
- }
328
+ const found = await resolveGitPlace(services, state, ctx, config.source);
329
+ if (!found.ok)
330
+ return found;
331
+ const sourcePlace = found.place;
332
+ const root = sourcePlace.root;
323
333
  const base = {
324
334
  ok: true,
325
335
  source: config.source,
@@ -330,15 +340,75 @@ async function resolveGitSource(req, state, opts = {}) {
330
340
  createdBy: config.createdBy,
331
341
  };
332
342
  if (repo === undefined)
333
- return { ...base, root };
343
+ return { ...base, root, place: sourcePlace };
334
344
  // E1 braces — membership + fresh re-check on the nested root. ONE constant
335
345
  // 404 for non-member / non-repo / symlink-escape / raced-away children —
336
346
  // the response never reveals whether the child exists.
337
- const nestedRoot = await resolveNestedRepoRoot(root, repo);
338
- if (!nestedRoot) {
347
+ const nested = await resolveNestedRepoPlace(sourcePlace, repo);
348
+ if (!nested) {
339
349
  return { ok: false, response: { status: 404, body: { error: `Repository not found: ${repo}` } } };
340
350
  }
341
- return { ...base, root: nestedRoot };
351
+ return { ...base, root: nested.root, place: nested };
352
+ }
353
+ /**
354
+ * The place git runs for a source: the in-process folder's root, or a device
355
+ * folder behind the ONE device gate's `exec` arm (D7′ + the owner's per-host
356
+ * folders and "others" level, D-L1). Every git call on a device is a program run
357
+ * there, so the gate answers BEFORE anything spawns: the device's owner holding
358
+ * `device.own` always; anyone else only with `exec.device` on a device whose
359
+ * live verdict is `sandboxed` — and even then the broker re-judges at the spawn
360
+ * (`requireConfinement` + `actor:'other'` against the owner's per-folder
361
+ * "others" setting). The refusal is the gate's FIXED code and sentence.
362
+ */
363
+ async function resolveGitPlace(services, state, ctx, source) {
364
+ const connector = services.infra?.connectors?.resolveBySource?.(source) ?? null;
365
+ if (!(connector instanceof HostConnector)) {
366
+ return { ok: false, response: { status: 400, body: { error: `Source "${source}" has no resolvable checkout root` } } };
367
+ }
368
+ const device = connector.device;
369
+ if (device === undefined)
370
+ return { ok: true, place: { root: connector.root } };
371
+ const devices = state.ctx.packages.getPackageApi('@neuralis/agent-core')?.devices;
372
+ const verdict = devices
373
+ ? await devices.mayRun({ userId: ctx.userId, grantedFeatures: ctx.grantedFeatures ?? [] }, device)
374
+ : { ok: false, code: 'devices_unavailable', reason: 'The device plane is not available on this server.' };
375
+ if (!verdict.ok) {
376
+ return { ok: false, response: { status: 403, body: { ok: false, code: verdict.code, error: verdict.reason } } };
377
+ }
378
+ // A device whose plane is down answers its live reason (the listing's own
379
+ // probe, cached per device) before git is asked — never an empty repo.
380
+ const probe = await connector.probeConnection();
381
+ if (!probe.connected)
382
+ return { ok: false, response: gitDeviceUnavailable(probe.reason ?? 'store_unreachable') };
383
+ return { ok: true, place: { root: connector.root, device: { transport: connector.transport, owner: verdict.owner } } };
384
+ }
385
+ /**
386
+ * The E1 braces on a DEVICE folder: membership in the discovered set (which
387
+ * admitted only real, non-symlinked child directories with a real `.git`, see
388
+ * `scanDeviceDepth1RepoChildren`) plus a FRESH `.git` stat on the device. A
389
+ * device answers inside its owner's ceiling and never follows a link out of it;
390
+ * the child's own `.git` redirect is clamped again by the engine's floor 1b at
391
+ * the first spawn.
392
+ */
393
+ async function resolveNestedRepoPlace(sourcePlace, repo) {
394
+ const seat = sourcePlace.device;
395
+ if (!seat) {
396
+ const nestedRoot = await resolveNestedRepoRoot(sourcePlace.root, repo);
397
+ return nestedRoot ? { root: nestedRoot } : null;
398
+ }
399
+ const discovered = await discoverSourceRepoRoots({ root: sourcePlace.root, device: { transport: seat.transport } });
400
+ if (!discovered.some((entry) => entry.rel === repo))
401
+ return null;
402
+ const nested = childPlace(sourcePlace, repo);
403
+ try {
404
+ const p = seat.transport.flavour === 'win32' ? path.win32 : path.posix;
405
+ if ((await seat.transport.stat(p.join(nested.root, '.git'))) === null)
406
+ return null;
407
+ }
408
+ catch {
409
+ return null;
410
+ }
411
+ return { root: nested.root, device: { transport: seat.transport, owner: seat.owner } };
342
412
  }
343
413
  /**
344
414
  * E1 `repo` syntactic whitelist — ONE path segment (no `/` or `\`), 1–128
@@ -434,24 +504,16 @@ async function hasNestedDotGit(nestedRoot) {
434
504
  return false;
435
505
  }
436
506
  }
437
- function resolveLocalRootForSource(services, source) {
438
- const connector = services.infra?.connectors?.resolveBySource?.(source) ?? null;
439
- if (connector instanceof LocalDiskConnector)
440
- return connector.root;
441
- return null;
442
- }
443
507
  async function handleGitStatus(req, state) {
444
508
  const resolved = await resolveGitSource(req, state);
445
509
  if (!resolved.ok)
446
510
  return resolved.response;
447
- const status = await getSourceGitStatus(resolved.root);
448
- // Fail-soft: a non-repo / slow / broken checkout yields an empty change-set,
449
- // never an error (the source-row indicator already told the UI it is a repo).
511
+ const status = await getSourceGitStatus(resolved.place);
512
+ // A non-repo / slow / broken checkout is a typed refusal like /git/outgoing's —
513
+ // an empty `ok:true` change-set reads as "No changes". The sentence is fixed:
514
+ // git's stderr carries host paths (invariant 9).
450
515
  if (!status) {
451
- return {
452
- status: 200,
453
- body: { ok: true, status: { branch: null, staged: [], unstaged: [], untracked: [] } },
454
- };
516
+ return { status: 200, body: { ok: false, code: 'unavailable', error: 'Git status is unavailable for this folder.' } };
455
517
  }
456
518
  // Q1 closure: drop per-path read-denied file NAMES from every bucket BEFORE
457
519
  // capping (a root-allowed caller must not enumerate a `<sub>/**`-denied path;
@@ -468,12 +530,15 @@ async function handleGitStatus(req, state) {
468
530
  // this reads FILES, so counting one the caller may not see would be work done
469
531
  // on their behalf on content they are not allowed to know exists.
470
532
  // Tracked rows already carry their numbers from `getSourceGitStatus`.
471
- const untrackedBudget = getBrainConfigNumber('brainGitUntrackedCountCap', undefined, 200);
533
+ // A device folder's untracked files carry no number: counting reads every
534
+ // file over the link (one `stat` + one range read each, ~15 ms per RPC), which
535
+ // the panel's refresh cannot afford — absent means "no number", never zero.
536
+ const untrackedBudget = resolved.place.device ? 0 : getBrainConfigNumber('brainGitUntrackedCountCap', undefined, 200);
472
537
  if (untrackedBudget > 0 && capped.untracked.length > 0) {
473
538
  const targets = capped.untracked.slice(0, untrackedBudget).map((c) => c.path);
474
539
  const counts = await countUntrackedAdditions(resolved.root, targets, {
475
540
  maxBytes: UNTRACKED_MAX_BYTES,
476
- timeoutMs: getBrainConfigNumber('brainGitPanelTimeoutMs', undefined, 5000),
541
+ timeoutMs: getBrainConfigNumber('brainGitPanelTimeoutMs', undefined, 15000),
477
542
  });
478
543
  capped.untracked = capped.untracked.map((c) => {
479
544
  const n = counts.get(c.path);
@@ -525,7 +590,7 @@ async function handleGitBranch(req, state) {
525
590
  const resolved = await resolveGitSource(req, state);
526
591
  if (!resolved.ok)
527
592
  return resolved.response;
528
- const branches = await getSourceBranches(resolved.root);
593
+ const branches = await getSourceBranches(resolved.place);
529
594
  if (!branches) {
530
595
  return { status: 200, body: { ok: true, branches: [] } };
531
596
  }
@@ -596,7 +661,7 @@ async function handleGitDiff(req, state) {
596
661
  // `getSourceGitDiff` passes the repo-relative path straight into
597
662
  // `GitRunner.diff`, whose containment floor rejects any escape (→ null →
598
663
  // empty diff here).
599
- const result = await getSourceGitDiff(resolved.root, rawPath, target);
664
+ const result = await getSourceGitDiff(resolved.place, rawPath, target);
600
665
  if (result && !result.ok) {
601
666
  // The engine KILLED the read past its ~4 MB accumulation bound (MINOR-6):
602
667
  // there is no leading-hunk prefix to serve, so this is a typed refusal
@@ -651,7 +716,7 @@ async function handleGitShow(req, state) {
651
716
  const resolved = await resolveGitSource(req, state, { policyPath: rawPath });
652
717
  if (!resolved.ok)
653
718
  return resolved.response;
654
- const result = await getSourceGitShow(resolved.root, rawPath, rev);
719
+ const result = await getSourceGitShow(resolved.place, rawPath, rev);
655
720
  if (!result) {
656
721
  // Fail-soft: non-repo / path missing at the rev / timeout — never an error
657
722
  // that leaks path detail.
@@ -695,7 +760,7 @@ async function handleGitLog(req, state) {
695
760
  const skip = Number.isFinite(skipRaw) && skipRaw > 0 ? Math.min(skipRaw, MAX_LOG_SKIP) : 0;
696
761
  const ref = typeof req.query?.ref === 'string' && req.query.ref ? req.query.ref : undefined;
697
762
  // Fail-soft: an empty repo (no commits) / slow / broken checkout → `commits:[]`.
698
- const result = await getSourceGitLog(resolved.root, {
763
+ const result = await getSourceGitLog(resolved.place, {
699
764
  maxCount: maxCount + 1,
700
765
  ...(skip > 0 ? { skip } : {}),
701
766
  ...(ref ? { ref } : {}),
@@ -756,7 +821,7 @@ async function handleGitLogStats(req, state) {
756
821
  const skipRaw = typeof req.query?.skip === 'string' ? Number.parseInt(req.query.skip, 10) : NaN;
757
822
  const skip = Number.isFinite(skipRaw) && skipRaw > 0 ? Math.min(skipRaw, MAX_LOG_SKIP) : 0;
758
823
  const ref = typeof req.query?.ref === 'string' && req.query.ref ? req.query.ref : undefined;
759
- const result = await getSourceGitLogStats(resolved.root, {
824
+ const result = await getSourceGitLogStats(resolved.place, {
760
825
  maxCount,
761
826
  ...(skip > 0 ? { skip } : {}),
762
827
  ...(ref ? { ref } : {}),
@@ -828,7 +893,7 @@ async function handleGitCommitFiles(req, state) {
828
893
  const resolved = await resolveGitSource(req, state);
829
894
  if (!resolved.ok)
830
895
  return resolved.response;
831
- const files = await getSourceGitCommitFiles(resolved.root, sha);
896
+ const files = await getSourceGitCommitFiles(resolved.place, sha);
832
897
  if (!files) {
833
898
  return { status: 200, body: { ok: false, code: 'unavailable', sha } };
834
899
  }
@@ -856,7 +921,7 @@ async function handleGitOutgoing(req, state) {
856
921
  const resolved = await resolveGitSource(req, state);
857
922
  if (!resolved.ok)
858
923
  return resolved.response;
859
- const outgoing = await getSourceGitOutgoing(resolved.root);
924
+ const outgoing = await getSourceGitOutgoing(resolved.place);
860
925
  if (!outgoing) {
861
926
  // Dialect unification (3b): a DEEP failure (non-repo / unborn HEAD / any git
862
927
  // error → `getSourceGitOutgoing` returns null) is a typed refusal, matching
@@ -901,7 +966,7 @@ async function handleGitRepos(req, state) {
901
966
  const resolved = await resolveGitSource(req, state, { ignoreRepo: true });
902
967
  if (!resolved.ok)
903
968
  return resolved.response;
904
- const discovered = await discoverSourceRepoRoots(resolved.root);
969
+ const discovered = await discoverSourceRepoRoots(resolved.place);
905
970
  // Q1 closure (m3): per-path READ-gate the NESTED repo DIRS — the exact call
906
971
  // the file tree already makes (`filterVisibleRepoNames`, `${source}://<rel>/`).
907
972
  // The root-repo `rel:''` row is source-root-gated already (a `${source}:///`
@@ -915,7 +980,7 @@ async function handleGitRepos(req, state) {
915
980
  const repos = await Promise.all(visibleRepos.map(async (entry) => {
916
981
  // Branch enrichment is the on-demand step split OFF the discovery
917
982
  // (MINOR-5); fail-soft — any git problem just omits the branch.
918
- const summary = await getSourceGitSummary(entry.root);
983
+ const summary = await getSourceGitSummary(entry.place);
919
984
  return {
920
985
  rel: entry.rel,
921
986
  name: entry.name,
@@ -1062,7 +1127,7 @@ async function handleStage(req, state) {
1062
1127
  }
1063
1128
  let runner;
1064
1129
  try {
1065
- runner = await GitRunner.create({ containerRoot: resolved.root });
1130
+ runner = await GitRunner.create({ root: resolved.place });
1066
1131
  }
1067
1132
  catch (error) {
1068
1133
  return gitWriteError(error, resolved.root);
@@ -1100,7 +1165,7 @@ async function handleUnstage(req, state) {
1100
1165
  }
1101
1166
  let runner;
1102
1167
  try {
1103
- runner = await GitRunner.create({ containerRoot: resolved.root });
1168
+ runner = await GitRunner.create({ root: resolved.place });
1104
1169
  }
1105
1170
  catch (error) {
1106
1171
  return gitWriteError(error, resolved.root);
@@ -1134,7 +1199,7 @@ async function handleDiscard(req, state) {
1134
1199
  return pathDenied;
1135
1200
  let runner;
1136
1201
  try {
1137
- runner = await GitRunner.create({ containerRoot: resolved.root });
1202
+ runner = await GitRunner.create({ root: resolved.place });
1138
1203
  }
1139
1204
  catch (error) {
1140
1205
  return gitWriteError(error, resolved.root);
@@ -1176,7 +1241,7 @@ async function handleCommit(req, state) {
1176
1241
  return resolved.response;
1177
1242
  let runner;
1178
1243
  try {
1179
- runner = await GitRunner.create({ containerRoot: resolved.root });
1244
+ runner = await GitRunner.create({ root: resolved.place });
1180
1245
  }
1181
1246
  catch (error) {
1182
1247
  return gitWriteError(error, resolved.root);
@@ -1209,7 +1274,7 @@ async function handleBranchWrite(req, state) {
1209
1274
  return resolved.response;
1210
1275
  let runner;
1211
1276
  try {
1212
- runner = await GitRunner.create({ containerRoot: resolved.root });
1277
+ runner = await GitRunner.create({ root: resolved.place });
1213
1278
  }
1214
1279
  catch (error) {
1215
1280
  return gitWriteError(error, resolved.root);
@@ -1263,7 +1328,7 @@ async function handleCheckout(req, state) {
1263
1328
  return resolved.response;
1264
1329
  let runner;
1265
1330
  try {
1266
- runner = await GitRunner.create({ containerRoot: resolved.root });
1331
+ runner = await GitRunner.create({ root: resolved.place });
1267
1332
  }
1268
1333
  catch (error) {
1269
1334
  return gitWriteError(error, resolved.root);
@@ -1318,7 +1383,7 @@ async function handleRestore(req, state) {
1318
1383
  return resolved.response;
1319
1384
  let runner;
1320
1385
  try {
1321
- runner = await GitRunner.create({ containerRoot: resolved.root });
1386
+ runner = await GitRunner.create({ root: resolved.place });
1322
1387
  }
1323
1388
  catch (error) {
1324
1389
  return gitWriteError(error, resolved.root);
@@ -1382,9 +1447,16 @@ async function handleRemoteOp(req, state, op) {
1382
1447
  });
1383
1448
  if (!resolved.ok)
1384
1449
  return resolved.response;
1450
+ // A paired device's folder: its OWNER runs fetch/pull/push there with their own
1451
+ // git credentials on their own machine — no binding or server token is read,
1452
+ // and nothing of this server's crosses the link. Anyone else is refused: the
1453
+ // only credential on that machine is the owner's, and using it for another
1454
+ // person would be borrowing it.
1455
+ if (resolved.place.device)
1456
+ return handleDeviceRemoteOp(resolved, op);
1385
1457
  let runner;
1386
1458
  try {
1387
- runner = await GitRunner.create({ containerRoot: resolved.root });
1459
+ runner = await GitRunner.create({ root: resolved.place });
1388
1460
  }
1389
1461
  catch (error) {
1390
1462
  return gitWriteError(error, resolved.root);
@@ -1414,7 +1486,7 @@ async function handleRemoteOp(req, state, op) {
1414
1486
  projectId: ctx.projectId,
1415
1487
  ...(ctx.agentId ? { agentId: ctx.agentId } : {}),
1416
1488
  callerId: '@neuralis/brain-core',
1417
- callerTrust: 'first-party',
1489
+ callerTrust: 'native',
1418
1490
  ...(ctx.grantedFeatures ? { grantedFeatures: ctx.grantedFeatures } : {}),
1419
1491
  };
1420
1492
  const agentCore = state.ctx.packages.getPackageApi('@neuralis/agent-core', session);
@@ -1455,12 +1527,58 @@ async function handleRemoteOp(req, state, op) {
1455
1527
  catch (error) {
1456
1528
  return gitWriteError(error, resolved.root);
1457
1529
  }
1458
- invalidateSourceGitCache(resolved.root);
1530
+ invalidateSourceGitCache(resolved.place);
1459
1531
  publishInAppGitBadge(resolved.services, resolved.ctx, resolved.source);
1460
1532
  // fetch/pull re-read status so the UI shows TRUE divergence immediately.
1461
1533
  const body = { ok: true, op, host };
1462
1534
  if (op !== 'push') {
1463
- const status = await getSourceGitStatus(resolved.root);
1535
+ // The op landed: a status the device can no longer answer only leaves it out.
1536
+ const status = await getSourceGitStatus(resolved.place).catch(() => null);
1537
+ if (status)
1538
+ body.status = capStatus(status);
1539
+ }
1540
+ return { status: 200, body };
1541
+ }
1542
+ /** fetch / pull / push on a device folder — its owner's own git, on that device. */
1543
+ async function handleDeviceRemoteOp(resolved, op) {
1544
+ if (resolved.place.device?.owner !== true) {
1545
+ return {
1546
+ status: 409,
1547
+ body: { ok: false, code: 'git_remote_owner_only', error: "Only the device's owner fetches, pulls and pushes a folder on it — with their own git credentials there." },
1548
+ };
1549
+ }
1550
+ let runner;
1551
+ let host;
1552
+ try {
1553
+ runner = await GitRunner.create({ root: resolved.place });
1554
+ host = await runner.remoteHost(GIT_REMOTE, { push: op === 'push' });
1555
+ }
1556
+ catch (error) {
1557
+ return gitWriteError(error, resolved.root);
1558
+ }
1559
+ if (!host) {
1560
+ return {
1561
+ status: 409,
1562
+ body: { ok: false, code: 'no_https_remote', error: 'This checkout has no HTTPS remote configured (SSH remotes are not supported).' },
1563
+ };
1564
+ }
1565
+ try {
1566
+ if (op === 'fetch')
1567
+ await runner.fetch({ remote: GIT_REMOTE });
1568
+ else if (op === 'push')
1569
+ await runner.push({ remote: GIT_REMOTE });
1570
+ else
1571
+ await runner.pull({ remote: GIT_REMOTE });
1572
+ }
1573
+ catch (error) {
1574
+ return gitWriteError(error, resolved.root);
1575
+ }
1576
+ invalidateSourceGitCache(resolved.place);
1577
+ publishInAppGitBadge(resolved.services, resolved.ctx, resolved.source);
1578
+ const body = { ok: true, op, host };
1579
+ if (op !== 'push') {
1580
+ // The op landed: a status the device can no longer answer only leaves it out.
1581
+ const status = await getSourceGitStatus(resolved.place).catch(() => null);
1464
1582
  if (status)
1465
1583
  body.status = capStatus(status);
1466
1584
  }
@@ -1544,7 +1662,7 @@ async function guardWritePaths(resolved, paths) {
1544
1662
  * SOURCE-scoped — an in-source over-refresh is fine.
1545
1663
  */
1546
1664
  function finishWrite(resolved, extra) {
1547
- invalidateSourceGitCache(resolved.root);
1665
+ invalidateSourceGitCache(resolved.place);
1548
1666
  publishInAppGitBadge(resolved.services, resolved.ctx, resolved.source);
1549
1667
  return { status: 200, body: { ok: true, ...extra } };
1550
1668
  }
@@ -1556,6 +1674,8 @@ function finishWrite(resolved, extra) {
1556
1674
  * unmerged branch delete, …) → 409 with git's own (repo-relative) message.
1557
1675
  */
1558
1676
  function gitWriteError(error, root) {
1677
+ if (error instanceof GitDeviceUnavailableError)
1678
+ return gitDeviceUnavailable(error.reason);
1559
1679
  if (error instanceof GitArgumentError || error instanceof GitOutsideSourceError) {
1560
1680
  return { status: 400, body: { ok: false, code: error.code, error: scrubHostPath(error.message, root) } };
1561
1681
  }
@@ -1566,6 +1686,15 @@ function gitWriteError(error, root) {
1566
1686
  const message = error instanceof Error ? error.message : 'git operation failed';
1567
1687
  return { status: 409, body: { ok: false, code, error: scrubHostPath(message, root) } };
1568
1688
  }
1689
+ /**
1690
+ * git could not run on a paired device — its plane is down (`devices_disabled`,
1691
+ * `runtime_offline`, `broker_outdated`, …) or it refused the spawn
1692
+ * (`others_denied`, …). ONE answer for reads and writes: the fixed code, never
1693
+ * the broker's text.
1694
+ */
1695
+ function gitDeviceUnavailable(reason) {
1696
+ return { status: 409, body: { ok: false, code: 'git_device_unavailable', reason, error: `git could not run on the device (${reason})` } };
1697
+ }
1569
1698
  /** Replace any leaked container-root prefix in a git message with `<repo>`. */
1570
1699
  function scrubHostPath(message, root) {
1571
1700
  return root ? message.split(root).join('<repo>') : message;