@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.
- package/README.md +80 -1410
- package/app/README.md +1 -1
- package/app/cards/FilesystemCardShell.tsx +42 -4
- package/app/cards/FilesystemChangeCard.tsx +34 -11
- package/app/cards/README.md +6 -5
- package/app/cards/diffUtils.ts +99 -1
- package/app/filesystem/FilesystemHost.tsx +17 -2
- package/app/filesystem/api/README.md +3 -3
- package/app/filesystem/api/index.ts +35 -11
- package/app/filesystem/api/projectPackages.ts +13 -102
- package/app/filesystem/domain/types.ts +30 -10
- package/app/filesystem/hooks/README.md +3 -3
- package/app/filesystem/hooks/useDiscoverableSources.ts +19 -30
- package/app/filesystem/hooks/useFilesystemSSE.ts +1 -1
- package/app/filesystem/host/README.md +5 -3
- package/app/filesystem/host/buildFilesystemHostValue.ts +19 -0
- package/app/filesystem/host/installFilesystemHostComponents.tsx +1 -1
- package/app/filesystem/lib/sourceKindForm.ts +118 -39
- package/app/filesystem/lib/treeVisualState.tsx +98 -4
- package/app/filesystem/store/README.md +1 -0
- package/app/filesystem/store/filesystemStore.ts +86 -5
- package/app/filesystem/store/gitSlice.ts +5 -0
- package/app/filesystem/store/helpers.ts +17 -0
- package/app/filesystem/store/listSlice.ts +8 -0
- package/app/filesystem/ui/CodeEditor.tsx +18 -3
- package/app/filesystem/ui/FileEditor.tsx +15 -10
- package/app/filesystem/ui/FileTree.tsx +41 -16
- package/app/filesystem/ui/FolderPicker.tsx +251 -0
- package/app/filesystem/ui/GitControlPanel.tsx +5 -0
- package/app/filesystem/ui/PackagesPanel.tsx +52 -374
- package/app/filesystem/ui/PolicyEditor.tsx +109 -24
- package/app/filesystem/ui/README.md +17 -11
- package/app/filesystem/ui/RawMediaPreview.tsx +58 -0
- package/app/filesystem/ui/SourceBranchHeader.tsx +4 -4
- package/app/filesystem/ui/SourcesPanel.tsx +420 -360
- package/app/filesystem/ui/Toolbar.tsx +1 -2
- package/app/shared/filesystem.png +0 -0
- package/dist/app/host.js +53 -48
- package/dist/scripts/sourceRootPairV1.d.ts +47 -0
- package/dist/scripts/sourceRootPairV1.d.ts.map +1 -0
- package/dist/scripts/sourceRootPairV1.js +147 -0
- package/dist/scripts/sourceRootPairV1.js.map +1 -0
- package/dist/scripts/sourceToFolderV1.d.ts +56 -0
- package/dist/scripts/sourceToFolderV1.d.ts.map +1 -0
- package/dist/scripts/sourceToFolderV1.js +152 -0
- package/dist/scripts/sourceToFolderV1.js.map +1 -0
- package/dist/scripts/sourceToHostV1.d.ts +56 -0
- package/dist/scripts/sourceToHostV1.d.ts.map +1 -0
- package/dist/scripts/sourceToHostV1.js +132 -0
- package/dist/scripts/sourceToHostV1.js.map +1 -0
- package/dist/src/config/env.d.ts +8 -0
- package/dist/src/config/env.d.ts.map +1 -1
- package/dist/src/config/env.js +17 -6
- package/dist/src/config/env.js.map +1 -1
- package/dist/src/connectors/AppSourceConfigStore.d.ts +17 -3
- package/dist/src/connectors/AppSourceConfigStore.d.ts.map +1 -1
- package/dist/src/connectors/AppSourceConfigStore.js +46 -6
- package/dist/src/connectors/AppSourceConfigStore.js.map +1 -1
- package/dist/src/connectors/HostConnector.d.ts +201 -0
- package/dist/src/connectors/HostConnector.d.ts.map +1 -0
- package/dist/src/connectors/HostConnector.js +903 -0
- package/dist/src/connectors/HostConnector.js.map +1 -0
- package/dist/src/connectors/inProcessTransport.d.ts +131 -0
- package/dist/src/connectors/inProcessTransport.d.ts.map +1 -0
- package/dist/src/connectors/inProcessTransport.js +447 -0
- package/dist/src/connectors/inProcessTransport.js.map +1 -0
- package/dist/src/domain/BrainError.d.ts +14 -0
- package/dist/src/domain/BrainError.d.ts.map +1 -1
- package/dist/src/domain/BrainError.js +21 -0
- package/dist/src/domain/BrainError.js.map +1 -1
- package/dist/src/domain/access/callerPermissions.d.ts +29 -0
- package/dist/src/domain/access/callerPermissions.d.ts.map +1 -1
- package/dist/src/domain/access/callerPermissions.js +85 -5
- package/dist/src/domain/access/callerPermissions.js.map +1 -1
- package/dist/src/domain/access/nativeLocalFence.d.ts +65 -0
- package/dist/src/domain/access/nativeLocalFence.d.ts.map +1 -0
- package/dist/src/domain/access/nativeLocalFence.js +171 -0
- package/dist/src/domain/access/nativeLocalFence.js.map +1 -0
- package/dist/src/domain/access/uriPermission.js +3 -3
- package/dist/src/domain/access/uriPermission.js.map +1 -1
- package/dist/src/domain/byteRange.d.ts +15 -0
- package/dist/src/domain/byteRange.d.ts.map +1 -0
- package/dist/src/domain/byteRange.js +30 -0
- package/dist/src/domain/byteRange.js.map +1 -0
- package/dist/src/domain/defaultPermissions.d.ts.map +1 -1
- package/dist/src/domain/defaultPermissions.js +29 -0
- package/dist/src/domain/defaultPermissions.js.map +1 -1
- package/dist/src/domain/mime.d.ts +8 -16
- package/dist/src/domain/mime.d.ts.map +1 -1
- package/dist/src/domain/mime.js +10 -99
- package/dist/src/domain/mime.js.map +1 -1
- package/dist/src/domain/paths.d.ts.map +1 -1
- package/dist/src/domain/paths.js +5 -3
- package/dist/src/domain/paths.js.map +1 -1
- package/dist/src/domain/sourceConfig.d.ts +52 -19
- package/dist/src/domain/sourceConfig.d.ts.map +1 -1
- package/dist/src/domain/sourceConfig.js +103 -19
- package/dist/src/domain/sourceConfig.js.map +1 -1
- package/dist/src/domain/sourcePackages.d.ts +8 -8
- package/dist/src/domain/sourcePackages.d.ts.map +1 -1
- package/dist/src/domain/sourceRootPair.d.ts +88 -0
- package/dist/src/domain/sourceRootPair.d.ts.map +1 -0
- package/dist/src/domain/sourceRootPair.js +108 -0
- package/dist/src/domain/sourceRootPair.js.map +1 -0
- package/dist/src/domain/syncTypes.d.ts +8 -1
- package/dist/src/domain/syncTypes.d.ts.map +1 -1
- package/dist/src/domain/syncTypes.js +1 -0
- package/dist/src/domain/syncTypes.js.map +1 -1
- package/dist/src/domain/types.d.ts +29 -1
- package/dist/src/domain/types.d.ts.map +1 -1
- package/dist/src/domain/uri.d.ts.map +1 -1
- package/dist/src/domain/uri.js +3 -2
- package/dist/src/domain/uri.js.map +1 -1
- package/dist/src/embeddings/clients/GeminiEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/GeminiEmbedder.js +2 -5
- package/dist/src/embeddings/clients/GeminiEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/OpenAIEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/OpenAIEmbedder.js +2 -3
- package/dist/src/embeddings/clients/OpenAIEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/QwenEmbedder.d.ts +2 -0
- package/dist/src/embeddings/clients/QwenEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/QwenEmbedder.js +10 -2
- package/dist/src/embeddings/clients/QwenEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.d.ts +2 -0
- package/dist/src/embeddings/clients/VoyageEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.js +8 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.js.map +1 -1
- package/dist/src/embeddings/factory.d.ts +5 -3
- package/dist/src/embeddings/factory.d.ts.map +1 -1
- package/dist/src/embeddings/factory.js +7 -3
- package/dist/src/embeddings/factory.js.map +1 -1
- package/dist/src/embeddings/models.d.ts +2 -3
- package/dist/src/embeddings/models.d.ts.map +1 -1
- package/dist/src/embeddings/models.js +1 -2
- package/dist/src/embeddings/models.js.map +1 -1
- package/dist/src/embeddings/retry.js +1 -1
- package/dist/src/embeddings/retry.js.map +1 -1
- package/dist/src/embeddings/types.d.ts +6 -0
- package/dist/src/embeddings/types.d.ts.map +1 -1
- package/dist/src/embeddings/types.js +11 -0
- package/dist/src/embeddings/types.js.map +1 -1
- package/dist/src/git/GitRunner.d.ts +110 -30
- package/dist/src/git/GitRunner.d.ts.map +1 -1
- package/dist/src/git/GitRunner.js +511 -199
- package/dist/src/git/GitRunner.js.map +1 -1
- package/dist/src/git/GitWatchRegistry.d.ts +41 -35
- package/dist/src/git/GitWatchRegistry.d.ts.map +1 -1
- package/dist/src/git/GitWatchRegistry.js +61 -79
- package/dist/src/git/GitWatchRegistry.js.map +1 -1
- package/dist/src/git/gitPlace.d.ts +61 -0
- package/dist/src/git/gitPlace.d.ts.map +1 -0
- package/dist/src/git/gitPlace.js +74 -0
- package/dist/src/git/gitPlace.js.map +1 -0
- package/dist/src/git/sourceGitControl.d.ts +31 -19
- package/dist/src/git/sourceGitControl.d.ts.map +1 -1
- package/dist/src/git/sourceGitControl.js +208 -92
- package/dist/src/git/sourceGitControl.js.map +1 -1
- package/dist/src/git/sourceGitStatus.js +1 -1
- package/dist/src/git/sourceGitStatus.js.map +1 -1
- package/dist/src/git/untrackedStats.js +1 -1
- package/dist/src/git/untrackedStats.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lifecycle.d.ts +12 -16
- package/dist/src/lifecycle.d.ts.map +1 -1
- package/dist/src/lifecycle.js +2 -1
- package/dist/src/lifecycle.js.map +1 -1
- package/dist/src/routes/approve.d.ts.map +1 -1
- package/dist/src/routes/approve.js +3 -3
- package/dist/src/routes/approve.js.map +1 -1
- package/dist/src/routes/git.d.ts.map +1 -1
- package/dist/src/routes/git.js +183 -54
- package/dist/src/routes/git.js.map +1 -1
- package/dist/src/routes/health.d.ts.map +1 -1
- package/dist/src/routes/health.js +8 -5
- package/dist/src/routes/health.js.map +1 -1
- package/dist/src/routes/helpers/uriGuard.d.ts +1 -1
- package/dist/src/routes/helpers/uriGuard.d.ts.map +1 -1
- package/dist/src/routes/helpers/uriGuard.js +3 -2
- package/dist/src/routes/helpers/uriGuard.js.map +1 -1
- package/dist/src/routes/helpers.d.ts +20 -4
- package/dist/src/routes/helpers.d.ts.map +1 -1
- package/dist/src/routes/helpers.js +38 -5
- package/dist/src/routes/helpers.js.map +1 -1
- package/dist/src/routes/list.d.ts.map +1 -1
- package/dist/src/routes/list.js +5 -6
- package/dist/src/routes/list.js.map +1 -1
- package/dist/src/routes/pending.d.ts.map +1 -1
- package/dist/src/routes/pending.js +5 -5
- package/dist/src/routes/pending.js.map +1 -1
- package/dist/src/routes/policies.d.ts +6 -4
- package/dist/src/routes/policies.d.ts.map +1 -1
- package/dist/src/routes/policies.js +22 -16
- package/dist/src/routes/policies.js.map +1 -1
- package/dist/src/routes/raw.d.ts.map +1 -1
- package/dist/src/routes/raw.js +68 -14
- package/dist/src/routes/raw.js.map +1 -1
- package/dist/src/routes/read.d.ts.map +1 -1
- package/dist/src/routes/read.js +3 -3
- package/dist/src/routes/read.js.map +1 -1
- package/dist/src/routes/search.d.ts.map +1 -1
- package/dist/src/routes/search.js +3 -3
- package/dist/src/routes/search.js.map +1 -1
- package/dist/src/routes/sources.d.ts +60 -18
- package/dist/src/routes/sources.d.ts.map +1 -1
- package/dist/src/routes/sources.js +420 -308
- package/dist/src/routes/sources.js.map +1 -1
- package/dist/src/routes/upload.d.ts.map +1 -1
- package/dist/src/routes/upload.js +3 -3
- package/dist/src/routes/upload.js.map +1 -1
- package/dist/src/services/BridgeService.d.ts +15 -35
- package/dist/src/services/BridgeService.d.ts.map +1 -1
- package/dist/src/services/BridgeService.js +30 -88
- package/dist/src/services/BridgeService.js.map +1 -1
- package/dist/src/services/FilesystemService.d.ts +3 -2
- package/dist/src/services/FilesystemService.d.ts.map +1 -1
- package/dist/src/services/FilesystemService.js +116 -32
- package/dist/src/services/FilesystemService.js.map +1 -1
- package/dist/src/services/FilesystemUiService.d.ts +4 -1
- package/dist/src/services/FilesystemUiService.d.ts.map +1 -1
- package/dist/src/services/FilesystemUiService.js +71 -27
- package/dist/src/services/FilesystemUiService.js.map +1 -1
- package/dist/src/services/SyncScheduler.d.ts +12 -4
- package/dist/src/services/SyncScheduler.d.ts.map +1 -1
- package/dist/src/services/SyncScheduler.js +45 -10
- package/dist/src/services/SyncScheduler.js.map +1 -1
- package/dist/src/services/baselineRepair.d.ts +13 -3
- package/dist/src/services/baselineRepair.d.ts.map +1 -1
- package/dist/src/services/baselineRepair.js +13 -3
- package/dist/src/services/baselineRepair.js.map +1 -1
- package/dist/src/services/declaredSources.d.ts +125 -42
- package/dist/src/services/declaredSources.d.ts.map +1 -1
- package/dist/src/services/declaredSources.js +117 -45
- package/dist/src/services/declaredSources.js.map +1 -1
- package/dist/src/store/dataFormats.d.ts +17 -2
- package/dist/src/store/dataFormats.d.ts.map +1 -1
- package/dist/src/store/dataFormats.js +18 -3
- package/dist/src/store/dataFormats.js.map +1 -1
- package/dist/src/sync/DeltaSyncRunner.d.ts.map +1 -1
- package/dist/src/sync/DeltaSyncRunner.js +144 -4
- package/dist/src/sync/DeltaSyncRunner.js.map +1 -1
- package/dist/src/sync/SyncJobQueue.d.ts +14 -2
- package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
- package/dist/src/sync/SyncJobQueue.js +56 -10
- package/dist/src/sync/SyncJobQueue.js.map +1 -1
- package/dist/src/sync/SyncWatchService.d.ts +21 -4
- package/dist/src/sync/SyncWatchService.d.ts.map +1 -1
- package/dist/src/sync/SyncWatchService.js +115 -10
- package/dist/src/sync/SyncWatchService.js.map +1 -1
- package/dist/src/sync/categoryInference.d.ts +1 -1
- package/dist/src/sync/categoryInference.js +1 -1
- package/dist/src/tools/execCtx.d.ts +6 -0
- package/dist/src/tools/execCtx.d.ts.map +1 -1
- package/dist/src/tools/execCtx.js +11 -0
- package/dist/src/tools/execCtx.js.map +1 -1
- package/dist/src/tools/fs_list.js +2 -2
- package/dist/src/tools/fs_list.js.map +1 -1
- package/dist/src/tools/fs_read.js +2 -2
- package/dist/src/tools/fs_read.js.map +1 -1
- package/dist/src/tools/fs_search.js +2 -2
- package/dist/src/tools/fs_search.js.map +1 -1
- package/dist/src/tools/fs_write.js +2 -2
- package/dist/src/tools/fs_write.js.map +1 -1
- package/dist/src/usecases/admitSourceRoot.d.ts +65 -0
- package/dist/src/usecases/admitSourceRoot.d.ts.map +1 -0
- package/dist/src/usecases/admitSourceRoot.js +85 -0
- package/dist/src/usecases/admitSourceRoot.js.map +1 -0
- package/dist/src/usecases/browseSourceFolders.d.ts +85 -0
- package/dist/src/usecases/browseSourceFolders.d.ts.map +1 -0
- package/dist/src/usecases/browseSourceFolders.js +210 -0
- package/dist/src/usecases/browseSourceFolders.js.map +1 -0
- package/dist/src/usecases/createDeclaredSources.d.ts +13 -2
- package/dist/src/usecases/createDeclaredSources.d.ts.map +1 -1
- package/dist/src/usecases/createDeclaredSources.js +39 -0
- package/dist/src/usecases/createDeclaredSources.js.map +1 -1
- package/dist/src/usecases/deprovisionProject.d.ts +4 -5
- package/dist/src/usecases/deprovisionProject.d.ts.map +1 -1
- package/dist/src/usecases/deprovisionProject.js +3 -8
- package/dist/src/usecases/deprovisionProject.js.map +1 -1
- package/dist/src/usecases/list.d.ts.map +1 -1
- package/dist/src/usecases/list.js +83 -26
- package/dist/src/usecases/list.js.map +1 -1
- package/dist/src/usecases/listAttachableDevices.d.ts +13 -0
- package/dist/src/usecases/listAttachableDevices.d.ts.map +1 -0
- package/dist/src/usecases/listAttachableDevices.js +10 -0
- package/dist/src/usecases/listAttachableDevices.js.map +1 -0
- package/dist/src/usecases/listSourcePackages.d.ts.map +1 -1
- package/dist/src/usecases/listSourcePackages.js +95 -79
- package/dist/src/usecases/listSourcePackages.js.map +1 -1
- package/dist/src/usecases/purgeExcludedPoints.d.ts.map +1 -1
- package/dist/src/usecases/purgeExcludedPoints.js +3 -2
- package/dist/src/usecases/purgeExcludedPoints.js.map +1 -1
- package/dist/src/usecases/readFiles.d.ts.map +1 -1
- package/dist/src/usecases/readFiles.js +17 -1
- package/dist/src/usecases/readFiles.js.map +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.d.ts +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.d.ts.map +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.js +2 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.js.map +1 -1
- package/dist/src/usecases/revokePrincipal.d.ts +7 -5
- package/dist/src/usecases/revokePrincipal.d.ts.map +1 -1
- package/dist/src/usecases/revokePrincipal.js +29 -7
- package/dist/src/usecases/revokePrincipal.js.map +1 -1
- package/dist/src/usecases/scheduleSourceSync.d.ts +7 -0
- package/dist/src/usecases/scheduleSourceSync.d.ts.map +1 -1
- package/dist/src/usecases/scheduleSourceSync.js +6 -5
- package/dist/src/usecases/scheduleSourceSync.js.map +1 -1
- package/dist/src/usecases/searchFiles.d.ts.map +1 -1
- package/dist/src/usecases/searchFiles.js +13 -3
- package/dist/src/usecases/searchFiles.js.map +1 -1
- package/dist/src/usecases/sourcePackageInventory.d.ts +10 -2
- package/dist/src/usecases/sourcePackageInventory.d.ts.map +1 -1
- package/dist/src/usecases/sourcePackageInventory.js +24 -7
- package/dist/src/usecases/sourcePackageInventory.js.map +1 -1
- package/dist/src/usecases/triggerSourceSync.d.ts +46 -0
- package/dist/src/usecases/triggerSourceSync.d.ts.map +1 -0
- package/dist/src/usecases/triggerSourceSync.js +75 -0
- package/dist/src/usecases/triggerSourceSync.js.map +1 -0
- package/dist/src/usecases/uploadBinary.d.ts +2 -1
- package/dist/src/usecases/uploadBinary.d.ts.map +1 -1
- package/dist/src/usecases/uploadBinary.js +2 -2
- package/dist/src/usecases/uploadBinary.js.map +1 -1
- package/dist/src/usecases/vector/endpointGuard.d.ts +1 -1
- package/dist/src/usecases/vector/endpointGuard.js +1 -1
- package/dist/src/usecases/vectorActivityWatch.d.ts +20 -13
- package/dist/src/usecases/vectorActivityWatch.d.ts.map +1 -1
- package/dist/src/usecases/vectorActivityWatch.js +61 -36
- package/dist/src/usecases/vectorActivityWatch.js.map +1 -1
- package/dist/src/usecases/vectorMaintenance.d.ts.map +1 -1
- package/dist/src/usecases/vectorMaintenance.js +16 -1
- package/dist/src/usecases/vectorMaintenance.js.map +1 -1
- package/dist/src/usecases/write/index.d.ts.map +1 -1
- package/dist/src/usecases/write/index.js +17 -2
- package/dist/src/usecases/write/index.js.map +1 -1
- package/dist/src/usecases/write/occupancy.d.ts +5 -1
- package/dist/src/usecases/write/occupancy.d.ts.map +1 -1
- package/dist/src/usecases/write/occupancy.js +13 -4
- package/dist/src/usecases/write/occupancy.js.map +1 -1
- package/dist/src/usecases/write/structure.d.ts.map +1 -1
- package/dist/src/usecases/write/structure.js +20 -5
- package/dist/src/usecases/write/structure.js.map +1 -1
- package/dist/src/vector/FilesystemVectorIndex.d.ts +72 -2
- package/dist/src/vector/FilesystemVectorIndex.d.ts.map +1 -1
- package/dist/src/vector/FilesystemVectorIndex.js +211 -27
- package/dist/src/vector/FilesystemVectorIndex.js.map +1 -1
- package/dist/src/vector/InMemoryVectorIndex.d.ts.map +1 -1
- package/dist/src/vector/InMemoryVectorIndex.js +55 -7
- package/dist/src/vector/InMemoryVectorIndex.js.map +1 -1
- package/dist/src/vector/qdrantClient.d.ts +18 -1
- package/dist/src/vector/qdrantClient.d.ts.map +1 -1
- package/dist/src/vector/qdrantClient.js +48 -6
- package/dist/src/vector/qdrantClient.js.map +1 -1
- package/dist/src/wiring.d.ts +10 -12
- package/dist/src/wiring.d.ts.map +1 -1
- package/dist/src/wiring.js +101 -61
- package/dist/src/wiring.js.map +1 -1
- package/package.json +166 -54
- package/skills/connect-business-data/SKILL.md +2 -2
- package/skills/create-package/SKILL.md +18 -18
- package/skills/create-package/references/config-and-credentials.md +16 -13
- package/skills/create-package/references/connectors-and-uri-policies.md +36 -27
- package/skills/create-package/references/manifest-and-discovery.md +12 -12
- package/skills/create-package/references/runtime-and-build.md +18 -18
- package/skills/create-package/references/skills-and-context.md +35 -19
- package/skills/create-package/references/surfaces-and-design.md +16 -16
- package/skills/create-package/references/team-and-workflows.md +2 -2
- package/skills/create-package/references/test-and-ship.md +17 -17
- package/skills/create-package/references/tools-and-schemas.md +5 -5
- package/skills/create-package/scripts/{check-package.sh → check-package.mjs} +78 -64
- package/skills/create-package/scripts/{verify-loaded.sh → verify-loaded.mjs} +156 -162
- package/skills/git/SKILL.md +31 -29
- package/skills/manage-files/SKILL.md +11 -14
- package/skills/manage-sources/SKILL.md +85 -45
- package/skills/manage-uri-policy/SKILL.md +9 -6
- package/skills/sync/SKILL.md +2 -2
- package/dist/src/connectors/LocalDiskConnector.d.ts +0 -171
- package/dist/src/connectors/LocalDiskConnector.d.ts.map +0 -1
- package/dist/src/connectors/LocalDiskConnector.js +0 -1233
- package/dist/src/connectors/LocalDiskConnector.js.map +0 -1
- package/skills/manage-files/scripts/copy.sh +0 -7
- package/skills/manage-files/scripts/create.sh +0 -7
- package/skills/manage-files/scripts/mkdir.sh +0 -7
- package/skills/manage-files/scripts/modify.sh +0 -7
- package/skills/manage-files/scripts/upload.sh +0 -16
- package/skills/manage-files/scripts/write.sh +0 -29
- package/skills/manage-sources/scripts/reembed.sh +0 -23
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Client
|
|
3
|
-
* (
|
|
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
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
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?: '
|
|
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 —
|
|
410
|
-
* default `_packages/` drop-zone)
|
|
411
|
-
*
|
|
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
|
-
|
|
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 —
|
|
466
|
-
|
|
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 —
|
|
488
|
-
|
|
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
|
|
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
|
|
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
|
|
42
|
-
import {
|
|
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
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
//
|
|
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
|