@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,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
requiredFeatures: [
|
|
2
|
+
requiredFeatures: [files.write]
|
|
3
3
|
name: manage-files
|
|
4
4
|
description: "Perform bulk or route-level filesystem operations—list, search, read, raw, write (every verb), upload, and review approval—when fs_* calls are insufficient or an approval flow is involved. Use source URIs and preserve policy/scope; prefer direct fs_* for ordinary small file work."
|
|
5
5
|
allowed-tools: execute
|
|
@@ -12,38 +12,37 @@ The `fs_*` tools (`fs_read`, `fs_write`, etc.) remain the primary path for one-o
|
|
|
12
12
|
file operations — this skill is for *bulk*: iterating with a shell loop, posting a
|
|
13
13
|
batch, or scripting an `upload + approve` sequence end-to-end. Call the routes with
|
|
14
14
|
`neuralis request` (the session ticket inside an activated skill, `neuralis login`
|
|
15
|
-
on your own machine)
|
|
15
|
+
on your own machine) — every route is one call line, with no script in between.
|
|
16
16
|
|
|
17
17
|
## Routes covered
|
|
18
18
|
|
|
19
19
|
| Action | Method | Path (`@neuralis/brain-core/…`) | Feature gate |
|
|
20
20
|
|---|---|---|---|
|
|
21
|
-
| List files / folders at a URI | POST | `list` | `
|
|
22
|
-
| Search vector index | POST | `search` | `
|
|
23
|
-
| Read multiple files | POST | `read` | `
|
|
24
|
-
| Raw (un-summarized) read | GET | `raw` | `
|
|
25
|
-
| Write — every verb (create / overwrite / edit / insert / lines / fields / move / copy / mkdir / revert / delete) | POST | `write`
|
|
26
|
-
| Upload a payload (multipart/form-data) | POST | `upload`
|
|
27
|
-
| Approve a pending change | POST | `approve` | `
|
|
28
|
-
| List pending changes (project-wide) | GET | `pending` | `
|
|
21
|
+
| List files / folders at a URI | POST | `list` | `files.read` |
|
|
22
|
+
| Search vector index | POST | `search` | `files.search` |
|
|
23
|
+
| Read multiple files | POST | `read` | `files.read` |
|
|
24
|
+
| Raw (un-summarized) read | GET | `raw` | `files.read` |
|
|
25
|
+
| Write — every verb (create / overwrite / edit / insert / lines / fields / move / copy / mkdir / revert / delete) | POST | `write` | `files.write` |
|
|
26
|
+
| Upload a payload (multipart/form-data) | POST | `upload` | `files.write` |
|
|
27
|
+
| Approve a pending change | POST | `approve` | `files.write` |
|
|
28
|
+
| List pending changes (project-wide) | GET | `pending` | `files.read` |
|
|
29
29
|
|
|
30
30
|
Per-route feature gates are enforced server-side by the RouteDispatcher against the
|
|
31
31
|
caller's real `grantedFeatures`, independently of this skill's `requiredFeatures`
|
|
32
|
-
frontmatter — `/list`, `/read`, `/raw` and `GET /pending` need `
|
|
33
|
-
`
|
|
34
|
-
verbs (`revert`, `discard`, `dismiss`, `discard-orphans`) need `
|
|
35
|
-
`
|
|
32
|
+
frontmatter — `/list`, `/read`, `/raw` and `GET /pending` need `files.read`; `/search` needs
|
|
33
|
+
`files.search`; `/write`, `/upload`, `/approve` and the mutating `/pending`
|
|
34
|
+
verbs (`revert`, `discard`, `dismiss`, `discard-orphans`) need `files.write`. A caller who holds
|
|
35
|
+
`files.write` (enough to see and activate this skill) but NOT `files.search` gets a
|
|
36
36
|
server-side **403** from `search` even though the other routes work.
|
|
37
37
|
|
|
38
38
|
## Bodies
|
|
39
39
|
|
|
40
|
-
- `list` / `search` / `read` / `approve` take a JSON body (
|
|
41
|
-
|
|
42
|
-
- `/write` body = `{"agentId":"…","uri":"data://notes/plan.md","<verb>":…}` — the VERB is a KEY and its presence is the intent. Content verbs COMPOSE in one call, in a fixed order, as ONE write with ONE baseline: `create` (`{content, client_request_id?}` — never overwrites; a taken name lands BESIDE as `name-2.ext` and the response `uri` is where it went, so read it back), `overwrite` (`{content}` — refuses on a missing file and names `create`), `edit` (`[{old_string, new_string?, replace_all?, expected_replacements?}]`, applied in order, one failure discards all of them), `insert` (`{insert_text, insert_line?}` — inserts AFTER that line, `0` = start of file, omitted = append), `lines` (`{line_start, line_end, content}`), `fields` (`{category, status, pinned, tags{add,remove,set}, metadata}`). Structural verbs stand ALONE: `move`/`copy` (a destination uri or, for a file move, a bare new filename; `copy` may cross sources), `mkdir:true` (a real empty directory; not on `brain://`, where folders are implicit), `revert:true` (one-level undo), `delete:true` (a file, or a whole folder recursively). **A 2xx does not mean success** — a refusal is 200 with `ok:false`, so branch on `ok`. A `move` (or a `revert` that relocates or re-creates) onto a uri that already holds something answers `ok:false` + `error:"DESTINATION_EXISTS"` — nothing was overwritten; delete or rename the occupant first. A delete has ONE spelling, the `delete` key: `fields.status:"deleted"` is refused. `review` is never read from the body — a content edit (`overwrite`/`edit`/`insert`/`lines`) lands `pending_review` on every lane (visible and revertible in Changes); `create`/`move`/`copy`/`mkdir` land committed for a human interactive caller and `pending_review` from this ticket lane; `/upload` also journals agent-origin uploads as pending review; interactive human uploads land committed. Use `/write` for JSON text and `/upload` for multipart file bytes. A missing `agentId`/`uri` is a **400** naming the field, a body the server could not parse a **400** `Request body must be a JSON object`. A uri-policy denial is a **403 with no `ok` field**, a disabled source a **409** with `code:"source_disabled"`. A source slug this project does not have answers one of two ways, and BOTH mean "stop guessing this name": with a scheme (`zzz://a.md`) the uri gate answers **403 `uri_policy_denied`** first; without one (`notes.md`) you get **404 `code:"source_not_configured"`** carrying `availableSources` — the sources you CAN address. `/list` gives the 404 in both forms. Switch to a source from that list (or from `<runtime_stack>`); retrying the same name never works. `/read` is different again: it reports PER FILE inside a 200, so a denied or disabled source arrives as `{uri, error, code:"forbidden"}` — never a 409 — and a missing file as `code:"not_found"`. No code means the read failed for some other reason; do not conclude the file is gone. A folder delete or copy that partly succeeded reports what really happened: `affected` (files touched) and `failed` (the NAMES that could not be), so "failed" does not mean "nothing happened". `warning:"moved_with_source_retained"` on a move means the copy landed but the original could not be removed — BOTH copies exist on purpose; do not re-run the move. `indexed:false` means the bytes DID land and are readable, but search indexing was skipped or failed; report it, do not re-write. Sync retries failed indexing only for eligible files; excluded files remain unindexed. A non-2xx prints the route's body too — on stderr, followed by an `HTTP <code>` line, under a `--- stderr ---` separator, so read the whole output.
|
|
40
|
+
- `list` / `search` / `read` / `approve` / `write` take a JSON body on stdin (`echo '<json>' | neuralis request POST @neuralis/brain-core/<route> --input -`, the one form bash and PowerShell both parse; a `'` inside the text is written `\u0027` in the JSON); file content and other free text ride that body, never a `-f` argument (PowerShell strips the quotes inside an argument).
|
|
41
|
+
- `/write` body = `{"agentId":"…","uri":"data://notes/plan.md","<verb>":…}` — the VERB is a KEY and its presence is the intent. Content verbs COMPOSE in one call, in a fixed order, as ONE write with ONE baseline: `create` (`{content, client_request_id?}` — never overwrites; a taken name lands BESIDE as `name-2.ext` and the response `uri` is where it went, so read it back), `overwrite` (`{content}` — refuses on a missing file and names `create`), `edit` (`[{old_string, new_string?, replace_all?, expected_replacements?}]`, applied in order, one failure discards all of them), `insert` (`{insert_text, insert_line?}` — inserts AFTER that line, `0` = start of file, omitted = append), `lines` (`{line_start, line_end, content}`), `fields` (`{category, status, pinned, tags{add,remove,set}, metadata}`). Structural verbs stand ALONE: `move`/`copy` (a destination uri or, for a file move, a bare new filename; `copy` may cross sources), `mkdir:true` (a real empty directory; not on `brain://`, where folders are implicit), `revert:true` (one-level undo), `delete:true` (a file, or a whole folder recursively). **A 2xx does not mean success** — a refusal is 200 with `ok:false` and the CLI exits 0, so branch on `ok`, never the status or the exit code. A `move` (or a `revert` that relocates or re-creates) onto a uri that already holds something answers `ok:false` + `error:"DESTINATION_EXISTS"` — nothing was overwritten; delete or rename the occupant first. A delete has ONE spelling, the `delete` key: `fields.status:"deleted"` is refused. `review` is never read from the body — a content edit (`overwrite`/`edit`/`insert`/`lines`) lands `pending_review` on every lane (visible and revertible in Changes); `create`/`move`/`copy`/`mkdir` land committed for a human interactive caller and `pending_review` from this ticket lane; `/upload` also journals agent-origin uploads as pending review; interactive human uploads land committed. Use `/write` for JSON text and `/upload` for multipart file bytes. A missing `agentId`/`uri` is a **400** naming the field, a body the server could not parse a **400** `Request body must be a JSON object`. A uri-policy denial is a **403 with no `ok` field**, a disabled source a **409** with `code:"source_disabled"`. A source slug this project does not have answers one of two ways, and BOTH mean "stop guessing this name": with a scheme (`zzz://a.md`) the uri gate answers **403 `uri_policy_denied`** first; without one (`notes.md`) you get **404 `code:"source_not_configured"`** carrying `availableSources` — the sources you CAN address. `/list` gives the 404 in both forms. Switch to a source from that list (or from `<runtime_stack>`); retrying the same name never works. `/read` is different again: it reports PER FILE inside a 200, so a denied or disabled source arrives as `{uri, error, code:"forbidden"}` — never a 409 — a missing file as `code:"not_found"`, and a device folder that cannot serve as `code:"source_unavailable"` or `"device_refused"` with a `reason` (`device_not_ready` adds `not_ready`: what the device's owner fixes there). No code means the read failed for some other reason; do not conclude the file is gone. A folder delete or copy that partly succeeded reports what really happened: `affected` (files touched) and `failed` (the NAMES that could not be), so "failed" does not mean "nothing happened". `warning:"moved_with_source_retained"` on a move means the copy landed but the original could not be removed — BOTH copies exist on purpose; do not re-run the move. `indexed:false` means the bytes DID land and are readable, but search indexing was skipped or failed; report it, do not re-write. Sync retries failed indexing only for eligible files; excluded files remain unindexed. A non-2xx prints the route's body too — on stderr, followed by an `HTTP <code>` line, under a `--- stderr ---` separator, so read the whole output.
|
|
43
42
|
- `/search` body key is `search_mode` (semantic|filter|grep) — the SAME vocabulary as the `fs_search` tool; the legacy `mode` key is rejected with 400. The route forwards `search_mode`, `query`, `folder_uri`, `glob`, `category`, `tags`, `status`, `created_after`/`created_before`, `limit`, and the grep-only `path_glob`, `context` and `case_sensitive`. In `grep` mode the search is uri-policy `read`-gated (only paths the caller holds `read` policy on are grepped), the match is a FIXED STRING, and the answer carries `truncated` + `total_seen` — a cut set says so, so never read a full-looking list as proof that the rest is absent.
|
|
44
43
|
- `/raw` is a GET — pass the file URI as `-f uri=<uri>` and redirect stdout to a file: it always returns the full bytes, unaffected by the response headers; what those headers say is a BROWSER instruction. Safe types (images except SVG, video, audio, PDF, text, JSON) are marked for inline display; SVG, HTML and XML are marked `attachment` so a person clicking the link downloads them instead of executing them on the app origin. Do not describe a `.svg` or `.html` you wrote as viewable in the browser — offer it as a download, or convert it to a raster image if a human needs to look at it.
|
|
45
44
|
- `/read` is at parity with the `fs_read` tool: the body takes `files[]` — each entry a URI string or `{"uri":"…","line_start":N,"line_end":M}` with that file's own window — plus `read_version`, batch-level `line_start`/`line_end` and `include_ids`. An entry that is neither shape is a **400**. Text is a bounded preview; native media may accompany it, while unsupported/invalid binary data has a URI and marker. For a byte-exact binary copy use the authorized `/raw` byte lane and multipart `/upload`, never re-encode a text preview. If you only need the pre-edit content, a plain `/read` response already carries it: each file's `version.baseline.content`, with `available_versions` listing `baseline` exactly when one exists.
|
|
46
|
-
- `/upload` is **multipart/form-data**, NOT JSON —
|
|
45
|
+
- `/upload` is **multipart/form-data**, NOT JSON — `--form file=@<local path>` and `--form agentId=<id>` are required, `--form uri=…` / `--form tags=a,b` optional; a JSON body is rejected with 400. The 200 carries `indexed`: `false` means the bytes DID land but search indexing was skipped by the source selection or failed (provider outage/quota) — report it, do not re-upload. An eligible sync retries failed indexing; excluded uploads remain unindexed until the selection changes. The 200 also carries `mimeType`, and it may differ from what the upload declared: the stored type is resolved from the filename extension first, with the declared value kept only for an extension the platform does not know, and a common-image claim the leading bytes contradict falls back to `application/octet-stream`. Give the file a truthful extension and the stored type follows.
|
|
47
46
|
- `GET /pending` lists durable pending records inside the Changes workspace. `status` (`pending_review`\|`approved`\|`reverted`), `source`, `op` (`create`\|`modify`\|`delete`\|`move`) and `limit` filter the list; owner/scope and URI READ gates apply per record. Review begins with `POST /pending` `{action:"preview",id}`: it returns the current connector content separately from the recorded snapshot and saved baseline, typed missing/unavailable/binary/too-large states, `indexState`, `requiresAcknowledgement`, and `expectedFingerprint`. The preview is bounded by `pendingPreviewMaxBytes`; it never fabricates missing content or vectors. Resolve through `POST /approve` `{id,expectedFingerprint}` or `POST /pending` `{action:"revert"|"dismiss",id,expectedFingerprint}`. If the preview requires acknowledgement, inspect those states and include `acknowledgeCurrentState:true`; never auto-acknowledge an unseen preview. The server rechecks freshness and WRITE authority at apply: a changed fingerprint requires a new preview, and acknowledgement grants no missing permission. Bare legacy `/write revert:true` refuses unsafe pending recovery; ordinary non-pending one-level undo remains available. Approval/dismissal preserve the stored snapshot/index state (including recovery-only or absent index), rather than certifying current connector bytes as indexed. For a file the preview shows `missing` with a saved `journal-latest-write` baseline, an acknowledged approve/dismiss closes the review and the file stays gone; revert is the restore. Terminal retries remain owner-gated and idempotent; `uri` is omitted without current READ and WRITE access. Revert restores the saved baseline and refuses missing baselines or occupied move destinations. Discard/Repair remain orphan-only, owner-gated operations; no transient outage is proof of orphanhood.
|
|
48
47
|
|
|
49
48
|
|
|
@@ -55,14 +54,14 @@ For a disposable pending record you created in your project, substitute its real
|
|
|
55
54
|
|
|
56
55
|
```bash
|
|
57
56
|
neuralis request POST @neuralis/brain-core/pending -f action=preview -f id=<scratch-record-id>
|
|
58
|
-
|
|
57
|
+
echo '{"action":"revert","id":"<scratch-record-id>","expectedFingerprint":"<64-hex-preview-fingerprint>","acknowledgeCurrentState":true}' | neuralis request POST @neuralis/brain-core/pending --input -
|
|
59
58
|
```
|
|
60
59
|
|
|
61
60
|
Pending calls return one page; scan-orphans preserves that page in `changes` and puts its orphan subset in `orphans`/`orphanIds`: pass `cursor` from `nextCursor` unchanged with the same filters, or `uri` for an exact URI. Check `complete`, `partial` and `hasMoreAvailable`; a partial exhausted branch remains incomplete. On `restartRequired`, restart the list instead of retrying the old cursor. Repair returns scannedVisible/orphaned/attempted/discarded/refused/failed/reasons for one batch; continue only via nextCursor; pause on partial and use an explicit Continue available/Retry.
|
|
62
61
|
|
|
63
62
|
```bash
|
|
64
63
|
# Recursive list of /data
|
|
65
|
-
|
|
64
|
+
echo '{"uri":"data://","recursive":true,"limit":100}' | neuralis request POST @neuralis/brain-core/list --input -
|
|
66
65
|
|
|
67
66
|
# Vector search across all sources (body key is `search_mode`, same as the fs_search tool)
|
|
68
67
|
neuralis request POST @neuralis/brain-core/search -f search_mode=semantic -f query='telemetry pipeline' -F limit=10
|
|
@@ -74,15 +73,13 @@ neuralis request GET @neuralis/brain-core/pending -f status=pending_review -f li
|
|
|
74
73
|
neuralis request GET @neuralis/brain-core/raw -f uri=data://report.pdf > /tmp/report.pdf
|
|
75
74
|
|
|
76
75
|
# Create a text file — the journaled write lane. The verb is the KEY.
|
|
77
|
-
# `<agent-id>` is a placeholder; a real id makes this line write for real.
|
|
78
|
-
|
|
79
|
-
bash ${SKILL_DIR}/scripts/write.sh
|
|
76
|
+
# `<agent-id>` is a placeholder; a real id makes this line write for real. Read `ok` in the answer.
|
|
77
|
+
echo '{"agentId":"<agent-id>","uri":"data://scratch/manage-files-probe.md","create":{"content":"# probe\n"}}' | neuralis request POST @neuralis/brain-core/write --input -
|
|
80
78
|
|
|
81
79
|
# Upload a payload (multipart, NOT JSON): file + agentId are required form fields.
|
|
82
80
|
# The route never overwrites: a `URI` already in use lands the upload BESIDE the
|
|
83
81
|
# existing file as `name (2).ext`, and the response `uri` is where it went — read
|
|
84
82
|
# it, do not assume the path. `<agent-id>` is a placeholder; take a real id from the agents
|
|
85
83
|
# list, and note that a real id makes this line write for real.
|
|
86
|
-
|
|
87
|
-
bash ${SKILL_DIR}/scripts/upload.sh
|
|
84
|
+
neuralis request POST @neuralis/brain-core/upload --form file=@/tmp/report.pdf --form agentId=<agent-id> --form uri=data://report.pdf --form tags=reports,q3
|
|
88
85
|
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
requiredFeatures: [
|
|
2
|
+
requiredFeatures: [files.read]
|
|
3
3
|
name: manage-sources
|
|
4
4
|
description: "Manage the full source lifecycle: survey freshness/index health, inspect kinds/schema, create/update/enable/disable/delete, browse, sync/cancel/reset/reindex, re-embed or clean a file/folder/source index, and diagnose vectors. Use when a source is stale, missing, misconfigured, offline, or needs lifecycle changes."
|
|
5
5
|
allowed-tools: execute fs_list fs_read fs_search
|
|
@@ -24,7 +24,7 @@ Useful for:
|
|
|
24
24
|
## Read / survey mode (sources + freshness)
|
|
25
25
|
|
|
26
26
|
To just **survey** the configured sources and their freshness (read-only, the
|
|
27
|
-
`
|
|
27
|
+
`files.read` floor — no mutation), use the `fs_*` tools rather than the routes:
|
|
28
28
|
|
|
29
29
|
1. Call `fs_list` with `include_counts: true` (no `uri` — root registry) to
|
|
30
30
|
enumerate sources with `on_disk`, `indexed_count`, `unindexed`,
|
|
@@ -32,8 +32,10 @@ To just **survey** the configured sources and their freshness (read-only, the
|
|
|
32
32
|
are opt-in: without `include_counts` the registry still lists the sources but
|
|
33
33
|
`on_disk`/`indexed_count`/`unindexed` are usually omitted (survey mode is
|
|
34
34
|
exactly when you want them).
|
|
35
|
-
2. For any source
|
|
36
|
-
|
|
35
|
+
2. For any source that carries `last_error`, report it — it is the per-source
|
|
36
|
+
diagnosis and needs no extra call. `sync_status: "error"` means the last
|
|
37
|
+
SYNC failed; a `last_error` without it means the walk or count failed now
|
|
38
|
+
(no `on_disk`), not the sync. Do **not** reach for the log
|
|
37
39
|
files with `fs_read`: `data://<package>/logs/**` is read-denied by uri policy
|
|
38
40
|
for everyone below owner/admin, so on a member's behalf that call fails.
|
|
39
41
|
Read them through `inspect-agent-core` (or, for the platform-wide view, the
|
|
@@ -50,29 +52,29 @@ server-side source rows rather than the index-count survey.)
|
|
|
50
52
|
|
|
51
53
|
## Routes covered
|
|
52
54
|
|
|
53
|
-
`
|
|
55
|
+
`files.read` is the skill's floor; mutating + sync-lifecycle routes escalate
|
|
54
56
|
**in-handler** to a stronger feature and 403 an under-privileged caller (see
|
|
55
57
|
**Feature gates** below). The `Feature` column is the gate actually enforced.
|
|
56
58
|
|
|
57
59
|
| Action | Method | Path (`@neuralis/brain-core/…`) | Fields | Feature |
|
|
58
60
|
|---|---|---|---|---|
|
|
59
|
-
| List configured sources | GET | `sources` | `scope?`, `observed?` | `
|
|
60
|
-
| Get one source's config | GET | `sources/<slug>` | | `
|
|
61
|
-
| List registered kinds | GET | `sources/kinds` | | `
|
|
62
|
-
| Get a kind's config schema | GET | `sources/kinds/<kind>/schema` | | `
|
|
63
|
-
| Discoverable connectors (filesystem hints) | GET | `sources/discoverable` | | `
|
|
64
|
-
| Browse
|
|
65
|
-
| Create a new source | POST | `sources` | body (below) | `
|
|
66
|
-
| Update an existing source | PATCH | `sources` | body (below) | `
|
|
67
|
-
| Delete a source | DELETE | `sources/<slug>[?purge=1]` | | `
|
|
68
|
-
| Enable / disable a source | POST | `sources/enabled` | `source`, `enabled` (`true`\|`false`\|`"auto"`) | `
|
|
69
|
-
| Trigger sync (202 + queue job snapshot) | POST | `sources/sync` | `source`, `agentId?` | `
|
|
70
|
-
| Cancel an in-flight sync | POST | `sources/cancel` | `source?` | `
|
|
71
|
-
| Job status | GET | `sources/sync-status` | `source?` | `
|
|
72
|
-
| Forget sync state (next tick re-walks; deletes nothing) | POST | `sources/reset` | `source` | `
|
|
73
|
-
| Rescan changes (full re-walk now; unchanged files keep their vectors; 202 + job) | POST | `sources/reindex` | `source`, `agentId?` | `
|
|
74
|
-
| Clean a file / folder / source index (estimate first) | POST | `sources/purge` | body (below) | `
|
|
75
|
-
| Catch up embedding debt
|
|
61
|
+
| List configured sources | GET | `sources` | `scope?`, `observed?` | `files.read` |
|
|
62
|
+
| Get one source's config | GET | `sources/<slug>` | | `files.read` |
|
|
63
|
+
| List registered kinds | GET | `sources/kinds` | | `files.read` |
|
|
64
|
+
| Get a kind's config schema | GET | `sources/kinds/<kind>/schema` | | `files.read` |
|
|
65
|
+
| Discoverable connectors (filesystem hints) | GET | `sources/discoverable` | | `sources.mount` |
|
|
66
|
+
| Browse folders before adding one | GET | `sources/browse` | `path`, `device?` | `sources.mount`; with `device` the device's owner (`device.own`) |
|
|
67
|
+
| Create a new source | POST | `sources` | body (below) | `sources.mount` |
|
|
68
|
+
| Update an existing source | PATCH | `sources` | body (below) | `sources.mount` |
|
|
69
|
+
| Delete a source | DELETE | `sources/<slug>[?purge=1]` | | `sources.mount` |
|
|
70
|
+
| Enable / disable a source | POST | `sources/enabled` | `source`, `enabled` (`true`\|`false`\|`"auto"`) | `sources.mount` |
|
|
71
|
+
| Trigger sync (202 + queue job snapshot) | POST | `sources/sync` | `source`, `agentId?`, `confirmEmpty?` | `sources.sync` |
|
|
72
|
+
| Cancel an in-flight sync | POST | `sources/cancel` | `source?` | `sources.sync` |
|
|
73
|
+
| Job status | GET | `sources/sync-status` | `source?` | `sources.sync` |
|
|
74
|
+
| Forget sync state (next tick re-walks; deletes nothing) | POST | `sources/reset` | `source` | `sources.sync` |
|
|
75
|
+
| Rescan changes (full re-walk now; unchanged files keep their vectors; 202 + job) | POST | `sources/reindex` | `source`, `agentId?` | `sources.sync` |
|
|
76
|
+
| Clean a file / folder / source index (estimate first) | POST | `sources/purge` | body (below) | `sources.mount` + `sources.sync` |
|
|
77
|
+
| Catch up embedding debt, or re-embed with `force` (estimate first) | POST | `sources/reindex` + `embeddingOnly` or `force` (lines under §Re-embed) | `source`, `folder?`/`uri?`, `estimate?` | `sources.sync` |
|
|
76
78
|
|
|
77
79
|
> **`update` takes no `<slug>`.** PATCH targets the bare `sources` path; the
|
|
78
80
|
> source to patch is the body `source` field (the handler ignores the path).
|
|
@@ -87,51 +89,77 @@ array** of source rows (NOT `{ sources: [...] }`). Pipe `jq '.[]'`, never
|
|
|
87
89
|
`jq '.sources[]'` (that errors `Cannot index array with string "sources"`). Each
|
|
88
90
|
element carries `slug`, `enabled`, `connection.kind`, `scope`, plus the enrichment
|
|
89
91
|
fields above. `connection.config` is `{}` unless you could attach the source or
|
|
90
|
-
read its root, and `sync.lastSyncResult.error` is a fixed text without `
|
|
92
|
+
read its root, and `sync.lastSyncResult.error` is a fixed text without `sources.sync`. `GET sources/<slug>` returns a single object, not an array.
|
|
91
93
|
|
|
92
94
|
## Feature gates
|
|
93
95
|
|
|
94
|
-
The skill declares `
|
|
96
|
+
The skill declares `files.read`, which covers the source-config READ routes.
|
|
95
97
|
Everything that mutates, syncs, or ENUMERATES THE HOST enforces a **stronger**
|
|
96
|
-
feature server-side, beyond the `
|
|
97
|
-
`
|
|
98
|
+
feature server-side, beyond the `files.read` floor — a caller holding only
|
|
99
|
+
`files.read` gets a `403`:
|
|
98
100
|
|
|
99
|
-
- **`
|
|
101
|
+
- **`sources.mount`** — create, update, delete, enable/disable, browse and the
|
|
100
102
|
discoverable list. Browsing and the
|
|
101
103
|
discoverable list are the steps that PRECEDE attaching, and they enumerate the
|
|
102
|
-
host: you may browse exactly what you would be allowed to attach.
|
|
103
|
-
|
|
104
|
+
host: you may browse exactly what you would be allowed to attach. On a native
|
|
105
|
+
install (no container) a folder on this server may root only in the project's own
|
|
106
|
+
folder — browsable with its parents on the way down to it — or a privileged
|
|
107
|
+
zone below; any other folder answers `403 native_local_root_outside_project`
|
|
108
|
+
and is attached as a folder on the user's own paired device instead.
|
|
109
|
+
- **`sources.privileged`** — browsing the filesystem root or any
|
|
104
110
|
protected host zone (the App Zone, the Neuralis tree), the same zones whose
|
|
105
111
|
ATTACH needs it. A protected directory is also omitted from the listing of a
|
|
106
112
|
parent you may browse, so an absent entry is not proof it does not exist.
|
|
107
|
-
- **`
|
|
113
|
+
- **`sources.sync`** — sync, cancel, reset, reindex, re-embed, sync-status.
|
|
108
114
|
|
|
109
|
-
The index purge requires both `
|
|
115
|
+
The index purge requires both `sources.mount` and `sources.sync`, source-scope management authority and current READ visibility.
|
|
110
116
|
|
|
111
117
|
Create/update/delete/enable additionally enforce `canAccessScope(.., 'write')`
|
|
112
118
|
on the target source's scope, and create validates the kind's scope rules.
|
|
119
|
+
Send a folder's `root` alone: the server derives its `hostRoot` (the same
|
|
120
|
+
folder on the machine) and stores both, so the source opens whether the server runs
|
|
121
|
+
in Docker or natively. A `hostRoot` that contradicts that derivation answers
|
|
122
|
+
`400 source_root_pair_mismatch`; one nothing derives is accepted only from a
|
|
123
|
+
`sources.privileged` caller, and audited.
|
|
113
124
|
|
|
114
|
-
### Privileged and
|
|
125
|
+
### Privileged sources and device folders
|
|
115
126
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
One escalation sits above `sources.mount`, not granted below the `admin` tier (`admin` holds
|
|
128
|
+
it through its enumerated default grant, `owner` through the `'*'` wildcard; grantable to any
|
|
129
|
+
custom role):
|
|
119
130
|
|
|
120
|
-
- **`
|
|
131
|
+
- **`sources.privileged`** — attaching (or seeing) a source rooted in, over, or at a
|
|
121
132
|
high-blast-radius zone: the platform App Zone, the Neuralis source tree, or the whole
|
|
122
133
|
filesystem (`/`). Containment is checked in both directions on canonical paths, so a
|
|
123
134
|
sub-path or an ancestor of a protected zone is caught too.
|
|
124
|
-
- **`drive.mount.host`** — attaching or editing any source on the HOST plane (a connector
|
|
125
|
-
kind of `host` / `host-*`, resolving on the operator's machine rather than in the
|
|
126
|
-
container). **Both features are required together for a host source, at every root** —
|
|
127
|
-
there is no unprivileged host root, so `/home/me/notes` is gated exactly like `/`.
|
|
128
135
|
|
|
129
|
-
A
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
A folder is one kind, `host`, on one of two places its stored config names: without
|
|
137
|
+
`connection.config.device` it is a folder on this server; with one it is a folder on that
|
|
138
|
+
paired device (the DEVICE plane), reached through the device's broker. A device folder has one
|
|
139
|
+
rule: **only that device's owner, holding `device.own`, attaches or edits it** — at every
|
|
140
|
+
root, and no role feature replaces it. Anyone else gets 403, whatever they hold. It is
|
|
141
|
+
attached at user scope unless you send `"scope":"project"` (never `agent`), its `root` is an
|
|
142
|
+
absolute path on that device, and the place never changes after the attach — to move a
|
|
143
|
+
folder between this server and a device, delete it and attach it again.
|
|
144
|
+
|
|
145
|
+
A device folder is also bounded by the device's own allowlist, which the platform cannot
|
|
146
|
+
widen: even a permissive source policy only reaches paths the device's owner granted. If a
|
|
147
|
+
device read or write fails while the source policy allows it, report the allowlist as the
|
|
148
|
+
limit — the owner widens it with `neuralis device grant`, not a policy edit. The git panel
|
|
149
|
+
and `/git/*` answer for a folder on this server only.
|
|
150
|
+
|
|
151
|
+
To find the folder on your OWN device, browse it: `sources/browse -f device=dev_… -f path=`
|
|
152
|
+
(empty path) lists the folders that device allows this server, with `-f path=/abs/dir` one
|
|
153
|
+
level below. Anyone but the owner gets `403 Only the device's owner may browse it.`, an
|
|
154
|
+
unknown id too. A `200` with `state` other than `ok` and no entries is the device's answer:
|
|
155
|
+
`ceiling_denied` (not allowed yet), `device_offline`, `broker_outdated` (an older CLI there).
|
|
156
|
+
For a folder it does not allow yet, ask the device to record it for its owner — the grant
|
|
157
|
+
stays on that machine (tray → Allow a folder…, or `neuralis device grant <dir>`):
|
|
158
|
+
`neuralis request POST @neuralis/agent-core/devices/dev_…/requests -f path=/abs/dir -f list=read`
|
|
159
|
+
(`list=write` for a writable folder) → `{recorded:true}`, or `{recorded:false,
|
|
160
|
+
reason:"inside_ceiling"}` when it is already allowed.
|
|
161
|
+
|
|
162
|
+
Attaching a device folder is not the same act as granting host command execution: reading
|
|
135
163
|
files through `fs_*` and running commands there are separate grants.
|
|
136
164
|
|
|
137
165
|
The same split holds for every exec-capable source (a virtual desktop, any
|
|
@@ -152,13 +180,15 @@ server-side sync queue. Poll `sources/sync-status` (`-f source=<slug>`) until
|
|
|
152
180
|
with `source` stops one source's job mid-run; without it, EVERY job on
|
|
153
181
|
sources you can see.
|
|
154
182
|
|
|
155
|
-
An embedding job can end `paused`: report `result.embedding.pausedReason` and partial counts. Resume is a new explicitly authorized `
|
|
183
|
+
An embedding job can end `paused`: report `result.embedding.pausedReason` and partial counts. Resume is a new explicitly authorized `embeddingOnly` request, using durable point debt; no saved job ID or automatic paid restart.
|
|
156
184
|
|
|
157
185
|
`sources/sync` refuses in two ways worth telling apart. **404** — the slug does not
|
|
158
186
|
resolve for you (it does not exist, or it is outside your scope; the two answer
|
|
159
187
|
alike on purpose). **400** — the source exists but carries no `sync` block, so
|
|
160
188
|
there is nothing to trigger: add one with an update first. Neither is a server
|
|
161
|
-
fault, so neither should be retried unchanged.
|
|
189
|
+
fault, so neither should be retried unchanged. A job that fails `root_empty`
|
|
190
|
+
(or `root_unreachable`) removed nothing; `confirmEmpty:true` is for a folder the
|
|
191
|
+
user confirmed is empty (the `sync` skill).
|
|
162
192
|
|
|
163
193
|
## Fields, bodies and script env
|
|
164
194
|
|
|
@@ -170,20 +200,20 @@ fault, so neither should be retried unchanged.
|
|
|
170
200
|
- `?purge=1` on delete enqueues an async vector purge. Delete then returns
|
|
171
201
|
**202 + `{purgeJob, …}`** (vs 200 normally). Any delete resolves the source's
|
|
172
202
|
open notifications (its unread failure warnings) for you and its creator.
|
|
173
|
-
-
|
|
174
|
-
source). `
|
|
175
|
-
`
|
|
203
|
+
- The re-embed body takes `source` (required) and `folder` / `uri` — its scope (one of them, inside `source`; neither = the whole
|
|
204
|
+
source). `embeddingOnly:true` catches up debt, `force:true` selects a forced connector re-embed instead, and `estimate:true` on
|
|
205
|
+
either only ESTIMATES. `scope:"platform"` (catch-up only, whole source, needs `platform.vector.maintain`) catches up EVERY
|
|
176
206
|
writer's points of the source, not only yours — the way back after an operator dense clear.
|
|
177
207
|
- Create and update bodies (`--input -`) MUST include
|
|
178
208
|
`source` + `permissions`; create additionally requires `connection.kind`. May also
|
|
179
|
-
carry `
|
|
209
|
+
carry `packageFolders` (an array of folders; absent or `null` = unchanged, so a listing
|
|
180
210
|
round-tripped through jq never 400s on it) — see **Package sources** below. A `sync`
|
|
181
211
|
block may carry an `include` allowlist alongside `exclude`/`trigger`
|
|
182
212
|
(`"sync": {"exclude": [], "include": ["skills/**"], "trigger": "manual"}`): non-empty
|
|
183
213
|
means only matching files sync, and an exclude still wins. A `sync.media` object
|
|
184
214
|
(`{"images":true,"pdf":true,"video":false,"audio":false}`, absent key = that default)
|
|
185
215
|
picks which binary kinds a MULTIMODAL active model embeds; a text-only model embeds
|
|
186
|
-
none, and `lastSyncResult.mediaSkipped` counts what was left out; `lastSyncResult.binarySkipped` is the last count of binary files not indexed as text (a binary extension, or a NUL in the first `brainSyncBinarySniffChars` characters); `lastSyncResult.embeddingDegraded` lists the reasons (`quota`, `credentials`, `rate_limit`, …) when the embedder was unavailable during the pass — the files are indexed and text-searchable, their semantic embedding is owed and caught up by `
|
|
216
|
+
none, and `lastSyncResult.mediaSkipped` counts what was left out; `lastSyncResult.binarySkipped` is the last count of binary files not indexed as text (a binary extension, or a NUL in the first `brainSyncBinarySniffChars` characters); `lastSyncResult.embeddingDegraded` lists the reasons (`quota`, `credentials`, `rate_limit`, …) when the embedder was unavailable during the pass — the files are indexed and text-searchable, their semantic embedding is owed and caught up by an `embeddingOnly` re-embed once the embedder answers. The `invalid` reason is a local PNG structural check before provider work; invalid input preserves existing indexed and recovery payloads. **`include` bounds the
|
|
187
217
|
INDEX, never the read.** What an agent can `fs_read` is set by the source ROOT and by
|
|
188
218
|
`permissions.paths[]` — so narrowing a wide source with `include` alone leaves every
|
|
189
219
|
file under that root readable. Re-root it, or add a path deny, or both.
|
|
@@ -199,7 +229,7 @@ to change. Every update example below does exactly that.
|
|
|
199
229
|
|
|
200
230
|
**`syncExcludes` is a PREFERENCE; the uri policy is the security half. Do not
|
|
201
231
|
confuse them.** A source's `sync.exclude` list is yours to edit — it is noise
|
|
202
|
-
control (do not index `node_modules`), per source, managed through `
|
|
232
|
+
control (do not index `node_modules`), per source, managed through `sources.mount`.
|
|
203
233
|
It is NOT how you keep a secret out of the index. The immutable `floor:true`
|
|
204
234
|
uri-policy rows are: a path whose floor denies `read` cannot be read by any
|
|
205
235
|
caller AND is never newly embedded, because *what cannot be read cannot be
|
|
@@ -220,25 +250,35 @@ theirs.
|
|
|
220
250
|
|
|
221
251
|
```bash
|
|
222
252
|
# Disposable source from the lifecycle walkthrough only; estimate first.
|
|
223
|
-
|
|
253
|
+
echo '{"source":"scratch-demo","mode":"estimate","obsoleteOnly":true,"selector":{"kind":"source"}}' | neuralis request POST @neuralis/brain-core/sources/purge --input -
|
|
224
254
|
# Apply only after reviewing the same selection’s counts.
|
|
225
|
-
|
|
255
|
+
echo '{"source":"scratch-demo","mode":"apply","obsoleteOnly":true,"selector":{"kind":"source"}}' | neuralis request POST @neuralis/brain-core/sources/purge --input -
|
|
226
256
|
# A canonical folder selection, still estimate-only:
|
|
227
|
-
|
|
257
|
+
echo '{"source":"scratch-demo","mode":"estimate","obsoleteOnly":false,"selector":{"kind":"folder","uri":"scratch-demo://docs"}}' | neuralis request POST @neuralis/brain-core/sources/purge --input -
|
|
228
258
|
```
|
|
229
259
|
|
|
230
260
|
## Re-embed (a file, a folder, a source)
|
|
231
261
|
|
|
232
|
-
"Rescan changes" reuses unchanged indexed files, but rebuilds re-included recovery-only content. `
|
|
262
|
+
"Rescan changes" reuses unchanged indexed files, but rebuilds re-included recovery-only content. `embeddingOnly:true` catches up missing/stale indexed embeddings, including brain-only and unchanged legacy records. Its read-only estimate returns `estimate_kind:scope_upper_bound`: authorized indexed scope counts are an upper bound, not a provider quote; no provider call or job starts. Show the estimate before you send the same body without `estimate` (202 + embedding job; poll `sources/sync-status`). Disabled embedding refuses: each `GET sources` row's `embedding_enabled` is the live platform switch, and while it is `false` the re-embed answers 409 `embedding_disabled`; without an active dense generation the estimate refuses and a submitted job pauses as `metadata_only`, never activating a model. `force:true` instead rereads and re-embeds the connector scope; its estimate includes `{documents,estimate:{tokens,relStdErr,usd,seconds}}` (`usd:null` for an unpriced model). A single file you may not read answers
|
|
233
263
|
`404`, exactly like a missing one. Switching the platform to a DIFFERENT model is not this:
|
|
234
264
|
that is the owner's rebuild in the admin Vector section.
|
|
235
265
|
|
|
236
|
-
|
|
266
|
+
```bash
|
|
267
|
+
# Read-only estimates first (no job, no provider call): debt catch-up, then a forced re-embed of one folder.
|
|
268
|
+
neuralis request POST @neuralis/brain-core/sources/reindex -f source=scratch-demo -F embeddingOnly=true -F estimate=true
|
|
269
|
+
neuralis request POST @neuralis/brain-core/sources/reindex -f source=scratch-demo -f folder=scratch-demo://docs -F force=true -F estimate=true
|
|
270
|
+
# Starts a paid embedding job (202) — the same body without `estimate`.
|
|
271
|
+
neuralis request POST @neuralis/brain-core/sources/reindex -f source=scratch-demo -F embeddingOnly=true
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Package sources (`packageFolders`)
|
|
237
275
|
|
|
238
|
-
Create and update accept `
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
276
|
+
Create and update accept `packageFolders` in the body: the folders of the source, relative
|
|
277
|
+
to its root, whose packages the host loads (`""` = the whole source, `"tools/pkgs"` = that
|
|
278
|
+
folder; no `..`, no absolute path; `[]` clears them). It does NOT switch markdown discovery
|
|
279
|
+
on — a synced source's markdown becomes source-package contributions (skill / instruction /
|
|
280
|
+
rule / agent / docs) either way; the folders let the host load packages from them as runtime
|
|
281
|
+
package sources (create-package
|
|
242
282
|
`references/connectors-and-uri-policies.md` §Declare source instances owns the details). Two
|
|
243
283
|
server-side gates apply regardless of what you send (`src/routes/sources.ts`):
|
|
244
284
|
|
|
@@ -248,14 +288,16 @@ server-side gates apply regardless of what you send (`src/routes/sources.ts`):
|
|
|
248
288
|
member 20 · viewer 30, lower = stronger), or who holds a `'*'` wildcard
|
|
249
289
|
feature grant. A CUSTOM role that declares `priority: 2` passes exactly like
|
|
250
290
|
the built-in `admin`; a role NAMED `admin` is not what is checked. Anything
|
|
251
|
-
weaker gets `403 Setting
|
|
291
|
+
weaker gets `403 Setting packageFolders requires an owner/admin-effective
|
|
252
292
|
role.` — quote that string verbatim when you report it. It names the required
|
|
253
293
|
STRENGTH, not a role you have to be called. This is the SECOND gate on the
|
|
254
|
-
route: `
|
|
294
|
+
route: `sources.mount` is checked first for the whole PATCH, so a caller without
|
|
255
295
|
it never reaches this message and sees `403 Updating sources requires
|
|
256
|
-
|
|
296
|
+
sources.mount.` instead. Read the two strings as different answers — a missing
|
|
257
297
|
feature grant versus insufficient role strength.
|
|
258
|
-
-
|
|
298
|
+
- **`host` kind only** — setting it on another kind returns `400`. On a folder on a paired
|
|
299
|
+
device the packages are read over its link, never copied here; their skill scripts run on
|
|
300
|
+
that device. While it is offline its packages read "Not available".
|
|
259
301
|
|
|
260
302
|
A package delivered through a **user/agent-scoped** source is advertised only to that
|
|
261
303
|
scope (a different run identity sees nothing — correct-by-design, not a load failure).
|
|
@@ -265,11 +307,11 @@ scope (a different run identity sees nothing — correct-by-design, not a load f
|
|
|
265
307
|
# and already holds markdown, so this edits a REAL source. `repo` is a stand-in:
|
|
266
308
|
# substitute a slug from the sources list. The effect is live — every matching .md under
|
|
267
309
|
# it starts being advertised as a package contribution on the next sync — and it
|
|
268
|
-
# is reversible only by resending the same body with `
|
|
269
|
-
# Needs
|
|
270
|
-
#
|
|
310
|
+
# is reversible only by resending the same body with `packageFolders:[]`.
|
|
311
|
+
# Needs sources.mount, then priority <= 2 (the admin anchor) or a '*' grant, and a
|
|
312
|
+
# folder source. The body carries the source's CURRENT permissions back —
|
|
271
313
|
# PATCH replaces them:
|
|
272
|
-
neuralis request GET @neuralis/brain-core/sources --jq '.[] | select(.source=="repo") | {source, permissions,
|
|
314
|
+
neuralis request GET @neuralis/brain-core/sources --jq '.[] | select(.source=="repo") | {source, permissions, packageFolders:[""]}' | neuralis request PATCH @neuralis/brain-core/sources --input -
|
|
273
315
|
```
|
|
274
316
|
|
|
275
317
|
## `description` field
|
|
@@ -298,18 +340,17 @@ neuralis request GET @neuralis/brain-core/sources
|
|
|
298
340
|
# a TOP-LEVEL ARRAY → filter with .[] (NOT .sources[]):
|
|
299
341
|
# Each row IS the source config: the slug lives in `.source` (there is no `.slug` key).
|
|
300
342
|
neuralis request GET @neuralis/brain-core/sources --jq '.[] | {source, enabled, kind: .connection.kind, orphan}'
|
|
301
|
-
neuralis request GET @neuralis/brain-core/sources --jq '.[] | select(.connection.kind=="
|
|
343
|
+
neuralis request GET @neuralis/brain-core/sources --jq '.[] | select(.connection.kind=="host" and (.connection.config.device|not))'
|
|
302
344
|
# The kind is the registry KIND, not a connector id or a UI label. Enumerate them
|
|
303
|
-
# (today: brain, host,
|
|
345
|
+
# (today: brain, host, webtop); an unregistered value is 404
|
|
304
346
|
# `Unknown kind "<x>"` for EVERY caller, so it is never a permission problem.
|
|
305
|
-
# The on-disk connector's id is `local-disk` but its kind is `local` — send `local`.
|
|
306
347
|
neuralis request GET @neuralis/brain-core/sources/kinds --jq '.kinds[].kind'
|
|
307
|
-
neuralis request GET @neuralis/brain-core/sources/kinds/
|
|
308
|
-
neuralis request POST @neuralis/brain-core/sources/sync -f source=data # needs
|
|
348
|
+
neuralis request GET @neuralis/brain-core/sources/kinds/host/schema
|
|
349
|
+
neuralis request POST @neuralis/brain-core/sources/sync -f source=data # needs sources.sync
|
|
309
350
|
neuralis request GET @neuralis/brain-core/sources/sync-status -f source=data
|
|
310
351
|
# `"auto"` = live only while the source's runtime runs; a boolean is typed with -F
|
|
311
352
|
neuralis request POST @neuralis/brain-core/sources/enabled -f source=data -F enabled=true
|
|
312
|
-
neuralis request GET @neuralis/brain-core/sources/browse -f path
|
|
353
|
+
neuralis request GET @neuralis/brain-core/sources/browse -f path="$DATA_ROOT" # needs sources.mount; DATA_ROOT = the data source's container= path
|
|
313
354
|
```
|
|
314
355
|
|
|
315
356
|
### Lifecycle walkthrough — create → update → delete
|
|
@@ -325,10 +366,10 @@ the `delete` on the last line would destroy the project's real source instead of
|
|
|
325
366
|
the throwaway.
|
|
326
367
|
|
|
327
368
|
```bash
|
|
328
|
-
# 1. Create (needs
|
|
369
|
+
# 1. Create (needs sources.mount). source + connection.kind + permissions.default.* required.
|
|
329
370
|
# The root does not have to exist yet — create records the coordinate, sync walks it.
|
|
330
|
-
|
|
331
|
-
# 2. Update — NO SLUG; the body `source` field is the key (needs
|
|
371
|
+
echo '{"source":"scratch-demo","connection":{"kind":"host","config":{"root":"/tmp/scratch-demo"}},"permissions":{"default":{"read":true,"write":true,"exec":false}}}' | neuralis request POST @neuralis/brain-core/sources --input -
|
|
372
|
+
# 2. Update — NO SLUG; the body `source` field is the key (needs sources.mount).
|
|
332
373
|
# Sets the description shown in the agent <runtime_stack>. `permissions` is
|
|
333
374
|
# REPLACED, so read the live object back and resend it unchanged, editing only
|
|
334
375
|
# the field you meant to change — a hand-written {"default":…} body here would
|
|
@@ -344,8 +385,8 @@ neuralis request DELETE '@neuralis/brain-core/sources/scratch-demo?purge=1'
|
|
|
344
385
|
## Vector health (index diagnostics)
|
|
345
386
|
|
|
346
387
|
The health route is SPLIT into a count-cheap path and a scan path (pattern `health/*`, feature
|
|
347
|
-
`
|
|
348
|
-
read paths run on `
|
|
388
|
+
`files.read`) — call it with `neuralis request`. **The two
|
|
389
|
+
read paths run on `files.read`; the `gc` path does not** — it additionally requires `files.write`
|
|
349
390
|
and is POST-only (see below). That covers its actions: `gc`, `repair-orphans` and `repair-pending`
|
|
350
391
|
mutate, and `deduplicate` is read-only but rides the same gate — its rows enumerate other agents'
|
|
351
392
|
`data://` paths.
|
|
@@ -362,14 +403,14 @@ mutate, and `deduplicate` is read-only but rides the same gate — its rows enum
|
|
|
362
403
|
- **`POST …/brain-core/health/gc`** with `{action}` (`gc` / `repair-orphans` / `repair-pending` / `deduplicate`) —
|
|
363
404
|
`gc`, `repair-orphans` and `repair-pending` MUTATE — run those only after a scan confirms a finding; `deduplicate`
|
|
364
405
|
removes nothing (it reports groups) but is gated identically. **POST only** — a GET answers
|
|
365
|
-
`405 Method GET not allowed`. It needs **`
|
|
366
|
-
caller without it gets `403 {"error":"Missing feature:
|
|
406
|
+
`405 Method GET not allowed`. It needs **`files.write`** on top of the route's `files.read`; a
|
|
407
|
+
caller without it gets `403 {"error":"Missing feature: files.write (vector health repair)"}`.
|
|
367
408
|
That is a capability the caller lacks, not a broken call: report the finding and say that the
|
|
368
|
-
sweep needs `
|
|
409
|
+
sweep needs `files.write` (manager tier and up), rather than retrying.
|
|
369
410
|
`dryRun` DEFAULTS TO FALSE — pass `{"dryRun": true}` first when you want a preview. `repair-pending` processes one visible batch (default 50) and returns `scannedVisible`, `orphaned`, `attempted`, `discarded`, `refused`, `failed`, safe reason counts, `nextCursor`, `complete` and `partial`. Pass the returned `nextCursor` as `cursor` in the next POST only after checking the result; pause on partial/failure, retry explicitly, and restart on `restartRequired`. Each page reconstructs the complete projected inventory; the batch bounds mutations, not scan work. A terminal acknowledgement is not a newly discarded record.
|
|
370
411
|
- **`GET …/brain-core/health/hot-uris`** → the files the index rewrote most in the last hour:
|
|
371
412
|
`{windowMinutes, threshold, uris: [{uri, writes, points, lastWriteAt, hot}]}` (`writes` = file
|
|
372
|
-
writes, `points` = index points incl. chunks). Same `
|
|
413
|
+
writes, `points` = index points incl. chunks). Same `files.write` gate; already filtered to the
|
|
373
414
|
files you may read. Use it when indexing load is high or `deletedCount` keeps growing.
|
|
374
415
|
|
|
375
416
|
`unindexed` / `stale_indexed` are NOT in the health route at all — get those per-source from
|
|
@@ -390,5 +431,5 @@ neuralis request GET @neuralis/brain-core/health/scan
|
|
|
390
431
|
duplicate groups (from `/health/scan`); unindexed/stale per source (from `fs_list`).
|
|
391
432
|
3. A changed embedding model is never mixed in: the index keeps embedding with the model
|
|
392
433
|
it was built with until the owner rebuilds it from the admin Vector section — no reset.
|
|
393
|
-
4. If issues found, suggest specific remediation: source sync for stale data, `
|
|
434
|
+
4. If issues found, suggest specific remediation: source sync for stale data, a `force` re-embed for
|
|
394
435
|
files whose vectors look wrong, `POST /health/gc` to gc / repair-orphans / deduplicate.
|