@neuralis/brain-core 0.3.0 → 0.3.2
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 +41 -40
- package/app/README.md +3 -3
- package/app/filesystem/FilesystemHost.tsx +7 -0
- package/app/filesystem/README.md +1 -1
- package/app/filesystem/api/index.ts +4 -4
- package/app/filesystem/hooks/README.md +1 -1
- package/app/filesystem/hooks/useFilesystemSSE.ts +41 -1
- package/app/filesystem/host/README.md +2 -2
- package/app/filesystem/host/buildFilesystemHostValue.ts +9 -2
- package/app/filesystem/lib/sourceKindForm.ts +109 -5
- package/app/filesystem/store/filesystemStore.ts +13 -3
- package/app/filesystem/ui/DiscoverDock.tsx +5 -1
- package/app/filesystem/ui/FileTree.tsx +34 -8
- package/app/filesystem/ui/FilesystemWidget.tsx +10 -2
- package/app/filesystem/ui/GitControlPanel.tsx +2 -2
- package/app/filesystem/ui/PendingChangesPanel.tsx +1 -1
- package/app/filesystem/ui/README.md +14 -13
- package/app/filesystem/ui/SourcesPanel.tsx +124 -24
- package/app/filesystem/ui/VectorHealthPanel.tsx +2 -2
- package/dist/app/host.js +41 -37
- package/dist/src/channels/filesystem.d.ts +1 -1
- package/dist/src/channels/filesystem.js +1 -1
- package/dist/src/domain/mime.d.ts +3 -3
- package/dist/src/domain/mime.js +3 -3
- package/dist/src/domain/scopeAccessCtx.d.ts +2 -2
- package/dist/src/domain/scopeAccessCtx.js +2 -2
- package/dist/src/domain/types.d.ts +8 -1
- package/dist/src/domain/types.d.ts.map +1 -1
- package/dist/src/events/pending.d.ts +1 -1
- package/dist/src/events/pending.js +1 -1
- package/dist/src/git/sourceGitControl.d.ts +2 -2
- package/dist/src/git/sourceGitControl.js +3 -3
- package/dist/src/lifecycle.d.ts +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.js +18 -18
- 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.d.ts +1 -1
- package/dist/src/routes/helpers.js +1 -1
- package/dist/src/routes/list.d.ts +1 -1
- package/dist/src/routes/list.js +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 +4 -4
- package/dist/src/routes/policies.d.ts.map +1 -1
- package/dist/src/routes/policies.js +11 -11
- package/dist/src/routes/policies.js.map +1 -1
- package/dist/src/routes/raw.d.ts +1 -1
- package/dist/src/routes/raw.js +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 +20 -5
- package/dist/src/routes/sources.d.ts.map +1 -1
- package/dist/src/routes/sources.js +118 -118
- 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 +7 -1
- package/dist/src/services/BridgeService.d.ts.map +1 -1
- package/dist/src/services/BridgeService.js +15 -3
- package/dist/src/services/BridgeService.js.map +1 -1
- package/dist/src/services/FilesystemService.d.ts +1 -1
- package/dist/src/services/FilesystemService.js +2 -2
- package/dist/src/services/declaredSources.d.ts +9 -3
- package/dist/src/services/declaredSources.d.ts.map +1 -1
- package/dist/src/services/declaredSources.js +2 -1
- package/dist/src/services/declaredSources.js.map +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/embeddingBacklog.js +1 -1
- package/dist/src/usecases/embeddingBacklog.js.map +1 -1
- package/dist/src/usecases/readFiles.d.ts.map +1 -1
- package/dist/src/usecases/readFiles.js +84 -1
- package/dist/src/usecases/readFiles.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/vectorMaintenance.js +1 -1
- package/dist/src/usecases/vectorMaintenance.js.map +1 -1
- package/dist/src/usecases/write/content.js +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 +70 -63
- package/rules/brain-rules.md +2 -2
- package/skills/brain-start/SKILL.md +1 -1
- package/skills/connect-business-data/SKILL.md +1 -1
- package/skills/create-package/SKILL.md +8 -8
- package/skills/create-package/references/connectors-and-uri-policies.md +7 -2
- package/skills/create-package/references/runtime-and-build.md +1 -1
- package/skills/create-package/references/skills-and-context.md +1 -1
- package/skills/create-package/references/test-and-ship.md +4 -4
- package/skills/create-package/scripts/check-package.sh +1 -1
- package/skills/git/SKILL.md +23 -23
- package/skills/manage-files/SKILL.md +13 -13
- package/skills/manage-files/scripts/upload.sh +1 -1
- package/skills/manage-sources/SKILL.md +55 -54
- package/skills/manage-sources/scripts/reembed.sh +1 -1
- package/skills/manage-uri-policy/SKILL.md +9 -9
- package/skills/organize/SKILL.md +1 -1
- package/skills/sync/SKILL.md +2 -2
- 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/docs/drive-overview.md +0 -59
package/skills/git/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: git
|
|
3
3
|
description: "Operate git on a git-backed source through governed routes: inspect status, diff, history, and outgoing changes; stage, discard, commit, branch, switch, fetch, pull, or push. Use for repository work; choose governed git by default, raw CLI for allowed local inspection, and GitHub tools for remote collaboration."
|
|
4
4
|
allowed-tools: execute
|
|
5
|
-
requiredFeatures: [
|
|
5
|
+
requiredFeatures: [files.read]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Git
|
|
@@ -10,7 +10,7 @@ requiredFeatures: [drive.read]
|
|
|
10
10
|
Drive git on a **git-backed source** (any `local`-kind source that is a git checkout)
|
|
11
11
|
through brain-core's governed git routes. These are the **same routes the Git Control
|
|
12
12
|
panel drives**, so an agent gets exactly the rights a human member has: gated by
|
|
13
|
-
`
|
|
13
|
+
`files.read` / `files.write` + the source's uri-policy, with a **server-side snapshot
|
|
14
14
|
before every destructive op** and **credential-safe remotes** (the push/pull token is
|
|
15
15
|
resolved server-side and never touches the agent shell).
|
|
16
16
|
|
|
@@ -83,25 +83,25 @@ unreadable; never write "no changes" into a report you cannot back.
|
|
|
83
83
|
|
|
84
84
|
| Action | Method | Route | Key params | Gate |
|
|
85
85
|
|---|---|---|---|---|
|
|
86
|
-
| Whole-repo change-set + branch + ahead/behind | GET | `status` | `source`,`repo?` | `
|
|
87
|
-
| Local branch list | GET | `branch` | `source`,`repo?` | `
|
|
88
|
-
| Per-file unified diff | GET | `diff` | `source`,`path` **(required)**; optionally one of `staged=1` \| `commit=<sha>` \| `base=<sha>&head=<sha>` (omit all three for the unstaged working-tree diff) | `
|
|
89
|
-
| Blob content at a rev | GET | `show` | `source`,`path`,`rev=index\|<sha>` | `
|
|
90
|
-
| Commit-DAG page (+ `outgoing[]`) | GET | `log` | `source`,`maxCount?`,`skip?`,`ref?` | `
|
|
91
|
-
| Per-commit `+/-` totals for a log page | GET | `log-stats` | `source`,`maxCount?`,`skip?`,`ref?` | `
|
|
92
|
-
| Files a commit changed | GET | `commit` | `source`,`sha=<sha>` | `
|
|
93
|
-
| Committed-but-not-pushed files | GET | `outgoing` | `source` | `
|
|
94
|
-
| In-source repo picker — **and the plane-liveness test: empty `repos` ⇒ every root-gated read fails soft** | GET | `repos` | `source` | `
|
|
95
|
-
| Stage whole files or a hunk | POST | `stage` | `source`,`paths:[…]` **or** `hunk:"<patch>"` | `
|
|
96
|
-
| Unstage whole files or a hunk | POST | `unstage` | `source`,`paths:[…]` **or** `hunk` | `
|
|
97
|
-
| Discard working-tree changes (**destructive** → returns `rescue`) | POST | `discard` | `source`,`paths:[…]` | `
|
|
98
|
-
| Create a commit from the index | POST | `commit` | `source`,`message`,`amend?` | `
|
|
99
|
-
| Create / delete a branch (delete **destructive** → `rescue`) | POST | `branch` | `source`,`action:"create"\|"delete"`,`name`,`startPoint?`,`force?` | `
|
|
100
|
-
| Switch branch (plain, refuses to clobber → 409) | POST | `checkout` | `source`,`ref` | `
|
|
101
|
-
| **Undo** a `discard` / `branch` delete from its `rescue` carrier | POST | `restore` | `source`,`rescue:{kind:"stash"\|"branch",ref,name?}` | `
|
|
102
|
-
| Fetch from the connected remote | POST | `fetch` | `source` | `
|
|
103
|
-
| Pull (fetch + fast-forward-only merge) | POST | `pull` | `source` | `
|
|
104
|
-
| Push `HEAD` (no force) | POST | `push` | `source` | `
|
|
86
|
+
| Whole-repo change-set + branch + ahead/behind | GET | `status` | `source`,`repo?` | `files.read` + uri-policy `read` (root) |
|
|
87
|
+
| Local branch list | GET | `branch` | `source`,`repo?` | `files.read` + `read` (root) |
|
|
88
|
+
| Per-file unified diff | GET | `diff` | `source`,`path` **(required)**; optionally one of `staged=1` \| `commit=<sha>` \| `base=<sha>&head=<sha>` (omit all three for the unstaged working-tree diff) | `files.read` + `read` (per-path) |
|
|
89
|
+
| Blob content at a rev | GET | `show` | `source`,`path`,`rev=index\|<sha>` | `files.read` + `read` (per-path) |
|
|
90
|
+
| Commit-DAG page (+ `outgoing[]`) | GET | `log` | `source`,`maxCount?`,`skip?`,`ref?` | `files.read` + `read` (root) |
|
|
91
|
+
| Per-commit `+/-` totals for a log page | GET | `log-stats` | `source`,`maxCount?`,`skip?`,`ref?` | `files.read` + `read` (root) |
|
|
92
|
+
| Files a commit changed | GET | `commit` | `source`,`sha=<sha>` | `files.read` + `read` (root) |
|
|
93
|
+
| Committed-but-not-pushed files | GET | `outgoing` | `source` | `files.read` + `read` (root) |
|
|
94
|
+
| In-source repo picker — **and the plane-liveness test: empty `repos` ⇒ every root-gated read fails soft** | GET | `repos` | `source` | `files.read` + `read` (root) |
|
|
95
|
+
| Stage whole files or a hunk | POST | `stage` | `source`,`paths:[…]` **or** `hunk:"<patch>"` | `files.write` + `write` (per-path) |
|
|
96
|
+
| Unstage whole files or a hunk | POST | `unstage` | `source`,`paths:[…]` **or** `hunk` | `files.write` + `write` (per-path) |
|
|
97
|
+
| Discard working-tree changes (**destructive** → returns `rescue`) | POST | `discard` | `source`,`paths:[…]` | `files.write` + `write` (per-path) |
|
|
98
|
+
| Create a commit from the index | POST | `commit` | `source`,`message`,`amend?` | `files.write` + `write` (root) |
|
|
99
|
+
| Create / delete a branch (delete **destructive** → `rescue`) | POST | `branch` | `source`,`action:"create"\|"delete"`,`name`,`startPoint?`,`force?` | `files.write` + `write` (root) |
|
|
100
|
+
| Switch branch (plain, refuses to clobber → 409) | POST | `checkout` | `source`,`ref` | `files.write` + `write` (root) |
|
|
101
|
+
| **Undo** a `discard` / `branch` delete from its `rescue` carrier | POST | `restore` | `source`,`rescue:{kind:"stash"\|"branch",ref,name?}` | `files.write` + `write` (root) |
|
|
102
|
+
| Fetch from the connected remote | POST | `fetch` | `source` | `files.write` + uri-policy **`exec`** + connected remote |
|
|
103
|
+
| Pull (fetch + fast-forward-only merge) | POST | `pull` | `source` | `files.write` + `exec` + `write` + connected remote |
|
|
104
|
+
| Push `HEAD` (no force) | POST | `push` | `source` | `files.write` + `exec` + connected remote |
|
|
105
105
|
|
|
106
106
|
Notes:
|
|
107
107
|
- `GET commit` (what a commit changed) and `POST commit` (create a commit) are **different**
|
|
@@ -111,7 +111,7 @@ Notes:
|
|
|
111
111
|
only (never paths), and read-denied paths are excluded from the totals. Use it instead of
|
|
112
112
|
fetching diffs to count lines.
|
|
113
113
|
- The three capability tiers are gated **independently server-side**, regardless of this skill's
|
|
114
|
-
`requiredFeatures`: read routes need `
|
|
114
|
+
`requiredFeatures`: read routes need `files.read`, write routes additionally need `files.write`
|
|
115
115
|
(a read-only caller sees a **403** from any POST), and the remote routes additionally need
|
|
116
116
|
uri-policy **`exec`** on the source root (`exec` is off by default → a **403** whose body
|
|
117
117
|
carries a grant-exec affordance) **plus a connected remote** (409 `not_connected` /
|
|
@@ -120,7 +120,7 @@ Notes:
|
|
|
120
120
|
return a typed `rescue` carrier. **Undo it through the governed `restore` route** — echo the
|
|
121
121
|
carrier straight back: `POST restore` with `{"source":"…","rescue":{"kind":"stash","ref":"<sha>"}}`
|
|
122
122
|
for discarded content, `{"kind":"branch","ref":"<anchor>","name":"<branch>"}` for a deleted
|
|
123
|
-
branch. Same gate as any other write (`
|
|
123
|
+
branch. Same gate as any other write (`files.write` + `write` on the root — no `exec`, no new
|
|
124
124
|
capability), and the restore itself snapshots first. Do **not** reach for raw-shell
|
|
125
125
|
`git stash apply` / `git branch` instead: Plane C has no snapshot, so a failed recovery there is
|
|
126
126
|
unrecoverable. Surface the `rescue` to the user either way — a carrier you never mention is a
|
|
@@ -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
|
|
@@ -18,21 +18,21 @@ on your own machine); `write` and `upload` go through their scripts.
|
|
|
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` — `scripts/write.sh` | `
|
|
26
|
-
| Upload a payload (multipart/form-data) | POST | `upload` — `scripts/upload.sh` | `
|
|
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` — `scripts/write.sh` | `files.write` |
|
|
26
|
+
| Upload a payload (multipart/form-data) | POST | `upload` — `scripts/upload.sh` | `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
|
|
@@ -3,7 +3,7 @@ set -euo pipefail
|
|
|
3
3
|
# POST /upload REQUIRES multipart/form-data (NOT a JSON body): the handler reads the
|
|
4
4
|
# form fields file (the binary/text payload), agentId, uri (optional), tags (optional,
|
|
5
5
|
# comma-split). projectId is taken from the session ticket — passing a different one
|
|
6
|
-
# is a 403. Requires the caller to hold the `
|
|
6
|
+
# is a 403. Requires the caller to hold the `files.write` feature. agentId here is read
|
|
7
7
|
# from the form field.
|
|
8
8
|
FILE_PATH="${FILE_PATH:?FILE_PATH is required (local path of the payload to upload)}"
|
|
9
9
|
AGENT_ID="${AGENT_ID:?AGENT_ID is required (form field; the destination agent)}"
|
|
@@ -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`,
|
|
@@ -50,29 +50,29 @@ server-side source rows rather than the index-count survey.)
|
|
|
50
50
|
|
|
51
51
|
## Routes covered
|
|
52
52
|
|
|
53
|
-
`
|
|
53
|
+
`files.read` is the skill's floor; mutating + sync-lifecycle routes escalate
|
|
54
54
|
**in-handler** to a stronger feature and 403 an under-privileged caller (see
|
|
55
55
|
**Feature gates** below). The `Feature` column is the gate actually enforced.
|
|
56
56
|
|
|
57
57
|
| Action | Method | Path (`@neuralis/brain-core/…`) | Fields | Feature |
|
|
58
58
|
|---|---|---|---|---|
|
|
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 a filesystem path before adding it | GET | `sources/browse` | `path` | `
|
|
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; FORCE=1 re-embeds (estimate first) | POST | `sources/reindex` + `embeddingOnly` or `force` — run `bash ${SKILL_DIR}/scripts/reembed.sh` | env | `
|
|
59
|
+
| List configured sources | GET | `sources` | `scope?`, `observed?` | `files.read` |
|
|
60
|
+
| Get one source's config | GET | `sources/<slug>` | | `files.read` |
|
|
61
|
+
| List registered kinds | GET | `sources/kinds` | | `files.read` |
|
|
62
|
+
| Get a kind's config schema | GET | `sources/kinds/<kind>/schema` | | `files.read` |
|
|
63
|
+
| Discoverable connectors (filesystem hints) | GET | `sources/discoverable` | | `sources.mount` |
|
|
64
|
+
| Browse a filesystem path before adding it | GET | `sources/browse` | `path` | `sources.mount` |
|
|
65
|
+
| Create a new source | POST | `sources` | body (below) | `sources.mount` |
|
|
66
|
+
| Update an existing source | PATCH | `sources` | body (below) | `sources.mount` |
|
|
67
|
+
| Delete a source | DELETE | `sources/<slug>[?purge=1]` | | `sources.mount` |
|
|
68
|
+
| Enable / disable a source | POST | `sources/enabled` | `source`, `enabled` (`true`\|`false`\|`"auto"`) | `sources.mount` |
|
|
69
|
+
| Trigger sync (202 + queue job snapshot) | POST | `sources/sync` | `source`, `agentId?` | `sources.sync` |
|
|
70
|
+
| Cancel an in-flight sync | POST | `sources/cancel` | `source?` | `sources.sync` |
|
|
71
|
+
| Job status | GET | `sources/sync-status` | `source?` | `sources.sync` |
|
|
72
|
+
| Forget sync state (next tick re-walks; deletes nothing) | POST | `sources/reset` | `source` | `sources.sync` |
|
|
73
|
+
| Rescan changes (full re-walk now; unchanged files keep their vectors; 202 + job) | POST | `sources/reindex` | `source`, `agentId?` | `sources.sync` |
|
|
74
|
+
| Clean a file / folder / source index (estimate first) | POST | `sources/purge` | body (below) | `sources.mount` + `sources.sync` |
|
|
75
|
+
| Catch up embedding debt; FORCE=1 re-embeds (estimate first) | POST | `sources/reindex` + `embeddingOnly` or `force` — run `bash ${SKILL_DIR}/scripts/reembed.sh` | env | `sources.sync` |
|
|
76
76
|
|
|
77
77
|
> **`update` takes no `<slug>`.** PATCH targets the bare `sources` path; the
|
|
78
78
|
> source to patch is the body `source` field (the handler ignores the path).
|
|
@@ -87,49 +87,50 @@ array** of source rows (NOT `{ sources: [...] }`). Pipe `jq '.[]'`, never
|
|
|
87
87
|
`jq '.sources[]'` (that errors `Cannot index array with string "sources"`). Each
|
|
88
88
|
element carries `slug`, `enabled`, `connection.kind`, `scope`, plus the enrichment
|
|
89
89
|
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 `
|
|
90
|
+
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
91
|
|
|
92
92
|
## Feature gates
|
|
93
93
|
|
|
94
|
-
The skill declares `
|
|
94
|
+
The skill declares `files.read`, which covers the source-config READ routes.
|
|
95
95
|
Everything that mutates, syncs, or ENUMERATES THE HOST enforces a **stronger**
|
|
96
|
-
feature server-side, beyond the `
|
|
97
|
-
`
|
|
96
|
+
feature server-side, beyond the `files.read` floor — a caller holding only
|
|
97
|
+
`files.read` gets a `403`:
|
|
98
98
|
|
|
99
|
-
- **`
|
|
99
|
+
- **`sources.mount`** — create, update, delete, enable/disable, browse and the
|
|
100
100
|
discoverable list. Browsing and the
|
|
101
101
|
discoverable list are the steps that PRECEDE attaching, and they enumerate the
|
|
102
102
|
host: you may browse exactly what you would be allowed to attach.
|
|
103
|
-
- **`
|
|
103
|
+
- **`sources.privileged`** — browsing the filesystem root or any
|
|
104
104
|
protected host zone (the App Zone, the Neuralis tree), the same zones whose
|
|
105
105
|
ATTACH needs it. A protected directory is also omitted from the listing of a
|
|
106
106
|
parent you may browse, so an absent entry is not proof it does not exist.
|
|
107
|
-
- **`
|
|
107
|
+
- **`sources.sync`** — sync, cancel, reset, reindex, `reembed.sh`, sync-status.
|
|
108
108
|
|
|
109
|
-
The index purge requires both `
|
|
109
|
+
The index purge requires both `sources.mount` and `sources.sync`, source-scope management authority and current READ visibility.
|
|
110
110
|
|
|
111
111
|
Create/update/delete/enable additionally enforce `canAccessScope(.., 'write')`
|
|
112
112
|
on the target source's scope, and create validates the kind's scope rules.
|
|
113
113
|
|
|
114
114
|
### Privileged and host-plane sources
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
One escalation sits above `sources.mount`, not granted below the `admin` tier (`admin` holds
|
|
117
|
+
it through its enumerated default grant, `owner` through the `'*'` wildcard; grantable to any
|
|
118
|
+
custom role):
|
|
119
119
|
|
|
120
|
-
- **`
|
|
120
|
+
- **`sources.privileged`** — attaching (or seeing) a source rooted in, over, or at a
|
|
121
121
|
high-blast-radius zone: the platform App Zone, the Neuralis source tree, or the whole
|
|
122
122
|
filesystem (`/`). Containment is checked in both directions on canonical paths, so a
|
|
123
123
|
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
124
|
|
|
129
|
-
A
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
A source on the HOST plane (a connector kind of `host` / `host-*`, on a paired device
|
|
126
|
+
rather than in the container) has one rule: **only that device's owner, holding
|
|
127
|
+
`device.own`, attaches or edits it** — at every root, and no role feature replaces it.
|
|
128
|
+
Anyone else gets 403, whatever they hold.
|
|
129
|
+
|
|
130
|
+
A host source is also bounded by the device's own allowlist, which the platform cannot
|
|
131
|
+
widen: even a permissive source policy only reaches paths the device's owner granted. If a
|
|
132
|
+
host read or write fails while the source policy allows it, report the allowlist as the
|
|
133
|
+
limit — the owner widens it with `neuralis device grant`, not a policy edit.
|
|
133
134
|
|
|
134
135
|
Attaching a host source is not the same act as granting host command execution: reading
|
|
135
136
|
files through `fs_*` and running commands there are separate grants.
|
|
@@ -199,7 +200,7 @@ to change. Every update example below does exactly that.
|
|
|
199
200
|
|
|
200
201
|
**`syncExcludes` is a PREFERENCE; the uri policy is the security half. Do not
|
|
201
202
|
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 `
|
|
203
|
+
control (do not index `node_modules`), per source, managed through `sources.mount`.
|
|
203
204
|
It is NOT how you keep a secret out of the index. The immutable `floor:true`
|
|
204
205
|
uri-policy rows are: a path whose floor denies `read` cannot be read by any
|
|
205
206
|
caller AND is never newly embedded, because *what cannot be read cannot be
|
|
@@ -251,9 +252,9 @@ server-side gates apply regardless of what you send (`src/routes/sources.ts`):
|
|
|
251
252
|
weaker gets `403 Setting recognizesPackages requires an owner/admin-effective
|
|
252
253
|
role.` — quote that string verbatim when you report it. It names the required
|
|
253
254
|
STRENGTH, not a role you have to be called. This is the SECOND gate on the
|
|
254
|
-
route: `
|
|
255
|
+
route: `sources.mount` is checked first for the whole PATCH, so a caller without
|
|
255
256
|
it never reaches this message and sees `403 Updating sources requires
|
|
256
|
-
|
|
257
|
+
sources.mount.` instead. Read the two strings as different answers — a missing
|
|
257
258
|
feature grant versus insufficient role strength.
|
|
258
259
|
- **Local-kind only** — setting it on a non-`local` connection returns `400`.
|
|
259
260
|
|
|
@@ -266,7 +267,7 @@ scope (a different run identity sees nothing — correct-by-design, not a load f
|
|
|
266
267
|
# substitute a slug from the sources list. The effect is live — every matching .md under
|
|
267
268
|
# it starts being advertised as a package contribution on the next sync — and it
|
|
268
269
|
# is reversible only by resending the same body with `recognizesPackages:false`.
|
|
269
|
-
# Needs
|
|
270
|
+
# Needs sources.mount, then priority <= 2 (the admin anchor) or a '*' grant, and a
|
|
270
271
|
# local-kind source. The body carries the source's CURRENT permissions back —
|
|
271
272
|
# PATCH replaces them:
|
|
272
273
|
neuralis request GET @neuralis/brain-core/sources --jq '.[] | select(.source=="repo") | {source, permissions, recognizesPackages:true}' | neuralis request PATCH @neuralis/brain-core/sources --input -
|
|
@@ -305,11 +306,11 @@ neuralis request GET @neuralis/brain-core/sources --jq '.[] | select(.connection
|
|
|
305
306
|
# The on-disk connector's id is `local-disk` but its kind is `local` — send `local`.
|
|
306
307
|
neuralis request GET @neuralis/brain-core/sources/kinds --jq '.kinds[].kind'
|
|
307
308
|
neuralis request GET @neuralis/brain-core/sources/kinds/local/schema
|
|
308
|
-
neuralis request POST @neuralis/brain-core/sources/sync -f source=data # needs
|
|
309
|
+
neuralis request POST @neuralis/brain-core/sources/sync -f source=data # needs sources.sync
|
|
309
310
|
neuralis request GET @neuralis/brain-core/sources/sync-status -f source=data
|
|
310
311
|
# `"auto"` = live only while the source's runtime runs; a boolean is typed with -F
|
|
311
312
|
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=/tmp # needs
|
|
313
|
+
neuralis request GET @neuralis/brain-core/sources/browse -f path=/tmp # needs sources.mount
|
|
313
314
|
```
|
|
314
315
|
|
|
315
316
|
### Lifecycle walkthrough — create → update → delete
|
|
@@ -325,10 +326,10 @@ the `delete` on the last line would destroy the project's real source instead of
|
|
|
325
326
|
the throwaway.
|
|
326
327
|
|
|
327
328
|
```bash
|
|
328
|
-
# 1. Create (needs
|
|
329
|
+
# 1. Create (needs sources.mount). source + connection.kind + permissions.default.* required.
|
|
329
330
|
# The root does not have to exist yet — create records the coordinate, sync walks it.
|
|
330
331
|
neuralis request POST @neuralis/brain-core/sources --input - <<<'{"source":"scratch-demo","connection":{"kind":"local","config":{"root":"/tmp/scratch-demo"}},"permissions":{"default":{"read":true,"write":true,"exec":false}}}'
|
|
331
|
-
# 2. Update — NO SLUG; the body `source` field is the key (needs
|
|
332
|
+
# 2. Update — NO SLUG; the body `source` field is the key (needs sources.mount).
|
|
332
333
|
# Sets the description shown in the agent <runtime_stack>. `permissions` is
|
|
333
334
|
# REPLACED, so read the live object back and resend it unchanged, editing only
|
|
334
335
|
# the field you meant to change — a hand-written {"default":…} body here would
|
|
@@ -344,8 +345,8 @@ neuralis request DELETE '@neuralis/brain-core/sources/scratch-demo?purge=1'
|
|
|
344
345
|
## Vector health (index diagnostics)
|
|
345
346
|
|
|
346
347
|
The health route is SPLIT into a count-cheap path and a scan path (pattern `health/*`, feature
|
|
347
|
-
`
|
|
348
|
-
read paths run on `
|
|
348
|
+
`files.read`) — call it with `neuralis request`. **The two
|
|
349
|
+
read paths run on `files.read`; the `gc` path does not** — it additionally requires `files.write`
|
|
349
350
|
and is POST-only (see below). That covers its actions: `gc`, `repair-orphans` and `repair-pending`
|
|
350
351
|
mutate, and `deduplicate` is read-only but rides the same gate — its rows enumerate other agents'
|
|
351
352
|
`data://` paths.
|
|
@@ -362,14 +363,14 @@ mutate, and `deduplicate` is read-only but rides the same gate — its rows enum
|
|
|
362
363
|
- **`POST …/brain-core/health/gc`** with `{action}` (`gc` / `repair-orphans` / `repair-pending` / `deduplicate`) —
|
|
363
364
|
`gc`, `repair-orphans` and `repair-pending` MUTATE — run those only after a scan confirms a finding; `deduplicate`
|
|
364
365
|
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:
|
|
366
|
+
`405 Method GET not allowed`. It needs **`files.write`** on top of the route's `files.read`; a
|
|
367
|
+
caller without it gets `403 {"error":"Missing feature: files.write (vector health repair)"}`.
|
|
367
368
|
That is a capability the caller lacks, not a broken call: report the finding and say that the
|
|
368
|
-
sweep needs `
|
|
369
|
+
sweep needs `files.write` (manager tier and up), rather than retrying.
|
|
369
370
|
`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
371
|
- **`GET …/brain-core/health/hot-uris`** → the files the index rewrote most in the last hour:
|
|
371
372
|
`{windowMinutes, threshold, uris: [{uri, writes, points, lastWriteAt, hot}]}` (`writes` = file
|
|
372
|
-
writes, `points` = index points incl. chunks). Same `
|
|
373
|
+
writes, `points` = index points incl. chunks). Same `files.write` gate; already filtered to the
|
|
373
374
|
files you may read. Use it when indexing load is high or `deletedCount` keeps growing.
|
|
374
375
|
|
|
375
376
|
`unindexed` / `stale_indexed` are NOT in the health route at all — get those per-source from
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
|
-
# Requires
|
|
3
|
+
# Requires sources.sync (403 otherwise). FORCE=1 re-embeds with the ACTIVE model; otherwise catches up durable embedding debt — a
|
|
4
4
|
# file (URI), a folder's indexed files (FOLDER) or, with neither, the whole
|
|
5
5
|
# source — even when nothing changed. Default = the ESTIMATE only (changes
|
|
6
6
|
# nothing); CONFIRM=1 starts it (202 + job). Only files you may read count.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
requiredFeatures: [
|
|
2
|
+
requiredFeatures: [sources.policy]
|
|
3
3
|
name: manage-uri-policy
|
|
4
|
-
description: "Inspect and patch role-aware read, write, and execute URI policy for any source. Use when a legitimate path is denied or access must be narrowed; patching needs the
|
|
4
|
+
description: "Inspect and patch role-aware read, write, and execute URI policy for any source. Use when a legitimate path is denied or access must be narrowed; patching needs the sources.policy feature, and prefer the smallest explicit exception over broad defaults."
|
|
5
5
|
allowed-tools: execute
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -100,24 +100,24 @@ package's seed.
|
|
|
100
100
|
|
|
101
101
|
- **Two arms, both keyed on FEATURES — there is no role-name check on this
|
|
102
102
|
route.** Reading (`GET policies/uri/...`) is
|
|
103
|
-
the module feature `
|
|
103
|
+
the module feature `files.read`, which every built-in role holds down to
|
|
104
104
|
`viewer`. Patching (`POST policies/uri`) escalates in-handler to
|
|
105
|
-
`
|
|
106
|
-
`403 Missing feature:
|
|
105
|
+
`sources.policy` and otherwise returns
|
|
106
|
+
`403 Missing feature: sources.policy (URI policy editing)`. `sources.policy` has
|
|
107
107
|
no grant below the `admin` tier (enumerated for `admin`, `'*'` for `owner`)
|
|
108
108
|
and is grantable to any custom role — so a custom role can hold it and a
|
|
109
109
|
built-in one can lack it.
|
|
110
110
|
- **Being able to SEE this skill is not the route gate.** Its
|
|
111
|
-
`requiredFeatures: [
|
|
111
|
+
`requiredFeatures: [sources.policy]` frontmatter hides the bundle from anyone
|
|
112
112
|
without that feature; that is the ADVERTISEMENT layer. The session ticket
|
|
113
113
|
carries your real identity to the route, and there is no synthetic owner
|
|
114
114
|
upgrade anywhere.
|
|
115
115
|
- **Patching SOMEONE ELSE'S user- or agent-scoped source additionally needs scope
|
|
116
116
|
WRITE.** The POST runs `canAccessScope(..., 'write')` on the owning scope, which
|
|
117
117
|
passes unconditionally for a project-scoped source and for your OWN user/agent
|
|
118
|
-
scope — so on the common path `
|
|
119
|
-
CROSS-scope patch consults `
|
|
120
|
-
`
|
|
118
|
+
scope — so on the common path `sources.policy` is the whole answer. Only a
|
|
119
|
+
CROSS-scope patch consults `files.writeOthers`; an
|
|
120
|
+
`files.readOthers`-but-not-`files.writeOthers` holder gets
|
|
121
121
|
`403 Forbidden for source scope` there.
|
|
122
122
|
- **Manifest baselines are not edited by this skill.** Package
|
|
123
123
|
manifests ship `permissions.uriPolicies` as the read-only baseline;
|
package/skills/organize/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
requiredFeatures: [
|
|
2
|
+
requiredFeatures: [files.write]
|
|
3
3
|
name: organize
|
|
4
4
|
description: "Analyze a workspace for duplicate, misplaced, stale, or poorly indexed material and design a safer information architecture. Use when asked to clean up or reorganize; inspect references and propose or preview moves before mutating shared files."
|
|
5
5
|
allowed-tools: fs_search fs_write fs_list fs_read
|
package/skills/sync/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
requiredFeatures: [
|
|
2
|
+
requiredFeatures: [sources.sync]
|
|
3
3
|
name: sync
|
|
4
4
|
description: "Run and verify brain-core delta synchronization for configured sources. Use when live connector content and the vector index may differ, files are stale or unindexed, or changes must become searchable; inspect completion and index state instead of trusting dispatch alone."
|
|
5
5
|
allowed-tools: fs_list fs_read execute
|
|
@@ -12,7 +12,7 @@ Trigger a delta sync for the brain-core filesystem.
|
|
|
12
12
|
## Steps
|
|
13
13
|
|
|
14
14
|
1. Use `fs_list` with no `uri` first to identify configured sources, scopes, current sync status, and recent errors.
|
|
15
|
-
2. Call the brain-core source sync route for the intended source. The route answers 202 + a queue job snapshot — the sync runs in the background. Explicit sync requires `
|
|
15
|
+
2. Call the brain-core source sync route for the intended source. The route answers 202 + a queue job snapshot — the sync runs in the background. Explicit sync requires `sources.sync`; source create/update/delete uses `sources.mount`; file writes use `files.write`.
|
|
16
16
|
3. Poll `GET /sources/sync-status?source=<slug>` until the job finishes, then report the job `result` counts: `filesAdded`, `filesUpdated`, `filesRemoved`, `filesSkipped`, `filesMoved`, `chunksRemoved`, `chunksEmbedded` and `chunksSkipped` plus `embeddingDegraded` (safe, deduplicated embedding stop reasons). Payload indexing can succeed with missing/stale embeddings; report that debt separately. Read the two flags before interpreting completion. `cancelled: true` is not a failure, but the run stopped early: the counts are partial and a re-run converges. `truncated: true` means the walk stopped at `filesScanCap`, so files past the cap were never examined and no deletion or move was inferred — call that a partial pass, never a completed sync.
|
|
17
17
|
4. If any errors occur, list them clearly with the affected source, scope, and file path.
|
|
18
18
|
5. Distinguish live connector data, indexed payload and embedding freshness. Provider outage or disabled embedding preserves metadata/full-text indexing; semantic results may be old, or the response may fall back to filter search. Ordinary sync completion does not settle all embedding debt. Use `manage-sources` explicit debt catchup; terminal `paused` carries `result.embedding.pausedReason`, and Resume creates a new authorized job from durable debt.
|
package/tools/fs_list.json
CHANGED
package/tools/fs_read.json
CHANGED
package/tools/fs_search.json
CHANGED
package/tools/fs_write.json
CHANGED
package/docs/drive-overview.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: drive-overview
|
|
3
|
-
title: Drive Overview
|
|
4
|
-
description: URI schemes, tool capabilities, and sync reality for the virtual filesystem
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## URI Schemes
|
|
8
|
-
|
|
9
|
-
| Scheme | Connector kind | Storage | Indexed | Example |
|
|
10
|
-
|--------|---------|---------|---------|---------|
|
|
11
|
-
| `brain://` | `brain` (builtin) | Qdrant vector DB (inline) | always | `brain://docs/note.md` |
|
|
12
|
-
| `data://` | `local` (builtin) | Project data zone on disk + Qdrant | if configured & synced | `data://code/app.ts` |
|
|
13
|
-
| `<slug>://` | `local` (user) | Any additional `local` mount, under its own slug (lower-case letters, digits and hyphens only — never a dot) + Qdrant | if configured & synced | `archive://old/x.md` |
|
|
14
|
-
| `packages://` | `local` (builtin) | `_packages/` on disk + Qdrant | if configured & synced | `packages://my-pkg/tools/tool.json` |
|
|
15
|
-
| `app://` | `local` (builtin, privileged mount) | Platform app zone (`~/.neuralis/app/`) | rarely synced | `app://config/sources/...` |
|
|
16
|
-
| `neuralis://` | `local` (user, via `pnpm neuralis:mount add … --neuralis`) | The deployment's own `neuralis/` folder, live from the host (`scripts/`, `skills/`, `src/`, config — and `.env`) + Qdrant | if synced | `neuralis://scripts/mount.mts` |
|
|
17
|
-
| `neuralis-skills://` | `local` (user, same overlay rooted at `<root>/skills`) | Just the shipped operator skills — the narrower default, offered first | if synced | `neuralis-skills://neuralis-operations/SKILL.md` |
|
|
18
|
-
| `machine://` | `webtop` (`@neuralis/machine-core`) | Webtop sandbox | n/a | `machine://desktop/clipboard.txt` |
|
|
19
|
-
| `<slug>://` | `host` (`@neuralis/agent-core`) | Operator's machine, OUTSIDE the container, via the operator-provisioned host broker | if configured & synced | `host-dev://repos/app/src/main.ts` |
|
|
20
|
-
|
|
21
|
-
`os://<key>` is **not** a callable scheme — it is a decorative label
|
|
22
|
-
rendered inside the system prompt's `<runtime_stack>` block for
|
|
23
|
-
`NEURALIS_MOUNT_<KEY>` mounts. To address files inside a mount, use the
|
|
24
|
-
`local`-kind source slug that was attached to that mount (e.g.
|
|
25
|
-
`neuralis://` after `pnpm neuralis:mount add … --neuralis`).
|
|
26
|
-
|
|
27
|
-
## Tool Quick Reference
|
|
28
|
-
|
|
29
|
-
| Tool | Purpose | Key Detail |
|
|
30
|
-
|------|---------|------------|
|
|
31
|
-
| `fs_search` | Find by meaning, keyword, metadata, or live grep | `query` = semantic / grep pattern / filter content-keyword (tokenized over indexed text in `filter` mode), `glob` = filename keyword, `search_mode: "filter"` = metadata only, `search_mode: "grep"` + `folder_uri` = ripgrep over the live connector (works even for unsynced subpaths; results stay scoped to `folder_uri`; uri-policy `read`-gated). |
|
|
32
|
-
| `fs_read` | Read content (batch max 10) | URIs or UUIDs. `line_start`/`line_end` for large files. |
|
|
33
|
-
| `fs_list` | Workspace overview + folder browse (unified) | Omit / empty / `/` → full root (`all://`) with source registry. Pass a real URI to scope. `recursive:false` = direct children only (fast). `include=folders\|files\|all`, `summary_chars>0` attaches previews (use on small scoped folders — identity, rules). `include_metadata:true` surfaces id/category/tags/timestamps in the markdown. `only_indexed:true` skips the live merge. |
|
|
34
|
-
| `fs_write` | Create, edit or restructure — one tool, one call | The VERB is a KEY: `create` (never overwrites — a taken name lands beside as `name-2.ext`), `overwrite`, `edit[]` (targeted `old_string`→`new_string`, in order), `insert` (by line), `lines` (replace a range), `fields` (category/tags/metadata/pinned), `move`, `copy` (file or folder; the destination may be in another source), `mkdir` (not on `brain://`), `revert` (1-level undo), `delete` (a file, or a whole folder recursively). Content verbs compose in ONE write; structural verbs stand alone. Agent-runtime deletes require approval. |
|
|
35
|
-
|
|
36
|
-
## Indexed vs Live (connector-first contract)
|
|
37
|
-
|
|
38
|
-
- **`brain://`** — Always indexed (content lives inline in Qdrant).
|
|
39
|
-
- **`data://`, `packages://`, `neuralis://`, `app://` and any other `local`-kind slug** — Backed by a live `local`-kind connector; indexed mirror follows once sync has run.
|
|
40
|
-
- `fs_read` / `fs_list` go connector-first, so they work even when the index is cold or Qdrant is unreachable.
|
|
41
|
-
- Indexed searches require a warm index; payload and full-text indexing work without embeddings. Check `effective_mode`, `embedding_degraded` and row `embedding_status`: semantic requests can fall back to indexed text, and retained vectors can lag behind current content.
|
|
42
|
-
- `fs_search` in `grep` mode bypasses the index entirely and greps the connector directly (ripgrep / git grep / grep). It is uri-policy `read`-gated — only paths the caller holds `read` policy on are grepped (a `read:false` subtree is silently absent; a fully-denied `folder_uri` → 403). It needs no `execute`/shell/`exec.unconfined` access: `drive.search` + `read` policy is enough, making it the uri-policy-gated counterpart to `execute`+grep.
|
|
43
|
-
- **`machine://`** — Backed by `machine-core`'s `webtop` connector against a running webtop session; `'auto'` enabled-state resolves through the host-injected probe.
|
|
44
|
-
- **`host`-kind slugs** — Backed by `agent-core`'s host connector, resolving on the operator's machine outside the container. It exists only where the operator provisioned the broker; attaching one needs `drive.mount.host` **and** `drive.mount.privileged`. Addressed by its own slug like any other source.
|
|
45
|
-
- **`FilePresence`** per node: `brain` (vector-only), `synced` (index + connector agree), `unindexed` (on-disk but not indexed yet), `stale_indexed` (index has it, connector doesn't).
|
|
46
|
-
- **Unmounted dirs** — Not addressable as a Neuralis URI; the agent can still touch them through the `execute` tool's shell pipeline when the runtime grants exec, but `fs_*` will reject the URI.
|
|
47
|
-
|
|
48
|
-
## Sources, Scope, and Access
|
|
49
|
-
|
|
50
|
-
- Source slugs are URI schemes. Scoped clones use distinct schemes such as `local-alice://` or `machine-agent1://`; never assume every local source is named `data://`.
|
|
51
|
-
- Built-in connector kinds come from package manifests: `local` is live disk, `brain` is Qdrant-backed internal memory, and other packages can contribute more `type: "source"` connectors through the same registry.
|
|
52
|
-
- Source scopes are `project`, `user`, or `agent`. Project sources are visible to project members with the right feature grants; user/agent sources require ownership or scoped observation/modification features.
|
|
53
|
-
- Feature gates: `drive.read` covers read/list/raw/events, the vector-health READS (stats and scan) and source metadata reads, `drive.search` covers indexed and grep search, `drive.write` covers create/modify/mkdir/copy/approve/upload, the mutating Pending Changes verbs and the vector-health `gc` sweep (`POST health/gc` — POST-only, `dryRun` defaults to false), `drive.mount` covers source create/update/delete/enable **and the two host-enumeration reads that precede an attach** (`sources/browse`, `sources/discoverable`), and `drive.sync` gates explicit sync plus cancel, reset, reindex and sync-status. Three features escalate above those and none is granted below the admin tier: `drive.policy` edits a source's URI policy, and `drive.mount.privileged` together with `drive.mount.host` are both required to attach a source on a high-blast-radius or host-plane root (and `drive.mount.privileged` alone gates BROWSING the filesystem root or a high-blast-radius zone). Reaching another identity's user- or agent-scoped source additionally needs `filesystem.observeScoped` (read) or `filesystem.modifyScoped` (write). The package declares two more features that gate affordances rather than paths: `packages.author` (the Packages panel authoring launcher) and `packages.registry` (the marketplace skill) — neither widens filesystem access.
|
|
54
|
-
|
|
55
|
-
## Recovery and Health
|
|
56
|
-
|
|
57
|
-
- Every write snapshots `version.baseline`; `fs_write {revert:true}` is the one-level recovery path.
|
|
58
|
-
- A certified embedding generation locks its model and dimension. Existing collections without that proof retain unknown vectors as metadata indexes. Typed provider unavailability leaves payload indexing operational; invalid lock/schema records still fail closed. Changing an active generation requires an explicit rebuild rather than guessing vector compatibility.
|
|
59
|
-
- Tool usage/accounting belongs under `_meta.neuralis.usage`; model-visible results stay in `content` and `structuredContent`.
|