@neuralis/brain-core 0.1.0 → 0.2.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 +26 -35
- package/app/README.md +1 -1
- package/app/cards/DiffView.tsx +9 -7
- package/app/cards/README.md +1 -1
- package/app/cards/diffLine.tsx +2 -4
- package/app/filesystem/README.md +4 -4
- package/app/filesystem/api/README.md +3 -3
- package/app/filesystem/api/index.ts +137 -123
- package/app/filesystem/domain/types.ts +36 -5
- package/app/filesystem/hooks/README.md +5 -5
- package/app/filesystem/hooks/useDiscoverableSources.ts +4 -2
- package/app/filesystem/hooks/useFilesystemSSE.ts +31 -23
- package/app/filesystem/hooks/useGitChangesInventory.ts +4 -2
- package/app/filesystem/host/README.md +3 -2
- package/app/filesystem/host/installFilesystemHostComponents.tsx +22 -9
- package/app/filesystem/store/README.md +11 -7
- package/app/filesystem/store/filesystemStore.ts +454 -162
- package/app/filesystem/store/gitSlice.ts +6 -6
- package/app/filesystem/store/listSlice.ts +10 -6
- package/app/filesystem/store/searchSlice.ts +27 -4
- package/app/filesystem/ui/FileEditor.tsx +48 -35
- package/app/filesystem/ui/FileTree.tsx +10 -9
- package/app/filesystem/ui/FileTreeSearch.tsx +29 -2
- package/app/filesystem/ui/GitCommitChangesView.tsx +5 -3
- package/app/filesystem/ui/GitCommitGraph.tsx +6 -5
- package/app/filesystem/ui/GitControlPanel.tsx +14 -13
- package/app/filesystem/ui/GitDiffView.tsx +2 -1
- package/app/filesystem/ui/GitFileDiff.tsx +7 -6
- package/app/filesystem/ui/PendingChangesPanel.tsx +88 -28
- package/app/filesystem/ui/PendingReviewDialog.tsx +52 -24
- package/app/filesystem/ui/README.md +8 -7
- package/app/filesystem/ui/ReembedDialog.tsx +22 -9
- package/app/filesystem/ui/SourceDeleteConfirm.tsx +1 -1
- package/app/filesystem/ui/SourcesPanel.tsx +135 -42
- package/app/filesystem/ui/VectorHealthPanel.tsx +20 -4
- package/app/filesystem/ui/pendingChangesModel.ts +9 -5
- package/dist/app/chunks/{astro-LRAFGXNX.js → astro-B2J4AS2D.js} +1 -1
- package/dist/app/chunks/bash-KY6SAQTH.js +1 -0
- package/dist/app/chunks/c-OBOPYVZ7.js +1 -0
- package/dist/app/chunks/{chunk-5H7ZCOD3.js → chunk-2X3GNKJ3.js} +1 -1
- package/dist/app/chunks/{chunk-XIFGTNRM.js → chunk-JPJIVRFI.js} +1 -1
- package/dist/app/chunks/{chunk-RH3QY5LF.js → chunk-LEFIFWND.js} +1 -1
- package/dist/app/chunks/{chunk-G4RZ3UNX.js → chunk-N6RXX3PH.js} +1 -1
- package/dist/app/chunks/{chunk-QXXJ73P5.js → chunk-PZAW4HPB.js} +1 -1
- package/dist/app/chunks/{chunk-3QLE7Y4L.js → chunk-ZBYWWTO6.js} +1 -1
- package/dist/app/chunks/cpp-TVWVOTEQ.js +1 -0
- package/dist/app/chunks/css-MANZBYA4.js +1 -0
- package/dist/app/chunks/{elixir-M36XROA6.js → elixir-S725Z7EH.js} +1 -1
- package/dist/app/chunks/{elm-7BG6QAIK.js → elm-5WUUSTNB.js} +1 -1
- package/dist/app/chunks/graphql-UGOPR3WU.js +1 -0
- package/dist/app/chunks/html-F6FWTBSG.js +1 -0
- package/dist/app/chunks/java-ANIVV5H5.js +1 -0
- package/dist/app/chunks/javascript-IH374YWG.js +1 -0
- package/dist/app/chunks/json-WGGVVXSB.js +1 -0
- package/dist/app/chunks/jsx-OTXJQD32.js +1 -0
- package/dist/app/chunks/{latex-ZWK7SXB6.js → latex-QCZNITGN.js} +1 -1
- package/dist/app/chunks/lua-4CRZ64PU.js +1 -0
- package/dist/app/chunks/{nginx-2L6VRV3A.js → nginx-V4CYS7WR.js} +1 -1
- package/dist/app/chunks/{perl-PBUAXXK6.js → perl-BHTX7F5B.js} +1 -1
- package/dist/app/chunks/{php-QJX57PA6.js → php-AYGJ5WYZ.js} +1 -1
- package/dist/app/chunks/r-4YFCFA4B.js +1 -0
- package/dist/app/chunks/{ruby-RLOWMVPO.js → ruby-42NMJWAL.js} +1 -1
- package/dist/app/chunks/{scss-B5CAI3HR.js → scss-XD7VU2CU.js} +1 -1
- package/dist/app/chunks/sql-B55MH6JJ.js +1 -0
- package/dist/app/chunks/{svelte-GT3D4C44.js → svelte-WR3QPIJU.js} +1 -1
- package/dist/app/chunks/tsx-S73GAE2L.js +1 -0
- package/dist/app/chunks/typescript-NEWOAB5Z.js +1 -0
- package/dist/app/chunks/{vue-JOW62MHD.js → vue-CCDS4VZK.js} +1 -1
- package/dist/app/chunks/xml-UXKAGLDR.js +1 -0
- package/dist/app/chunks/yaml-UMWKDTK7.js +1 -0
- package/dist/app/host.js +46 -46
- package/dist/scripts/embeddingLockV3.d.ts +30 -0
- package/dist/scripts/embeddingLockV3.d.ts.map +1 -0
- package/dist/scripts/embeddingLockV3.js +100 -0
- package/dist/scripts/embeddingLockV3.js.map +1 -0
- package/dist/scripts/vectorProofV1.d.ts +90 -0
- package/dist/scripts/vectorProofV1.d.ts.map +1 -0
- package/dist/scripts/vectorProofV1.js +220 -0
- package/dist/scripts/vectorProofV1.js.map +1 -0
- package/dist/src/config/env.d.ts +21 -0
- package/dist/src/config/env.d.ts.map +1 -1
- package/dist/src/config/env.js +55 -0
- package/dist/src/config/env.js.map +1 -1
- package/dist/src/connectors/AppSourceConfigStore.d.ts +12 -2
- package/dist/src/connectors/AppSourceConfigStore.d.ts.map +1 -1
- package/dist/src/connectors/AppSourceConfigStore.js +48 -40
- package/dist/src/connectors/AppSourceConfigStore.js.map +1 -1
- package/dist/src/connectors/LocalDiskConnector.d.ts +11 -14
- package/dist/src/connectors/LocalDiskConnector.d.ts.map +1 -1
- package/dist/src/connectors/LocalDiskConnector.js +87 -107
- package/dist/src/connectors/LocalDiskConnector.js.map +1 -1
- package/dist/src/connectors/sourceConfigMutation.d.ts +11 -1
- package/dist/src/connectors/sourceConfigMutation.d.ts.map +1 -1
- package/dist/src/connectors/sourceConfigMutation.js +36 -3
- package/dist/src/connectors/sourceConfigMutation.js.map +1 -1
- package/dist/src/domain/chunker.js +8 -3
- package/dist/src/domain/chunker.js.map +1 -1
- package/dist/src/domain/healthTypes.d.ts +11 -0
- package/dist/src/domain/healthTypes.d.ts.map +1 -1
- package/dist/src/domain/mime.d.ts +1 -0
- package/dist/src/domain/mime.d.ts.map +1 -1
- package/dist/src/domain/mime.js +48 -0
- package/dist/src/domain/mime.js.map +1 -1
- package/dist/src/domain/pendingChange.d.ts +7 -0
- package/dist/src/domain/pendingChange.d.ts.map +1 -1
- package/dist/src/domain/pendingChange.js +11 -0
- package/dist/src/domain/pendingChange.js.map +1 -1
- package/dist/src/domain/sourceConfig.d.ts +7 -14
- package/dist/src/domain/sourceConfig.d.ts.map +1 -1
- package/dist/src/domain/sourceConfig.js +1 -13
- package/dist/src/domain/sourceConfig.js.map +1 -1
- package/dist/src/domain/sourcePackages.d.ts +11 -2
- package/dist/src/domain/sourcePackages.d.ts.map +1 -1
- package/dist/src/domain/syncTrigger.d.ts +2 -3
- package/dist/src/domain/syncTrigger.d.ts.map +1 -1
- package/dist/src/domain/syncTrigger.js +2 -3
- package/dist/src/domain/syncTrigger.js.map +1 -1
- package/dist/src/domain/syncTypes.d.ts +21 -4
- package/dist/src/domain/syncTypes.d.ts.map +1 -1
- package/dist/src/domain/syncTypes.js.map +1 -1
- package/dist/src/domain/text.d.ts +3 -0
- package/dist/src/domain/text.d.ts.map +1 -1
- package/dist/src/domain/text.js +5 -0
- package/dist/src/domain/text.js.map +1 -1
- package/dist/src/domain/types.d.ts +9 -0
- package/dist/src/domain/types.d.ts.map +1 -1
- package/dist/src/embeddings/clients/GeminiEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/GeminiEmbedder.js +11 -5
- package/dist/src/embeddings/clients/GeminiEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/OllamaEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/OllamaEmbedder.js +13 -6
- package/dist/src/embeddings/clients/OllamaEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/OpenAIEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/OpenAIEmbedder.js +12 -9
- package/dist/src/embeddings/clients/OpenAIEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/QwenEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/QwenEmbedder.js +12 -5
- package/dist/src/embeddings/clients/QwenEmbedder.js.map +1 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.d.ts.map +1 -1
- package/dist/src/embeddings/clients/VoyageEmbedder.js +12 -5
- package/dist/src/embeddings/clients/VoyageEmbedder.js.map +1 -1
- package/dist/src/embeddings/factory.d.ts +2 -0
- package/dist/src/embeddings/factory.d.ts.map +1 -1
- package/dist/src/embeddings/factory.js +23 -3
- package/dist/src/embeddings/factory.js.map +1 -1
- package/dist/src/embeddings/lock.d.ts +22 -11
- package/dist/src/embeddings/lock.d.ts.map +1 -1
- package/dist/src/embeddings/lock.js +47 -29
- package/dist/src/embeddings/lock.js.map +1 -1
- package/dist/src/embeddings/retry.d.ts +5 -0
- package/dist/src/embeddings/retry.d.ts.map +1 -1
- package/dist/src/embeddings/retry.js +35 -0
- package/dist/src/embeddings/retry.js.map +1 -1
- package/dist/src/events/pending.d.ts +56 -0
- package/dist/src/events/pending.d.ts.map +1 -0
- package/dist/src/events/pending.js +108 -0
- package/dist/src/events/pending.js.map +1 -0
- package/dist/src/events/source.d.ts +60 -14
- package/dist/src/events/source.d.ts.map +1 -1
- package/dist/src/events/source.js +149 -31
- package/dist/src/events/source.js.map +1 -1
- package/dist/src/events/vector.d.ts +33 -0
- package/dist/src/events/vector.d.ts.map +1 -0
- package/dist/src/events/vector.js +57 -0
- package/dist/src/events/vector.js.map +1 -0
- package/dist/src/git/GitRunner.d.ts.map +1 -1
- package/dist/src/git/GitRunner.js +11 -8
- package/dist/src/git/GitRunner.js.map +1 -1
- package/dist/src/git/sourceGitControl.d.ts.map +1 -1
- package/dist/src/git/sourceGitControl.js +2 -1
- package/dist/src/git/sourceGitControl.js.map +1 -1
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/lifecycle.d.ts +20 -4
- package/dist/src/lifecycle.d.ts.map +1 -1
- package/dist/src/lifecycle.js +5 -1
- package/dist/src/lifecycle.js.map +1 -1
- package/dist/src/routes/health.js +6 -1
- package/dist/src/routes/health.js.map +1 -1
- package/dist/src/routes/pending.d.ts.map +1 -1
- package/dist/src/routes/pending.js +2 -1
- package/dist/src/routes/pending.js.map +1 -1
- package/dist/src/routes/sources.d.ts.map +1 -1
- package/dist/src/routes/sources.js +60 -11
- package/dist/src/routes/sources.js.map +1 -1
- package/dist/src/services/BridgeService.d.ts +2 -2
- package/dist/src/services/BridgeService.d.ts.map +1 -1
- package/dist/src/services/BridgeService.js +11 -2
- package/dist/src/services/BridgeService.js.map +1 -1
- package/dist/src/services/FilesystemService.d.ts +3 -1
- package/dist/src/services/FilesystemService.d.ts.map +1 -1
- package/dist/src/services/FilesystemService.js +3 -1
- package/dist/src/services/FilesystemService.js.map +1 -1
- package/dist/src/services/FilesystemUiService.js +1 -1
- package/dist/src/services/FilesystemUiService.js.map +1 -1
- package/dist/src/services/SyncScheduler.d.ts.map +1 -1
- package/dist/src/services/SyncScheduler.js +0 -14
- package/dist/src/services/SyncScheduler.js.map +1 -1
- package/dist/src/services/VectorHealthService.d.ts.map +1 -1
- package/dist/src/services/VectorHealthService.js +2 -46
- package/dist/src/services/VectorHealthService.js.map +1 -1
- package/dist/src/services/baselineRepair.d.ts +2 -2
- package/dist/src/services/baselineRepair.js +2 -2
- package/dist/src/services/declaredSources.d.ts +8 -1
- package/dist/src/services/declaredSources.d.ts.map +1 -1
- package/dist/src/services/declaredSources.js +19 -19
- package/dist/src/services/declaredSources.js.map +1 -1
- package/dist/src/store/dataFormats.d.ts +14 -3
- package/dist/src/store/dataFormats.d.ts.map +1 -1
- package/dist/src/store/dataFormats.js +15 -5
- 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 +78 -243
- package/dist/src/sync/DeltaSyncRunner.js.map +1 -1
- package/dist/src/sync/SyncJobQueue.d.ts +33 -4
- package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
- package/dist/src/sync/SyncJobQueue.js +179 -19
- package/dist/src/sync/SyncJobQueue.js.map +1 -1
- package/dist/src/sync/moveDetector.d.ts +2 -1
- package/dist/src/sync/moveDetector.d.ts.map +1 -1
- package/dist/src/sync/moveDetector.js +2 -1
- package/dist/src/sync/moveDetector.js.map +1 -1
- package/dist/src/tools/fs_search.d.ts.map +1 -1
- package/dist/src/tools/fs_search.js +8 -0
- package/dist/src/tools/fs_search.js.map +1 -1
- package/dist/src/tools/fs_write.js +3 -1
- package/dist/src/tools/fs_write.js.map +1 -1
- package/dist/src/usecases/chunkUpsert.d.ts +4 -0
- package/dist/src/usecases/chunkUpsert.d.ts.map +1 -1
- package/dist/src/usecases/chunkUpsert.js +103 -60
- package/dist/src/usecases/chunkUpsert.js.map +1 -1
- package/dist/src/usecases/embeddingBacklog.d.ts +31 -0
- package/dist/src/usecases/embeddingBacklog.d.ts.map +1 -0
- package/dist/src/usecases/embeddingBacklog.js +244 -0
- package/dist/src/usecases/embeddingBacklog.js.map +1 -0
- package/dist/src/usecases/listSourcePackages.js +17 -1
- package/dist/src/usecases/listSourcePackages.js.map +1 -1
- package/dist/src/usecases/mediaLane.d.ts +11 -4
- package/dist/src/usecases/mediaLane.d.ts.map +1 -1
- package/dist/src/usecases/mediaLane.js +67 -30
- package/dist/src/usecases/mediaLane.js.map +1 -1
- package/dist/src/usecases/pendingReview.d.ts.map +1 -1
- package/dist/src/usecases/pendingReview.js +24 -7
- package/dist/src/usecases/pendingReview.js.map +1 -1
- package/dist/src/usecases/purgeExcludedPoints.d.ts +2 -0
- 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 +33 -6
- package/dist/src/usecases/readFiles.js.map +1 -1
- package/dist/src/usecases/reconcileSourcePackageRoots.d.ts +31 -0
- package/dist/src/usecases/reconcileSourcePackageRoots.d.ts.map +1 -0
- package/dist/src/usecases/reconcileSourcePackageRoots.js +114 -0
- package/dist/src/usecases/reconcileSourcePackageRoots.js.map +1 -0
- package/dist/src/usecases/searchFiles.d.ts.map +1 -1
- package/dist/src/usecases/searchFiles.js +62 -64
- package/dist/src/usecases/searchFiles.js.map +1 -1
- package/dist/src/usecases/syncIndexedFile.d.ts +42 -0
- package/dist/src/usecases/syncIndexedFile.d.ts.map +1 -0
- package/dist/src/usecases/syncIndexedFile.js +242 -0
- package/dist/src/usecases/syncIndexedFile.js.map +1 -0
- package/dist/src/usecases/syncPointWrites.d.ts +5 -0
- package/dist/src/usecases/syncPointWrites.d.ts.map +1 -1
- package/dist/src/usecases/syncPointWrites.js +32 -5
- package/dist/src/usecases/syncPointWrites.js.map +1 -1
- package/dist/src/usecases/uploadBinary.d.ts.map +1 -1
- package/dist/src/usecases/uploadBinary.js +36 -49
- package/dist/src/usecases/uploadBinary.js.map +1 -1
- package/dist/src/usecases/vector/endpointGuard.js +2 -1
- package/dist/src/usecases/vector/endpointGuard.js.map +1 -1
- package/dist/src/usecases/vector/estimate.d.ts +7 -4
- package/dist/src/usecases/vector/estimate.d.ts.map +1 -1
- package/dist/src/usecases/vector/estimate.js +8 -5
- package/dist/src/usecases/vector/estimate.js.map +1 -1
- package/dist/src/usecases/vector/rebuildGeneration.d.ts +29 -5
- package/dist/src/usecases/vector/rebuildGeneration.d.ts.map +1 -1
- package/dist/src/usecases/vector/rebuildGeneration.js +224 -82
- package/dist/src/usecases/vector/rebuildGeneration.js.map +1 -1
- package/dist/src/usecases/vectorMaintenance.d.ts +46 -4
- package/dist/src/usecases/vectorMaintenance.d.ts.map +1 -1
- package/dist/src/usecases/vectorMaintenance.js +190 -11
- package/dist/src/usecases/vectorMaintenance.js.map +1 -1
- package/dist/src/usecases/write/commit.d.ts +6 -8
- package/dist/src/usecases/write/commit.d.ts.map +1 -1
- package/dist/src/usecases/write/commit.js +96 -112
- package/dist/src/usecases/write/commit.js.map +1 -1
- package/dist/src/usecases/write/content.js +1 -2
- package/dist/src/usecases/write/content.js.map +1 -1
- package/dist/src/usecases/write/ports.d.ts +1 -0
- package/dist/src/usecases/write/ports.d.ts.map +1 -1
- package/dist/src/vector/FilesystemVectorIndex.d.ts +34 -3
- package/dist/src/vector/FilesystemVectorIndex.d.ts.map +1 -1
- package/dist/src/vector/FilesystemVectorIndex.js +254 -20
- package/dist/src/vector/FilesystemVectorIndex.js.map +1 -1
- package/dist/src/vector/InMemoryVectorIndex.d.ts +9 -2
- package/dist/src/vector/InMemoryVectorIndex.d.ts.map +1 -1
- package/dist/src/vector/InMemoryVectorIndex.js +25 -6
- package/dist/src/vector/InMemoryVectorIndex.js.map +1 -1
- package/dist/src/vector/QdrantVectorIndex.d.ts +35 -9
- package/dist/src/vector/QdrantVectorIndex.d.ts.map +1 -1
- package/dist/src/vector/QdrantVectorIndex.js +209 -90
- package/dist/src/vector/QdrantVectorIndex.js.map +1 -1
- package/dist/src/vector/qdrantFilter.d.ts +3 -1
- package/dist/src/vector/qdrantFilter.d.ts.map +1 -1
- package/dist/src/vector/qdrantFilter.js +2 -0
- package/dist/src/vector/qdrantFilter.js.map +1 -1
- package/dist/src/vector/types.d.ts +81 -0
- package/dist/src/vector/types.d.ts.map +1 -1
- package/dist/src/vector/types.js +2 -0
- package/dist/src/vector/types.js.map +1 -1
- package/dist/src/wiring.d.ts +6 -0
- package/dist/src/wiring.d.ts.map +1 -1
- package/dist/src/wiring.js +62 -3
- package/dist/src/wiring.js.map +1 -1
- package/dist/tools/fs_search.json +2 -2
- package/docs/drive-overview.md +2 -2
- package/instructions/brain-model.md +1 -1
- package/package.json +1000 -11
- package/rules/brain-rules.md +1 -1
- package/skills/connect-business-data/SKILL.md +6 -4
- package/skills/create-package/SKILL.md +14 -12
- package/skills/create-package/references/config-and-credentials.md +3 -3
- package/skills/create-package/references/connectors-and-uri-policies.md +5 -3
- package/skills/create-package/references/manifest-and-discovery.md +5 -4
- package/skills/create-package/references/runtime-and-build.md +9 -9
- package/skills/create-package/references/skills-and-context.md +3 -3
- package/skills/create-package/references/surfaces-and-design.md +9 -6
- package/skills/create-package/references/team-and-workflows.md +2 -2
- package/skills/create-package/references/test-and-ship.md +15 -15
- package/skills/create-package/references/tools-and-schemas.md +1 -1
- package/skills/create-package/scripts/check-package.sh +50 -4
- package/skills/create-package/scripts/verify-loaded.sh +16 -16
- package/skills/manage-files/SKILL.md +2 -2
- package/skills/manage-sources/SKILL.md +16 -15
- package/skills/manage-sources/scripts/reembed.sh +9 -3
- package/skills/sync/SKILL.md +4 -4
- package/tools/fs_search.json +2 -2
- package/app/filesystem/hooks/useContainerWidth.ts +0 -39
- package/dist/app/chunks/bash-M45GHPBQ.js +0 -1
- package/dist/app/chunks/c-X3REOAWD.js +0 -1
- package/dist/app/chunks/cpp-VOWI743W.js +0 -1
- package/dist/app/chunks/css-2ZVPHE25.js +0 -1
- package/dist/app/chunks/graphql-7V2NP54C.js +0 -1
- package/dist/app/chunks/html-UF3LFLNA.js +0 -1
- package/dist/app/chunks/java-PNTAU4L3.js +0 -1
- package/dist/app/chunks/javascript-4JJTQGEL.js +0 -1
- package/dist/app/chunks/json-VLQ6D3JH.js +0 -1
- package/dist/app/chunks/jsx-KQKSLAAH.js +0 -1
- package/dist/app/chunks/lua-UFPYUJ2O.js +0 -1
- package/dist/app/chunks/r-QEZB45SR.js +0 -1
- package/dist/app/chunks/sql-DTZHNUZP.js +0 -1
- package/dist/app/chunks/tsx-WPR2WRZD.js +0 -1
- package/dist/app/chunks/typescript-LWO362OA.js +0 -1
- package/dist/app/chunks/xml-A5H72RTS.js +0 -1
- package/dist/app/chunks/yaml-MXHSIJCI.js +0 -1
- package/dist/src/services/purgePendingNodes.d.ts +0 -32
- package/dist/src/services/purgePendingNodes.d.ts.map +0 -1
- package/dist/src/services/purgePendingNodes.js +0 -61
- package/dist/src/services/purgePendingNodes.js.map +0 -1
- /package/dist/app/chunks/{chunk-737Y24HS.js → chunk-3JASFUPF.js} +0 -0
- /package/dist/app/chunks/{chunk-DKD2L57N.js → chunk-6EYLOQ4F.js} +0 -0
- /package/dist/app/chunks/{chunk-KYH5EHHY.js → chunk-7YRZ5LOQ.js} +0 -0
- /package/dist/app/chunks/{chunk-6TC3DVWV.js → chunk-C7LU4RID.js} +0 -0
- /package/dist/app/chunks/{chunk-TY33BMKR.js → chunk-CD52YDZP.js} +0 -0
- /package/dist/app/chunks/{chunk-OLEIKJ3X.js → chunk-DCJKTCJ5.js} +0 -0
- /package/dist/app/chunks/{chunk-QLBZ4JR2.js → chunk-EXIU2KBV.js} +0 -0
- /package/dist/app/chunks/{chunk-SFUNBBEA.js → chunk-FDP4LO4P.js} +0 -0
- /package/dist/app/chunks/{chunk-BGRVFATT.js → chunk-HNETUS7U.js} +0 -0
- /package/dist/app/chunks/{chunk-4QNMHAIR.js → chunk-LBFZJEDR.js} +0 -0
- /package/dist/app/chunks/{chunk-TRRUHDPN.js → chunk-ULRXL5VM.js} +0 -0
- /package/dist/app/chunks/{chunk-S6B4WWIF.js → chunk-XJK47SMJ.js} +0 -0
- /package/dist/app/chunks/{chunk-DZ5C5FKI.js → chunk-YYAAIAU2.js} +0 -0
- /package/dist/app/chunks/{clojure-OC6KPSJO.js → clojure-4QCN4GHG.js} +0 -0
- /package/dist/app/chunks/{core-KGE7TQJ3.js → core-ZHTX3P2Q.js} +0 -0
- /package/dist/app/chunks/{csharp-E7VIFITL.js → csharp-HQWR4N52.js} +0 -0
- /package/dist/app/chunks/{dark-plus-BOSCZXE4.js → dark-plus-GYPKKZES.js} +0 -0
- /package/dist/app/chunks/{dart-6Y3X27SZ.js → dart-FO4TTVO2.js} +0 -0
- /package/dist/app/chunks/{diff-TR2NPA64.js → diff-SHANV4YC.js} +0 -0
- /package/dist/app/chunks/{dist-T32U2VVR.js → dist-WSDF34DM.js} +0 -0
- /package/dist/app/chunks/{docker-N33HOW54.js → docker-VX55HTDS.js} +0 -0
- /package/dist/app/chunks/{go-6DGG5UTP.js → go-5UCPEC6S.js} +0 -0
- /package/dist/app/chunks/{haskell-KK36PMMM.js → haskell-25PJ3OSG.js} +0 -0
- /package/dist/app/chunks/{ini-VHVQ5TPB.js → ini-BJIVD5MK.js} +0 -0
- /package/dist/app/chunks/{kotlin-44WS3JHE.js → kotlin-MNR6XOEQ.js} +0 -0
- /package/dist/app/chunks/{less-5WZ3KLAK.js → less-KA5JURX6.js} +0 -0
- /package/dist/app/chunks/{light-plus-HGGBC43G.js → light-plus-QXH2UUWZ.js} +0 -0
- /package/dist/app/chunks/{make-X7RXMVW7.js → make-LPD5KOCO.js} +0 -0
- /package/dist/app/chunks/{markdown-46IKUAIB.js → markdown-LMWF6MQR.js} +0 -0
- /package/dist/app/chunks/{mdx-DGLHDAO7.js → mdx-WPMNN5BS.js} +0 -0
- /package/dist/app/chunks/{nix-Q6FYQZLX.js → nix-QGWLUUMZ.js} +0 -0
- /package/dist/app/chunks/{powershell-L4KJJ6DK.js → powershell-7GSBBEFF.js} +0 -0
- /package/dist/app/chunks/{prisma-IKS4LVH2.js → prisma-FPMPQISO.js} +0 -0
- /package/dist/app/chunks/{proto-AYCDOTJO.js → proto-7KDX5Z2U.js} +0 -0
- /package/dist/app/chunks/{python-KXMCSAFQ.js → python-CFG4FTQW.js} +0 -0
- /package/dist/app/chunks/{rust-J3BC3P6V.js → rust-X7A37WU3.js} +0 -0
- /package/dist/app/chunks/{scala-AYIIHBJK.js → scala-OYHJSUG2.js} +0 -0
- /package/dist/app/chunks/{swift-QPHHCQD3.js → swift-PE7VNYW5.js} +0 -0
- /package/dist/app/chunks/{toml-UV7JK7K7.js → toml-ETQRDILP.js} +0 -0
|
@@ -431,6 +431,7 @@ export function GitCommitGraph({
|
|
|
431
431
|
* E) — two-part `slug:// Name` header render; absent → slug-only fallback. */
|
|
432
432
|
repoName?: string;
|
|
433
433
|
}) {
|
|
434
|
+
const client = useFilesystemStore((s) => s.client);
|
|
434
435
|
const [page, setPage] = useState<GraphPageState>(emptyGraphPageState);
|
|
435
436
|
const [loading, setLoading] = useState(false);
|
|
436
437
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -508,7 +509,7 @@ export function GitCommitGraph({
|
|
|
508
509
|
...(repo ? { repo } : {}),
|
|
509
510
|
maxCount,
|
|
510
511
|
skip,
|
|
511
|
-
});
|
|
512
|
+
}, client);
|
|
512
513
|
if (mySeq !== seqRef.current) return;
|
|
513
514
|
const fetched = {
|
|
514
515
|
commits: Array.isArray(res?.commits) ? res.commits : [],
|
|
@@ -530,7 +531,7 @@ export function GitCommitGraph({
|
|
|
530
531
|
...(repo ? { repo } : {}),
|
|
531
532
|
maxCount,
|
|
532
533
|
skip,
|
|
533
|
-
})
|
|
534
|
+
}, client)
|
|
534
535
|
.then((stats) => {
|
|
535
536
|
if (mySeq !== seqRef.current) return;
|
|
536
537
|
setCommitStats((cur) => (mode === 'append' ? { ...cur, ...stats.stats } : { ...stats.stats }));
|
|
@@ -643,7 +644,7 @@ export function GitCommitGraph({
|
|
|
643
644
|
source,
|
|
644
645
|
...(repo ? { repo } : {}),
|
|
645
646
|
sha,
|
|
646
|
-
});
|
|
647
|
+
}, client);
|
|
647
648
|
if (epoch !== filesEpochRef.current) return;
|
|
648
649
|
setCommitFiles((prev) =>
|
|
649
650
|
new Map(prev).set(
|
|
@@ -702,7 +703,7 @@ export function GitCommitGraph({
|
|
|
702
703
|
...(projectId ? { projectId } : {}),
|
|
703
704
|
source,
|
|
704
705
|
...(repo ? { repo } : {}),
|
|
705
|
-
});
|
|
706
|
+
}, client);
|
|
706
707
|
if (epoch !== outgoingEpochRef.current) return;
|
|
707
708
|
// 3b: a deep-fail is a typed `{ok:false,'unavailable'}` refusal now — treat
|
|
708
709
|
// it like no-upstream (nothing to show), never crash on a missing files[].
|
|
@@ -812,7 +813,7 @@ export function GitCommitGraph({
|
|
|
812
813
|
...(projectId ? { projectId } : {}),
|
|
813
814
|
source,
|
|
814
815
|
...(repo ? { repo } : {}),
|
|
815
|
-
});
|
|
816
|
+
}, client);
|
|
816
817
|
if (epoch !== outgoingEpochRef.current) return;
|
|
817
818
|
// 3b: a deep-fail is a typed `{ok:false,'unavailable'}` refusal now — treat
|
|
818
819
|
// it like no-upstream (nothing to show), never crash on a missing files[].
|
|
@@ -453,6 +453,7 @@ type ConfirmState = { title: string; message: string; confirmLabel: string; onCo
|
|
|
453
453
|
type RescueState = { message: string; rescue: GitRescue };
|
|
454
454
|
|
|
455
455
|
export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
456
|
+
const client = useFilesystemStore((s) => s.client);
|
|
456
457
|
const sources = useFilesystemStore((s) => s.sources);
|
|
457
458
|
const projectId = useFilesystemStore((s) => s.activeProjectId);
|
|
458
459
|
const activeSource = useFilesystemStore((s) => s.activeSource);
|
|
@@ -554,7 +555,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
554
555
|
if (cached && (cached instanceof Promise || !opts?.force)) return cached;
|
|
555
556
|
const task = (async () => {
|
|
556
557
|
try {
|
|
557
|
-
const res = await getGitRepos({ agentId, ...(projectId ? { projectId } : {}), source: slug });
|
|
558
|
+
const res = await getGitRepos({ agentId, ...(projectId ? { projectId } : {}), source: slug }, client);
|
|
558
559
|
const repos = Array.isArray(res?.repos) ? res.repos : [];
|
|
559
560
|
repoListsRef.current.set(slug, repos);
|
|
560
561
|
setRepoLists((prev) => new Map(prev).set(slug, repos));
|
|
@@ -799,7 +800,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
799
800
|
const handleStage = useCallback(
|
|
800
801
|
(paths: string[]) => {
|
|
801
802
|
if (paths.length === 0) return;
|
|
802
|
-
void doWrite(() => stagePaths({ agentId, ...p, source: selectedSlug, paths }));
|
|
803
|
+
void doWrite(() => stagePaths({ agentId, ...p, source: selectedSlug, paths }, client));
|
|
803
804
|
},
|
|
804
805
|
[doWrite, agentId, p, selectedSlug],
|
|
805
806
|
);
|
|
@@ -807,7 +808,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
807
808
|
const handleUnstage = useCallback(
|
|
808
809
|
(paths: string[]) => {
|
|
809
810
|
if (paths.length === 0) return;
|
|
810
|
-
void doWrite(() => unstagePaths({ agentId, ...p, source: selectedSlug, paths }));
|
|
811
|
+
void doWrite(() => unstagePaths({ agentId, ...p, source: selectedSlug, paths }, client));
|
|
811
812
|
},
|
|
812
813
|
[doWrite, agentId, p, selectedSlug],
|
|
813
814
|
);
|
|
@@ -815,7 +816,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
815
816
|
const runDiscard = useCallback(
|
|
816
817
|
(paths: string[]) => {
|
|
817
818
|
void (async () => {
|
|
818
|
-
const res = await doWrite(() => discardPaths({ agentId, ...p, source: selectedSlug, paths }));
|
|
819
|
+
const res = await doWrite(() => discardPaths({ agentId, ...p, source: selectedSlug, paths }, client));
|
|
819
820
|
if (res && res.rescue) {
|
|
820
821
|
setRescue({
|
|
821
822
|
message: `Discarded ${paths.length} file${paths.length === 1 ? '' : 's'} — recoverable`,
|
|
@@ -875,7 +876,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
875
876
|
const message = commitMessage.trim();
|
|
876
877
|
if (!message) return;
|
|
877
878
|
void (async () => {
|
|
878
|
-
const res = await doWrite(() => commitGit({ agentId, ...p, source: selectedSlug, message, amend }));
|
|
879
|
+
const res = await doWrite(() => commitGit({ agentId, ...p, source: selectedSlug, message, amend }, client));
|
|
879
880
|
if (res && res.ok) {
|
|
880
881
|
setCommitMessage('');
|
|
881
882
|
setAmend(false);
|
|
@@ -901,7 +902,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
901
902
|
(ref: string) => {
|
|
902
903
|
setBranchPickerOpen(false);
|
|
903
904
|
void (async () => {
|
|
904
|
-
const res = await doWrite(() => checkoutGitBranch({ agentId, ...p, source: selectedSlug, ref }));
|
|
905
|
+
const res = await doWrite(() => checkoutGitBranch({ agentId, ...p, source: selectedSlug, ref }, client));
|
|
905
906
|
if (res)
|
|
906
907
|
void loadGitBranches({ agentId, projectId: projectId ?? null, source: selectedSlug, repo: activeRepoRel });
|
|
907
908
|
})();
|
|
@@ -920,10 +921,10 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
920
921
|
void (async () => {
|
|
921
922
|
// Create then switch to it (VS-Code "Create new branch" also checks out).
|
|
922
923
|
const created = await doWrite(() =>
|
|
923
|
-
createGitBranch({ agentId, ...p, source: selectedSlug, name, ...(from ? { startPoint: from } : {}) }),
|
|
924
|
+
createGitBranch({ agentId, ...p, source: selectedSlug, name, ...(from ? { startPoint: from } : {}) }, client),
|
|
924
925
|
);
|
|
925
926
|
if (created) {
|
|
926
|
-
await doWrite(() => checkoutGitBranch({ agentId, ...p, source: selectedSlug, ref: name }));
|
|
927
|
+
await doWrite(() => checkoutGitBranch({ agentId, ...p, source: selectedSlug, ref: name }, client));
|
|
927
928
|
void loadGitBranches({ agentId, projectId: projectId ?? null, source: selectedSlug, repo: activeRepoRel });
|
|
928
929
|
}
|
|
929
930
|
})();
|
|
@@ -932,7 +933,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
932
933
|
const runDeleteBranch = useCallback(
|
|
933
934
|
(name: string) => {
|
|
934
935
|
void (async () => {
|
|
935
|
-
const res = await doWrite(() => deleteGitBranch({ agentId, ...p, source: selectedSlug, name }));
|
|
936
|
+
const res = await doWrite(() => deleteGitBranch({ agentId, ...p, source: selectedSlug, name }, client));
|
|
936
937
|
if (res && res.rescue) {
|
|
937
938
|
setRescue({ message: `Deleted branch "${name}" — recoverable`, rescue: res.rescue });
|
|
938
939
|
}
|
|
@@ -966,7 +967,7 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
966
967
|
if (!rescue) return;
|
|
967
968
|
const carrier = rescue.rescue;
|
|
968
969
|
setRescue(null);
|
|
969
|
-
void doWrite(() => restoreGit({ agentId, ...p, source: selectedSlug, rescue: carrier }));
|
|
970
|
+
void doWrite(() => restoreGit({ agentId, ...p, source: selectedSlug, rescue: carrier }, client));
|
|
970
971
|
}, [rescue, doWrite, agentId, p, selectedSlug]);
|
|
971
972
|
|
|
972
973
|
// --- Remote operations (G4 keyring-kestrel Slice 2) ------------------------
|
|
@@ -976,17 +977,17 @@ export function GitControlPanel({ agentId }: { agentId: string }) {
|
|
|
976
977
|
|
|
977
978
|
const handleFetch = useCallback(() => {
|
|
978
979
|
setRemotePickerOpen(false);
|
|
979
|
-
void doWrite(() => fetchGit({ agentId, ...p, source: selectedSlug }));
|
|
980
|
+
void doWrite(() => fetchGit({ agentId, ...p, source: selectedSlug }, client));
|
|
980
981
|
}, [doWrite, agentId, p, selectedSlug]);
|
|
981
982
|
|
|
982
983
|
const handlePull = useCallback(() => {
|
|
983
984
|
setRemotePickerOpen(false);
|
|
984
|
-
void doWrite(() => pullGit({ agentId, ...p, source: selectedSlug }));
|
|
985
|
+
void doWrite(() => pullGit({ agentId, ...p, source: selectedSlug }, client));
|
|
985
986
|
}, [doWrite, agentId, p, selectedSlug]);
|
|
986
987
|
|
|
987
988
|
const handlePush = useCallback(() => {
|
|
988
989
|
setRemotePickerOpen(false);
|
|
989
|
-
void doWrite(() => pushGit({ agentId, ...p, source: selectedSlug }));
|
|
990
|
+
void doWrite(() => pushGit({ agentId, ...p, source: selectedSlug }, client));
|
|
990
991
|
}, [doWrite, agentId, p, selectedSlug]);
|
|
991
992
|
|
|
992
993
|
const unstagedChanges = gitStatus?.unstaged ?? [];
|
|
@@ -26,11 +26,12 @@ export function GitDiffView({
|
|
|
26
26
|
agentId: string | null;
|
|
27
27
|
projectId: string | null;
|
|
28
28
|
}): React.ReactElement {
|
|
29
|
+
const client = useFilesystemStore((s) => s.client);
|
|
29
30
|
const [canWrite, setCanWrite] = useState(false);
|
|
30
31
|
const revision = useFilesystemStore(state => state.sourceChangeRevision[target.source] ?? 0);
|
|
31
32
|
useEffect(() => {
|
|
32
33
|
let alive = true; setCanWrite(false);
|
|
33
|
-
if (agentId) void getGitRepos({ agentId, ...(projectId ? { projectId } : {}), source: target.source }).then(result => {
|
|
34
|
+
if (agentId) void getGitRepos({ agentId, ...(projectId ? { projectId } : {}), source: target.source }, client).then(result => {
|
|
34
35
|
if (alive) setCanWrite(result.repos.find(repo => repo.rel === (target.repo ?? ''))?.canWrite === true);
|
|
35
36
|
}).catch(() => { if (alive) setCanWrite(false); });
|
|
36
37
|
return () => { alive = false; };
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
import { computeGitDiffTokens, renderShikiToken } from './gitDiffShikiTokenizer';
|
|
37
37
|
import { resolveShikiLang, isShikiReady, ensureLanguage, getHighlighter } from './codeEditor/shikiHighlighter';
|
|
38
38
|
import { detectCodeLanguage } from '../lib/detectLanguage';
|
|
39
|
-
import { useContainerWidth } from '
|
|
39
|
+
import { useContainerWidth } from '@neuralis/package-system/client';
|
|
40
40
|
import type { VisibleDiffQueue } from '../hooks/useVisibleDiffCards';
|
|
41
41
|
import { DiffModeToggle } from './DiffModeToggle';
|
|
42
42
|
|
|
@@ -156,6 +156,7 @@ export function GitFileDiff({
|
|
|
156
156
|
/** The lane's synchronous cache read: a re-mounted card paints its last answer on its first frame. */
|
|
157
157
|
peekContent?: VisibleDiffQueue['peek'];
|
|
158
158
|
}): React.ReactElement {
|
|
159
|
+
const client = useFilesystemStore((s) => s.client);
|
|
159
160
|
const [initial] = useState(() => peekContent?.<DiffAnswer>(`${diffFamily(source, repo, path, mode)}\u0000${revision}`, diffFamily(source, repo, path, mode)));
|
|
160
161
|
const [raw, setRaw] = useState<string | null>(() => initial === undefined ? null : initial && initial.ok !== false ? initial.diff : '');
|
|
161
162
|
const [loading, setLoading] = useState(false);
|
|
@@ -262,7 +263,7 @@ export function GitFileDiff({
|
|
|
262
263
|
path,
|
|
263
264
|
// ONE mode per request — the server 400s any combination.
|
|
264
265
|
...diffRequestParams(normalizedMode),
|
|
265
|
-
});
|
|
266
|
+
}, client);
|
|
266
267
|
// Keyed on everything the answer depends on; after a hunk apply the refetch
|
|
267
268
|
// replaces the cached answer instead of reading it.
|
|
268
269
|
const family = diffFamily(source, repo, path, normalizedMode);
|
|
@@ -364,7 +365,7 @@ export function GitFileDiff({
|
|
|
364
365
|
...(repo ? { repo } : {}),
|
|
365
366
|
path,
|
|
366
367
|
rev: expanderSrc.rev,
|
|
367
|
-
});
|
|
368
|
+
}, client);
|
|
368
369
|
const res = runContent ? await runContent(fetchSource, () => mySeq === seqRef.current) : await fetchSource();
|
|
369
370
|
if (!res || mySeq !== seqRef.current) return null;
|
|
370
371
|
return settle(res.ok ? { ok: true, content: res.content } : { ok: false });
|
|
@@ -376,7 +377,7 @@ export function GitFileDiff({
|
|
|
376
377
|
agentId,
|
|
377
378
|
...(projectId ? { projectId } : {}),
|
|
378
379
|
files: [`${source}://${repo ? `${repo}/` : ''}${path}`],
|
|
379
|
-
});
|
|
380
|
+
}, client);
|
|
380
381
|
const res = runContent ? await runContent(fetchSource, () => mySeq === seqRef.current) : await fetchSource();
|
|
381
382
|
if (!res || mySeq !== seqRef.current) return null;
|
|
382
383
|
const file = extractReadFilesPayload(res)[0];
|
|
@@ -467,9 +468,9 @@ export function GitFileDiff({
|
|
|
467
468
|
setHunkError(null);
|
|
468
469
|
try {
|
|
469
470
|
if (staged) {
|
|
470
|
-
await unstageHunk({ agentId, ...(projectId ? { projectId } : {}), source, ...(repo ? { repo } : {}), hunk: patch });
|
|
471
|
+
await unstageHunk({ agentId, ...(projectId ? { projectId } : {}), source, ...(repo ? { repo } : {}), hunk: patch }, client);
|
|
471
472
|
} else {
|
|
472
|
-
await stageHunk({ agentId, ...(projectId ? { projectId } : {}), source, ...(repo ? { repo } : {}), hunk: patch });
|
|
473
|
+
await stageHunk({ agentId, ...(projectId ? { projectId } : {}), source, ...(repo ? { repo } : {}), hunk: patch }, client);
|
|
473
474
|
}
|
|
474
475
|
// The index changed → the cached `rev=index` source is stale (the WT
|
|
475
476
|
// entry would survive, but a whole-map clear is cheap and race-free).
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
ChevronLeft, CheckCheck, X, XCircle, Wrench, Unlink, ShieldAlert,
|
|
24
24
|
} from 'lucide-react';
|
|
25
25
|
import { SkillLauncher } from '@neuralis/package-system/client';
|
|
26
|
-
import { useFilesystemStore } from '../store/filesystemStore';
|
|
26
|
+
import { useFilesystemStore, useFilesystemStoreApi } from '../store/filesystemStore';
|
|
27
27
|
import {
|
|
28
28
|
listPendingChanges, previewPendingChange, discardPendingChange, discardOrphanedPending,
|
|
29
29
|
type PendingChangeRecord, type PendingPreview,
|
|
@@ -98,18 +98,24 @@ export function CurrentGitDiffs({ uri, rows: gitRows, agentId, projectId, canWri
|
|
|
98
98
|
</div>)}</React.Fragment>)}</>;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/** The lane key one card's answer belongs to: the record and its source revision. */
|
|
102
|
+
const previewKey = (rec: PendingChangeRecord, revision: number): string => `preview\u0000${rec.id}\u0000${rec.updatedAt}\u0000${revision}`;
|
|
103
|
+
|
|
101
104
|
const previewBytes = (p: PendingPreview): number =>
|
|
102
105
|
2 * ((p.baseline.state === 'text' ? p.baseline.text.length : 0) + (p.current.state === 'text' ? p.current.text.length : 0)) + 256;
|
|
103
106
|
|
|
104
107
|
|
|
105
108
|
export const PendingDiffCard = memo(function PendingDiffCard({
|
|
106
|
-
rec, agentId, projectId, focused, orphaned, onOpen, onApprove, onRevert, onDiscard, onDismiss, onFocus, busy, queue, revision, canWrite, onPreview, peekPreview, extra,
|
|
109
|
+
rec, agentId, projectId, focused, orphaned, onOpen, onApprove, onRevert, onDiscard, onDismiss, onFocus, busy, queue, revision, canWrite, onPreview, peekPreview, takeRefetch, extra,
|
|
107
110
|
}: {
|
|
108
111
|
rec: PendingChangeRecord; agentId: string; projectId: string | null; focused: boolean; orphaned: boolean;
|
|
109
112
|
onOpen: (uri: string) => void; onApprove: () => void; onRevert: () => void; onDiscard: () => void; onDismiss: () => void;
|
|
110
113
|
onFocus: () => void; busy: boolean; queue: VisibleDiffQueue; revision: number; canWrite: boolean;
|
|
111
|
-
onPreview: (preview: PendingPreview) => void; peekPreview: (id: string) => PendingPreview | undefined;
|
|
114
|
+
onPreview: (preview: PendingPreview) => void; peekPreview: (id: string) => PendingPreview | undefined;
|
|
115
|
+
/** The dialog's post-409 refetch: `'wait'` while in flight, then its answer ONCE for the key it was taken for. */
|
|
116
|
+
takeRefetch: (id: string, key: string) => PendingPreview | 'wait' | undefined; extra?: React.ReactNode;
|
|
112
117
|
}) {
|
|
118
|
+
const client = useFilesystemStore((s) => s.client);
|
|
113
119
|
// Cards open inline by default — the diff is the review unit.
|
|
114
120
|
const [expanded, setExpanded] = useState(true);
|
|
115
121
|
// The last answer this record had (a remount or a new source revision) stays on screen
|
|
@@ -126,13 +132,16 @@ export const PendingDiffCard = memo(function PendingDiffCard({
|
|
|
126
132
|
active.current = expanded && shown;
|
|
127
133
|
// The record + source revision this card's answer belongs to; leaving the viewport
|
|
128
134
|
// keeps it (the lane cache answers a re-entry).
|
|
129
|
-
const cacheKey =
|
|
135
|
+
const cacheKey = previewKey(rec, revision);
|
|
130
136
|
const loadedKey = useRef('');
|
|
131
137
|
useEffect(() => {
|
|
132
138
|
const generation = ++seq.current;
|
|
133
139
|
if (!expanded || !shown || loadedKey.current === cacheKey) { setLoading(false); return; }
|
|
140
|
+
const adopted = takeRefetch(rec.id, cacheKey);
|
|
141
|
+
if (adopted === 'wait') { setLoading(true); return; }
|
|
142
|
+
if (adopted) { setPreview(adopted); setLoadError(null); setAnswerKey(cacheKey); loadedKey.current = cacheKey; setLoading(false); return; }
|
|
134
143
|
setLoading(true);
|
|
135
|
-
void queue.run(() => previewPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id }),
|
|
144
|
+
void queue.run(() => previewPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id }, client),
|
|
136
145
|
() => generation === seq.current && active.current, { key: cacheKey, bytes: previewBytes }).then(next => {
|
|
137
146
|
if (!next || generation !== seq.current || !active.current) return;
|
|
138
147
|
onPreview(next);
|
|
@@ -204,10 +213,19 @@ const NO_FILTERS: ChangeFilters = { kind: 'all', source: '', repo: '', branch: '
|
|
|
204
213
|
/** One bulk pass (the sweep and the grouped dialog) covers at most this many records. */ const REVIEW_BATCH = 100;
|
|
205
214
|
|
|
206
215
|
export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
216
|
+
const client = useFilesystemStore((s) => s.client);
|
|
207
217
|
const host = useFilesystemHost();
|
|
208
218
|
const canWrite = hasFeature({ grantedFeatures: [...(host.grantedFeatures ?? [])] }, 'drive.write');
|
|
219
|
+
const storeApi = useFilesystemStoreApi();
|
|
209
220
|
const sources = useFilesystemStore(s => s.sources);
|
|
210
|
-
const
|
|
221
|
+
const liveRevisions = useFilesystemStore(s => s.sourceChangeRevision);
|
|
222
|
+
// A review batch (the sweep, a dialog group) HOLDS the revisions its own writes bump: one re-list
|
|
223
|
+
// at its end (`afterMutation`) instead of a re-list and every visible card's re-preview per write.
|
|
224
|
+
const [held, setHeld] = useState<typeof liveRevisions | null>(null);
|
|
225
|
+
const revisions = held ?? liveRevisions;
|
|
226
|
+
const liveRef = useRef(liveRevisions); liveRef.current = liveRevisions;
|
|
227
|
+
const listedRevisions = useRef(liveRevisions);
|
|
228
|
+
const holdRevisions = useCallback(() => setHeld(prev => prev ?? liveRef.current), []);
|
|
211
229
|
const pendingPanelFilter = useFilesystemStore((s) => s.pendingPanelFilter);
|
|
212
230
|
const setPendingPanelFilter = useFilesystemStore((s) => s.setPendingPanelFilter);
|
|
213
231
|
const openFile = useFilesystemStore((s) => s.openFile);
|
|
@@ -220,6 +238,16 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
220
238
|
const queue = useVisibleDiffCards(scrollRoot);
|
|
221
239
|
const previews = useRef(new Map<string, PendingPreview>());
|
|
222
240
|
const peekPreview = useCallback((id: string) => previews.current.get(id), []);
|
|
241
|
+
// ONE fetch per dialog 409: the dialog's refetch waits for the re-list; the record's card
|
|
242
|
+
// holds (`null`) until it lands, then adopts it under the key the final nonce gives it.
|
|
243
|
+
const refetches = useRef(new Map<string, { key: string; preview: PendingPreview } | null>());
|
|
244
|
+
const relisted = useRef(Promise.withResolvers<PendingChangeRecord[] | undefined>());
|
|
245
|
+
const takeRefetch = useCallback((id: string, key: string): PendingPreview | 'wait' | undefined => {
|
|
246
|
+
const entry = refetches.current.get(id);
|
|
247
|
+
if (entry === null) return 'wait';
|
|
248
|
+
if (entry) refetches.current.delete(id);
|
|
249
|
+
return entry?.key === key ? entry.preview : undefined;
|
|
250
|
+
}, []);
|
|
223
251
|
const [filters, setFilters] = useState<ChangeFilters>(NO_FILTERS);
|
|
224
252
|
const setFilter = (key: keyof ChangeFilters) => (event: React.ChangeEvent<HTMLSelectElement>) =>
|
|
225
253
|
setFilters(f => ({ ...f, [key]: event.target.value }));
|
|
@@ -229,7 +257,21 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
229
257
|
const [loading, setLoading] = useState(false);
|
|
230
258
|
const [error, setError] = useState<string | null>(null);
|
|
231
259
|
const [busyId, setBusyId] = useState<string | null>(null);
|
|
232
|
-
|
|
260
|
+
// Per record: a refused review refetches only ITS card's preview.
|
|
261
|
+
const [nonces, setNonces] = useState<Readonly<Record<string, number>>>({});
|
|
262
|
+
const latest = useRef({ nonces, revisions }); latest.current = { nonces, revisions };
|
|
263
|
+
const refetch = useCallback(async (rec: PendingChangeRecord): Promise<PendingPreview> => {
|
|
264
|
+
refetches.current.set(rec.id, null);
|
|
265
|
+
try {
|
|
266
|
+
const listed = (await relisted.current.promise)?.find(r => r.id === rec.id) ?? rec;
|
|
267
|
+
const fresh = await previewPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id }, client);
|
|
268
|
+
const revision = (latest.current.nonces[rec.id] ?? 0) + 1 + (latest.current.revisions[listed.sourceSlug] ?? 0);
|
|
269
|
+
refetches.current.set(rec.id, { key: previewKey(listed, revision), preview: fresh });
|
|
270
|
+
previews.current.set(rec.id, fresh);
|
|
271
|
+
return fresh;
|
|
272
|
+
} catch (failure) { refetches.current.delete(rec.id); throw failure; }
|
|
273
|
+
finally { setNonces(prev => ({ ...prev, [rec.id]: (prev[rec.id] ?? 0) + 1 })); }
|
|
274
|
+
}, [agentId, projectId]);
|
|
233
275
|
const [focusIndex, setFocusIndex] = useState(0);
|
|
234
276
|
const [review, setReview] = useState<ReviewRequest | null>(null);
|
|
235
277
|
const [results, setResults] = useState<ReviewResult[]>([]);
|
|
@@ -250,7 +292,7 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
250
292
|
setLoading(true); setError(null);
|
|
251
293
|
try {
|
|
252
294
|
const list = await listPendingChanges({ agentId, ...(projectId ? { projectId } : {}),
|
|
253
|
-
...(convFilter ? { conversationId: convFilter } : {}), ...(withOrphans ? { include_orphans: true } : {}) });
|
|
295
|
+
...(convFilter ? { conversationId: convFilter } : {}), ...(withOrphans ? { include_orphans: true } : {}) }, client);
|
|
254
296
|
if (mine !== listSeq.current) return undefined;
|
|
255
297
|
const ids = new Set(list.changes.map(rec => rec.id));
|
|
256
298
|
setChanges(list.changes);
|
|
@@ -277,6 +319,7 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
277
319
|
const firstRevision = useRef(true);
|
|
278
320
|
useEffect(() => {
|
|
279
321
|
if (firstRevision.current) { firstRevision.current = false; return; }
|
|
322
|
+
if (revisions === listedRevisions.current) return;
|
|
280
323
|
void fetchPendingRef.current(false);
|
|
281
324
|
}, [revisions]);
|
|
282
325
|
|
|
@@ -291,7 +334,11 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
291
334
|
const groupsVisible = useMemo(() => visibleGitGroups(gitGroups, filters), [gitGroups, filters]);
|
|
292
335
|
const gitRows = useMemo(() => currentGitRows(groupsVisible), [groupsVisible]);
|
|
293
336
|
const items = useMemo(() => buildChangeItems(visible, gitRows, filters.kind, view), [visible, gitRows, filters.kind, view]);
|
|
294
|
-
|
|
337
|
+
// A landed preview that needs an acknowledgement moves its record into the count (no fetch of its own).
|
|
338
|
+
const [ackPreviews, setAckPreviews] = useState(0);
|
|
339
|
+
const { approvable, needsAck } = useMemo(() => splitApprovable(visible, orphanIds, REVIEW_BATCH, peekPreview),
|
|
340
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- `ackPreviews` re-reads the preview map
|
|
341
|
+
[visible, orphanIds, peekPreview, ackPreviews]);
|
|
295
342
|
// The records one review session already acted on: the next batch starts after them,
|
|
296
343
|
// so a refused record does not come straight back.
|
|
297
344
|
const reviewed = useRef(new Set<string>());
|
|
@@ -328,28 +375,33 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
328
375
|
*/
|
|
329
376
|
const dropResolvedDeleteRow = useCallback((rec: PendingChangeRecord) => {
|
|
330
377
|
if (rec.op !== 'delete' || !rec.uri) return;
|
|
331
|
-
const node =
|
|
378
|
+
const node = storeApi.getState().files[rec.uri];
|
|
332
379
|
if (!node || node.status === 'deleted') removeFilePath(rec.uri);
|
|
333
|
-
}, [removeFilePath]);
|
|
380
|
+
}, [removeFilePath, storeApi]);
|
|
334
381
|
|
|
335
382
|
const afterMutation = useCallback(async (done: ReviewResult[]) => {
|
|
336
383
|
for (const result of done) {
|
|
337
384
|
const rec = changes.find(c => c.id === result.id);
|
|
338
385
|
if (rec && result.outcome === 'ok' && result.action !== 'revert') dropResolvedDeleteRow(rec);
|
|
339
|
-
|
|
386
|
+
// A `needs-ack` answer came from a still-valid preview: it stays cached (the header counts it).
|
|
387
|
+
if (result.outcome !== 'ok' && result.outcome !== 'needs-ack' && !refetches.current.has(result.id)) previews.current.delete(result.id);
|
|
340
388
|
}
|
|
341
|
-
|
|
389
|
+
const refused = done.filter(r => r.outcome !== 'ok' && r.outcome !== 'needs-ack' && !refetches.current.has(r.id));
|
|
390
|
+
if (refused.length) setNonces(prev => { const next = { ...prev }; for (const r of refused) next[r.id] = (next[r.id] ?? 0) + 1; return next; });
|
|
342
391
|
setResults(done);
|
|
343
|
-
await fetchPending(false);
|
|
392
|
+
const after = await fetchPending(false);
|
|
393
|
+
// The STORE's value, not the last render's: the batch's own bumps may not have rendered yet.
|
|
394
|
+
listedRevisions.current = storeApi.getState().sourceChangeRevision; setHeld(null);
|
|
395
|
+
relisted.current.resolve(after); relisted.current = Promise.withResolvers();
|
|
344
396
|
void refreshPendingCount({ agentId, projectId });
|
|
345
|
-
}, [changes, dropResolvedDeleteRow, fetchPending, refreshPendingCount, agentId, projectId]);
|
|
397
|
+
}, [changes, dropResolvedDeleteRow, fetchPending, refreshPendingCount, agentId, projectId, storeApi]);
|
|
346
398
|
|
|
347
399
|
const resolveReview = useCallback(async (rec: PendingChangeRecord, action: ReviewAction) => {
|
|
348
400
|
if (!canWrite) return;
|
|
349
401
|
const preview = previews.current.get(rec.id);
|
|
350
402
|
if (!preview || preview.requiresAcknowledgement.length) { setReview({ kind: 'single', rec, action, ...(preview ? { preview } : {}) }); return; }
|
|
351
403
|
setBusyId(rec.id);
|
|
352
|
-
try { await afterMutation([await applyReview({ agentId, projectId }, rec, preview, action, false)]); }
|
|
404
|
+
try { await afterMutation([await applyReview({ agentId, projectId, client }, rec, preview, action, false)]); }
|
|
353
405
|
finally { setBusyId(null); }
|
|
354
406
|
}, [canWrite, agentId, projectId, afterMutation]);
|
|
355
407
|
|
|
@@ -357,7 +409,7 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
357
409
|
const discard = useCallback(async (rec: PendingChangeRecord) => {
|
|
358
410
|
setBusyId(rec.id);
|
|
359
411
|
try {
|
|
360
|
-
const res = await discardPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id });
|
|
412
|
+
const res = await discardPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id }, client);
|
|
361
413
|
if (!res.ok) setError(res.error || 'Discard failed'); else dropResolvedDeleteRow(rec);
|
|
362
414
|
await fetchPending(false);
|
|
363
415
|
void refreshPendingCount({ agentId, projectId });
|
|
@@ -370,7 +422,7 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
370
422
|
if (repairTimer.current) { clearTimeout(repairTimer.current); repairTimer.current = null; }
|
|
371
423
|
setRepairing(true); setConfirmRepair(false); setError(null);
|
|
372
424
|
try {
|
|
373
|
-
await discardOrphanedPending({ agentId, ...(projectId ? { projectId } : {}), ...(convFilter ? { conversationId: convFilter } : {}) });
|
|
425
|
+
await discardOrphanedPending({ agentId, ...(projectId ? { projectId } : {}), ...(convFilter ? { conversationId: convFilter } : {}) }, client);
|
|
374
426
|
const candidates = changes.filter((rec) => orphanIds.has(rec.id));
|
|
375
427
|
const after = await fetchPending(true);
|
|
376
428
|
if (after) {
|
|
@@ -388,22 +440,30 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
388
440
|
}, [confirmRepair, repair]); useEffect(() => () => { if (repairTimer.current) clearTimeout(repairTimer.current); }, []);
|
|
389
441
|
|
|
390
442
|
// Approve the visible records whose own fields need no acknowledgement (two-step
|
|
391
|
-
// confirm). A record whose fresh preview turns out to need one is reported
|
|
443
|
+
// confirm). A record whose fresh preview turns out to need one is reported AND handed
|
|
444
|
+
// to the grouped review dialog, where it is approved or dismissed with its acknowledgement.
|
|
392
445
|
const approveAll = useCallback(async () => {
|
|
393
|
-
setApprovingAll(true); setConfirmAll(false); setError(null);
|
|
446
|
+
setApprovingAll(true); setConfirmAll(false); setError(null); holdRevisions();
|
|
394
447
|
const done: ReviewResult[] = [];
|
|
395
448
|
try {
|
|
396
449
|
for (const rec of approvable) {
|
|
397
450
|
let preview = previews.current.get(rec.id);
|
|
398
451
|
if (!preview) {
|
|
399
|
-
try { preview = await previewPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id }); }
|
|
452
|
+
try { preview = await previewPendingChange({ agentId, ...(projectId ? { projectId } : {}), id: rec.id }, client); }
|
|
400
453
|
catch (e) { done.push({ id: rec.id, uri: rec.uri, action: 'approve', outcome: 'error', detail: e instanceof Error ? e.message : 'Preview failed' }); continue; }
|
|
454
|
+
previews.current.set(rec.id, preview);
|
|
401
455
|
}
|
|
402
456
|
if (preview.requiresAcknowledgement.length) { done.push({ id: rec.id, uri: rec.uri, action: 'approve', outcome: 'needs-ack' }); continue; }
|
|
403
|
-
done.push(await applyReview({ agentId, projectId }, rec, preview, 'approve', false));
|
|
457
|
+
done.push(await applyReview({ agentId, projectId, client }, rec, preview, 'approve', false));
|
|
404
458
|
}
|
|
405
|
-
} finally {
|
|
406
|
-
|
|
459
|
+
} finally {
|
|
460
|
+
setApprovingAll(false);
|
|
461
|
+
const handed = approvable.filter(rec => done.some(r => r.id === rec.id && r.outcome === 'needs-ack'));
|
|
462
|
+
if (handed.length) setAckPreviews(n => n + 1);
|
|
463
|
+
await afterMutation(done);
|
|
464
|
+
if (handed.length && canWrite) { reviewed.current.clear(); setReview({ kind: 'group', records: handed.slice(0, REVIEW_BATCH), total: handed.length }); }
|
|
465
|
+
}
|
|
466
|
+
}, [approvable, agentId, projectId, afterMutation, canWrite]);
|
|
407
467
|
|
|
408
468
|
const move = useCallback((delta: number) => setFocusIndex((i) => (visible.length === 0 ? 0
|
|
409
469
|
: Math.max(0, Math.min(visible.length - 1, i + delta)))), [visible.length]);
|
|
@@ -437,8 +497,8 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
437
497
|
if (item.kind === 'pending-card') {
|
|
438
498
|
return <PendingDiffCard rec={rec} agentId={agentId} projectId={projectId} focused={index === focusIndex} orphaned={orphaned}
|
|
439
499
|
onOpen={openInTree} {...handlers} onFocus={() => setFocusIndex(index)} busy={busyId === rec.id} queue={queue}
|
|
440
|
-
revision={
|
|
441
|
-
onPreview={preview => { previews.current.set(rec.id, preview); }} peekPreview={peekPreview}
|
|
500
|
+
revision={(nonces[rec.id] ?? 0) + (revisions[rec.sourceSlug] ?? 0)} canWrite={canWrite}
|
|
501
|
+
onPreview={preview => { previews.current.set(rec.id, preview); if (preview.requiresAcknowledgement.length) setAckPreviews(n => n + 1); }} peekPreview={peekPreview} takeRefetch={takeRefetch}
|
|
442
502
|
extra={filters.kind === 'all' ? <CurrentGitDiffs uri={rec.uri} rows={gitRows} agentId={agentId} projectId={projectId} canWrite={canWrite} revisions={revisions} queue={queue} /> : null} />;
|
|
443
503
|
}
|
|
444
504
|
return <div onMouseDown={() => setFocusIndex(index)} className={`group h-8 flex items-center gap-2 px-2 rounded-lg ${
|
|
@@ -461,7 +521,7 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
461
521
|
{canWrite && review ? <PendingReviewDialog request={review} agentId={agentId} projectId={projectId} run={queue.run}
|
|
462
522
|
key={review.kind === 'group' ? `group\u0000${review.records[0]?.id ?? ''}` : `single\u0000${review.rec.id}`}
|
|
463
523
|
onClose={() => setReview(null)} next={review.kind === 'group' ? unreviewed.filter(rec => !review.records.some(r => r.id === rec.id)).length : 0}
|
|
464
|
-
onNext={openReviewBatch}
|
|
524
|
+
onNext={openReviewBatch} refetch={refetch} onBatchStart={holdRevisions}
|
|
465
525
|
onDone={done => { for (const result of done) reviewed.current.add(result.id); void afterMutation(done); }} /> : null}
|
|
466
526
|
{/* Header: title + nav cursor + approve-all + view toggle + refresh */}
|
|
467
527
|
<div className="flex flex-wrap items-center gap-1.5 px-3 py-2 border-b border-white/5 shrink-0">
|
|
@@ -548,7 +608,7 @@ export function PendingChangesPanel({ agentId, projectId }: Props) {
|
|
|
548
608
|
<div className="mx-3 mt-2 max-h-28 overflow-auto overlay-scroll rounded-lg border border-amber-500/25 bg-amber-500/[0.06] px-2.5 py-1.5 text-[10.5px] text-amber-100/85 shrink-0">
|
|
549
609
|
<div className="flex items-center gap-2 font-semibold">{results.length - failed.length} done · {failed.length} not done
|
|
550
610
|
<button type="button" onClick={() => setResults([])} className="ml-auto rounded hover:bg-white/10" title="Dismiss"><X className="w-3 h-3" /></button></div>
|
|
551
|
-
{failed.map(r => <div key={r.id} className="truncate font-mono" title={r.detail}>{r.action} {r.uri}: {r.outcome === 'changed' ? 'changed since the preview (409)' : r.outcome === 'needs-ack' ? 'needs confirmation' : r.detail ?? 'refused'}</div>)}
|
|
611
|
+
{failed.map(r => <div key={r.id} className="truncate font-mono" title={r.detail}>{r.action} {r.uri}: {r.outcome === 'changed' ? 'changed since the preview (409)' : r.outcome === 'needs-ack' ? 'needs confirmation — opened in the review dialog' : r.detail ?? 'refused'}</div>)}
|
|
552
612
|
</div>
|
|
553
613
|
) : null}
|
|
554
614
|
|