dsh-gitnexus-plus 0.1.1 → 0.1.3

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 (64) hide show
  1. package/README-CN.md +174 -0
  2. package/README.md +184 -447
  3. package/lib/bin/search-helper.d.ts +22 -0
  4. package/lib/bin/search-helper.d.ts.map +1 -0
  5. package/lib/bin/search-helper.js +57 -0
  6. package/lib/bin/search-helper.js.map +1 -0
  7. package/lib/client.js +978 -122
  8. package/lib/gitnexus/analyze.d.ts +27 -2
  9. package/lib/gitnexus/analyze.d.ts.map +1 -1
  10. package/lib/gitnexus/analyze.js +71 -6
  11. package/lib/gitnexus/analyze.js.map +1 -1
  12. package/lib/gitnexus/commands.d.ts +41 -8
  13. package/lib/gitnexus/commands.d.ts.map +1 -1
  14. package/lib/gitnexus/commands.js +62 -9
  15. package/lib/gitnexus/commands.js.map +1 -1
  16. package/lib/gitnexus/coverage.d.ts +16 -0
  17. package/lib/gitnexus/coverage.d.ts.map +1 -1
  18. package/lib/gitnexus/coverage.js +61 -2
  19. package/lib/gitnexus/coverage.js.map +1 -1
  20. package/lib/gitnexus/git-activity.d.ts +85 -0
  21. package/lib/gitnexus/git-activity.d.ts.map +1 -1
  22. package/lib/gitnexus/git-activity.js +286 -1
  23. package/lib/gitnexus/git-activity.js.map +1 -1
  24. package/lib/gitnexus/index-meta.d.ts +15 -5
  25. package/lib/gitnexus/index-meta.d.ts.map +1 -1
  26. package/lib/gitnexus/index-meta.js +25 -5
  27. package/lib/gitnexus/index-meta.js.map +1 -1
  28. package/lib/gitnexus/languages.d.ts +7 -0
  29. package/lib/gitnexus/languages.d.ts.map +1 -1
  30. package/lib/gitnexus/languages.js +82 -2
  31. package/lib/gitnexus/languages.js.map +1 -1
  32. package/lib/gitnexus/root.d.ts +6 -0
  33. package/lib/gitnexus/root.d.ts.map +1 -1
  34. package/lib/gitnexus/root.js +6 -0
  35. package/lib/gitnexus/root.js.map +1 -1
  36. package/lib/gitnexus/scan.d.ts +3 -0
  37. package/lib/gitnexus/scan.d.ts.map +1 -1
  38. package/lib/gitnexus/scan.js +6 -3
  39. package/lib/gitnexus/scan.js.map +1 -1
  40. package/lib/gitnexus/search.d.ts +167 -0
  41. package/lib/gitnexus/search.d.ts.map +1 -0
  42. package/lib/gitnexus/search.js +517 -0
  43. package/lib/gitnexus/search.js.map +1 -0
  44. package/lib/index.d.ts +32 -13
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +68 -21
  47. package/lib/index.js.map +1 -1
  48. package/lib/routes/analyze.d.ts +8 -2
  49. package/lib/routes/analyze.d.ts.map +1 -1
  50. package/lib/routes/analyze.js +5 -1
  51. package/lib/routes/analyze.js.map +1 -1
  52. package/lib/routes/coverage.d.ts +15 -6
  53. package/lib/routes/coverage.d.ts.map +1 -1
  54. package/lib/routes/coverage.js +77 -12
  55. package/lib/routes/coverage.js.map +1 -1
  56. package/lib/routes/file-history.d.ts +21 -0
  57. package/lib/routes/file-history.d.ts.map +1 -0
  58. package/lib/routes/file-history.js +69 -0
  59. package/lib/routes/file-history.js.map +1 -0
  60. package/lib/routes/search.d.ts +27 -0
  61. package/lib/routes/search.d.ts.map +1 -0
  62. package/lib/routes/search.js +77 -0
  63. package/lib/routes/search.js.map +1 -0
  64. package/package.json +3 -2
