@neuralis/brain-core 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -1417
- package/app/README.md +4 -4
- 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 +24 -2
- package/app/filesystem/README.md +1 -1
- package/app/filesystem/api/README.md +3 -3
- package/app/filesystem/api/index.ts +38 -14
- package/app/filesystem/api/projectPackages.ts +13 -102
- package/app/filesystem/domain/types.ts +30 -10
- package/app/filesystem/hooks/README.md +4 -4
- package/app/filesystem/hooks/useDiscoverableSources.ts +19 -30
- package/app/filesystem/hooks/useFilesystemSSE.ts +42 -2
- package/app/filesystem/host/README.md +6 -4
- package/app/filesystem/host/buildFilesystemHostValue.ts +28 -2
- package/app/filesystem/host/installFilesystemHostComponents.tsx +1 -1
- package/app/filesystem/lib/sourceKindForm.ts +210 -27
- package/app/filesystem/lib/treeVisualState.tsx +98 -4
- package/app/filesystem/store/README.md +1 -0
- package/app/filesystem/store/filesystemStore.ts +99 -8
- 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/DiscoverDock.tsx +5 -1
- package/app/filesystem/ui/FileEditor.tsx +15 -10
- package/app/filesystem/ui/FileTree.tsx +75 -24
- package/app/filesystem/ui/FilesystemWidget.tsx +10 -2
- package/app/filesystem/ui/FolderPicker.tsx +251 -0
- package/app/filesystem/ui/GitControlPanel.tsx +7 -2
- package/app/filesystem/ui/PackagesPanel.tsx +52 -374
- package/app/filesystem/ui/PendingChangesPanel.tsx +1 -1
- package/app/filesystem/ui/PolicyEditor.tsx +109 -24
- package/app/filesystem/ui/README.md +30 -23
- package/app/filesystem/ui/RawMediaPreview.tsx +58 -0
- package/app/filesystem/ui/SourceBranchHeader.tsx +4 -4
- package/app/filesystem/ui/SourcesPanel.tsx +502 -342
- package/app/filesystem/ui/Toolbar.tsx +1 -2
- package/app/filesystem/ui/VectorHealthPanel.tsx +2 -2
- package/app/shared/filesystem.png +0 -0
- package/dist/app/host.js +58 -46
- 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/channels/filesystem.d.ts +1 -1
- package/dist/src/channels/filesystem.js +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/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 +11 -19
- package/dist/src/domain/mime.d.ts.map +1 -1
- package/dist/src/domain/mime.js +13 -102
- 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/scopeAccessCtx.d.ts +2 -2
- package/dist/src/domain/scopeAccessCtx.js +2 -2
- 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 +32 -2
- 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 +1 -1
- package/dist/src/embeddings/models.d.ts.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/events/pending.d.ts +1 -1
- package/dist/src/events/pending.js +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 +33 -21
- package/dist/src/git/sourceGitControl.d.ts.map +1 -1
- package/dist/src/git/sourceGitControl.js +211 -95
- 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 +9 -12
- 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 +1 -1
- package/dist/src/routes/approve.js +1 -1
- package/dist/src/routes/events.d.ts +1 -1
- package/dist/src/routes/events.js +1 -1
- package/dist/src/routes/git.d.ts +7 -7
- package/dist/src/routes/git.d.ts.map +1 -1
- package/dist/src/routes/git.js +201 -72
- package/dist/src/routes/git.js.map +1 -1
- package/dist/src/routes/health.d.ts +6 -6
- package/dist/src/routes/health.js +12 -12
- package/dist/src/routes/helpers/sourceNotConfigured.d.ts +1 -1
- package/dist/src/routes/helpers/sourceNotConfigured.js +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 +11 -4
- package/dist/src/routes/helpers.d.ts.map +1 -1
- package/dist/src/routes/helpers.js +13 -6
- package/dist/src/routes/helpers.js.map +1 -1
- package/dist/src/routes/list.d.ts +1 -1
- package/dist/src/routes/list.d.ts.map +1 -1
- package/dist/src/routes/list.js +3 -4
- package/dist/src/routes/list.js.map +1 -1
- package/dist/src/routes/pending.d.ts +4 -4
- package/dist/src/routes/pending.js +9 -9
- package/dist/src/routes/policies.d.ts +10 -8
- package/dist/src/routes/policies.d.ts.map +1 -1
- package/dist/src/routes/policies.js +31 -25
- package/dist/src/routes/policies.js.map +1 -1
- package/dist/src/routes/raw.d.ts +1 -1
- package/dist/src/routes/raw.d.ts.map +1 -1
- package/dist/src/routes/raw.js +66 -12
- package/dist/src/routes/raw.js.map +1 -1
- package/dist/src/routes/read.d.ts +1 -1
- package/dist/src/routes/read.js +1 -1
- package/dist/src/routes/search.d.ts +1 -1
- package/dist/src/routes/search.js +1 -1
- package/dist/src/routes/sources.d.ts +63 -6
- package/dist/src/routes/sources.d.ts.map +1 -1
- package/dist/src/routes/sources.js +494 -382
- package/dist/src/routes/sources.js.map +1 -1
- package/dist/src/routes/upload.d.ts +1 -1
- package/dist/src/routes/upload.js +1 -1
- package/dist/src/routes/write.d.ts +2 -2
- package/dist/src/routes/write.js +2 -2
- package/dist/src/services/BridgeService.d.ts +21 -35
- package/dist/src/services/BridgeService.d.ts.map +1 -1
- package/dist/src/services/BridgeService.js +42 -88
- package/dist/src/services/BridgeService.js.map +1 -1
- package/dist/src/services/FilesystemService.d.ts +4 -3
- package/dist/src/services/FilesystemService.d.ts.map +1 -1
- package/dist/src/services/FilesystemService.js +112 -34
- 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 +66 -25
- 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 +37 -8
- 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 +132 -43
- package/dist/src/services/declaredSources.d.ts.map +1 -1
- package/dist/src/services/declaredSources.js +118 -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 +7 -2
- package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
- package/dist/src/sync/SyncJobQueue.js +16 -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 +2 -2
- package/dist/src/tools/execCtx.js +2 -2
- package/dist/src/tools/fs_read.d.ts.map +1 -1
- package/dist/src/tools/fs_read.js +5 -0
- package/dist/src/tools/fs_read.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/embeddingBacklog.js +1 -1
- package/dist/src/usecases/embeddingBacklog.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 +2 -5
- 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 +99 -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/syncPointWrites.d.ts +2 -0
- package/dist/src/usecases/syncPointWrites.d.ts.map +1 -1
- package/dist/src/usecases/syncPointWrites.js +5 -1
- package/dist/src/usecases/syncPointWrites.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/vectorMaintenance.js +1 -1
- package/dist/src/usecases/vectorMaintenance.js.map +1 -1
- package/dist/src/usecases/write/content.js +1 -1
- package/dist/src/vector/qdrantClient.d.ts +1 -1
- package/dist/src/vector/qdrantClient.js +1 -1
- package/dist/src/wiring.d.ts +3 -0
- package/dist/src/wiring.d.ts.map +1 -1
- package/dist/src/wiring.js +72 -6
- package/dist/src/wiring.js.map +1 -1
- package/dist/tools/fs_list.json +1 -1
- package/dist/tools/fs_read.json +1 -1
- package/dist/tools/fs_search.json +1 -1
- package/dist/tools/fs_write.json +1 -1
- package/instructions/brain-model.md +1 -1
- package/package.json +212 -114
- package/rules/brain-rules.md +2 -2
- package/skills/brain-start/SKILL.md +1 -1
- package/skills/connect-business-data/SKILL.md +3 -3
- package/skills/create-package/SKILL.md +26 -26
- package/skills/create-package/references/config-and-credentials.md +16 -13
- package/skills/create-package/references/connectors-and-uri-policies.md +39 -25
- package/skills/create-package/references/manifest-and-discovery.md +12 -12
- package/skills/create-package/references/runtime-and-build.md +19 -19
- package/skills/create-package/references/skills-and-context.md +36 -20
- 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 +21 -21
- package/skills/create-package/references/tools-and-schemas.md +5 -5
- package/skills/create-package/scripts/{check-package.sh → check-package.mjs} +79 -65
- package/skills/create-package/scripts/{verify-loaded.sh → verify-loaded.mjs} +156 -162
- package/skills/git/SKILL.md +53 -51
- package/skills/manage-files/SKILL.md +22 -25
- package/skills/manage-sources/SKILL.md +128 -87
- package/skills/manage-uri-policy/SKILL.md +18 -15
- package/skills/organize/SKILL.md +1 -1
- package/skills/sync/SKILL.md +3 -3
- package/tools/fs_list.json +1 -1
- package/tools/fs_read.json +1 -1
- package/tools/fs_search.json +1 -1
- package/tools/fs_write.json +1 -1
- package/workflows/sources-digest.json +1 -1
- 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/docs/drive-overview.md +0 -59
- 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,4 +1,5 @@
|
|
|
1
1
|
import type { FileNode, FilePrev } from '../domain/types';
|
|
2
|
+
import { deviceRefusalLabel, sourceLiveReasonLabel } from '../lib/treeVisualState';
|
|
2
3
|
|
|
3
4
|
// ---------------------------------------------------------------------------
|
|
4
5
|
// URI helpers (lightweight, client-side — no dependency on brain-core/src/)
|
|
@@ -213,3 +214,19 @@ export function contextKey(
|
|
|
213
214
|
): string {
|
|
214
215
|
return `${userId ?? ''}::${projectId ?? ''}::${agentId}`;
|
|
215
216
|
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* One file's read failure as the Files UI says it: a device folder that could
|
|
220
|
+
* not serve names its state in the tree's own words (`source_unavailable` →
|
|
221
|
+
* the live-reason label, `device_refused` → the refusal code); any other
|
|
222
|
+
* failure keeps the server's text. `undefined` when the file read.
|
|
223
|
+
*/
|
|
224
|
+
export function readFailureMessage(file: { error?: unknown; code?: unknown; reason?: unknown; not_ready?: unknown }): string | undefined {
|
|
225
|
+
if (typeof file.error !== 'string') return undefined;
|
|
226
|
+
// `source_unavailable` is a device folder's answer only (the `host` connector's device transport).
|
|
227
|
+
if (file.code === 'source_unavailable' && typeof file.reason === 'string') {
|
|
228
|
+
return sourceLiveReasonLabel(file.reason, { kind: 'host', notReady: Array.isArray(file.not_ready) ? file.not_ready : null });
|
|
229
|
+
}
|
|
230
|
+
if (file.code === 'device_refused') return deviceRefusalLabel(file.reason) ?? file.error;
|
|
231
|
+
return file.error;
|
|
232
|
+
}
|
|
@@ -436,9 +436,17 @@ export function createListSlice(
|
|
|
436
436
|
}
|
|
437
437
|
}
|
|
438
438
|
|
|
439
|
+
// An expanded folder of a source this listing no longer names (deleted, or no
|
|
440
|
+
// longer visible) would be listed on every load and refused: one pass drops it,
|
|
441
|
+
// and the window's persisted projection follows.
|
|
442
|
+
const listedSources = new Set(sources.map((s) => sourceFromUri(s.uri_root)));
|
|
443
|
+
const expanded = state.expandedFolders as Set<string>;
|
|
444
|
+
const keptExpanded = sources.length > 0 ? [...expanded].filter((uri) => listedSources.has(sourceFromUri(uri))) : [];
|
|
445
|
+
|
|
439
446
|
return {
|
|
440
447
|
files: next,
|
|
441
448
|
sources,
|
|
449
|
+
...(sources.length > 0 && keptExpanded.length !== expanded.size ? { expandedFolders: new Set(keptExpanded) } : {}),
|
|
442
450
|
sourcesLoading: false,
|
|
443
451
|
// A listing that answered clears the previous failure's banner.
|
|
444
452
|
snapshotError: undefined,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* diff surfaces exactly, so the editor ↔ diff transition never jumps.
|
|
14
14
|
*/
|
|
15
15
|
import { useEffect, useRef } from 'react';
|
|
16
|
-
import { EditorState, Compartment } from '@codemirror/state';
|
|
16
|
+
import { EditorState, Compartment, type Extension } from '@codemirror/state';
|
|
17
17
|
import {
|
|
18
18
|
EditorView,
|
|
19
19
|
lineNumbers,
|
|
@@ -67,6 +67,7 @@ export function CodeEditor({
|
|
|
67
67
|
const readOnlyComp = useRef(new Compartment());
|
|
68
68
|
const wrapComp = useRef(new Compartment());
|
|
69
69
|
const gitGutterComp = useRef(new Compartment());
|
|
70
|
+
const labelComp = useRef(new Compartment());
|
|
70
71
|
|
|
71
72
|
onChangeRef.current = onChange;
|
|
72
73
|
|
|
@@ -93,13 +94,12 @@ export function CodeEditor({
|
|
|
93
94
|
]),
|
|
94
95
|
wrapComp.current.of(wrap ? EditorView.lineWrapping : []),
|
|
95
96
|
gitGutterComp.current.of([]),
|
|
96
|
-
placeholder
|
|
97
|
+
labelComp.current.of(labelExtensions(placeholder, ariaLabel)),
|
|
97
98
|
EditorView.updateListener.of((u) => {
|
|
98
99
|
if (u.docChanged && !applyingExternal.current) {
|
|
99
100
|
onChangeRef.current?.(u.state.doc.toString());
|
|
100
101
|
}
|
|
101
102
|
}),
|
|
102
|
-
EditorView.contentAttributes.of(ariaLabel ? { 'aria-label': ariaLabel } : {}),
|
|
103
103
|
],
|
|
104
104
|
});
|
|
105
105
|
|
|
@@ -155,6 +155,14 @@ export function CodeEditor({
|
|
|
155
155
|
});
|
|
156
156
|
}, [wrap]);
|
|
157
157
|
|
|
158
|
+
// Empty-state line + accessible name reconfigure — the view outlives the file
|
|
159
|
+
// it shows, so a read that FAILS after mount replaces "Loading…" here.
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
const view = viewRef.current;
|
|
162
|
+
if (!view) return;
|
|
163
|
+
view.dispatch({ effects: labelComp.current.reconfigure(labelExtensions(placeholder, ariaLabel)) });
|
|
164
|
+
}, [placeholder, ariaLabel]);
|
|
165
|
+
|
|
158
166
|
// Git left-gutter reconfigure — present only when there's a non-empty status.
|
|
159
167
|
useEffect(() => {
|
|
160
168
|
const view = viewRef.current;
|
|
@@ -165,3 +173,10 @@ export function CodeEditor({
|
|
|
165
173
|
|
|
166
174
|
return <div ref={hostRef} className={className} />;
|
|
167
175
|
}
|
|
176
|
+
|
|
177
|
+
function labelExtensions(placeholder: string | undefined, ariaLabel: string | undefined): Extension[] {
|
|
178
|
+
return [
|
|
179
|
+
placeholder ? cmPlaceholder(placeholder) : [],
|
|
180
|
+
EditorView.contentAttributes.of(ariaLabel ? { 'aria-label': ariaLabel } : {}),
|
|
181
|
+
];
|
|
182
|
+
}
|
|
@@ -56,9 +56,13 @@ export function DiscoverDock({ suggestions, expanded, onToggleExpanded, onPick,
|
|
|
56
56
|
return (
|
|
57
57
|
<div
|
|
58
58
|
className={cn(
|
|
59
|
-
'group/discover shrink-0 border-t border-white/[0.06]
|
|
59
|
+
'group/discover shrink-0 border-t border-white/[0.06]',
|
|
60
60
|
overlay ? 'absolute inset-x-0 bottom-0 z-20 shadow-[0_-8px_24px_rgba(0,0,0,0.45)]' : '',
|
|
61
61
|
)}
|
|
62
|
+
// Collapsed it carries no surface of its own (the panel chrome owns it);
|
|
63
|
+
// only the overlay form needs a scrim, derived from the theme so it
|
|
64
|
+
// matches every workspace theme.
|
|
65
|
+
style={overlay ? { backgroundColor: 'rgba(var(--w-bg-rgb), 0.96)' } : undefined}
|
|
62
66
|
data-testid="discover-dock"
|
|
63
67
|
>
|
|
64
68
|
<div className="flex items-center justify-between px-2 pt-1.5 pb-1">
|
|
@@ -18,6 +18,7 @@ import { GitDiffView } from './GitDiffView';
|
|
|
18
18
|
import { GitCommitChangesView } from './GitCommitChangesView';
|
|
19
19
|
import { gitDiffTargetModeLabel, repoQualifiedLabel, shortSha } from './gitFileDiffMode';
|
|
20
20
|
import { getRawFileUrl, approveFileReview, writeFile, writeRefusalMessage, getGitDiff } from '../api';
|
|
21
|
+
import { RawMediaPreview } from './RawMediaPreview';
|
|
21
22
|
import { InlineUploader } from './InlineUploader';
|
|
22
23
|
import { SourcesPanel } from './SourcesPanel';
|
|
23
24
|
import { PackagesPanel } from './PackagesPanel';
|
|
@@ -172,6 +173,9 @@ export function FileEditor() {
|
|
|
172
173
|
if (!activeNode?.uri || !rawAgentId) return null;
|
|
173
174
|
return getRawFileUrl(rawAgentId, activeNode.uri, projectId ?? undefined);
|
|
174
175
|
}, [activeNode?.uri, rawAgentId, projectId]);
|
|
176
|
+
// An image or video renders from the byte lane, which says itself why it
|
|
177
|
+
// cannot (`RawMediaPreview`): the text read's failure is not this file's.
|
|
178
|
+
const mediaPreview = (isImage || isVideo) && !!rawUrl && !editing;
|
|
175
179
|
const previousActiveKeyRef = useRef<string | null>(null);
|
|
176
180
|
const paneRef = useRef<HTMLDivElement | null>(null);
|
|
177
181
|
const isWidePane = useContainerWidth(paneRef);
|
|
@@ -404,12 +408,12 @@ export function FileEditor() {
|
|
|
404
408
|
}, [hasMetaDetails]);
|
|
405
409
|
|
|
406
410
|
const handleStartEdit = useCallback(() => {
|
|
407
|
-
if (!activeNode || isDeleted) return;
|
|
411
|
+
if (!activeNode || isDeleted || errorMessage) return;
|
|
408
412
|
setDraftUri(activeNode.uri);
|
|
409
413
|
setDraftContent(activeContent);
|
|
410
414
|
setEditError(null);
|
|
411
415
|
setEditing(true);
|
|
412
|
-
}, [activeNode, activeContent, isDeleted]);
|
|
416
|
+
}, [activeNode, activeContent, isDeleted, errorMessage]);
|
|
413
417
|
|
|
414
418
|
const handleCancelEdit = useCallback(() => {
|
|
415
419
|
if (!activeNode) return;
|
|
@@ -703,7 +707,7 @@ export function FileEditor() {
|
|
|
703
707
|
<span className="truncate font-mono text-white/42">{displayFolderPath}</span>
|
|
704
708
|
</div>
|
|
705
709
|
)}
|
|
706
|
-
{errorMessage ? (
|
|
710
|
+
{errorMessage && !mediaPreview ? (
|
|
707
711
|
<div className="text-[10px] text-red-300/80 truncate" title={errorMessage}>
|
|
708
712
|
Read failed
|
|
709
713
|
</div>
|
|
@@ -741,8 +745,8 @@ export function FileEditor() {
|
|
|
741
745
|
type="button"
|
|
742
746
|
className="inline-flex items-center justify-center rounded-md bg-white/5 p-1.5 text-white/60 hover:text-white/80 hover:bg-white/10 transition disabled:opacity-40 disabled:cursor-not-allowed"
|
|
743
747
|
onClick={handleStartEdit}
|
|
744
|
-
disabled={!targetAgentId || isDeleted || isBinary}
|
|
745
|
-
title={isBinary ? 'Binary files cannot be edited in-place' : 'Edit in-place'}
|
|
748
|
+
disabled={!targetAgentId || isDeleted || isBinary || !!errorMessage}
|
|
749
|
+
title={isBinary ? 'Binary files cannot be edited in-place' : errorMessage ? 'The file could not be read — reload it to edit' : 'Edit in-place'}
|
|
746
750
|
aria-label="Edit in-place"
|
|
747
751
|
>
|
|
748
752
|
<Pencil className="w-3 h-3" />
|
|
@@ -916,7 +920,7 @@ export function FileEditor() {
|
|
|
916
920
|
) : null}
|
|
917
921
|
{showPackagesTab && projectId ? (
|
|
918
922
|
<div className="w-full h-full overflow-y-auto">
|
|
919
|
-
<PackagesPanel projectId={projectId} />
|
|
923
|
+
<PackagesPanel projectId={projectId} agentId={agentId ?? undefined} />
|
|
920
924
|
</div>
|
|
921
925
|
) : null}
|
|
922
926
|
{showPendingTab && agentId ? (
|
|
@@ -984,8 +988,8 @@ export function FileEditor() {
|
|
|
984
988
|
<div className="w-full h-full min-h-0 overflow-auto px-2 py-1.5">
|
|
985
989
|
<div className={cn(isDeleted && 'blur-[2px] opacity-65')}>
|
|
986
990
|
<div className="text-[11px] text-white/45 mb-3">Image preview</div>
|
|
987
|
-
|
|
988
|
-
|
|
991
|
+
<RawMediaPreview
|
|
992
|
+
kind="image"
|
|
989
993
|
src={rawUrl}
|
|
990
994
|
alt={activeNode.name}
|
|
991
995
|
className="max-w-full max-h-[calc(100vh-220px)] rounded-xl bg-black/20 shadow-[0_18px_46px_-26px_rgba(0,0,0,0.65),inset_0_1px_0_rgba(255,255,255,0.06)]"
|
|
@@ -996,9 +1000,10 @@ export function FileEditor() {
|
|
|
996
1000
|
<div className="w-full h-full min-h-0 overflow-auto px-2 py-1.5">
|
|
997
1001
|
<div className={cn(isDeleted && 'blur-[2px] opacity-65')}>
|
|
998
1002
|
<div className="text-[11px] text-white/45 mb-3">Video preview</div>
|
|
999
|
-
<
|
|
1003
|
+
<RawMediaPreview
|
|
1004
|
+
kind="video"
|
|
1000
1005
|
src={rawUrl}
|
|
1001
|
-
|
|
1006
|
+
alt={activeNode.name}
|
|
1002
1007
|
className="w-full max-w-[1100px] rounded-xl bg-black/20 shadow-[0_18px_46px_-26px_rgba(0,0,0,0.65),inset_0_1px_0_rgba(255,255,255,0.06)]"
|
|
1003
1008
|
/>
|
|
1004
1009
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useFilesystemStore, useFilesystemStoreApi, type SidebarView } from '../store/filesystemStore';
|
|
4
|
-
import React, { useMemo, useState, useCallback, useRef, useEffect } from 'react';
|
|
4
|
+
import React, { useMemo, useState, useCallback, useRef, useEffect, useLayoutEffect } from 'react';
|
|
5
5
|
import { SkillLauncher } from '@neuralis/package-system/client';
|
|
6
6
|
import { meetsRequires } from '@neuralis/package-system/access';
|
|
7
7
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
@@ -17,6 +17,7 @@ import { FileTreeContextMenu, type TreeMenuAction } from './FileTreeContextMenu'
|
|
|
17
17
|
import { TreeDeleteConfirm } from './TreeDeleteConfirm';
|
|
18
18
|
import { ReembedDialog, type ReembedTarget } from './ReembedDialog';
|
|
19
19
|
import { SourceBranchHeader } from './SourceBranchHeader';
|
|
20
|
+
import { sourceUnavailableLabel } from '../lib/treeVisualState';
|
|
20
21
|
import { FileTreeSearch } from './FileTreeSearch';
|
|
21
22
|
import { GitControlPanel } from './GitControlPanel';
|
|
22
23
|
import { fileKeyFromNode, folderUri, sourceFromUri, sourceRootUri, uriAncestors } from '../store/helpers';
|
|
@@ -109,7 +110,7 @@ export function isMeasuredRow(kind: FlatItemKind): boolean {
|
|
|
109
110
|
type FlatItem =
|
|
110
111
|
| { kind: 'header'; key: string; info: SourceInfo; expanded: boolean }
|
|
111
112
|
| { kind: 'node'; key: string; node: FileNode; depth: number }
|
|
112
|
-
| { kind: 'empty'; key: string; sourceRoot: string }
|
|
113
|
+
| { kind: 'empty'; key: string; sourceRoot: string; unavailable?: string }
|
|
113
114
|
| { kind: 'creating'; key: string; parentUri: string; createKind: 'file' | 'folder'; depth: number };
|
|
114
115
|
|
|
115
116
|
function sortNodes(a: FileNode, b: FileNode): number {
|
|
@@ -332,7 +333,10 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
332
333
|
if (!branchExpanded) continue;
|
|
333
334
|
const visible = flattenSource(treeIndex, info.uri_root, expanded);
|
|
334
335
|
if (visible.length === 0) {
|
|
335
|
-
|
|
336
|
+
// A source that cannot be reached is not an empty one: it says why, and
|
|
337
|
+
// offers nothing to populate.
|
|
338
|
+
const unavailable = sourceUnavailableLabel(info);
|
|
339
|
+
items.push({ kind: 'empty', key: `e:${info.uri_root}`, sourceRoot: info.uri_root, ...(unavailable ? { unavailable } : {}) });
|
|
336
340
|
} else {
|
|
337
341
|
for (const entry of visible) {
|
|
338
342
|
items.push({ kind: 'node', key: `n:${entry.node.uri}`, node: entry.node, depth: entry.depth });
|
|
@@ -439,9 +443,9 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
439
443
|
return uris.map((u) => files[u]).filter(Boolean) as FileNode[];
|
|
440
444
|
}, [contextMenu, selection, files]);
|
|
441
445
|
|
|
442
|
-
// HIDE-ONLY mirror of the reindex route's `
|
|
446
|
+
// HIDE-ONLY mirror of the reindex route's `sources.sync` gate — the route decides.
|
|
443
447
|
const canSync = useMemo(
|
|
444
|
-
() => meetsRequires({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, { features: ['
|
|
448
|
+
() => meetsRequires({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, { features: ['sources.sync'] }),
|
|
445
449
|
[host.grantedFeatures],
|
|
446
450
|
);
|
|
447
451
|
const [reembedTarget, setReembedTarget] = useState<ReembedTarget | null>(null);
|
|
@@ -700,7 +704,7 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
700
704
|
() => sourceInfos.every((info) => !sourceBranchExpanded[info.uri_root]),
|
|
701
705
|
[sourceInfos, sourceBranchExpanded],
|
|
702
706
|
);
|
|
703
|
-
// HIDE-ONLY feature gate. The server list is already `
|
|
707
|
+
// HIDE-ONLY feature gate. The server list is already `files.read`-gated and
|
|
704
708
|
// `seeRequires`-filtered, so this hides an affordance the caller could not use
|
|
705
709
|
// and authorizes NOTHING — the attach route stays the boundary. Hidden
|
|
706
710
|
// entirely, never a locked row (the S2 discipline). Evaluated with the ONE
|
|
@@ -709,7 +713,7 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
709
713
|
// The host value keeps the list `readonly` so no UI file can mutate the
|
|
710
714
|
// caller's grants; the kernel predicate takes a mutable array, so copy at
|
|
711
715
|
// the boundary rather than widening the contract.
|
|
712
|
-
() => meetsRequires({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, { features: ['
|
|
716
|
+
() => meetsRequires({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, { features: ['sources.mount'] }),
|
|
713
717
|
[host.grantedFeatures],
|
|
714
718
|
);
|
|
715
719
|
// FETCH: lazily, only once the dock could actually render. An eager fetch on
|
|
@@ -779,6 +783,32 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
779
783
|
getItemKey,
|
|
780
784
|
});
|
|
781
785
|
|
|
786
|
+
// The scroller UNMOUNTS whenever the git panel or a loading/empty state replaces
|
|
787
|
+
// the tree, but the virtualizer instance survives with its old scroll offset. On
|
|
788
|
+
// re-attach virtual-core writes that offset onto the NEW element; when the new
|
|
789
|
+
// content is still too short the browser clamps `scrollTop` to 0 without firing
|
|
790
|
+
// a scroll event, and the virtualizer keeps windowing from the stale offset — the
|
|
791
|
+
// first rows stay unrendered above a blank gap until the user scrolls. One read
|
|
792
|
+
// per attach (declared after `useVirtualizer`, so it runs after its `_willUpdate`)
|
|
793
|
+
// re-feeds the real offset through the virtualizer's own scroll listener — in a
|
|
794
|
+
// microtask, because that listener re-renders with `flushSync`, which React
|
|
795
|
+
// refuses inside a commit; the microtask still lands before the frame paints.
|
|
796
|
+
const scrollerAttachedRef = useRef(false);
|
|
797
|
+
const attachScroller = useCallback((el: HTMLDivElement | null) => {
|
|
798
|
+
parentRef.current = el;
|
|
799
|
+
if (el) scrollerAttachedRef.current = true;
|
|
800
|
+
}, []);
|
|
801
|
+
useLayoutEffect(() => {
|
|
802
|
+
if (!scrollerAttachedRef.current) return;
|
|
803
|
+
scrollerAttachedRef.current = false;
|
|
804
|
+
const el = parentRef.current;
|
|
805
|
+
if (el && el.scrollTop !== (virtualizer.scrollOffset ?? 0)) {
|
|
806
|
+
queueMicrotask(() => {
|
|
807
|
+
if (parentRef.current === el) el.dispatchEvent(new Event('scroll'));
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
|
|
782
812
|
// Git Control view (G2.1, Q1) — the panel REPLACES the tree + search IN PLACE,
|
|
783
813
|
// exactly like search does. Early-return AFTER all hooks (so none are skipped)
|
|
784
814
|
// and BEFORE the loading/empty tree short-circuits (the git panel owns its own
|
|
@@ -806,7 +836,7 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
806
836
|
|
|
807
837
|
// Root-listing failure (the SERVICE answered nothing — a single source's
|
|
808
838
|
// failure is its own header's `error` state). Without this surface the tree
|
|
809
|
-
// was silently "
|
|
839
|
+
// was silently "No files yet": the store wrote `snapshotError` and nothing read
|
|
810
840
|
// it. Retry re-runs the same root listing; a listing that answers clears it.
|
|
811
841
|
const snapshotBanner = snapshotError && !showSearch ? (
|
|
812
842
|
<div
|
|
@@ -835,7 +865,7 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
835
865
|
) : null;
|
|
836
866
|
|
|
837
867
|
if (!allNodes.length && !showSearch && !hasSources) {
|
|
838
|
-
return snapshotBanner ?? <div className="p-4 text-center text-xs text-white/30">
|
|
868
|
+
return snapshotBanner ?? <div className="p-4 text-center text-xs text-white/30">No files yet</div>;
|
|
839
869
|
}
|
|
840
870
|
|
|
841
871
|
const renderNode = (node: FileNode, depth: number) => {
|
|
@@ -881,7 +911,7 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
881
911
|
// `relative` anchors the dock's EXPANDED overlay form.
|
|
882
912
|
<div className="relative flex min-h-0 flex-1 flex-col">
|
|
883
913
|
<div
|
|
884
|
-
ref={
|
|
914
|
+
ref={attachScroller}
|
|
885
915
|
tabIndex={0}
|
|
886
916
|
onKeyDown={handleTreeKeyDown}
|
|
887
917
|
onContextMenu={handleBackgroundContextMenu}
|
|
@@ -946,21 +976,11 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
946
976
|
compact
|
|
947
977
|
/>
|
|
948
978
|
) : item.kind === 'empty' ? (
|
|
949
|
-
<
|
|
950
|
-
|
|
979
|
+
<SourceEmptyRow
|
|
980
|
+
sourceRoot={item.sourceRoot}
|
|
981
|
+
unavailable={item.unavailable}
|
|
951
982
|
onContextMenu={(e) => handleSourceContextMenu(item.sourceRoot, e)}
|
|
952
|
-
|
|
953
|
-
<span className="text-xs text-white/35">
|
|
954
|
-
No files for {sourceFromUri(item.sourceRoot)}
|
|
955
|
-
</span>
|
|
956
|
-
<SkillLauncher
|
|
957
|
-
variant="label"
|
|
958
|
-
skill="manage-files"
|
|
959
|
-
packageId="@neuralis/brain-core"
|
|
960
|
-
scripts={["scripts/upload.sh", "scripts/modify.sh"]}
|
|
961
|
-
label="Populate this source with the agent"
|
|
962
|
-
/>
|
|
963
|
-
</div>
|
|
983
|
+
/>
|
|
964
984
|
) : item.kind === 'creating' ? (
|
|
965
985
|
<CreateRow
|
|
966
986
|
kind={item.createKind}
|
|
@@ -1026,6 +1046,37 @@ export function FileTree(props: { agentId: string; sidebarView?: SidebarView })
|
|
|
1026
1046
|
);
|
|
1027
1047
|
}
|
|
1028
1048
|
|
|
1049
|
+
/**
|
|
1050
|
+
* The placeholder under an expanded source with no rows: "No files" and the
|
|
1051
|
+
* populate launcher — or, for a source that cannot be reached, its live state
|
|
1052
|
+
* and nothing to populate (an unreachable folder is not an empty one).
|
|
1053
|
+
*/
|
|
1054
|
+
export function SourceEmptyRow(props: {
|
|
1055
|
+
sourceRoot: string;
|
|
1056
|
+
unavailable?: string;
|
|
1057
|
+
onContextMenu?: (e: React.MouseEvent) => void;
|
|
1058
|
+
}) {
|
|
1059
|
+
return (
|
|
1060
|
+
<div className="flex flex-col items-start gap-1.5 px-4 py-2" onContextMenu={props.onContextMenu}>
|
|
1061
|
+
{props.unavailable ? (
|
|
1062
|
+
<span role="status" className="text-xs text-white/45">{props.unavailable}</span>
|
|
1063
|
+
) : (
|
|
1064
|
+
<>
|
|
1065
|
+
<span className="text-xs text-white/35">
|
|
1066
|
+
No files for {sourceFromUri(props.sourceRoot)}
|
|
1067
|
+
</span>
|
|
1068
|
+
<SkillLauncher
|
|
1069
|
+
variant="label"
|
|
1070
|
+
skill="manage-files"
|
|
1071
|
+
packageId="@neuralis/brain-core"
|
|
1072
|
+
label="Populate this source with the agent"
|
|
1073
|
+
/>
|
|
1074
|
+
</>
|
|
1075
|
+
)}
|
|
1076
|
+
</div>
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1029
1080
|
/**
|
|
1030
1081
|
* Inline "New File / New Folder" input row spliced into the tree at the create
|
|
1031
1082
|
* position. Enter commits, Escape / empty-blur cancels — the `doneRef` guard
|
|
@@ -28,6 +28,7 @@ export function FilesystemWidget(props: { agentId: string; projectId?: string |
|
|
|
28
28
|
const setSidebarView = useFilesystemStore((s) => s.setSidebarView);
|
|
29
29
|
const lastAppliedNavRef = useRef<string | null>(null);
|
|
30
30
|
const splitRef = useRef<HTMLDivElement | null>(null);
|
|
31
|
+
const sidebarRef = useRef<HTMLDivElement | null>(null);
|
|
31
32
|
const dragRef = useRef<{ startX: number; startWidth: number } | null>(null);
|
|
32
33
|
const [dragging, setDragging] = useState(false);
|
|
33
34
|
|
|
@@ -103,11 +104,16 @@ export function FilesystemWidget(props: { agentId: string; projectId?: string |
|
|
|
103
104
|
// the move keeps tracking even when the cursor leaves the thin handle. The
|
|
104
105
|
// upper bound is the live container width (minus the handle), so the tree can
|
|
105
106
|
// be dragged all the way over the editor, leaving only tree + chat visible.
|
|
107
|
+
// The RENDERED width is capped by CSS at the same bound: a narrowing widget
|
|
108
|
+
// eats the editor first, then the tree, and widening grows the tree back to
|
|
109
|
+
// the stored width — so the drag starts from the rendered width, never the
|
|
110
|
+
// stored one, or a capped tree would not follow the pointer at first.
|
|
106
111
|
const HANDLE_WIDTH = 8;
|
|
107
112
|
const onHandlePointerDown = useCallback(
|
|
108
113
|
(e: React.PointerEvent<HTMLDivElement>) => {
|
|
109
114
|
e.preventDefault();
|
|
110
|
-
|
|
115
|
+
const rendered = sidebarRef.current?.offsetWidth;
|
|
116
|
+
dragRef.current = { startX: e.clientX, startWidth: rendered && rendered < sidebarWidth ? rendered : sidebarWidth };
|
|
111
117
|
setDragging(true);
|
|
112
118
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
113
119
|
},
|
|
@@ -150,9 +156,11 @@ export function FilesystemWidget(props: { agentId: string; projectId?: string |
|
|
|
150
156
|
className={`flex-1 min-h-0 flex flex-row ${dragging ? 'select-none cursor-col-resize' : ''}`}
|
|
151
157
|
>
|
|
152
158
|
<div
|
|
159
|
+
ref={sidebarRef}
|
|
153
160
|
className="h-full flex flex-col min-h-0 shrink-0 overflow-hidden"
|
|
154
161
|
style={{
|
|
155
162
|
width: sidebarOpen ? sidebarWidth : 0,
|
|
163
|
+
maxWidth: `calc(100% - ${HANDLE_WIDTH}px)`,
|
|
156
164
|
backgroundColor: 'transparent',
|
|
157
165
|
borderRight: sidebarOpen ? '1px solid rgba(255,255,255,0.05)' : 'none',
|
|
158
166
|
}}
|
|
@@ -238,7 +246,7 @@ export function FilesystemWidget(props: { agentId: string; projectId?: string |
|
|
|
238
246
|
</div>
|
|
239
247
|
)}
|
|
240
248
|
|
|
241
|
-
<div className="flex-1 min-w-0 min-h-0">
|
|
249
|
+
<div className="flex-1 min-w-0 min-h-0 overflow-hidden">
|
|
242
250
|
<FileEditor />
|
|
243
251
|
</div>
|
|
244
252
|
</div>
|