@nanonets/graft 0.5.1 → 0.7.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 +29 -7
- package/dist/ask/ask.d.ts +52 -1
- package/dist/ask/ask.d.ts.map +1 -1
- package/dist/ask/ask.js +274 -83
- package/dist/ask/ask.js.map +1 -1
- package/dist/ask/fuse.d.ts +59 -17
- package/dist/ask/fuse.d.ts.map +1 -1
- package/dist/ask/fuse.js +51 -25
- package/dist/ask/fuse.js.map +1 -1
- package/dist/ask/graphrank.d.ts +6 -0
- package/dist/ask/graphrank.d.ts.map +1 -1
- package/dist/ask/graphrank.js +5 -1
- package/dist/ask/graphrank.js.map +1 -1
- package/dist/claude/format.js +1 -1
- package/dist/claude/format.js.map +1 -1
- package/dist/claude/hooks.d.ts +16 -0
- package/dist/claude/hooks.d.ts.map +1 -1
- package/dist/claude/hooks.js +57 -2
- package/dist/claude/hooks.js.map +1 -1
- package/dist/claude/init.d.ts +3 -0
- package/dist/claude/init.d.ts.map +1 -1
- package/dist/claude/init.js +6 -1
- package/dist/claude/init.js.map +1 -1
- package/dist/claude/skill-template.d.ts.map +1 -1
- package/dist/claude/skill-template.js +20 -9
- package/dist/claude/skill-template.js.map +1 -1
- package/dist/cli.d.ts +3 -14
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +99 -70
- package/dist/cli.js.map +1 -1
- package/dist/context/savings.d.ts +34 -0
- package/dist/context/savings.d.ts.map +1 -0
- package/dist/context/savings.js +49 -0
- package/dist/context/savings.js.map +1 -0
- package/dist/engine.d.ts +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +7 -1
- package/dist/engine.js.map +1 -1
- package/dist/graph/build.d.ts.map +1 -1
- package/dist/graph/build.js +33 -0
- package/dist/graph/build.js.map +1 -1
- package/dist/graph/map.d.ts +38 -2
- package/dist/graph/map.d.ts.map +1 -1
- package/dist/graph/map.js +111 -24
- package/dist/graph/map.js.map +1 -1
- package/dist/graph/scopes.d.ts +15 -0
- package/dist/graph/scopes.d.ts.map +1 -1
- package/dist/graph/scopes.js +23 -0
- package/dist/graph/scopes.js.map +1 -1
- package/dist/graph/traverse-cli.d.ts +28 -18
- package/dist/graph/traverse-cli.d.ts.map +1 -1
- package/dist/graph/traverse-cli.js +68 -43
- package/dist/graph/traverse-cli.js.map +1 -1
- package/dist/graph/traverse.d.ts +35 -14
- package/dist/graph/traverse.d.ts.map +1 -1
- package/dist/graph/traverse.js +46 -20
- package/dist/graph/traverse.js.map +1 -1
- package/dist/graph/types.d.ts +12 -0
- package/dist/graph/types.d.ts.map +1 -1
- package/dist/graph/workspace-cli.d.ts +37 -0
- package/dist/graph/workspace-cli.d.ts.map +1 -0
- package/dist/graph/workspace-cli.js +70 -0
- package/dist/graph/workspace-cli.js.map +1 -0
- package/dist/graph/workspace.d.ts +128 -0
- package/dist/graph/workspace.d.ts.map +1 -0
- package/dist/graph/workspace.js +395 -0
- package/dist/graph/workspace.js.map +1 -0
- package/dist/hosts/instructions.d.ts.map +1 -1
- package/dist/hosts/instructions.js +7 -3
- package/dist/hosts/instructions.js.map +1 -1
- package/dist/hosts/mcp-config.d.ts +5 -0
- package/dist/hosts/mcp-config.d.ts.map +1 -1
- package/dist/hosts/mcp-config.js +2 -2
- package/dist/hosts/mcp-config.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +94 -66
- package/dist/mcp/tools.js.map +1 -1
- package/dist/search/grep-cli.d.ts.map +1 -1
- package/dist/search/grep-cli.js +4 -0
- package/dist/search/grep-cli.js.map +1 -1
- package/dist/search/grep.d.ts +4 -0
- package/dist/search/grep.d.ts.map +1 -1
- package/dist/search/grep.js +2 -0
- package/dist/search/grep.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,9 +71,11 @@ npx @nanonets/graft init
|
|
|
71
71
|
### MCP server
|
|
72
72
|
|
|
73
73
|
`graft init` also registers Graft's MCP server with agents that support it, so
|
|
74
|
-
`graft_ask`, `
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
`graft_ask`, `graft_callers`, `graft_grep`, `graft_skeleton`, `graft_map`, and
|
|
75
|
+
`graft_check` appear as native tools — no shell required. Claude Code now gets
|
|
76
|
+
this too: `graft init` writes the server into the project's `.mcp.json` (restart
|
|
77
|
+
Claude Code to load it). Skip with `--no-mcp`. Run it manually with
|
|
78
|
+
`graft mcp [dir]`, or register it by hand:
|
|
77
79
|
|
|
78
80
|
```json
|
|
79
81
|
{ "mcpServers": { "graft": { "command": "npx", "args": ["-y", "@nanonets/graft", "mcp"] } } }
|
|
@@ -187,10 +189,11 @@ graft build --extensions .ts .py # only include these code extensions
|
|
|
187
189
|
|
|
188
190
|
graft ask "<task>" [dir] # query the graph — ranked nodes + exact file:line (no LLM, no key)
|
|
189
191
|
graft ask "<task>" --json # machine-readable result
|
|
192
|
+
graft ask "<task>" --in <scope> # narrow to one sub-project of a monorepo/multi-repo folder (see below)
|
|
190
193
|
|
|
191
194
|
graft callers <symbol> [dir] # who calls/references/imports/implements/extends a symbol (no LLM, no key)
|
|
192
|
-
graft
|
|
193
|
-
graft
|
|
195
|
+
graft callers <symbol> --direction out # the reverse: what the symbol itself calls/references (was `graft callees`)
|
|
196
|
+
graft callers <symbol> -d N # walk transitively out to depth N — full blast radius (was `graft impact`)
|
|
194
197
|
|
|
195
198
|
graft grep "<regex>" [dir] # exhaustive regex search over indexed files, grouped by enclosing symbol (no LLM, no key)
|
|
196
199
|
graft grep "<regex>" --in <path> # narrow to files whose path contains this substring
|
|
@@ -205,7 +208,7 @@ graft check --json # print the drift report as JSON
|
|
|
205
208
|
graft viz [dir] # see the graph: serves an interactive viewer on localhost
|
|
206
209
|
graft viz --port 5000 --no-open # pick a port; don't auto-open the browser
|
|
207
210
|
|
|
208
|
-
graft init [dir] # wire Graft into the coding agents detected in this repo (Claude Code always gets full hooks + statusline)
|
|
211
|
+
graft init [dir] # wire Graft into the coding agents detected in this repo (Claude Code always gets full hooks + statusline + MCP)
|
|
209
212
|
graft init --no-build # wire the files only; don't build the graph
|
|
210
213
|
graft init --agents cursor kiro # wire only these agents (ids: agents, cursor, gemini, copilot, kiro, windsurf, claude)
|
|
211
214
|
graft init --all-agents # wire every known agent, detected or not
|
|
@@ -221,7 +224,7 @@ graft --version, -v # print the installed version and exit
|
|
|
221
224
|
|
|
222
225
|
Method calls resolve through the receiver's type — constructor assignments
|
|
223
226
|
(`self.router = APIRouter()`) and type annotations, not just the call-site
|
|
224
|
-
name — so `callers`/`
|
|
227
|
+
name — so `callers`/`grep --in` return calls bound to the right
|
|
225
228
|
type on method-heavy code, not every method anywhere with that name.
|
|
226
229
|
|
|
227
230
|
## Search & orient (`graft grep` / `graft map`)
|
|
@@ -257,6 +260,25 @@ scripts/ 2 files · 0 symbols
|
|
|
257
260
|
hotspots: set · method · src/graph/bindings.ts:L21-L23 · 38← contextDirFor · function · src/context/node-file.ts:L100-L103 · 11← wiringPath · function · src/graph/write.ts:L20-L22 · 10← ...
|
|
258
261
|
```
|
|
259
262
|
|
|
263
|
+
## Monorepos & multi-repo folders
|
|
264
|
+
|
|
265
|
+
Graft handles two shapes without any config:
|
|
266
|
+
|
|
267
|
+
- **A monorepo with one `.git`** (a `pnpm-workspace.yaml`/`package.json`
|
|
268
|
+
`workspaces`, or per-package `go.mod`/`pyproject.toml`/`Cargo.toml`) —
|
|
269
|
+
`graft build` discovers each sub-project as a ranking scope. `ask`/`map`
|
|
270
|
+
rank every scope on its own terms and fuse the results, so the biggest
|
|
271
|
+
sub-project can't drown a small one; hits carry `[scope/]` labels, and
|
|
272
|
+
`graft map` groups its directory clusters by scope first.
|
|
273
|
+
- **A folder of separate git repos** (no `.git` at the top) — `graft build`
|
|
274
|
+
auto-splits: each child keeps its own committable `graft/`, and the parent
|
|
275
|
+
gets a `graft/workspace.json` index. Queries from the parent federate across
|
|
276
|
+
every child, always labeled `<child>/`. Run `graft build` inside a child to
|
|
277
|
+
work on just that repo.
|
|
278
|
+
|
|
279
|
+
Either way, narrow to one sub-project with `graft ask "<task>" --in <scope>/`
|
|
280
|
+
once you know where you're working.
|
|
281
|
+
|
|
260
282
|
## Visualize it (`graft viz`)
|
|
261
283
|
|
|
262
284
|
`graft viz` opens a local, interactive view of both graphs — no install, no dev
|
package/dist/ask/ask.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Savings } from "../context/savings.js";
|
|
2
|
+
import type { NodeV1, Relation } from "../graph/types.js";
|
|
2
3
|
export interface AskHit {
|
|
3
4
|
kind: "concept" | "symbol" | "caller" | "callee";
|
|
4
5
|
title: string;
|
|
@@ -12,6 +13,10 @@ export interface AskHit {
|
|
|
12
13
|
* This is what makes `ask` substitutive — the agent reads the span here
|
|
13
14
|
* instead of opening the file, so no source read happens on top of the query. */
|
|
14
15
|
code?: string;
|
|
16
|
+
/** Multi-scope repos only: the ranking scope (path prefix, "" = root) this
|
|
17
|
+
* hit was ranked within — answers "which sub-project is this from?". Drives
|
|
18
|
+
* the `[scope/] ` label in formatAsk. Absent on single-scope repos. */
|
|
19
|
+
scope?: string;
|
|
15
20
|
}
|
|
16
21
|
export interface AskResult {
|
|
17
22
|
query: string;
|
|
@@ -33,7 +38,45 @@ export interface AskResult {
|
|
|
33
38
|
* best result, i.e. the pack is probably noise for this prompt. Absent in
|
|
34
39
|
* structural mode — a resolved "who calls X" is itself the relevance signal. */
|
|
35
40
|
coverage?: number;
|
|
41
|
+
/** Like {@link coverage}, but the top hit's idf-weighted matched share over
|
|
42
|
+
* its NAME + PATH fields ONLY (body excluded) — a match-STRENGTH signal:
|
|
43
|
+
* "did the query hit a high-value field, or only incidental body tokens?".
|
|
44
|
+
* A body-only collision (a variable that happens to share a query word) has
|
|
45
|
+
* `coverageStrong === 0` while `coverage` can still look respectable. Used by
|
|
46
|
+
* workspace federation to gate a weak child out of the cross-repo ranking.
|
|
47
|
+
* Absent in structural mode; same lexical-only contract as `coverage`. */
|
|
48
|
+
coverageStrong?: number;
|
|
49
|
+
/** Multi-scope lexical results only: which scopes federated into the fused
|
|
50
|
+
* ranking, plus scopes that matched too weakly to federate (with their best
|
|
51
|
+
* doc id). Drives formatAsk's `matched in:` / `also matched:` footer.
|
|
52
|
+
* Absent on single-scope repos — zero output change there. */
|
|
53
|
+
scopes?: {
|
|
54
|
+
federated: string[];
|
|
55
|
+
alsoMatched: {
|
|
56
|
+
scope: string;
|
|
57
|
+
bestId: string;
|
|
58
|
+
}[];
|
|
59
|
+
};
|
|
36
60
|
}
|
|
61
|
+
/** Idf-weighted share (0..1) of the query a document matches: each query term
|
|
62
|
+
* counts by its rarity, so this separates task prompts from chatter in a way a
|
|
63
|
+
* raw term count can't. A conversational prompt's words are either off-corpus
|
|
64
|
+
* (rare → heavy, unmatched → sinks the ratio) or generic code words ("list",
|
|
65
|
+
* "write": common → near-weightless even when they collide with a symbol name);
|
|
66
|
+
* a task prompt matches exactly its rare, discriminating identifiers. Terms the
|
|
67
|
+
* corpus has never seen take `dfltIdf` (the df=0 weight). */
|
|
68
|
+
/** The match-STRENGTH share behind `coverageStrong`: idf-weighted share of the
|
|
69
|
+
* query matched in the node's NAME field ONLY. The PATH field is deliberately
|
|
70
|
+
* excluded — a coincidental generic directory (`gateway/`) or file basename
|
|
71
|
+
* (`gateway.ts`) in an unrelated repo would otherwise clear the strength gate
|
|
72
|
+
* and float that repo to the top; an on-topic path-organized repo is still
|
|
73
|
+
* rescued by the broad-coverage HIGH_FLOOR clause instead. For the same reason
|
|
74
|
+
* a `kind:"file"` node contributes zero strength: its `name` is a basename (a
|
|
75
|
+
* path component), not a symbol name, so a file whose basename happens to share
|
|
76
|
+
* a query word is not a strong match. */
|
|
77
|
+
export declare function strongShare(q: Map<string, number>, node: NodeV1, doc: {
|
|
78
|
+
name: Map<string, number>;
|
|
79
|
+
}, idf: Map<string, number>, dfltIdf: number): number;
|
|
37
80
|
export interface AskOptions {
|
|
38
81
|
contextDir?: string;
|
|
39
82
|
limit?: number;
|
|
@@ -50,6 +93,12 @@ export interface AskOptions {
|
|
|
50
93
|
* decision point, ~10× cheaper than the full span — and the pack marks each
|
|
51
94
|
* crux so the agent knows `--full` (or the file itself) has the rest. */
|
|
52
95
|
full?: boolean;
|
|
96
|
+
/** Narrow the doc/node set to this path prefix BEFORE scoring (segment-aware,
|
|
97
|
+
* like `scopeOf` — "frontend" never matches "frontend-utils"). Per-scope
|
|
98
|
+
* IDF/BM25/walk come free: the filtered set is usually one scope, so the
|
|
99
|
+
* existing multi-scope machinery degrades to its single-scope passthrough
|
|
100
|
+
* with no scope labels. A prefix matching nothing indexed throws. */
|
|
101
|
+
in?: string;
|
|
53
102
|
}
|
|
54
103
|
/** Answer a query from the graft/ graph at `dir`. Deterministic, $0. */
|
|
55
104
|
export declare function ask(dir: string, query: string, opts?: AskOptions): AskResult;
|
|
@@ -65,6 +114,8 @@ export interface SkeletonResult {
|
|
|
65
114
|
file: string;
|
|
66
115
|
entries: SkeletonEntry[];
|
|
67
116
|
note?: string;
|
|
117
|
+
/** Tokens-saved baseline: this file read whole vs the signatures-only view. */
|
|
118
|
+
saved?: Savings;
|
|
68
119
|
}
|
|
69
120
|
/** Signatures-only view of one file, straight from the wiring graph — the
|
|
70
121
|
* cheapest way to understand a file's API surface (~10× less than reading it).
|
package/dist/ask/ask.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/ask/ask.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/ask/ask.ts"],"names":[],"mappings":"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"}
|