package/lib/index.js CHANGED
@@ -1,30 +1,36 @@
1
1
  /**
2
- * dsh-gitnexus-plus 鈥?host half.
2
+ * dsh-gitnexus-plus —host half.
3
3
  *
4
4
  * Registers one read-only tool and one loopback HTTP route over the coverage
5
- * engine in `./gitnexus/`. Both answer the same question 鈥?"what did this index
6
- * leave out?" 鈥?for the two callers that need it: the model, and a browser half
5
+ * engine in `./gitnexus/`. Both answer the same question —"what did this index
6
+ * leave out?" —for the two callers that need it: the model, and a browser half
7
7
  * that will render it.
8
8
  *
9
- * Deliberately read-only. Nothing here triggers `analyze`, writes to `.gitnexus/`,
10
- * or takes the index lock; driving updates is a separate concern with its own
11
- * safety story, and mixing the two would mean a status check could start a
12
- * 30-second rebuild.
9
+ * The read path is still never allowed to change anything: a status check must not
10
+ * start a 30-second rebuild. The two mutating capabilities are separate routes with
11
+ * their own guards, and both go through the host's shell executor rather than
12
+ * spawning from the read path. Keyword search is a third read-only route over the
13
+ * graph itself; the tool above stays read-only.
13
14
  */
15
+ import { fileURLToPath } from 'node:url';
14
16
  import Schema from '@deepseek-ai/schemastery';
15
17
  import { defineTool } from '@deepseek-ai/dsh-tools';
16
18
  import { analyzeCoverage } from './gitnexus/coverage.js';
17
19
  import { formatReport } from './gitnexus/format.js';
18
- import { maintenanceCommands, commandRationale } from './gitnexus/commands.js';
20
+ import { commandRationale, defaultGitnexusHome, effectiveSkipFts, maintenanceCommands, } from './gitnexus/commands.js';
19
21
  import { mountCoverageRoute } from './routes/coverage.js';
20
22
  import { mountAnalyzeRoute } from './routes/analyze.js';
21
23
  import { mountInstallRoute } from './routes/install.js';
24
+ import { mountSearchRoute } from './routes/search.js';
25
+ import { mountFileHistoryRoute } from './routes/file-history.js';
26
+ import { readFileActivity } from './gitnexus/git-activity.js';
27
+ import { searchWithFallback } from './gitnexus/search.js';
22
28
  import { createAnalyzeRunner } from './gitnexus/analyze.js';
23
- import { createInstallRunner } from './gitnexus/install.js';
29
+ import { createInstallRunner, defaultInstallPrefix } from './gitnexus/install.js';
24
30
  /**
25
31
  * Whether a service resolved from the context has the shape the runner needs.
26
32
  *
27
- * `ctx.get` is untyped here 鈥?the DSH packages ship no declarations, so the service
33
+ * `ctx.get` is untyped here —the DSH packages ship no declarations, so the service
28
34
  * arrives as `unknown`. Checking the two methods the runner actually calls is the
29
35
  * narrowest claim that can be made: asserting the full `ctx.shell` contract from this
30
36
  * side would be a guess, and a wrong guess fails at the first click rather than here.
@@ -38,7 +44,7 @@ function isShellLike(value) {
38
44
  export const name = 'gitnexus-plus';
39
45
  /**
40
46
  * Only `tools` is required. `webServer` is reached through `ctx.inject` because a
41
- * headless profile has no HTTP carrier at all 鈥?naming it here would leave the
47
+ * headless profile has no HTTP carrier at all —naming it here would leave the
42
48
  * plugin permanently pending there, and the tool would never register.
43
49
  */
44
50
  export const inject = ['tools'];
