gitnexus 1.6.7-rc.11 → 1.6.7-rc.13
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 +1 -1
- package/dist/cli/eval-server.d.ts +5 -1
- package/dist/cli/eval-server.js +16 -4
- package/dist/mcp/local/local-backend.d.ts +84 -17
- package/dist/mcp/local/local-backend.js +87 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/tools.d.ts +10 -0
- package/dist/mcp/tools.js +29 -3
- package/package.json +1 -1
- package/skills/gitnexus-guide.md +32 -1
- package/vendor/tree-sitter-c/prebuilds/SHA256SUMS +6 -0
- package/vendor/tree-sitter-c/prebuilds/darwin-arm64/tree-sitter-c.node +0 -0
- package/vendor/tree-sitter-c/prebuilds/darwin-x64/tree-sitter-c.node +0 -0
- package/vendor/tree-sitter-c/prebuilds/linux-arm64/tree-sitter-c.node +0 -0
- package/vendor/tree-sitter-c/prebuilds/linux-x64/tree-sitter-c.node +0 -0
- package/vendor/tree-sitter-c/prebuilds/win32-arm64/tree-sitter-c.node +0 -0
- package/vendor/tree-sitter-c/prebuilds/win32-x64/tree-sitter-c.node +0 -0
- package/vendor/tree-sitter-dart/prebuilds/SHA256SUMS +6 -0
- package/vendor/tree-sitter-dart/prebuilds/darwin-arm64/tree-sitter-dart.node +0 -0
- package/vendor/tree-sitter-dart/prebuilds/darwin-x64/tree-sitter-dart.node +0 -0
- package/vendor/tree-sitter-dart/prebuilds/linux-arm64/tree-sitter-dart.node +0 -0
- package/vendor/tree-sitter-dart/prebuilds/linux-x64/tree-sitter-dart.node +0 -0
- package/vendor/tree-sitter-dart/prebuilds/win32-arm64/tree-sitter-dart.node +0 -0
- package/vendor/tree-sitter-dart/prebuilds/win32-x64/tree-sitter-dart.node +0 -0
- package/vendor/tree-sitter-kotlin/prebuilds/SHA256SUMS +6 -0
- package/vendor/tree-sitter-kotlin/prebuilds/darwin-arm64/tree-sitter-kotlin.node +0 -0
- package/vendor/tree-sitter-kotlin/prebuilds/darwin-x64/tree-sitter-kotlin.node +0 -0
- package/vendor/tree-sitter-kotlin/prebuilds/linux-arm64/tree-sitter-kotlin.node +0 -0
- package/vendor/tree-sitter-kotlin/prebuilds/linux-x64/tree-sitter-kotlin.node +0 -0
- package/vendor/tree-sitter-kotlin/prebuilds/win32-arm64/tree-sitter-kotlin.node +0 -0
- package/vendor/tree-sitter-kotlin/prebuilds/win32-x64/tree-sitter-kotlin.node +0 -0
- package/vendor/tree-sitter-proto/prebuilds/SHA256SUMS +6 -0
- package/vendor/tree-sitter-proto/prebuilds/darwin-arm64/tree-sitter-proto.node +0 -0
- package/vendor/tree-sitter-proto/prebuilds/darwin-x64/tree-sitter-proto.node +0 -0
- package/vendor/tree-sitter-proto/prebuilds/linux-arm64/tree-sitter-proto.node +0 -0
- package/vendor/tree-sitter-proto/prebuilds/linux-x64/tree-sitter-proto.node +0 -0
- package/vendor/tree-sitter-proto/prebuilds/win32-arm64/tree-sitter-proto.node +0 -0
- package/vendor/tree-sitter-proto/prebuilds/win32-x64/tree-sitter-proto.node +0 -0
- package/vendor/tree-sitter-swift/prebuilds/SHA256SUMS +6 -0
- package/vendor/tree-sitter-swift/prebuilds/darwin-arm64/tree-sitter-swift.node +0 -0
- package/vendor/tree-sitter-swift/prebuilds/darwin-x64/tree-sitter-swift.node +0 -0
- package/vendor/tree-sitter-swift/prebuilds/linux-arm64/tree-sitter-swift.node +0 -0
- package/vendor/tree-sitter-swift/prebuilds/linux-x64/tree-sitter-swift.node +0 -0
- package/vendor/tree-sitter-swift/prebuilds/win32-arm64/tree-sitter-swift.node +0 -0
- package/vendor/tree-sitter-swift/prebuilds/win32-x64/tree-sitter-swift.node +0 -0
package/README.md
CHANGED
|
@@ -126,7 +126,7 @@ Your AI agent gets these tools automatically:
|
|
|
126
126
|
|
|
127
127
|
| Tool | What It Does | `repo` Param |
|
|
128
128
|
| ---------------- | ---------------------------------------------------------------- | ------------ |
|
|
129
|
-
| `list_repos` | Discover all indexed repositories
|
|
129
|
+
| `list_repos` | Discover all indexed repositories (paginated — `limit`/`offset`) | — |
|
|
130
130
|
| `query` | Process-grouped hybrid search (BM25 + semantic + RRF) | Optional |
|
|
131
131
|
| `context` | 360-degree symbol view — categorized refs, process participation | Optional |
|
|
132
132
|
| `impact` | Blast radius analysis with depth grouping and confidence | Optional |
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
* GET /health — Health check. Returns {"status":"ok","repos":[...]}
|
|
29
29
|
* POST /shutdown — Graceful shutdown.
|
|
30
30
|
*/
|
|
31
|
+
import { type RepoListing, type ListReposPagination } from '../mcp/local/local-backend.js';
|
|
31
32
|
export { formatDetectChangesResult } from './detect-changes-format.js';
|
|
32
33
|
export interface EvalServerOptions {
|
|
33
34
|
port?: string;
|
|
@@ -45,6 +46,9 @@ export declare function formatQueryResult(result: any): string;
|
|
|
45
46
|
export declare function formatContextResult(result: any): string;
|
|
46
47
|
export declare function formatImpactResult(result: any): string;
|
|
47
48
|
export declare function formatCypherResult(result: any): string;
|
|
48
|
-
export declare function formatListReposResult(result:
|
|
49
|
+
export declare function formatListReposResult(result: {
|
|
50
|
+
repositories: RepoListing[];
|
|
51
|
+
pagination?: ListReposPagination;
|
|
52
|
+
}): string;
|
|
49
53
|
export declare function evalServerCommand(options?: EvalServerOptions): Promise<void>;
|
|
50
54
|
export declare const MAX_BODY_SIZE: number;
|
package/dist/cli/eval-server.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
import http from 'http';
|
|
32
32
|
import { isIPv4, isIPv6 } from 'node:net';
|
|
33
33
|
import { writeSync } from 'node:fs';
|
|
34
|
-
import { LocalBackend } from '../mcp/local/local-backend.js';
|
|
34
|
+
import { LocalBackend, } from '../mcp/local/local-backend.js';
|
|
35
35
|
import { logger } from '../core/logger.js';
|
|
36
36
|
import { cliInfo, cliWarn, cliError } from './cli-message.js';
|
|
37
37
|
import { formatDetectChangesResult } from './detect-changes-format.js';
|
|
@@ -228,16 +228,26 @@ export function formatCypherResult(result) {
|
|
|
228
228
|
return typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
229
229
|
}
|
|
230
230
|
export function formatListReposResult(result) {
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
// `list_repos` always returns the paginated { repositories, pagination } object (#2119).
|
|
232
|
+
const repos = result.repositories;
|
|
233
|
+
const pg = result.pagination;
|
|
234
|
+
if (repos.length === 0) {
|
|
235
|
+
return pg && pg.total > 0
|
|
236
|
+
? `No repositories on this page (offset ${pg.offset} of ${pg.total} total).`
|
|
237
|
+
: 'No indexed repositories.';
|
|
233
238
|
}
|
|
234
239
|
const lines = ['Indexed repositories:\n'];
|
|
235
|
-
for (const r of
|
|
240
|
+
for (const r of repos) {
|
|
236
241
|
const stats = r.stats || {};
|
|
237
242
|
lines.push(` ${r.name} — ${stats.nodes || '?'} symbols, ${stats.edges || '?'} relationships, ${stats.processes || '?'} flows`);
|
|
238
243
|
lines.push(` Path: ${r.path}`);
|
|
239
244
|
lines.push(` Indexed: ${r.indexedAt}`);
|
|
240
245
|
}
|
|
246
|
+
if (pg) {
|
|
247
|
+
lines.push('');
|
|
248
|
+
lines.push(` Showing ${repos.length} of ${pg.total} (offset ${pg.offset}).` +
|
|
249
|
+
(pg.hasMore ? ` More available — re-run with offset ${pg.nextOffset}.` : ''));
|
|
250
|
+
}
|
|
241
251
|
return lines.join('\n');
|
|
242
252
|
}
|
|
243
253
|
/**
|
|
@@ -276,6 +286,8 @@ function getNextStepHint(toolName) {
|
|
|
276
286
|
return '\n---\nNext: To explore a result symbol in depth, run gitnexus-context "<name>"';
|
|
277
287
|
case 'detect_changes':
|
|
278
288
|
return '\n---\nNext: Run gitnexus-context "<symbol>" on high-risk changed symbols to check their callers.';
|
|
289
|
+
case 'list_repos':
|
|
290
|
+
return '\n---\nNext: READ gitnexus://repo/{name}/context for a repo above. If pagination.hasMore is true, re-run list_repos with offset set to pagination.nextOffset to page through the rest.';
|
|
279
291
|
default:
|
|
280
292
|
return '';
|
|
281
293
|
}
|
|
@@ -86,6 +86,67 @@ export declare function resolveWorktreeCwd(repoPath: string, launchCwd: string):
|
|
|
86
86
|
* (#2054).
|
|
87
87
|
*/
|
|
88
88
|
export declare const REPO_ID_HASH_LENGTH = 6;
|
|
89
|
+
/**
|
|
90
|
+
* One repository entry as returned by {@link LocalBackend.listRepos} and in each
|
|
91
|
+
* `list_repos` page. Named so the `listRepos`/`listReposPage` return types read
|
|
92
|
+
* clearly instead of an opaque `Awaited<ReturnType<…>>` expression.
|
|
93
|
+
*/
|
|
94
|
+
export interface RepoListing {
|
|
95
|
+
name: string;
|
|
96
|
+
path: string;
|
|
97
|
+
indexedAt: string;
|
|
98
|
+
lastCommit: string;
|
|
99
|
+
remoteUrl?: string;
|
|
100
|
+
stats?: any;
|
|
101
|
+
staleness?: {
|
|
102
|
+
commitsBehind: number;
|
|
103
|
+
hint?: string;
|
|
104
|
+
};
|
|
105
|
+
siblings?: Array<{
|
|
106
|
+
name: string;
|
|
107
|
+
path: string;
|
|
108
|
+
lastCommit: string;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
111
|
+
/** Continuation metadata for the paginated `list_repos` MCP tool (#2119). */
|
|
112
|
+
export interface ListReposPagination {
|
|
113
|
+
/** Total repositories across all pages. */
|
|
114
|
+
total: number;
|
|
115
|
+
/** Effective page size used (equals the requested limit; out-of-range is rejected, not clamped). */
|
|
116
|
+
limit: number;
|
|
117
|
+
/** Offset this page started at. */
|
|
118
|
+
offset: number;
|
|
119
|
+
/** Number of repositories actually returned in this page. */
|
|
120
|
+
returned: number;
|
|
121
|
+
/** True when more repositories remain past this page. */
|
|
122
|
+
hasMore: boolean;
|
|
123
|
+
/** Offset to request next; present only when `hasMore` is true. */
|
|
124
|
+
nextOffset?: number;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Validate and normalise `list_repos` pagination arguments.
|
|
128
|
+
*
|
|
129
|
+
* @internal Exported for unit testing; not part of the public API surface.
|
|
130
|
+
*
|
|
131
|
+
* There is NO MCP-SDK-level enforcement of a tool's advertised `inputSchema`
|
|
132
|
+
* (the SDK validates only the JSON-RPC envelope), and `callTool` is reachable
|
|
133
|
+
* directly, so the backend is the real validation boundary. Malformed values —
|
|
134
|
+
* non-number, `NaN`, non-integer, `limit < 1`, `limit > maxLimit`, or
|
|
135
|
+
* `offset < 0` — are REJECTED with a clear error. `limit` is bounded but NOT
|
|
136
|
+
* silently clamped: an over-max value throws (symmetric with the other bounds)
|
|
137
|
+
* so a client never receives a smaller page than it asked for without knowing.
|
|
138
|
+
* An omitted value (only `undefined`) falls back to the default.
|
|
139
|
+
*/
|
|
140
|
+
export declare function parseListReposPagination(params: {
|
|
141
|
+
limit?: unknown;
|
|
142
|
+
offset?: unknown;
|
|
143
|
+
} | null | undefined, opts: {
|
|
144
|
+
defaultLimit: number;
|
|
145
|
+
maxLimit: number;
|
|
146
|
+
}): {
|
|
147
|
+
limit: number;
|
|
148
|
+
offset: number;
|
|
149
|
+
};
|
|
89
150
|
export declare class LocalBackend {
|
|
90
151
|
private repos;
|
|
91
152
|
private contextCache;
|
|
@@ -198,23 +259,29 @@ export declare class LocalBackend {
|
|
|
198
259
|
* that another clone of the same logical repo is registered).
|
|
199
260
|
* - `remoteUrl`: the canonical origin URL recorded at index time.
|
|
200
261
|
*/
|
|
201
|
-
listRepos(): Promise<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
262
|
+
listRepos(): Promise<RepoListing[]>;
|
|
263
|
+
/**
|
|
264
|
+
* Paginated view over {@link listRepos} for the `list_repos` MCP tool (#2119).
|
|
265
|
+
*
|
|
266
|
+
* `listRepos()` itself still returns the FULL array — its resource and CLI
|
|
267
|
+
* consumers (`gitnexus://repos`, `gitnexus://setup`, startup logs) need every
|
|
268
|
+
* entry, so pagination lives ONLY here, on the tool surface, to keep the
|
|
269
|
+
* response under MCP/LLM token-truncation limits.
|
|
270
|
+
*
|
|
271
|
+
* Determinism: a single registry snapshot is taken per call, then sorted by
|
|
272
|
+
* lower-cased name with the repository path as a tie-breaker. Sibling clones
|
|
273
|
+
* share a name but never a path (#2054), so `(name, path)` is a total order —
|
|
274
|
+
* paging never skips or duplicates an entry while the registry is unchanged.
|
|
275
|
+
* Codepoint comparison (not `localeCompare`) keeps page boundaries stable
|
|
276
|
+
* across machines/locales, matching the existing `refreshRepos` ordering.
|
|
277
|
+
*/
|
|
278
|
+
listReposPage(params?: {
|
|
279
|
+
limit?: unknown;
|
|
280
|
+
offset?: unknown;
|
|
281
|
+
} | null): Promise<{
|
|
282
|
+
repositories: RepoListing[];
|
|
283
|
+
pagination: ListReposPagination;
|
|
284
|
+
}>;
|
|
218
285
|
/**
|
|
219
286
|
* Best-effort sibling-clone drift warning.
|
|
220
287
|
*
|
|
@@ -27,6 +27,7 @@ import { getExactScanLimit, isVectorExtensionSupportedByPlatform, } from '../../
|
|
|
27
27
|
import { PhaseTimer } from '../../core/search/phase-timer.js';
|
|
28
28
|
import { checkStalenessAsync, checkCwdMatch } from '../../core/git-staleness.js';
|
|
29
29
|
import { logger } from '../../core/logger.js';
|
|
30
|
+
import { LIST_REPOS_DEFAULT_LIMIT, LIST_REPOS_MAX_LIMIT } from '../tools.js';
|
|
30
31
|
// AI context generation is CLI-only (gitnexus analyze)
|
|
31
32
|
// import { generateAIContextFiles } from '../../cli/ai-context.js';
|
|
32
33
|
/**
|
|
@@ -272,6 +273,42 @@ export function resolveWorktreeCwd(repoPath, launchCwd) {
|
|
|
272
273
|
* (#2054).
|
|
273
274
|
*/
|
|
274
275
|
export const REPO_ID_HASH_LENGTH = 6;
|
|
276
|
+
/**
|
|
277
|
+
* Validate and normalise `list_repos` pagination arguments.
|
|
278
|
+
*
|
|
279
|
+
* @internal Exported for unit testing; not part of the public API surface.
|
|
280
|
+
*
|
|
281
|
+
* There is NO MCP-SDK-level enforcement of a tool's advertised `inputSchema`
|
|
282
|
+
* (the SDK validates only the JSON-RPC envelope), and `callTool` is reachable
|
|
283
|
+
* directly, so the backend is the real validation boundary. Malformed values —
|
|
284
|
+
* non-number, `NaN`, non-integer, `limit < 1`, `limit > maxLimit`, or
|
|
285
|
+
* `offset < 0` — are REJECTED with a clear error. `limit` is bounded but NOT
|
|
286
|
+
* silently clamped: an over-max value throws (symmetric with the other bounds)
|
|
287
|
+
* so a client never receives a smaller page than it asked for without knowing.
|
|
288
|
+
* An omitted value (only `undefined`) falls back to the default.
|
|
289
|
+
*/
|
|
290
|
+
export function parseListReposPagination(params, opts) {
|
|
291
|
+
const requireInt = (value, field, min, max) => {
|
|
292
|
+
const valid = typeof value === 'number' &&
|
|
293
|
+
Number.isInteger(value) &&
|
|
294
|
+
value >= min &&
|
|
295
|
+
(max === undefined || value <= max);
|
|
296
|
+
if (!valid) {
|
|
297
|
+
const bound = max === undefined ? `>= ${min}` : `between ${min} and ${max}`;
|
|
298
|
+
throw new Error(`list_repos: "${field}" must be an integer ${bound} (received ${JSON.stringify(value)})`);
|
|
299
|
+
}
|
|
300
|
+
return value;
|
|
301
|
+
};
|
|
302
|
+
let limit = opts.defaultLimit;
|
|
303
|
+
if (params?.limit !== undefined) {
|
|
304
|
+
limit = requireInt(params.limit, 'limit', 1, opts.maxLimit);
|
|
305
|
+
}
|
|
306
|
+
let offset = 0;
|
|
307
|
+
if (params?.offset !== undefined) {
|
|
308
|
+
offset = requireInt(params.offset, 'offset', 0);
|
|
309
|
+
}
|
|
310
|
+
return { limit, offset };
|
|
311
|
+
}
|
|
275
312
|
export class LocalBackend {
|
|
276
313
|
repos = new Map();
|
|
277
314
|
contextCache = new Map();
|
|
@@ -758,6 +795,52 @@ export class LocalBackend {
|
|
|
758
795
|
};
|
|
759
796
|
});
|
|
760
797
|
}
|
|
798
|
+
/**
|
|
799
|
+
* Paginated view over {@link listRepos} for the `list_repos` MCP tool (#2119).
|
|
800
|
+
*
|
|
801
|
+
* `listRepos()` itself still returns the FULL array — its resource and CLI
|
|
802
|
+
* consumers (`gitnexus://repos`, `gitnexus://setup`, startup logs) need every
|
|
803
|
+
* entry, so pagination lives ONLY here, on the tool surface, to keep the
|
|
804
|
+
* response under MCP/LLM token-truncation limits.
|
|
805
|
+
*
|
|
806
|
+
* Determinism: a single registry snapshot is taken per call, then sorted by
|
|
807
|
+
* lower-cased name with the repository path as a tie-breaker. Sibling clones
|
|
808
|
+
* share a name but never a path (#2054), so `(name, path)` is a total order —
|
|
809
|
+
* paging never skips or duplicates an entry while the registry is unchanged.
|
|
810
|
+
* Codepoint comparison (not `localeCompare`) keeps page boundaries stable
|
|
811
|
+
* across machines/locales, matching the existing `refreshRepos` ordering.
|
|
812
|
+
*/
|
|
813
|
+
async listReposPage(params) {
|
|
814
|
+
const { limit, offset } = parseListReposPagination(params, {
|
|
815
|
+
defaultLimit: LIST_REPOS_DEFAULT_LIMIT,
|
|
816
|
+
maxLimit: LIST_REPOS_MAX_LIMIT,
|
|
817
|
+
});
|
|
818
|
+
// One consistent snapshot per call (listRepos refreshes the registry once),
|
|
819
|
+
// sorted into a stable total order before slicing.
|
|
820
|
+
const all = await this.listRepos();
|
|
821
|
+
all.sort((a, b) => {
|
|
822
|
+
const an = a.name.toLowerCase();
|
|
823
|
+
const bn = b.name.toLowerCase();
|
|
824
|
+
if (an !== bn)
|
|
825
|
+
return an < bn ? -1 : 1;
|
|
826
|
+
return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
|
|
827
|
+
});
|
|
828
|
+
const total = all.length;
|
|
829
|
+
const repositories = all.slice(offset, offset + limit);
|
|
830
|
+
const returned = repositories.length;
|
|
831
|
+
const hasMore = offset + returned < total;
|
|
832
|
+
return {
|
|
833
|
+
repositories,
|
|
834
|
+
pagination: {
|
|
835
|
+
total,
|
|
836
|
+
limit,
|
|
837
|
+
offset,
|
|
838
|
+
returned,
|
|
839
|
+
hasMore,
|
|
840
|
+
...(hasMore && { nextOffset: offset + returned }),
|
|
841
|
+
},
|
|
842
|
+
};
|
|
843
|
+
}
|
|
761
844
|
/**
|
|
762
845
|
* Best-effort sibling-clone drift warning.
|
|
763
846
|
*
|
|
@@ -816,7 +899,10 @@ export class LocalBackend {
|
|
|
816
899
|
// ─── Tool Dispatch ───────────────────────────────────────────────
|
|
817
900
|
async callTool(method, params) {
|
|
818
901
|
if (method === 'list_repos') {
|
|
819
|
-
|
|
902
|
+
// Paginated tool surface (#2119). `listRepos()` is unchanged for internal
|
|
903
|
+
// callers; the tool wraps it in { repositories, pagination } and forwards
|
|
904
|
+
// the limit/offset args that this dispatch previously discarded.
|
|
905
|
+
return this.listReposPage(params);
|
|
820
906
|
}
|
|
821
907
|
if (method.startsWith('group_')) {
|
|
822
908
|
return this.handleGroupTool(method, params || {});
|
package/dist/mcp/server.js
CHANGED
|
@@ -32,7 +32,7 @@ function getNextStepHint(toolName, args) {
|
|
|
32
32
|
const repoPath = repo || '{name}';
|
|
33
33
|
switch (toolName) {
|
|
34
34
|
case 'list_repos':
|
|
35
|
-
return `\n\n---\n**Next:** READ gitnexus://repo/{name}/context for any repo above to get its overview and check staleness.`;
|
|
35
|
+
return `\n\n---\n**Next:** READ gitnexus://repo/{name}/context for any repo above to get its overview and check staleness. If pagination.hasMore is true, call list_repos again with offset set to pagination.nextOffset to fetch the rest.`;
|
|
36
36
|
case 'query':
|
|
37
37
|
return `\n\n---\n**Next:** To understand a specific symbol in depth, use context({name: "<symbol_name>"${repoParam}}) to see categorized refs and process participation.`;
|
|
38
38
|
case 'context':
|
package/dist/mcp/tools.d.ts
CHANGED
|
@@ -26,4 +26,14 @@ export interface ToolDefinition {
|
|
|
26
26
|
required: string[];
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Pagination bounds for the `list_repos` tool. Exported so the backend
|
|
31
|
+
* validation (`local-backend.ts`) and the schema below stay a single source of
|
|
32
|
+
* truth. `list_repos` is paginated to keep its response under MCP/LLM token
|
|
33
|
+
* truncation limits when many repos are indexed (#2119); the default page is
|
|
34
|
+
* small enough to render safely, and `LIST_REPOS_MAX_LIMIT` caps how much a
|
|
35
|
+
* caller can pull in one request.
|
|
36
|
+
*/
|
|
37
|
+
export declare const LIST_REPOS_DEFAULT_LIMIT = 50;
|
|
38
|
+
export declare const LIST_REPOS_MAX_LIMIT = 200;
|
|
29
39
|
export declare const GITNEXUS_TOOLS: ToolDefinition[];
|
package/dist/mcp/tools.js
CHANGED
|
@@ -22,12 +22,24 @@ const DESTRUCTIVE_TOOL_ANNOTATIONS = {
|
|
|
22
22
|
idempotentHint: false,
|
|
23
23
|
openWorldHint: false,
|
|
24
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Pagination bounds for the `list_repos` tool. Exported so the backend
|
|
27
|
+
* validation (`local-backend.ts`) and the schema below stay a single source of
|
|
28
|
+
* truth. `list_repos` is paginated to keep its response under MCP/LLM token
|
|
29
|
+
* truncation limits when many repos are indexed (#2119); the default page is
|
|
30
|
+
* small enough to render safely, and `LIST_REPOS_MAX_LIMIT` caps how much a
|
|
31
|
+
* caller can pull in one request.
|
|
32
|
+
*/
|
|
33
|
+
export const LIST_REPOS_DEFAULT_LIMIT = 50;
|
|
34
|
+
export const LIST_REPOS_MAX_LIMIT = 200;
|
|
25
35
|
export const GITNEXUS_TOOLS = [
|
|
26
36
|
{
|
|
27
37
|
name: 'list_repos',
|
|
28
|
-
description: `List
|
|
38
|
+
description: `List indexed repositories available to GitNexus (paginated).
|
|
29
39
|
|
|
30
|
-
Returns each
|
|
40
|
+
Returns a page of repositories — each with name, path, indexed date, last commit, and stats — plus a "pagination" object: { total, limit, offset, returned, hasMore, nextOffset }.
|
|
41
|
+
|
|
42
|
+
PAGINATION: Results are paginated so a large registry is not truncated by MCP/LLM token limits. "limit" sets the page size (default ${LIST_REPOS_DEFAULT_LIMIT}, max ${LIST_REPOS_MAX_LIMIT}; values above the max are rejected, not capped). "offset" selects the start. To enumerate EVERY repository: when pagination.hasMore is true, call list_repos again with offset set to pagination.nextOffset, and repeat until hasMore is false. Repositories are returned in a stable order, so paging never skips or duplicates an entry while the registry is unchanged.
|
|
31
43
|
|
|
32
44
|
WHEN TO USE: First step when multiple repos are indexed, or to discover available repos.
|
|
33
45
|
AFTER THIS: READ gitnexus://repo/{name}/context for the repo you want to work with.
|
|
@@ -37,7 +49,21 @@ on other tools (query, context, impact, etc.) to target the correct one.`,
|
|
|
37
49
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
38
50
|
inputSchema: {
|
|
39
51
|
type: 'object',
|
|
40
|
-
properties: {
|
|
52
|
+
properties: {
|
|
53
|
+
limit: {
|
|
54
|
+
type: 'integer',
|
|
55
|
+
description: `Max repositories to return in this page (default: ${LIST_REPOS_DEFAULT_LIMIT}, min: 1, max: ${LIST_REPOS_MAX_LIMIT}). Values outside [1, ${LIST_REPOS_MAX_LIMIT}] are rejected.`,
|
|
56
|
+
default: LIST_REPOS_DEFAULT_LIMIT,
|
|
57
|
+
minimum: 1,
|
|
58
|
+
maximum: LIST_REPOS_MAX_LIMIT,
|
|
59
|
+
},
|
|
60
|
+
offset: {
|
|
61
|
+
type: 'integer',
|
|
62
|
+
description: 'Number of repositories to skip before this page (default: 0). Pass pagination.nextOffset from the previous response to fetch the next page.',
|
|
63
|
+
default: 0,
|
|
64
|
+
minimum: 0,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
41
67
|
required: [],
|
|
42
68
|
},
|
|
43
69
|
},
|
package/package.json
CHANGED
package/skills/gitnexus-guide.md
CHANGED
|
@@ -38,7 +38,38 @@ For any task involving code understanding, debugging, impact analysis, or refact
|
|
|
38
38
|
| `detect_changes` | Git-diff impact — what do your current changes affect |
|
|
39
39
|
| `rename` | Multi-file coordinated rename with confidence-tagged edits |
|
|
40
40
|
| `cypher` | Raw graph queries (read `gitnexus://repo/{name}/schema` first) |
|
|
41
|
-
| `list_repos` | Discover indexed repos
|
|
41
|
+
| `list_repos` | Discover indexed repos (paginated — `limit`/`offset`) |
|
|
42
|
+
|
|
43
|
+
### Paginating `list_repos`
|
|
44
|
+
|
|
45
|
+
`list_repos` is paginated so a large registry is not truncated by MCP/LLM token limits. It takes optional `limit` (default **50**, max **200**) and `offset`, and returns:
|
|
46
|
+
|
|
47
|
+
```jsonc
|
|
48
|
+
{
|
|
49
|
+
"repositories": [
|
|
50
|
+
{ "name": "...", "path": "...", "indexedAt": "...", "lastCommit": "...", "stats": { } }
|
|
51
|
+
],
|
|
52
|
+
"pagination": {
|
|
53
|
+
"total": 437,
|
|
54
|
+
"limit": 50,
|
|
55
|
+
"offset": 0,
|
|
56
|
+
"returned": 50,
|
|
57
|
+
"hasMore": true,
|
|
58
|
+
"nextOffset": 50
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To enumerate **every** repository, keep calling with `offset` set to `pagination.nextOffset` until `hasMore` is `false`:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
list_repos {} → repos 1–50, nextOffset 50, hasMore true
|
|
67
|
+
list_repos { offset: 50 } → repos 51–100, nextOffset 100, hasMore true
|
|
68
|
+
…
|
|
69
|
+
list_repos { offset: 400 } → repos 401–437, hasMore false (done)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Notes: `offset` ≥ `total` returns an empty page (with `total` still reported). Out-of-range or malformed `limit`/`offset` (non-integer, `limit` outside `[1, 200]`, `offset < 0`) are rejected with a clear error — `limit` above the max is rejected, not silently capped. The order is deterministic (lower-cased name, then path), so paging never skips or duplicates an entry while the registry is unchanged.
|
|
42
73
|
|
|
43
74
|
## Resources Reference
|
|
44
75
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
0ef1ad3da01eacfbad1c83a4e6f39e5dfb563cb3ba663447ef563677e43f5802 ./darwin-arm64/tree-sitter-c.node
|
|
2
|
+
5bea052ac3530f56c6c4849d7ad435469eb684a05fb641c4b1df5a0047a224b3 ./darwin-x64/tree-sitter-c.node
|
|
3
|
+
c0b20e0ddbbf7f15441bc09855892e0720623113dd24cbbb81f3f6fec800650e ./linux-arm64/tree-sitter-c.node
|
|
4
|
+
85e912b183a49111b0f4c3a6c8908375732e70aca759ab0124501913cbbd942a ./linux-x64/tree-sitter-c.node
|
|
5
|
+
d15bd0478e24f6cedab5aea5b34a423b6918babb45fd81b6d05be740ac83f71e ./win32-arm64/tree-sitter-c.node
|
|
6
|
+
ce42c8f63ea0fbb21b36486c6aef8bd2208abb45cb478d1071bb44fda8d6558a ./win32-x64/tree-sitter-c.node
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
423e36a7cc1e3186d5b5d34435916c9746883d3745de33be21ec0c9db19a0d0c ./darwin-arm64/tree-sitter-dart.node
|
|
2
|
+
da526be2e8c6caf0d6b5421c33a59ff0ffcba3609172bd0399bfe98abd1550f2 ./darwin-x64/tree-sitter-dart.node
|
|
3
|
+
18ee4afbaaa883416ee671c551ba3c69b0dc7ff0bccc42463c9d8e32eea2e704 ./linux-arm64/tree-sitter-dart.node
|
|
4
|
+
209d3949337ebc59b0f31b19333345e1a45c800f81808cf9f811a3b469166549 ./linux-x64/tree-sitter-dart.node
|
|
5
|
+
535954d7ffe0b436551c9837be5cf5cf5d7b9cdb6a0d68dd9def2d154164cb51 ./win32-arm64/tree-sitter-dart.node
|
|
6
|
+
0c3790d0d9e440c11ea90d9a48b308cef4fe0e1e1865243131e4c3e7dfe7e2ff ./win32-x64/tree-sitter-dart.node
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
11e63706f960303259b842f98030bf7c5845f312ed9cfa1fcc44e6ff4c002841 ./darwin-arm64/tree-sitter-kotlin.node
|
|
2
|
+
e5cd10bf993a2d20f8187d39486e3cbcb0567ca192576fae745c70e8be43f223 ./darwin-x64/tree-sitter-kotlin.node
|
|
3
|
+
a73110ce49a421b4d09acfbbdbb05bc1d1a54b6c88017d2e59199144bb9c1853 ./linux-arm64/tree-sitter-kotlin.node
|
|
4
|
+
7409baf83f363d15bdcbc09698acc9ca8e7e25ccb62eb6074e787166ff0bf9ef ./linux-x64/tree-sitter-kotlin.node
|
|
5
|
+
1467a068fd28de07cd333e3e577ee2ccc34631780b7bd34b151c4c8118dddaf6 ./win32-arm64/tree-sitter-kotlin.node
|
|
6
|
+
c53bcf3c651e33d2778c83e9ef7cb7f18e547e1941132f6ade69d0717b9325eb ./win32-x64/tree-sitter-kotlin.node
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
dd9744a196fa560f1ec1c30110e3d023722c606dcb7cd4f4e07a2da68dc481e9 ./darwin-arm64/tree-sitter-proto.node
|
|
2
|
+
82bf2b335e7f8197be98a126a0c982a71ffb4c25c6780cc41463d57986a4727e ./darwin-x64/tree-sitter-proto.node
|
|
3
|
+
ba65d25de1fd881def2cf85f473094d90a45612bfa763f4f97d2841b3d7d715e ./linux-arm64/tree-sitter-proto.node
|
|
4
|
+
dea80ed2fb48a6d19866468f652ec48eab5435306c6477b213eafe51cbbbf2ee ./linux-x64/tree-sitter-proto.node
|
|
5
|
+
f057563de539abd6ada73aa9097e5bd1849bd6c31d721e34c791bf0388bfa237 ./win32-arm64/tree-sitter-proto.node
|
|
6
|
+
4269e6e073f22ed777400b6f4b553f51974c5d641c56374046bf5c0692f4c841 ./win32-x64/tree-sitter-proto.node
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
baffb118bb04eb3f2a3aea6e132a67f334323eec39fceb3420a04d4b31ac7544 ./darwin-arm64/tree-sitter-swift.node
|
|
2
|
+
b18b2b16c9ec26d4c43ad578fca3fdf1349dafbc5347fd897ff0b9e6c92927c0 ./darwin-x64/tree-sitter-swift.node
|
|
3
|
+
fed213320ee40a725f0b0728975ab9a472348f25b70ec1a0e9ff89e366849af5 ./linux-arm64/tree-sitter-swift.node
|
|
4
|
+
9376099fff5847941bac216afa7142d7b3e98d8c2e5bc8c8c2de486693eeeaf6 ./linux-x64/tree-sitter-swift.node
|
|
5
|
+
49300328ead166d005f5cf0065f21f6bfcacda570f2e026ce6886bad24f2004f ./win32-arm64/tree-sitter-swift.node
|
|
6
|
+
16c146f30c74953832be37b7a65230d62ea1347a1be6e8ffa7e9bd120cf7f30f ./win32-x64/tree-sitter-swift.node
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|