@neuralis/brain-core 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +2 -2
  2. package/dist/app/host.js +52 -55
  3. package/dist/src/config/env.d.ts +8 -0
  4. package/dist/src/config/env.d.ts.map +1 -1
  5. package/dist/src/config/env.js +17 -6
  6. package/dist/src/config/env.js.map +1 -1
  7. package/dist/src/domain/BrainError.d.ts +14 -0
  8. package/dist/src/domain/BrainError.d.ts.map +1 -1
  9. package/dist/src/domain/BrainError.js +21 -0
  10. package/dist/src/domain/BrainError.js.map +1 -1
  11. package/dist/src/domain/types.d.ts +5 -0
  12. package/dist/src/domain/types.d.ts.map +1 -1
  13. package/dist/src/embeddings/models.d.ts +1 -2
  14. package/dist/src/embeddings/models.d.ts.map +1 -1
  15. package/dist/src/embeddings/models.js +1 -2
  16. package/dist/src/embeddings/models.js.map +1 -1
  17. package/dist/src/lifecycle.d.ts +4 -5
  18. package/dist/src/lifecycle.d.ts.map +1 -1
  19. package/dist/src/lifecycle.js.map +1 -1
  20. package/dist/src/routes/approve.d.ts.map +1 -1
  21. package/dist/src/routes/approve.js +3 -3
  22. package/dist/src/routes/approve.js.map +1 -1
  23. package/dist/src/routes/health.d.ts.map +1 -1
  24. package/dist/src/routes/health.js +8 -5
  25. package/dist/src/routes/health.js.map +1 -1
  26. package/dist/src/routes/helpers.d.ts +10 -1
  27. package/dist/src/routes/helpers.d.ts.map +1 -1
  28. package/dist/src/routes/helpers.js +26 -0
  29. package/dist/src/routes/helpers.js.map +1 -1
  30. package/dist/src/routes/list.d.ts.map +1 -1
  31. package/dist/src/routes/list.js +3 -3
  32. package/dist/src/routes/list.js.map +1 -1
  33. package/dist/src/routes/pending.d.ts.map +1 -1
  34. package/dist/src/routes/pending.js +5 -5
  35. package/dist/src/routes/pending.js.map +1 -1
  36. package/dist/src/routes/raw.d.ts.map +1 -1
  37. package/dist/src/routes/raw.js +3 -3
  38. package/dist/src/routes/raw.js.map +1 -1
  39. package/dist/src/routes/read.d.ts.map +1 -1
  40. package/dist/src/routes/read.js +3 -3
  41. package/dist/src/routes/read.js.map +1 -1
  42. package/dist/src/routes/search.d.ts.map +1 -1
  43. package/dist/src/routes/search.js +3 -3
  44. package/dist/src/routes/search.js.map +1 -1
  45. package/dist/src/routes/sources.d.ts.map +1 -1
  46. package/dist/src/routes/sources.js +9 -9
  47. package/dist/src/routes/sources.js.map +1 -1
  48. package/dist/src/routes/upload.d.ts.map +1 -1
  49. package/dist/src/routes/upload.js +3 -3
  50. package/dist/src/routes/upload.js.map +1 -1
  51. package/dist/src/services/FilesystemService.d.ts.map +1 -1
  52. package/dist/src/services/FilesystemService.js +6 -0
  53. package/dist/src/services/FilesystemService.js.map +1 -1
  54. package/dist/src/services/FilesystemUiService.d.ts.map +1 -1
  55. package/dist/src/services/FilesystemUiService.js +5 -2
  56. package/dist/src/services/FilesystemUiService.js.map +1 -1
  57. package/dist/src/services/SyncScheduler.d.ts.map +1 -1
  58. package/dist/src/services/SyncScheduler.js +8 -2
  59. package/dist/src/services/SyncScheduler.js.map +1 -1
  60. package/dist/src/sync/SyncJobQueue.d.ts +7 -0
  61. package/dist/src/sync/SyncJobQueue.d.ts.map +1 -1
  62. package/dist/src/sync/SyncJobQueue.js +40 -0
  63. package/dist/src/sync/SyncJobQueue.js.map +1 -1
  64. package/dist/src/tools/execCtx.d.ts +6 -0
  65. package/dist/src/tools/execCtx.d.ts.map +1 -1
  66. package/dist/src/tools/execCtx.js +11 -0
  67. package/dist/src/tools/execCtx.js.map +1 -1
  68. package/dist/src/tools/fs_list.js +2 -2
  69. package/dist/src/tools/fs_list.js.map +1 -1
  70. package/dist/src/tools/fs_read.js +2 -2
  71. package/dist/src/tools/fs_read.js.map +1 -1
  72. package/dist/src/tools/fs_search.js +2 -2
  73. package/dist/src/tools/fs_search.js.map +1 -1
  74. package/dist/src/tools/fs_write.js +2 -2
  75. package/dist/src/tools/fs_write.js.map +1 -1
  76. package/dist/src/usecases/deprovisionProject.d.ts +4 -5
  77. package/dist/src/usecases/deprovisionProject.d.ts.map +1 -1
  78. package/dist/src/usecases/deprovisionProject.js +3 -8
  79. package/dist/src/usecases/deprovisionProject.js.map +1 -1
  80. package/dist/src/usecases/listSourcePackages.d.ts.map +1 -1
  81. package/dist/src/usecases/listSourcePackages.js +93 -74
  82. package/dist/src/usecases/listSourcePackages.js.map +1 -1
  83. package/dist/src/usecases/readFiles.d.ts.map +1 -1
  84. package/dist/src/usecases/readFiles.js +2 -1
  85. package/dist/src/usecases/readFiles.js.map +1 -1
  86. package/dist/src/usecases/searchFiles.d.ts.map +1 -1
  87. package/dist/src/usecases/searchFiles.js +13 -3
  88. package/dist/src/usecases/searchFiles.js.map +1 -1
  89. package/dist/src/usecases/sourcePackageInventory.d.ts +10 -2
  90. package/dist/src/usecases/sourcePackageInventory.d.ts.map +1 -1
  91. package/dist/src/usecases/sourcePackageInventory.js +24 -7
  92. package/dist/src/usecases/sourcePackageInventory.js.map +1 -1
  93. package/dist/src/usecases/vectorActivityWatch.d.ts +20 -13
  94. package/dist/src/usecases/vectorActivityWatch.d.ts.map +1 -1
  95. package/dist/src/usecases/vectorActivityWatch.js +61 -36
  96. package/dist/src/usecases/vectorActivityWatch.js.map +1 -1
  97. package/dist/src/usecases/vectorMaintenance.d.ts.map +1 -1
  98. package/dist/src/usecases/vectorMaintenance.js +16 -1
  99. package/dist/src/usecases/vectorMaintenance.js.map +1 -1
  100. package/dist/src/usecases/write/index.d.ts.map +1 -1
  101. package/dist/src/usecases/write/index.js +17 -2
  102. package/dist/src/usecases/write/index.js.map +1 -1
  103. package/dist/src/usecases/write/occupancy.d.ts +5 -1
  104. package/dist/src/usecases/write/occupancy.d.ts.map +1 -1
  105. package/dist/src/usecases/write/occupancy.js +13 -4
  106. package/dist/src/usecases/write/occupancy.js.map +1 -1
  107. package/dist/src/usecases/write/structure.d.ts.map +1 -1
  108. package/dist/src/usecases/write/structure.js +20 -5
  109. package/dist/src/usecases/write/structure.js.map +1 -1
  110. package/dist/src/vector/FilesystemVectorIndex.d.ts +72 -2
  111. package/dist/src/vector/FilesystemVectorIndex.d.ts.map +1 -1
  112. package/dist/src/vector/FilesystemVectorIndex.js +211 -27
  113. package/dist/src/vector/FilesystemVectorIndex.js.map +1 -1
  114. package/dist/src/vector/InMemoryVectorIndex.d.ts.map +1 -1
  115. package/dist/src/vector/InMemoryVectorIndex.js +55 -7
  116. package/dist/src/vector/InMemoryVectorIndex.js.map +1 -1
  117. package/dist/src/vector/qdrantClient.d.ts +17 -0
  118. package/dist/src/vector/qdrantClient.d.ts.map +1 -1
  119. package/dist/src/vector/qdrantClient.js +47 -5
  120. package/dist/src/vector/qdrantClient.js.map +1 -1
  121. package/dist/src/wiring.d.ts +7 -12
  122. package/dist/src/wiring.d.ts.map +1 -1
  123. package/dist/src/wiring.js +29 -55
  124. package/dist/src/wiring.js.map +1 -1
  125. package/package.json +24 -3
  126. package/skills/manage-files/SKILL.md +1 -1
  127. package/skills/sync/SKILL.md +1 -1
@@ -38,7 +38,7 @@ server-side **403** from `search` even though the other routes work.
38
38
  ## Bodies
39
39
 
40
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.
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. `code:"vector_store_unavailable"` (per file on `/read`, `ok:false` on `/write`, a **503** elsewhere) means the index is not available yet: a new file on a folder source still lands, a `brain://` file, an edit, move or delete waits — nothing was changed; retry later. 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.
42
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.
43
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.
44
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.
@@ -13,7 +13,7 @@ Trigger a delta sync for the brain-core filesystem.
13
13
 
14
14
  1. Use `fs_list` with no `uri` first to identify configured sources, scopes, current sync status, and recent errors.
15
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
- 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.
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. A job that stays `pending` while other calls answer `vector_store_unavailable` is held for the vector store: it runs by itself when the store is back — stop polling and report it as waiting, never as failed.
17
17
  4. If any errors occur, list them clearly with the affected source, scope, and file path. Two job errors are fixed codes and removed nothing: `root_unreachable` (the source root cannot be reached — unmounted, renamed, device offline; fix the mount, then sync again) and `root_empty` (the root answers but holds no file while the index still holds some). Re-send `confirmEmpty:true` with the sync only after the user confirms the folder really is empty — that one pass removes its files from the index.
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.
19
19