sigmap 6.10.0 → 6.10.2
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/AGENTS.md +504 -283
- package/CHANGELOG.md +31 -0
- package/README.md +41 -11
- package/gen-context.js +257 -20
- package/package.json +1 -1
- package/packages/adapters/index.js +4 -2
- package/packages/adapters/willow.js +200 -0
- package/packages/cli/package.json +1 -1
- package/packages/core/index.js +2 -0
- package/packages/core/package.json +1 -1
- package/src/discovery/language-detector.js +2 -0
- package/src/discovery/source-root-registry.js +9 -0
- package/src/discovery/source-root-resolver.js +5 -1
- package/src/eval/analyzer.js +2 -0
- package/src/extractors/gdscript.js +131 -0
- package/src/extractors/python.js +33 -2
- package/src/extractors/python_ast.py +348 -0
- package/src/extractors/r.js +136 -0
- package/src/map/import-graph.js +1 -1
- package/src/mcp/server.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,37 @@ Format: [Semantic Versioning](https://semver.org/)
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [6.10.2] — 2026-05-11
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Open-source agents documentation** — Comprehensive integration guides for OpenCode, Aider, OpenHands, and Cline with setup examples and context injection patterns. Clear separation of coding agents from inference backends.
|
|
18
|
+
- **Local LLM workflows guide** — Complete setup guide for Ollama, llama.cpp, vLLM with model recommendations, performance tuning, and benchmarking. Emphasizes model-agnostic nature: no API costs, full privacy, offline capability.
|
|
19
|
+
- **Integrations sidebar** — New VitePress navigation section highlighting open-source agents, local LLMs, MCP server, and Repomix integration.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **README model-agnostic messaging** — Updated to clarify support for cloud LLMs, open-source agents, and local models with full privacy. Removed proprietary-focused language.
|
|
24
|
+
- **Quick-start guide** — Added links to new agent and local-LLM guides in "Next steps" section.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [6.10.1] — 2026-05-10
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **R language support (Phase 1)** — Extract function signatures from `.r` and `.R` files with support for function definitions (`<-`, `=`, `<<-` forms), multi-line arguments with string-literal protection, S4 patterns (setGeneric, setMethod, setClass), and private function filtering. Shiny framework detection via `app.R`/`ui.R`/`server.R` triplet.
|
|
33
|
+
- **Native Python AST extractor** — Fallback to `python_ast.py` using `ast.parse()` for accurate extraction of complex signatures (multiline args, stacked decorators, complex generics). Preserves regex fallback for Python 2 / no-Python3 environments. Zero breaking changes to output format.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- **ReferenceError in `--query`** — Fixed variable scope issue where `adpIdx` was undefined when no context file present. Moved variable declaration to proper scope before conditional block.
|
|
38
|
+
- **Windows path handling** — Normalized path separators in nested path deduplication. Windows backslashes no longer cause false negatives when matching nested source roots.
|
|
39
|
+
- **.contextignore patterns** — Fixed bracket character classes (`[Bb]in/`) being treated as literals. Fixed trailing slashes on directory patterns not matching nested paths. Added error handling for malformed bracket syntax.
|
|
40
|
+
- **Claude adapter in per-module and hot-cold strategies** — Fixed adapter not being written to output in per-module and hot-cold context strategies.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
13
44
|
## [6.10.0] — 2026-05-05
|
|
14
45
|
|
|
15
46
|
### Added
|
package/README.md
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
[](package.json)
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](https://github.com/manojmallick/sigmap/stargazers)
|
|
15
|
-
[](https://star-history.com/#manojmallick/sigmap&Date)
|
|
16
|
+
[](https://shypd.ai/tools/sigmap)
|
|
16
17
|
|
|
17
18
|
</div>
|
|
18
19
|
|
|
@@ -20,9 +21,11 @@
|
|
|
20
21
|
|
|
21
22
|
## Try it now
|
|
22
23
|
|
|
24
|
+
**No install required.** Run instantly on any machine:
|
|
25
|
+
|
|
23
26
|
```bash
|
|
24
27
|
npx sigmap
|
|
25
|
-
sigmap ask "Where is auth handled?"
|
|
28
|
+
npx sigmap ask "Where is auth handled?"
|
|
26
29
|
```
|
|
27
30
|
|
|
28
31
|
Zero config. Zero dependencies. Under 10 seconds.
|
|
@@ -33,7 +36,12 @@ Zero config. Zero dependencies. Under 10 seconds.
|
|
|
33
36
|
|
|
34
37
|
SigMap extracts function and class signatures from your codebase and feeds the right files — not the whole repo — to your AI.
|
|
35
38
|
|
|
36
|
-
Works with
|
|
39
|
+
**Model-agnostic.** Works with:
|
|
40
|
+
- **Cloud LLMs:** Claude, GPT-4, Copilot, Gemini
|
|
41
|
+
- **Open-source agents:** OpenCode, Aider, OpenHands, Cline
|
|
42
|
+
- **Local LLMs:** Ollama, llama.cpp, vLLM (no API keys, full privacy)
|
|
43
|
+
- **Any editor:** VS Code, Cursor, Windsurf, Neovim, JetBrains
|
|
44
|
+
- **Any model:** Use what you want, no vendor lock-in
|
|
37
45
|
|
|
38
46
|
---
|
|
39
47
|
|
|
@@ -43,7 +51,9 @@ Works with Copilot, Claude, Cursor, Windsurf, and any LLM.
|
|
|
43
51
|
- **40–98% token reduction** — 2K–4K tokens instead of 80K+
|
|
44
52
|
- **52.2% task success rate** — up from 10% without context
|
|
45
53
|
- **1.68 prompts per task** — down from 2.84
|
|
46
|
-
- **
|
|
54
|
+
- **No vendor lock-in** — works with any AI assistant or local LLM
|
|
55
|
+
- **No API costs** — use local models (Ollama, llama.cpp, vLLM) with zero token fees
|
|
56
|
+
- **Full privacy** — keep your code and context on your machine
|
|
47
57
|
- **Zero npm dependencies** — `npx sigmap` on any machine
|
|
48
58
|
|
|
49
59
|
---
|
|
@@ -144,20 +154,26 @@ volta install sigmap
|
|
|
144
154
|
|
|
145
155
|
| Adapter | Output file | Used by |
|
|
146
156
|
|---|---|---|
|
|
147
|
-
| `copilot` | `.github/copilot-instructions.md` | GitHub Copilot |
|
|
157
|
+
| `copilot` | `.github/copilot-instructions.md` | GitHub Copilot, OpenCode |
|
|
148
158
|
| `claude` | `CLAUDE.md` | Claude / Claude Code |
|
|
149
|
-
| `cursor` | `.cursorrules` | Cursor |
|
|
159
|
+
| `cursor` | `.cursorrules` | Cursor, Cline |
|
|
150
160
|
| `windsurf` | `.windsurfrules` | Windsurf |
|
|
151
|
-
| `openai` | `.github/openai-context.md` | OpenAI
|
|
161
|
+
| `openai` | `.github/openai-context.md` | OpenAI API, Aider, local Ollama/llama.cpp |
|
|
152
162
|
| `gemini` | `.github/gemini-context.md` | Google Gemini |
|
|
153
|
-
| `codex` | `AGENTS.md` | OpenAI Codex
|
|
163
|
+
| `codex` | `AGENTS.md` | OpenAI Codex (legacy) |
|
|
154
164
|
|
|
155
165
|
```bash
|
|
156
|
-
sigmap --adapter copilot # default
|
|
157
|
-
sigmap --adapter
|
|
158
|
-
sigmap --adapter
|
|
166
|
+
sigmap --adapter copilot # default — works with Copilot, OpenCode
|
|
167
|
+
sigmap --adapter openai # works with Ollama, llama.cpp, vLLM, Aider
|
|
168
|
+
sigmap --adapter claude # works with Claude Code
|
|
159
169
|
```
|
|
160
170
|
|
|
171
|
+
**Open-source agents & local LLMs:**
|
|
172
|
+
|
|
173
|
+
Use SigMap with open-source tools and fully self-hosted setups:
|
|
174
|
+
- **[Open-source agents guide →](https://manojmallick.github.io/sigmap/guide/agents)** — OpenCode, Aider, OpenHands, Cline
|
|
175
|
+
- **[Local LLMs guide →](https://manojmallick.github.io/sigmap/guide/local-llms)** — Ollama, llama.cpp, vLLM (no API keys, full privacy)
|
|
176
|
+
|
|
161
177
|
**IDE extensions:**
|
|
162
178
|
|
|
163
179
|
| IDE | Install | Source | Features |
|
|
@@ -228,6 +244,20 @@ If SigMap saves you context or API spend, a ⭐ on [GitHub](https://github.com/m
|
|
|
228
244
|
|
|
229
245
|
---
|
|
230
246
|
|
|
247
|
+
## Contributing
|
|
248
|
+
|
|
249
|
+
SigMap welcomes contributions!
|
|
250
|
+
|
|
251
|
+
**Before submitting a PR:**
|
|
252
|
+
1. Read [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
253
|
+
2. Check [Discussions → Announcements](../../discussions) for workflow setup
|
|
254
|
+
3. Target the `develop` branch (not main)
|
|
255
|
+
4. Follow the [contributor checklist](.github/CONTRIBUTOR_CHECKLIST.txt)
|
|
256
|
+
|
|
257
|
+
See [.github/PULL_REQUEST_TEMPLATE.md](.github/PULL_REQUEST_TEMPLATE.md) for the PR checklist. All contributors are credited in the CHANGELOG and release notes.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
231
261
|
## Why not embeddings?
|
|
232
262
|
|
|
233
263
|
| | Embeddings | SigMap |
|
package/gen-context.js
CHANGED
|
@@ -2980,6 +2980,148 @@ __factories["./src/extractors/prdiff"] = function(module, exports) {
|
|
|
2980
2980
|
|
|
2981
2981
|
};
|
|
2982
2982
|
|
|
2983
|
+
// ── ./src/extractors/r ──
|
|
2984
|
+
__factories["./src/extractors/r"] = function(module, exports) {
|
|
2985
|
+
|
|
2986
|
+
'use strict';
|
|
2987
|
+
|
|
2988
|
+
/**
|
|
2989
|
+
* Extract signatures from R source code.
|
|
2990
|
+
* @param {string} src - Raw file content
|
|
2991
|
+
* @returns {string[]} Array of signature strings
|
|
2992
|
+
*/
|
|
2993
|
+
function extract(src) {
|
|
2994
|
+
if (!src || typeof src !== 'string') return [];
|
|
2995
|
+
const sigs = [];
|
|
2996
|
+
|
|
2997
|
+
// Strip line comments. R uses # comments. Roxygen2 (#') comments are
|
|
2998
|
+
// stripped along with regular ones; Phase 2 may parse them.
|
|
2999
|
+
const stripped = src.replace(/#.*$/gm, '');
|
|
3000
|
+
|
|
3001
|
+
// Function definitions:
|
|
3002
|
+
// name <- function(args) { ... }
|
|
3003
|
+
// name = function(args) { ... }
|
|
3004
|
+
// name <<- function(args) { ... }
|
|
3005
|
+
// Args may span multiple lines and contain default values, so we need to
|
|
3006
|
+
// match a balanced parenthesis group rather than a single line.
|
|
3007
|
+
const funcRe = /^(?:[ \t]*)([\w.]+)\s*(?:<<-|<-|=)\s*function\s*\(/gm;
|
|
3008
|
+
let m;
|
|
3009
|
+
while ((m = funcRe.exec(stripped)) !== null) {
|
|
3010
|
+
const name = m[1];
|
|
3011
|
+
if (name.startsWith('.')) continue; // private convention
|
|
3012
|
+
const argsStart = funcRe.lastIndex;
|
|
3013
|
+
const args = readBalancedParens(stripped, argsStart - 1);
|
|
3014
|
+
if (args === null) continue;
|
|
3015
|
+
sigs.push(`${name} <- function(${normalizeParams(args)})`);
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
// S4 setMethod / setGeneric:
|
|
3019
|
+
// setGeneric("name", function(args) standardGeneric("name"))
|
|
3020
|
+
// setMethod("name", "ClassName", function(args) { ... })
|
|
3021
|
+
for (const sm of stripped.matchAll(/^[ \t]*setGeneric\s*\(\s*["']([\w.]+)["']/gm)) {
|
|
3022
|
+
sigs.push(`setGeneric("${sm[1]}")`);
|
|
3023
|
+
}
|
|
3024
|
+
for (const sm of stripped.matchAll(/^[ \t]*setMethod\s*\(\s*["']([\w.]+)["']\s*,\s*["']([\w.]+)["']/gm)) {
|
|
3025
|
+
sigs.push(`setMethod("${sm[1]}", "${sm[2]}")`);
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
// S4 class definitions:
|
|
3029
|
+
// setClass("Name", representation(...), ...)
|
|
3030
|
+
for (const sm of stripped.matchAll(/^[ \t]*setClass\s*\(\s*["']([\w.]+)["']/gm)) {
|
|
3031
|
+
sigs.push(`setClass("${sm[1]}")`);
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
return sigs.slice(0, 30);
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
/**
|
|
3038
|
+
* Read a parenthesis-balanced substring starting at the position of the
|
|
3039
|
+
* opening '(' character, returning the inner content (without the outer
|
|
3040
|
+
* parens). Returns null if no matching close paren is found within `cap`
|
|
3041
|
+
* characters, which guards against runaway scans on malformed input.
|
|
3042
|
+
*/
|
|
3043
|
+
function readBalancedParens(src, openIdx, cap = 4096) {
|
|
3044
|
+
if (src[openIdx] !== '(') return null;
|
|
3045
|
+
let depth = 1;
|
|
3046
|
+
let i = openIdx + 1;
|
|
3047
|
+
const end = Math.min(src.length, openIdx + cap);
|
|
3048
|
+
let inString = null; // null | '"' | "'"
|
|
3049
|
+
while (i < end) {
|
|
3050
|
+
const ch = src[i];
|
|
3051
|
+
if (inString) {
|
|
3052
|
+
if (ch === '\\') { i += 2; continue; }
|
|
3053
|
+
if (ch === inString) inString = null;
|
|
3054
|
+
i++;
|
|
3055
|
+
continue;
|
|
3056
|
+
}
|
|
3057
|
+
if (ch === '"' || ch === "'") { inString = ch; i++; continue; }
|
|
3058
|
+
if (ch === '(') depth++;
|
|
3059
|
+
else if (ch === ')') {
|
|
3060
|
+
depth--;
|
|
3061
|
+
if (depth === 0) return src.slice(openIdx + 1, i);
|
|
3062
|
+
}
|
|
3063
|
+
i++;
|
|
3064
|
+
}
|
|
3065
|
+
return null;
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
/**
|
|
3069
|
+
* Compress whitespace inside a parameter list, collapse multi-line default
|
|
3070
|
+
* expressions onto a single line, and trim. The goal is one-line readable
|
|
3071
|
+
* signatures, not a faithful AST.
|
|
3072
|
+
*
|
|
3073
|
+
* String literals are protected so that commas/equals inside default values
|
|
3074
|
+
* like sep = "," don't get respaced.
|
|
3075
|
+
*/
|
|
3076
|
+
function normalizeParams(raw) {
|
|
3077
|
+
const tokens = [];
|
|
3078
|
+
let buf = '';
|
|
3079
|
+
let inString = null;
|
|
3080
|
+
for (let i = 0; i < raw.length; i++) {
|
|
3081
|
+
const ch = raw[i];
|
|
3082
|
+
if (inString) {
|
|
3083
|
+
buf += ch;
|
|
3084
|
+
if (ch === '\\' && i + 1 < raw.length) { buf += raw[i + 1]; i++; continue; }
|
|
3085
|
+
if (ch === inString) inString = null;
|
|
3086
|
+
continue;
|
|
3087
|
+
}
|
|
3088
|
+
if (ch === '"' || ch === "'") { inString = ch; buf += ch; continue; }
|
|
3089
|
+
buf += ch;
|
|
3090
|
+
}
|
|
3091
|
+
// Now buf === raw with strings preserved character-for-character.
|
|
3092
|
+
// Walk again: collapse non-string runs of whitespace, normalize ', ' and ' = '.
|
|
3093
|
+
let out = '';
|
|
3094
|
+
inString = null;
|
|
3095
|
+
for (let i = 0; i < buf.length; i++) {
|
|
3096
|
+
const ch = buf[i];
|
|
3097
|
+
if (inString) {
|
|
3098
|
+
out += ch;
|
|
3099
|
+
if (ch === '\\' && i + 1 < buf.length) { out += buf[i + 1]; i++; continue; }
|
|
3100
|
+
if (ch === inString) inString = null;
|
|
3101
|
+
continue;
|
|
3102
|
+
}
|
|
3103
|
+
if (ch === '"' || ch === "'") { inString = ch; out += ch; continue; }
|
|
3104
|
+
if (/\s/.test(ch)) {
|
|
3105
|
+
if (out.length && !/\s$/.test(out)) out += ' ';
|
|
3106
|
+
continue;
|
|
3107
|
+
}
|
|
3108
|
+
if (ch === ',') {
|
|
3109
|
+
out = out.replace(/\s+$/, '') + ', ';
|
|
3110
|
+
continue;
|
|
3111
|
+
}
|
|
3112
|
+
if (ch === '=') {
|
|
3113
|
+
out = out.replace(/\s+$/, '') + ' = ';
|
|
3114
|
+
continue;
|
|
3115
|
+
}
|
|
3116
|
+
out += ch;
|
|
3117
|
+
}
|
|
3118
|
+
return out.trim();
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
module.exports = { extract };
|
|
3122
|
+
|
|
3123
|
+
};
|
|
3124
|
+
|
|
2983
3125
|
// ── ./src/format/cache ──
|
|
2984
3126
|
__factories["./src/format/cache"] = function(module, exports) {
|
|
2985
3127
|
|
|
@@ -5387,7 +5529,7 @@ __factories["./src/mcp/server"] = function(module, exports) {
|
|
|
5387
5529
|
|
|
5388
5530
|
const SERVER_INFO = {
|
|
5389
5531
|
name: 'sigmap',
|
|
5390
|
-
version: '6.10.
|
|
5532
|
+
version: '6.10.2',
|
|
5391
5533
|
description: 'SigMap MCP server — code signatures on demand',
|
|
5392
5534
|
};
|
|
5393
5535
|
|
|
@@ -7913,6 +8055,95 @@ __factories["./src/discovery/source-root-resolver"] = function(module, exports)
|
|
|
7913
8055
|
module.exports = { resolveSourceRoots };
|
|
7914
8056
|
};
|
|
7915
8057
|
|
|
8058
|
+
// ── ./src/workspace/detector ──
|
|
8059
|
+
__factories["./src/workspace/detector"] = function(module, exports) {
|
|
8060
|
+
'use strict';
|
|
8061
|
+
const fs = require('fs');
|
|
8062
|
+
const path = require('path');
|
|
8063
|
+
module.exports = { detectWorkspaces, inferPackage, scopeToPackage };
|
|
8064
|
+
|
|
8065
|
+
function detectWorkspaces(cwd) {
|
|
8066
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
8067
|
+
if (!fs.existsSync(pkgPath)) return [];
|
|
8068
|
+
|
|
8069
|
+
let pkg;
|
|
8070
|
+
try {
|
|
8071
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
8072
|
+
} catch {
|
|
8073
|
+
return [];
|
|
8074
|
+
}
|
|
8075
|
+
|
|
8076
|
+
const patterns = pkg.workspaces || [];
|
|
8077
|
+
const dirs = [];
|
|
8078
|
+
|
|
8079
|
+
// Handle both flat array and object with packages field (Yarn v2 format)
|
|
8080
|
+
const patternArray = Array.isArray(patterns) ? patterns : (patterns.packages || []);
|
|
8081
|
+
|
|
8082
|
+
for (const p of patternArray) {
|
|
8083
|
+
const base = p.replace(/\/\*\*?$/, '');
|
|
8084
|
+
const resolved = path.join(cwd, base);
|
|
8085
|
+
if (fs.existsSync(resolved)) {
|
|
8086
|
+
try {
|
|
8087
|
+
for (const entry of fs.readdirSync(resolved, { withFileTypes: true })) {
|
|
8088
|
+
if (entry.isDirectory()) dirs.push(path.join(resolved, entry.name));
|
|
8089
|
+
}
|
|
8090
|
+
} catch (_) {}
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8093
|
+
|
|
8094
|
+
return dirs;
|
|
8095
|
+
}
|
|
8096
|
+
|
|
8097
|
+
// Infer package from query tokens: "add rate limiting to payments" → "packages/payments"
|
|
8098
|
+
function inferPackage(query, workspaceDirs, cwd) {
|
|
8099
|
+
const tokens = query.toLowerCase().split(/\W+/).filter(t => t.length > 2);
|
|
8100
|
+
|
|
8101
|
+
// Find longest matching package name
|
|
8102
|
+
let bestMatch = null;
|
|
8103
|
+
let bestLen = 0;
|
|
8104
|
+
let bestMatchLen = 0;
|
|
8105
|
+
|
|
8106
|
+
for (const dir of workspaceDirs) {
|
|
8107
|
+
const name = path.basename(dir).toLowerCase();
|
|
8108
|
+
for (const token of tokens) {
|
|
8109
|
+
const matchLen = _getMatchLength(name, token);
|
|
8110
|
+
// Only consider matches; use longest match, and break ties by longest package name
|
|
8111
|
+
if (matchLen > 0 && (matchLen > bestLen || (matchLen === bestLen && name.length > bestMatchLen))) {
|
|
8112
|
+
bestMatch = dir;
|
|
8113
|
+
bestLen = matchLen;
|
|
8114
|
+
bestMatchLen = name.length;
|
|
8115
|
+
}
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
8118
|
+
|
|
8119
|
+
return bestMatch;
|
|
8120
|
+
}
|
|
8121
|
+
|
|
8122
|
+
function _getMatchLength(name, token) {
|
|
8123
|
+
if (name === token) return 1000 + name.length; // Exact match is best
|
|
8124
|
+
if (name.startsWith(token) && token.length >= 3) return 100 + token.length;
|
|
8125
|
+
if (token.startsWith(name) && name.length >= 3) return name.length;
|
|
8126
|
+
return 0;
|
|
8127
|
+
}
|
|
8128
|
+
|
|
8129
|
+
// Return boost multiplier for files inside the inferred package
|
|
8130
|
+
function scopeToPackage(filePath, packageDir) {
|
|
8131
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
8132
|
+
const normalizedPkg = packageDir.replace(/\\/g, '/');
|
|
8133
|
+
|
|
8134
|
+
// Ensure we match the directory boundary, not just a prefix
|
|
8135
|
+
// e.g., packages/payment should not match packages/payment-old
|
|
8136
|
+
if (normalized.startsWith(normalizedPkg)) {
|
|
8137
|
+
const afterPrefix = normalized.slice(normalizedPkg.length);
|
|
8138
|
+
// Check if next char is / or if it's the exact match
|
|
8139
|
+
if (afterPrefix === '' || afterPrefix[0] === '/') {
|
|
8140
|
+
return 0.30;
|
|
8141
|
+
}
|
|
8142
|
+
}
|
|
8143
|
+
return 0;
|
|
8144
|
+
}
|
|
8145
|
+
};
|
|
8146
|
+
|
|
7916
8147
|
/**
|
|
7917
8148
|
* SigMap — gen-context.js v1.2.0
|
|
7918
8149
|
* Zero-dependency AI context engine.
|
|
@@ -7925,7 +8156,7 @@ const path = require('path');
|
|
|
7925
8156
|
const os = require('os');
|
|
7926
8157
|
const { execSync } = require('child_process');
|
|
7927
8158
|
|
|
7928
|
-
const VERSION = '6.10.
|
|
8159
|
+
const VERSION = '6.10.2';
|
|
7929
8160
|
const MARKER = '\n\n## Auto-generated signatures\n<!-- Updated by gen-context.js -->\n';
|
|
7930
8161
|
|
|
7931
8162
|
function requireSourceOrBundled(key) {
|
|
@@ -8005,14 +8236,22 @@ function loadIgnorePatterns(cwd) {
|
|
|
8005
8236
|
function matchesIgnore(relPath, patterns) {
|
|
8006
8237
|
for (const pat of patterns) {
|
|
8007
8238
|
const normalized = pat.replace(/\\/g, '/');
|
|
8008
|
-
//
|
|
8009
|
-
const
|
|
8010
|
-
.
|
|
8239
|
+
// Strip trailing slash (gitignore style — directory patterns)
|
|
8240
|
+
const patternToUse = normalized.endsWith('/')
|
|
8241
|
+
? normalized.slice(0, -1)
|
|
8242
|
+
: normalized;
|
|
8243
|
+
// Escape regex special chars but NOT brackets (keep them for character classes)
|
|
8244
|
+
const regexStr = patternToUse
|
|
8245
|
+
.replace(/[.+^${}()|\\]/g, '\\$&')
|
|
8011
8246
|
.replace(/\*\*/g, '___DOUBLE___')
|
|
8012
8247
|
.replace(/\*/g, '[^/]*')
|
|
8013
8248
|
.replace(/___DOUBLE___/g, '.*');
|
|
8014
|
-
|
|
8015
|
-
|
|
8249
|
+
try {
|
|
8250
|
+
const regex = new RegExp(`(^|/)${regexStr}($|/)`);
|
|
8251
|
+
if (regex.test(relPath)) return true;
|
|
8252
|
+
} catch (_) {
|
|
8253
|
+
// Malformed bracket syntax or invalid regex — skip this pattern
|
|
8254
|
+
}
|
|
8016
8255
|
}
|
|
8017
8256
|
return false;
|
|
8018
8257
|
}
|
|
@@ -8940,7 +9179,7 @@ function runPerModuleStrategy(cwd, config, fileEntries, inputTokenTotal) {
|
|
|
8940
9179
|
overviewLines.push('> Inject the relevant module file into your IDE context window.');
|
|
8941
9180
|
overviewLines.push('> For cross-module questions load both files.');
|
|
8942
9181
|
const overviewContent = overviewLines.join('\n') + '\n';
|
|
8943
|
-
const primaryTargets =
|
|
9182
|
+
const primaryTargets = config.outputs || ['copilot'];
|
|
8944
9183
|
writeOutputs(overviewContent, primaryTargets, cwd, config);
|
|
8945
9184
|
|
|
8946
9185
|
const overviewTokens = estimateTokens(overviewContent);
|
|
@@ -8959,7 +9198,7 @@ function runHotColdStrategy(cwd, config, fileEntries, recentFiles, inputTokenTot
|
|
|
8959
9198
|
const hotContent = hotEntries.length > 0
|
|
8960
9199
|
? formatOutput(hotEntries, cwd, false, config, null)
|
|
8961
9200
|
: '<!-- Generated by SigMap — no recently changed files -->\n';
|
|
8962
|
-
const primaryTargets =
|
|
9201
|
+
const primaryTargets = config.outputs || ['copilot'];
|
|
8963
9202
|
writeOutputs(hotContent, primaryTargets, cwd, config);
|
|
8964
9203
|
const hotTokens = estimateTokens(hotContent);
|
|
8965
9204
|
|
|
@@ -11093,6 +11332,7 @@ function main() {
|
|
|
11093
11332
|
// Priority: --output flag > --adapter flag > buildSigIndex probe order
|
|
11094
11333
|
// (customOutput from config is handled inside buildSigIndex itself)
|
|
11095
11334
|
let queryOpts;
|
|
11335
|
+
const adpIdx = args.indexOf('--adapter');
|
|
11096
11336
|
|
|
11097
11337
|
// 1. --output <file> pins to an explicit path
|
|
11098
11338
|
if (config.customOutput) {
|
|
@@ -11100,17 +11340,14 @@ function main() {
|
|
|
11100
11340
|
}
|
|
11101
11341
|
|
|
11102
11342
|
// 2. --adapter <name> pins to that adapter's output path (if --output not given)
|
|
11103
|
-
if (!queryOpts) {
|
|
11104
|
-
const
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
queryOpts = { contextPath: adapterMod.outputPath(cwd) };
|
|
11112
|
-
} catch (_) {}
|
|
11113
|
-
}
|
|
11343
|
+
if (!queryOpts && adpIdx >= 0) {
|
|
11344
|
+
const adapterName = (args[adpIdx + 1] || '').trim().toLowerCase();
|
|
11345
|
+
const VALID_ADAPTERS = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex'];
|
|
11346
|
+
if (VALID_ADAPTERS.includes(adapterName)) {
|
|
11347
|
+
try {
|
|
11348
|
+
const adapterMod = __require('./packages/adapters/' + adapterName);
|
|
11349
|
+
queryOpts = { contextPath: adapterMod.outputPath(cwd) };
|
|
11350
|
+
} catch (_) {}
|
|
11114
11351
|
}
|
|
11115
11352
|
}
|
|
11116
11353
|
|
package/package.json
CHANGED
|
@@ -11,14 +11,16 @@
|
|
|
11
11
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// Third-party adapters: 'willow' writes atoms to a Willow MCP knowledge store
|
|
15
|
+
// instead of a flat file (see willow.js for configuration).
|
|
16
|
+
const ADAPTER_NAMES = ['copilot', 'claude', 'cursor', 'windsurf', 'openai', 'gemini', 'codex', 'willow'];
|
|
15
17
|
|
|
16
18
|
// Lazy-load adapters so unused ones don't pay any require() cost
|
|
17
19
|
const _cache = {};
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Load and return an adapter module by name.
|
|
21
|
-
* @param {string} name - Adapter name (copilot|claude|cursor|windsurf|openai|gemini|codex)
|
|
23
|
+
* @param {string} name - Adapter name (copilot|claude|cursor|windsurf|openai|gemini|codex|willow)
|
|
22
24
|
* @returns {{ name: string, format: Function, outputPath: Function }|null}
|
|
23
25
|
*/
|
|
24
26
|
function getAdapter(name) {
|