feat: index extra source roots beside the workspace, for the code you write against
The workspace index cannot answer questions about an installed framework or SDK, and in plugin development that is where most of the reading goes: 64 of 80 tool calls in one real session went to the harness checkout under /usr/local/lib/node_modules to look up the API being implemented. A root is entered whatever it is called, and its dependencies are not: a path ending in node_modules/... is the normal way to name a package tree, while a node_modules below the root is somebody else's code. A result carries the label that says which tree it came from and an absolute sourcePath, the only form a follow-up read can resolve. The tool description now also claims the move this replaces - searching before reading files to find out what a module contains.
This commit is contained in:
1 parent
bccd112ce5
commit
de4d020dcb
8 files changed
+873
-22
No files matched your search
@@ -168,7 +168,99 @@ machine.
|
||||
|
||||
The tool description steers the model on when *not* to use it: prefer `grep` when
|
||||
you already know the symbol, `read` when you need the whole file, and do not
|
||||
follow up with a `read` of a range you were just handed.
|
||||
follow up with a `read` of a range you were just handed. It also claims the one
|
||||
move it exists to replace: **reaching for it before reading files to find out
|
||||
what a module contains**, because that is a search — and one search that warms a
|
||||
bounded slice of the index costs less than the first round of reads it avoids.
|
||||
|
||||
## Extra source roots: indexing the code you write *against*
|
||||
|
||||
A workspace index answers questions about the code you are writing. It cannot
|
||||
answer questions about the library that code is written against — the framework,
|
||||
the SDK, the installed platform — because none of that is under the workspace.
|
||||
|
||||
Measured on one real plugin-development session, **64 of 80 tool calls** went to
|
||||
the installed harness checkout under `/usr/local/lib/node_modules` to look up the
|
||||
contract being implemented: *"Read workspace slot contract"*, *"Locate
|
||||
DirectoryListing definition"*, *"Read UiWorkspace service type"*. That is the only
|
||||
authoritative copy of the API, and every one of those reads went into the
|
||||
conversation the expensive way.
|
||||
|
||||
```yaml
|
||||
# your profile's cordis.patch.yml
|
||||
- id: dsh-recall
|
||||
name: dsh-recall
|
||||
config:
|
||||
sourceRoots:
|
||||
- /usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai
|
||||
# or, with a chosen label and a workspace-relative path:
|
||||
# - vendor=../packages/node_modules/@vendor
|
||||
```
|
||||
|
||||
Registered through the settings form it is a comma-separated list, as every
|
||||
list-valued setting is.
|
||||
|
||||
An entry is a path, optionally prefixed with `name=`:
|
||||
|
||||
- an **absolute** path is taken as given — what a deployment's installed tree needs;
|
||||
- a **relative** path resolves against the workspace, which is what makes a
|
||||
checked-in configuration portable;
|
||||
- the **name** defaults to the directory's basename and becomes the first segment
|
||||
of every result path from that root, so a result says which tree it came from.
|
||||
|
||||
### The root is entered; its dependencies are not
|
||||
|
||||
A root is usually *a directory of packages*, which is the one shape the workspace
|
||||
walk handles worst: `node_modules` and friends are skipped at every depth, so the
|
||||
interesting files are exactly the ones it refuses to enter. So the rule is
|
||||
asymmetric, and the asymmetry is the feature:
|
||||
|
||||
- **the root itself is entered whatever it is called** — a path ending in
|
||||
`node_modules/...` is the normal way to name a package-manager tree;
|
||||
- **below the root** the usual skip list applies, so a `node_modules` inside one
|
||||
of those packages is not indexed. A dependency is somebody else's code, and it
|
||||
is the same code the root already holds.
|
||||
|
||||
Measured against the real harness packages (`@deepseek-ai`): **2,927 files** into
|
||||
11,926 chunks, a **113 ms** walk, and **zero** indexed paths containing
|
||||
`node_modules`. A query — *"how does a plugin register a settings section the
|
||||
client renders"* — returned its top six hits inside `dsh-client-ui-settings*`, the
|
||||
correct module, at 11 KB of excerpts against 373 KB across the 7 files they came
|
||||
from.
|
||||
|
||||
### How a result from a root is addressed
|
||||
|
||||
The paths a search returns are what the caller hands to `read`, which resolves
|
||||
them against the workspace. A file under an extra root is not under the workspace,
|
||||
so no prefixing makes `@dsh/dsh-agent/lib/index.js` readable. Each such result
|
||||
therefore carries **both**: the labelled path that says where it came from, and an
|
||||
absolute `sourcePath`:
|
||||
|
||||
```
|
||||
--- 3. @dsh/dsh-client-ui-settings/lib/types/client/contract/slots.d.ts:128-169 similarity 0.47
|
||||
at /usr/local/lib/node_modules/@deepseek-ai/.../slots.d.ts
|
||||
```
|
||||
|
||||
Reading that absolute path may still need a scope grant from the caller's own
|
||||
policy — a facet guard, say. This plugin cannot grant one and does not pretend to.
|
||||
|
||||
An unusable entry — a typo, a path that is a file rather than a directory, two
|
||||
roots claiming one name, or a name that collides with the active focus — is
|
||||
**reported in the result** and skipped. One bad entry must not cost the other
|
||||
roots, and it must not look like the feature doing nothing.
|
||||
|
||||
### Warming it before you need it
|
||||
|
||||
An extra root makes the index bigger, and a cold index is the one call that is
|
||||
slow. `index` runs as a background job by default for exactly that reason — and
|
||||
it is what makes the first search of a session cheap:
|
||||
|
||||
```
|
||||
recall action=index
|
||||
```
|
||||
|
||||
The job is owned by the session that started it, so its completion reaches that
|
||||
conversation and its cancellation follows the session.
|
||||
|
||||
## Focus: letting a conversation see less
|
||||
|
||||
|
||||
Reference in new issue
Block a user