@@ -46,7 +52,7 @@ export const Config = Schema.object({
46
52
  scanDefaultCapKb: Schema.natural().default(512),
47
53
  minifiedSampleLimit: Schema.natural().default(40),
48
54
  serveRoutes: Schema.boolean().default(true),
49
- skipFts: Schema.boolean().default(true),
55
+ skipFts: Schema.boolean().default(false),
50
56
  memoryOff: Schema.boolean().default(true),
51
57
  analyzeHeapMb: Schema.natural().default(8192),
52
58
  analyzeTimeoutMs: Schema.natural().default(600000),
@@ -59,6 +65,21 @@ void configShapeMatches;
59
65
  export function apply(ctx, config) {
60
66
  const cache = new Map();
61
67
  const CACHE_TTL_MS = 15_000;
68
+ /**
69
+ * The one install location, resolved once and shared by every path that needs to
70
+ * know it. This was the broken link in "install, then initialize": the installer
71
+ * wrote a plugin-owned tree under DSH_HOME, while the coverage engine and the
72
+ * analyze runner probed only PATH and the declared dependency. On a machine with
73
+ * no global GitNexus the install succeeded and then *nothing used it* — the panel
74
+ * still reported "absent" and the refresh still said "no CLI". Passing the same
75
+ * prefix to all three (reader, language detector, runner) is what makes the
76
+ * install a prerequisite rather than an isolated side effect.
77
+ */
78
+ const installPrefix = config.gitnexusInstallDir === '' ? defaultInstallPrefix() : config.gitnexusInstallDir;
79
+ const managedToolchain = { managedPrefix: installPrefix };
80
+ // Resolved at boot so a search never depends on the host's working directory. The
81
+ // file is run by the system Node (see `searchViaHelper`); this process only names it.
82
+ const searchHelperPath = fileURLToPath(new URL('./bin/search-helper.js', import.meta.url));
62
83
  /**
63
84
  * Resolve a coverage report, from cache when it is recent enough.
64
85
  *
@@ -68,7 +89,7 @@ export function apply(ctx, config) {
68
89
  *
69
90
  * `fresh` bypasses the TTL. A manual refresh is an explicit instruction from a
70
91
  * person who believes the numbers may have moved, and answering it with a cached
71
- * copy makes the control look broken 鈥?which is exactly how it was reported. A
92
+ * copy makes the control look broken —which is exactly how it was reported. A
72
93
  * background poll is the case the TTL exists for; a click is not.
73
94
  */
74
95
  const coverageFor = async (repoPath, options = {}) => {
@@ -80,6 +101,8 @@ export function apply(ctx, config) {
80
101
  }
81
102
  const report = await analyzeCoverage(key, {
82
103
  minifiedSampleLimit: config.minifiedSampleLimit,
104
+ toolchain: managedToolchain,
105
+ onProgress: options.onProgress,
83
106
  });
84
107
  cache.set(key, { at: Date.now(), report });
85
108
  return report;
@@ -91,13 +114,18 @@ export function apply(ctx, config) {
91
114
  */
92
115
  const maintenanceFor = (repoPath) => {
93
116
  const options = {
94
- skipFts: config.skipFts,
117
+ // `skipFts: false` means automatic, not "attempt FTS": if the index has no FTS,
118
+ // attempting the install dies with `spawn EPERM` in a confined host.
119
+ skipFts: effectiveSkipFts(repoPath, config.skipFts),
95
120
  memoryOff: config.memoryOff,
96
- gitnexusHome: config.gitnexusHome === '' ? null : config.gitnexusHome,
121
+ // Default to a plugin-owned home inside the project so the global registry
122
+ // write stays within the workspace. The explicit config still wins.
123
+ gitnexusHome: config.gitnexusHome === '' ? defaultGitnexusHome(repoPath) : config.gitnexusHome,
97
124
  };
98
125
  return {
99
126
  commands: maintenanceCommands(repoPath, options),
100
127
  rationale: commandRationale(options),
128
+ supportsForce: true,
101
129
  };
102
130
  };
103
131
  ctx.tools.register(defineTool({
@@ -124,7 +152,7 @@ export function apply(ctx, config) {
124
152
  additionalProperties: true,
125
153
  properties: {
126
154
  // `required: true` per property, never `required: [...]`. The DSL's
127
- // compiler rejects the array form outright 鈥?it collects these marks
155
+ // compiler rejects the array form outright —it collects these marks
128
156
  // into the JSON Schema `required` list itself.
129
157
  text: { type: 'string', required: true },
130
158
  indexed: { type: 'boolean', required: true },
@@ -157,12 +185,20 @@ export function apply(ctx, config) {
157
185
  // Read through `ctx.get` rather than injecting, because `shell` is optional here
158
186
  // and `inject` would make the whole route block wait for a service a headless
159
187
  // deployment never provides. `null` is handed to the runner, which reports
160
- // `unavailable` and tells the operator to run the command themselves 鈥?the
188
+ // `unavailable` and tells the operator to run the command themselves —the
161
189
  // read-only half of the panel keeps working either way.
162
190
  const shellRaw = svcCtx.get('shell');
191
+ const searchShell = isShellLike(shellRaw) ? shellRaw : null;
163
192
  const analyze = createAnalyzeRunner({
164
- shell: isShellLike(shellRaw) ? shellRaw : null,
193
+ shell: searchShell,
165
194
  timeoutMs: config.analyzeTimeoutMs,
195
+ toolchain: managedToolchain,
196
+ // The runner must read the same config as the command text it confirms,
197
+ // otherwise the dialog describes a command the run does not execute. It
198
+ // resolves `false` per repository (automatic), and defaults to the
199
+ // project-local `GITNEXUS_HOME` when the config leaves it empty.
200
+ skipFts: config.skipFts,
201
+ gitnexusHome: config.gitnexusHome === '' ? null : config.gitnexusHome,
166
202
  });
167
203
  // GitNexus is what produces the index this plugin reads, so a machine without it
168
204
  // has nothing to display and no way to change that from here. This runner is the
@@ -170,7 +206,7 @@ export function apply(ctx, config) {
170
206
  // out a package manager, a registry, or a global prefix themselves.
171
207
  const install = createInstallRunner({
172
208
  shell: isShellLike(shellRaw) ? shellRaw : null,
173
- prefix: config.gitnexusInstallDir === '' ? undefined : config.gitnexusInstallDir,
209
+ prefix: installPrefix,
174
210
  timeoutMs: config.installTimeoutMs,
175
211
  });
176
212
  const disposers = [
@@ -178,8 +214,11 @@ export function apply(ctx, config) {
178
214
  get: (repoPath, options) => coverageFor(repoPath, options),
179
215
  maintenance: (repoPath) => maintenanceFor(repoPath),
180
216
  }),
217
+ mountFileHistoryRoute(svcCtx.webServer, {
218
+ read: (repoPath, filePath, options) => readFileActivity(repoPath, filePath, options),
219
+ }),
181
220
  mountAnalyzeRoute(svcCtx.webServer, {
182
- start: (repoPath) => analyze.start(repoPath),
221
+ start: (repoPath, options) => analyze.start(repoPath, options),
183
222
  status: (repoPath) => analyze.status(repoPath),
184
223
  cancel: (repoPath) => analyze.cancel(repoPath),
185
224
  }),
@@ -189,6 +228,14 @@ export function apply(ctx, config) {
189
228
  cancel: () => install.cancel(),
190
229
  cliPath: () => install.cliPath(),
191
230
  }),
231
+ mountSearchRoute(svcCtx.webServer, {
232
+ search: (repoPath, query, options) => searchWithFallback(repoPath, query, {
233
+ shell: searchShell,
234
+ helperPath: searchHelperPath,
235
+ limit: options?.limit,
236
+ managedPrefix: installPrefix,
237
+ }),
238
+ }),
192
239
  ];
193
240
  ctx.effect(() => () => {
194
241
  for (const dispose of disposers)
@@ -203,7 +250,7 @@ export function apply(ctx, config) {
203
250
  }
204
251
  }
205
252
  /**
206
- * Human-readable rendering lives in `./gitnexus/format.js` 鈥?free of DSH imports
253
+ * Human-readable rendering lives in `./gitnexus/format.js` —free of DSH imports
207
254
  * so it can be tested without a host. Re-exported here for callers that already
208
255
  * hold the plugin module.
209
256
  */
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -23,8 +23,14 @@
23
23
  import type { WebServerService } from '@deepseek-ai/cordis';
24
24
  import type { AnalyzeStatus } from '../gitnexus/analyze.js';
25
25
  export interface AnalyzeRouteDeps {
26
- /** Begin a run, or return the one already in flight for this repository. */
27
- start: (repoPath: string) => AnalyzeStatus;
26
+ /**
27
+ * Begin a run, or return the one already in flight for this repository.
28
+ * `force` selects the destructive full rebuild; it is passed through, never
29
+ * inferred from the method or the route.
30
+ */
31
+ start: (repoPath: string, options?: {
32
+ force?: boolean;
33
+ }) => AnalyzeStatus;
28
34
  status: (repoPath: string) => AnalyzeStatus | null;
29
35
  cancel: (repoPath: string) => boolean;
30
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/routes/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAQ5D,MAAM,WAAW,gBAAgB;IAC/B,4EAA4E;IAC5E,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,aAAa,CAAC;IAC3C,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,aAAa,GAAG,IAAI,CAAC;IACnD,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,IAAI,CAuCjG"}
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/routes/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAQ5D,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,aAAa,CAAC;IAC1E,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,aAAa,GAAG,IAAI,CAAC;IACnD,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,IAAI,CA2CjG"}
@@ -49,7 +49,11 @@ export function mountAnalyzeRoute(webServer, deps) {
49
49
  // desktop shell's own fetch.
50
50
  if (!passWriteGuard(req, res))
51
51
  return;
52
- sendJson(res, 200, { ok: true, run: deps.start(absRepo) });
52
+ // `force=1` is the full rebuild. It is an explicit query flag rather than a
53
+ // body field because the panel's only other POST parameter is the repo, and a
54
+ // flag in the URL is visible in the run's own command and in a log.
55
+ const force = url.searchParams.get('force') === '1';
56
+ sendJson(res, 200, { ok: true, run: deps.start(absRepo, { force }) });
53
57
  return;
54
58
  }
55
59
  if (req.method === 'DELETE') {
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/routes/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3F;;;GAGG;AACH,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AASxF;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAA2B,EAAE,IAAsB;IACnF,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9C,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC;YAAE,OAAO;QAElD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC,CAAC;YACrG,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEnC,IAAI,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO;QAEjC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,6EAA6E;YAC7E,+EAA+E;YAC/E,6BAA6B;YAC7B,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;gBAAE,OAAO;YACtC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;gBAAE,OAAO;YACtC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvC,8EAA8E;YAC9E,uDAAuD;YACvD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,kFAAkF;QAClF,yCAAyC;QACzC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,CAAC,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/routes/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3F;;;GAGG;AACH,MAAM,eAAe,GAAwB,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAaxF;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAA2B,EAAE,IAAsB;IACnF,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9C,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC;YAAE,OAAO;QAElD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC,CAAC;YACrG,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEnC,IAAI,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO;QAEjC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1B,6EAA6E;YAC7E,+EAA+E;YAC/E,6BAA6B;YAC7B,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;gBAAE,OAAO;YACtC,4EAA4E;YAC5E,8EAA8E;YAC9E,oEAAoE;YACpE,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC;YACpD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;gBAAE,OAAO;YACtC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvC,8EAA8E;YAC9E,uDAAuD;YACvD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,kFAAkF;QAClF,yCAAyC;QACzC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,CAAC,CAAC;AACxF,CAAC"}
@@ -5,8 +5,8 @@
5
5
  * carrier contract in `@deepseek-ai/dsh-host-webserver`: bare `node:http`, no
6
6
  * Express, exact-then-longest-prefix matching, and a disposer for teardown.
7
7
  *
8
- * THE BOUND IS "IS A GITNEXUS INDEX", NOT "IS IN THE REGISTRY"
9
- * -----------------------------------------------------------
8
+ * THE BOUND IS "IS A PROJECT ROOT", NOT "IS IN THE REGISTRY"
9
+ * ----------------------------------------------------------
10
10
  * An earlier revision accepted only paths present in `~/.gitnexus/registry.json`.
11
11
  * That was wrong for the panel's actual job: it shows the project the user is
12
12
  * *in*, and a working directory the global registry has never heard of — a fresh
@@ -14,12 +14,20 @@
14
14
  * panel exists to report on. Refusing it would have been a correctness bug wearing
15
15
  * a security costume.
16
16
  *
17
- * The route still refuses to describe arbitrary directories: the path must already
18
- * contain `.gitnexus/gitnexus.json` or `.gitnexus/meta.json`, so a caller cannot
19
- * use it to enumerate a filesystem. Loopback and method guards live in `./guard.js`.
17
+ * A later revision required an index. That was also wrong, for the same reason at a
18
+ * different state: a project with no index yet still has a readable working tree,
19
+ * and the engine already builds a useful scan-only report for it. The bound is now a
20
+ * project root (`.gitnexus` or `.git`), which still refuses arbitrary directories.
21
+ *
22
+ * The route still refuses to describe arbitrary directories: the path must be a
23
+ * project root — carrying `.gitnexus/gitnexus.json`, `.gitnexus/meta.json`, or a
24
+ * `.git` marker — so a caller cannot use it to enumerate a filesystem. An index is
25
+ * no longer required: the engine's scan-only report is what makes the "no index
26
+ * yet" state informative instead of an empty command. Loopback and method guards
27
+ * live in `./guard.js`.
20
28
  */
21
29
  import type { WebServerService } from '@deepseek-ai/cordis';
22
- import type { CoverageReport } from '../gitnexus/coverage.js';
30
+ import type { CoverageProgress, CoverageReport } from '../gitnexus/coverage.js';
23
31
  import type { MaintenanceInfo } from '../index.js';
24
32
  /**
25
33
  * What the route needs from the host half.
@@ -34,6 +42,7 @@ export interface CoverageRouteDeps {
34
42
  */
35
43
  get: (repoPath: string, options?: {
36
44
  fresh?: boolean;
45
+ onProgress?: (progress: CoverageProgress) => void;
37
46
  }) => Promise<CoverageReport>;
38
47
  maintenance?: (repoPath: string) => MaintenanceInfo;
39
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/routes/coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClF,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAC;CACrD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,iBAAiB,GAAG,MAAM,IAAI,CA2CnG"}
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/routes/coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,GAAG,EAAE,CACH,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAA;KAAE,KAC7E,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAC;CACrD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAmGnG"}
@@ -5,8 +5,8 @@
5
5
  * carrier contract in `@deepseek-ai/dsh-host-webserver`: bare `node:http`, no
6
6
  * Express, exact-then-longest-prefix matching, and a disposer for teardown.
7
7
  *
8
- * THE BOUND IS "IS A GITNEXUS INDEX", NOT "IS IN THE REGISTRY"
9
- * -----------------------------------------------------------
8
+ * THE BOUND IS "IS A PROJECT ROOT", NOT "IS IN THE REGISTRY"
9
+ * ----------------------------------------------------------
10
10
  * An earlier revision accepted only paths present in `~/.gitnexus/registry.json`.
11
11
  * That was wrong for the panel's actual job: it shows the project the user is
12
12
  * *in*, and a working directory the global registry has never heard of — a fresh
@@ -14,12 +14,20 @@
14
14
  * panel exists to report on. Refusing it would have been a correctness bug wearing
15
15
  * a security costume.
16
16
  *
17
- * The route still refuses to describe arbitrary directories: the path must already
18
- * contain `.gitnexus/gitnexus.json` or `.gitnexus/meta.json`, so a caller cannot
19
- * use it to enumerate a filesystem. Loopback and method guards live in `./guard.js`.
17
+ * A later revision required an index. That was also wrong, for the same reason at a
18
+ * different state: a project with no index yet still has a readable working tree,
19
+ * and the engine already builds a useful scan-only report for it. The bound is now a
20
+ * project root (`.gitnexus` or `.git`), which still refuses arbitrary directories.
21
+ *
22
+ * The route still refuses to describe arbitrary directories: the path must be a
23
+ * project root — carrying `.gitnexus/gitnexus.json`, `.gitnexus/meta.json`, or a
24
+ * `.git` marker — so a caller cannot use it to enumerate a filesystem. An index is
25
+ * no longer required: the engine's scan-only report is what makes the "no index
26
+ * yet" state informative instead of an empty command. Loopback and method guards
27
+ * live in `./guard.js`.
20
28
  */
21
29
  import path from 'node:path';
22
- import { hasIndex } from '../gitnexus/index-meta.js';
30
+ import { isProjectRoot } from '../gitnexus/index-meta.js';
23
31
  import { guardHandler, passGuard, answerHead, sendJson } from './guard.js';
24
32
  /**
25
33
  * @returns disposer that unregisters the route
@@ -39,13 +47,18 @@ export function mountCoverageRoute(webServer, deps) {
39
47
  return;
40
48
  }
41
49
  const absRepo = path.resolve(repo);
42
- if (!(await hasIndex(absRepo))) {
43
- // Not an error the caller should retry: this directory simply has no index
44
- // yet, which is the state the panel's initialize action exists for.
50
+ // The bound changed from "is a GitNexus index" to "is a project root": a
51
+ // directory with neither an index nor a `.git` marker is still refused, so the
52
+ // route cannot be used to enumerate a filesystem. A git repository without an
53
+ // index is the state the panel's initialize action exists for, and the engine
54
+ // already produces a useful scan-only report for it (file counts, bytes,
55
+ // languages, the size cap). Refusing that state was hiding data, not protecting
56
+ // anything — the route only answers loopback callers.
57
+ if (!(await isProjectRoot(absRepo))) {
45
58
  sendJson(res, 404, {
46
59
  ok: false,
47
- code: 'not-indexed',
48
- message: 'directory has no GitNexus index (.gitnexus/gitnexus.json or meta.json)',
60
+ code: 'not-a-project',
61
+ message: 'directory is neither a GitNexus index nor a git repository root',
49
62
  });
50
63
  return;
51
64
  }
@@ -54,10 +67,62 @@ export function mountCoverageRoute(webServer, deps) {
54
67
  // `refresh=1` comes from the panel's manual refresh control. A background poll
55
68
  // omits it and gets the cached copy, which is what the TTL is for.
56
69
  const fresh = url.searchParams.get('refresh') === '1';
57
- const report = await deps.get(absRepo, { fresh });
58
70
  // The maintenance commands ride along with the report because they are
59
71
  // config-derived and only meaningful next to the index they would rebuild.
60
72
  const maintenance = typeof deps.maintenance === 'function' ? deps.maintenance(absRepo) : null;
73
+ // `stream=1` is the panel's numeric-progress channel. NDJSON rather than SSE:
74
+ // one JSON object per line needs no event naming and falls back to plain JSON
75
+ // for any caller that does not ask for it.
76
+ if (url.searchParams.get('stream') === '1') {
77
+ const write = (payload) => {
78
+ if (res.writableEnded)
79
+ return;
80
+ try {
81
+ res.write(`${JSON.stringify(payload)}\n`);
82
+ }
83
+ catch {
84
+ // The reader disconnected; the rest of the work is already in flight.
85
+ }
86
+ };
87
+ res.statusCode = 200;
88
+ res.setHeader('content-type', 'application/x-ndjson; charset=utf-8');
89
+ res.setHeader('cache-control', 'no-store');
90
+ res.setHeader('x-content-type-options', 'nosniff');
91
+ res.setHeader('referrer-policy', 'no-referrer');
92
+ res.setHeader('x-accel-buffering', 'no');
93
+ res.flushHeaders();
94
+ try {
95
+ const report = await deps.get(absRepo, {
96
+ fresh,
97
+ onProgress: (progress) => write({ type: 'progress', ...progress }),
98
+ });
99
+ // The engine ends at 99%; the final boundary is the route having the whole
100
+ // report in hand, so 100 is emitted here rather than invented earlier.
101
+ write({
102
+ type: 'progress',
103
+ phase: 'assemble',
104
+ percent: 100,
105
+ label: '报告已读取',
106
+ });
107
+ write({
108
+ type: 'report',
109
+ report,
110
+ maintenance,
111
+ readAt: new Date().toISOString(),
112
+ });
113
+ }
114
+ catch (error) {
115
+ write({
116
+ type: 'error',
117
+ status: 500,
118
+ code: 'internal-error',
119
+ message: error instanceof Error ? error.message : String(error),
120
+ });
121
+ }
122
+ res.end();
123
+ return;
124
+ }
125
+ const report = await deps.get(absRepo, { fresh });
61
126
  // `readAt` is what makes a refresh visible: without it two reads of an unchanged
62
127
  // repository are byte-identical on screen, so the control looks inert even when
63
128
  // it did exactly what it was asked.
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/routes/coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAoB3E;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAA2B,EAAE,IAAuB;IACrF,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9C,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO;QAEjC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;gBACjB,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,kCAAkC;aAC5C,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YAC/B,2EAA2E;YAC3E,oEAAoE;YACpE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;gBACjB,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,wEAAwE;aAClF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO;QAEjC,+EAA+E;QAC/E,mEAAmE;QACnE,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAClD,uEAAuE;QACvE,2EAA2E;QAC3E,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9F,iFAAiF;QACjF,gFAAgF;QAChF,oCAAoC;QACpC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,CAAC,CAAC;AACzF,CAAC"}
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/routes/coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `GET /api/gitnexus/file-history?repo=<project>&path=<file>&days=7`
3
+ *
4
+ * The file timeline is read on demand. It is deliberately a separate route from
5
+ * coverage: a report already crosses every file in the activity window, while
6
+ * "show me this one file's commits" is a single bounded `git log --follow`.
7
+ *
8
+ * Read-only like coverage/search. The path is resolved inside the project root, and
9
+ * the engine clamps `days` to 1–30, so a hand-written URL cannot walk the filesystem
10
+ * or request an unbounded history.
11
+ */
12
+ import type { WebServerService } from '@deepseek-ai/cordis';
13
+ import type { FileHistory } from '../gitnexus/git-activity.js';
14
+ export interface FileHistoryRouteDeps {
15
+ read: (repoPath: string, filePath: string, options?: {
16
+ days?: number;
17
+ }) => Promise<FileHistory>;
18
+ }
19
+ /** @returns disposer that unregisters the route */
20
+ export declare function mountFileHistoryRoute(webServer: WebServerService, deps: FileHistoryRouteDeps): () => void;
21
+ //# sourceMappingURL=file-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-history.d.ts","sourceRoot":"","sources":["../../src/routes/file-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,CACJ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KACxB,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3B;AAED,mDAAmD;AACnD,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,gBAAgB,EAC3B,IAAI,EAAE,oBAAoB,GACzB,MAAM,IAAI,CAyDZ"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * `GET /api/gitnexus/file-history?repo=<project>&path=<file>&days=7`
3
+ *
4
+ * The file timeline is read on demand. It is deliberately a separate route from
5
+ * coverage: a report already crosses every file in the activity window, while
6
+ * "show me this one file's commits" is a single bounded `git log --follow`.
7
+ *
8
+ * Read-only like coverage/search. The path is resolved inside the project root, and
9
+ * the engine clamps `days` to 1–30, so a hand-written URL cannot walk the filesystem
10
+ * or request an unbounded history.
11
+ */
12
+ import path from 'node:path';
13
+ import { isProjectRoot } from '../gitnexus/index-meta.js';
14
+ import { guardHandler, passGuard, answerHead, sendJson } from './guard.js';
15
+ /** @returns disposer that unregisters the route */
16
+ export function mountFileHistoryRoute(webServer, deps) {
17
+ const handler = guardHandler(async (req, res) => {
18
+ if (!passGuard(req, res))
19
+ return;
20
+ const url = new URL(req.url ?? '/', 'http://127.0.0.1');
21
+ const repo = url.searchParams.get('repo');
22
+ const file = url.searchParams.get('path');
23
+ if (repo === null || repo.trim() === '' || file === null || file.trim() === '') {
24
+ sendJson(res, 400, {
25
+ ok: false,
26
+ code: 'missing-params',
27
+ message: 'repo and path query parameters are required',
28
+ });
29
+ return;
30
+ }
31
+ const absRepo = path.resolve(repo);
32
+ if (!(await isProjectRoot(absRepo))) {
33
+ sendJson(res, 404, {
34
+ ok: false,
35
+ code: 'not-a-project',
36
+ message: 'directory is neither a GitNexus index nor a git repository root',
37
+ });
38
+ return;
39
+ }
40
+ const relative = file.trim();
41
+ const prefix = absRepo.endsWith(path.sep) ? absRepo : `${absRepo}${path.sep}`;
42
+ const absolute = path.resolve(absRepo, relative);
43
+ // Windows paths compare case-insensitively; normalising both sides avoids a
44
+ // false "outside project" for a path the caller spelled with another drive case.
45
+ const inside = process.platform === 'win32'
46
+ ? absolute.toLowerCase().startsWith(prefix.toLowerCase())
47
+ : absolute.startsWith(prefix);
48
+ if (!inside) {
49
+ sendJson(res, 400, {
50
+ ok: false,
51
+ code: 'invalid-path',
52
+ message: 'path must resolve inside the project root',
53
+ });
54
+ return;
55
+ }
56
+ if (answerHead(req, res))
57
+ return;
58
+ const parsedDays = Number.parseInt(url.searchParams.get('days') ?? '7', 10);
59
+ const days = Number.isFinite(parsedDays) ? Math.max(1, Math.min(30, parsedDays)) : 7;
60
+ const history = await deps.read(absRepo, relative, { days });
61
+ sendJson(res, 200, {
62
+ ok: true,
63
+ ...history,
64
+ readAt: new Date().toISOString(),
65
+ });
66
+ });
67
+ return webServer.register({ kind: 'prefix', path: '/api/gitnexus/file-history', handler });
68
+ }
69
+ //# sourceMappingURL=file-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-history.js","sourceRoot":"","sources":["../../src/routes/file-history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `GET /api/gitnexus/search?repo=<project>&q=<keyword>` — keyword search.
3
+ *
4
+ * The fourth route, and the first that is neither a reading of the index manifest
5
+ * nor a maintenance action: it queries the graph's symbol names and file paths.
6
+ * It is read-only in the strongest sense this plugin can offer — the engine opens
7
+ * LadybugDB with `readOnly: true` and takes no write lock — so the method policy is
8
+ * the read-only one (GET/HEAD), not the analyze route's wider set.
9
+ *
10
+ * The bound is the same project-root check the coverage route uses: a directory
11
+ * that is neither indexed nor a `.git` root is refused, so the route cannot be used
12
+ * to enumerate a filesystem. Search itself additionally requires a complete index
13
+ * store and returns a typed error when the graph is missing.
14
+ */
15
+ import type { WebServerService } from '@deepseek-ai/cordis';
16
+ import { type SearchReport } from '../gitnexus/search.js';
17
+ export interface SearchRouteDeps {
18
+ /** Run one keyword search. Errors are `SearchError` instances when typed. */
19
+ search: (repoPath: string, query: string, options?: {
20
+ limit?: number;
21
+ }) => Promise<SearchReport>;
22
+ }
23
+ /**
24
+ * @returns disposer that unregisters the route
25
+ */
26
+ export declare function mountSearchRoute(webServer: WebServerService, deps: SearchRouteDeps): () => void;
27
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/routes/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIvE,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAClG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,eAAe,GAAG,MAAM,IAAI,CAwD/F"}