@milo4jo/contextkit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -0
- package/dist/commands/index-cmd.d.ts +3 -0
- package/dist/commands/index-cmd.d.ts.map +1 -0
- package/dist/commands/index-cmd.js +111 -0
- package/dist/commands/index-cmd.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +56 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/select.d.ts +3 -0
- package/dist/commands/select.d.ts.map +1 -0
- package/dist/commands/select.js +64 -0
- package/dist/commands/select.js.map +1 -0
- package/dist/commands/source/add.d.ts +3 -0
- package/dist/commands/source/add.d.ts.map +1 -0
- package/dist/commands/source/add.js +87 -0
- package/dist/commands/source/add.js.map +1 -0
- package/dist/commands/source/index.d.ts +3 -0
- package/dist/commands/source/index.d.ts.map +1 -0
- package/dist/commands/source/index.js +14 -0
- package/dist/commands/source/index.js.map +1 -0
- package/dist/commands/source/list.d.ts +3 -0
- package/dist/commands/source/list.d.ts.map +1 -0
- package/dist/commands/source/list.js +46 -0
- package/dist/commands/source/list.js.map +1 -0
- package/dist/commands/source/remove.d.ts +3 -0
- package/dist/commands/source/remove.d.ts.map +1 -0
- package/dist/commands/source/remove.js +38 -0
- package/dist/commands/source/remove.js.map +1 -0
- package/dist/commands/source.d.ts +3 -0
- package/dist/commands/source.d.ts.map +1 -0
- package/dist/commands/source.js +153 -0
- package/dist/commands/source.js.map +1 -0
- package/dist/config/index.d.ts +38 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +100 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +21 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/db/index.d.ts +14 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +63 -0
- package/dist/db/index.js.map +1 -0
- package/dist/errors/index.d.ts +30 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +51 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/chunker.d.ts +44 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +102 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/discovery.d.ts +34 -0
- package/dist/indexer/discovery.d.ts.map +1 -0
- package/dist/indexer/discovery.js +66 -0
- package/dist/indexer/discovery.js.map +1 -0
- package/dist/indexer/embeddings.d.ts +32 -0
- package/dist/indexer/embeddings.d.ts.map +1 -0
- package/dist/indexer/embeddings.js +85 -0
- package/dist/indexer/embeddings.js.map +1 -0
- package/dist/indexer/index.d.ts +37 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +123 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/selector/budget.d.ts +26 -0
- package/dist/selector/budget.d.ts.map +1 -0
- package/dist/selector/budget.js +75 -0
- package/dist/selector/budget.js.map +1 -0
- package/dist/selector/formatter.d.ts +44 -0
- package/dist/selector/formatter.d.ts.map +1 -0
- package/dist/selector/formatter.js +114 -0
- package/dist/selector/formatter.js.map +1 -0
- package/dist/selector/index.d.ts +37 -0
- package/dist/selector/index.d.ts.map +1 -0
- package/dist/selector/index.js +67 -0
- package/dist/selector/index.js.map +1 -0
- package/dist/selector/scoring.d.ts +26 -0
- package/dist/selector/scoring.d.ts.map +1 -0
- package/dist/selector/scoring.js +113 -0
- package/dist/selector/scoring.js.map +1 -0
- package/dist/selector/search.d.ts +29 -0
- package/dist/selector/search.d.ts.map +1 -0
- package/dist/selector/search.js +48 -0
- package/dist/selector/search.js.map +1 -0
- package/dist/utils/cli.d.ts +20 -0
- package/dist/utils/cli.d.ts.map +1 -0
- package/dist/utils/cli.js +19 -0
- package/dist/utils/cli.js.map +1 -0
- package/dist/utils/format.d.ts +30 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +44 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/output.d.ts +42 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +62 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/prompts.d.ts +23 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +46 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/streams.d.ts +40 -0
- package/dist/utils/streams.d.ts.map +1 -0
- package/dist/utils/streams.js +61 -0
- package/dist/utils/streams.js.map +1 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# ContextKit 🎯
|
|
2
|
+
|
|
3
|
+
> Smart context selection for AI coding assistants
|
|
4
|
+
|
|
5
|
+
ContextKit indexes your codebase and selects the most relevant chunks for any query — fitting them into your token budget.
|
|
6
|
+
|
|
7
|
+
## Why?
|
|
8
|
+
|
|
9
|
+
AI coding assistants work better with relevant context. But dumping your entire codebase into the prompt wastes tokens and dilutes focus.
|
|
10
|
+
|
|
11
|
+
ContextKit solves this:
|
|
12
|
+
1. **Index** your code locally (embeddings stay on your machine)
|
|
13
|
+
2. **Query** with natural language
|
|
14
|
+
3. **Get** the most relevant chunks, formatted and ready to paste
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g contextkit
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Initialize in your project
|
|
26
|
+
cd your-project
|
|
27
|
+
contextkit init
|
|
28
|
+
|
|
29
|
+
# Add source directories
|
|
30
|
+
contextkit source add ./src
|
|
31
|
+
contextkit source add ./lib
|
|
32
|
+
|
|
33
|
+
# Index everything
|
|
34
|
+
contextkit index
|
|
35
|
+
|
|
36
|
+
# Find relevant context
|
|
37
|
+
contextkit select "How does authentication work?"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
### `contextkit init`
|
|
43
|
+
|
|
44
|
+
Initialize ContextKit in your project. Creates `.contextkit/` directory with config and database.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
contextkit init
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `contextkit source`
|
|
51
|
+
|
|
52
|
+
Manage source directories to index.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Add a source
|
|
56
|
+
contextkit source add ./src
|
|
57
|
+
|
|
58
|
+
# List sources
|
|
59
|
+
contextkit source list
|
|
60
|
+
|
|
61
|
+
# Remove a source
|
|
62
|
+
contextkit source remove src
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### `contextkit index`
|
|
66
|
+
|
|
67
|
+
Index all configured sources. Re-run after code changes.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Index everything
|
|
71
|
+
contextkit index
|
|
72
|
+
|
|
73
|
+
# Index specific source
|
|
74
|
+
contextkit index --source src
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `contextkit select`
|
|
78
|
+
|
|
79
|
+
Find relevant context for a query.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Basic usage
|
|
83
|
+
contextkit select "How does the auth middleware work?"
|
|
84
|
+
|
|
85
|
+
# Limit token budget (default: 8000)
|
|
86
|
+
contextkit select "error handling" --budget 4000
|
|
87
|
+
|
|
88
|
+
# Filter to specific sources
|
|
89
|
+
contextkit select "database queries" --sources src,lib
|
|
90
|
+
|
|
91
|
+
# Show scoring details
|
|
92
|
+
contextkit select "user validation" --explain
|
|
93
|
+
|
|
94
|
+
# JSON output for scripts
|
|
95
|
+
contextkit select "API routes" --json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Output Format
|
|
99
|
+
|
|
100
|
+
```markdown
|
|
101
|
+
## src/auth/middleware.ts (lines 1-45)
|
|
102
|
+
```typescript
|
|
103
|
+
export const authMiddleware = async (req, res, next) => {
|
|
104
|
+
// ... relevant code
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## src/auth/utils.ts (lines 12-30)
|
|
109
|
+
```typescript
|
|
110
|
+
export function validateToken(token: string) {
|
|
111
|
+
// ... relevant code
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
📊 3,847 tokens | 8 chunks | 2 files
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## How It Works
|
|
120
|
+
|
|
121
|
+
1. **Chunking**: Files are split into ~500 token chunks with overlap
|
|
122
|
+
2. **Embedding**: Each chunk is embedded using [gte-small](https://huggingface.co/thenlper/gte-small) (runs locally)
|
|
123
|
+
3. **Search**: Your query is embedded and compared via cosine similarity
|
|
124
|
+
4. **Scoring**: Chunks are ranked by similarity + path relevance
|
|
125
|
+
5. **Budget**: Top chunks are selected until token budget is filled
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
Edit `.contextkit/config.yaml`:
|
|
130
|
+
|
|
131
|
+
```yaml
|
|
132
|
+
version: 1
|
|
133
|
+
|
|
134
|
+
sources:
|
|
135
|
+
- id: src
|
|
136
|
+
path: ./src
|
|
137
|
+
patterns:
|
|
138
|
+
include:
|
|
139
|
+
- "**/*.ts"
|
|
140
|
+
- "**/*.js"
|
|
141
|
+
exclude:
|
|
142
|
+
- "**/node_modules/**"
|
|
143
|
+
- "**/*.test.ts"
|
|
144
|
+
|
|
145
|
+
settings:
|
|
146
|
+
chunk_size: 500 # Target tokens per chunk
|
|
147
|
+
chunk_overlap: 50 # Overlap between chunks
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Global Options
|
|
151
|
+
|
|
152
|
+
All commands support:
|
|
153
|
+
|
|
154
|
+
| Option | Description |
|
|
155
|
+
|--------|-------------|
|
|
156
|
+
| `--json` | Output as JSON |
|
|
157
|
+
| `--plain` | No colors (or set `NO_COLOR=1`) |
|
|
158
|
+
| `--quiet` | Suppress non-essential output |
|
|
159
|
+
|
|
160
|
+
## Privacy
|
|
161
|
+
|
|
162
|
+
- All processing happens locally
|
|
163
|
+
- Embeddings are stored in `.contextkit/index.db`
|
|
164
|
+
- No data leaves your machine
|
|
165
|
+
- Add `.contextkit` to `.gitignore` (done automatically)
|
|
166
|
+
|
|
167
|
+
## Requirements
|
|
168
|
+
|
|
169
|
+
- Node.js 18+
|
|
170
|
+
- ~500MB disk space for embedding model (downloaded on first run)
|
|
171
|
+
|
|
172
|
+
## Coming Soon
|
|
173
|
+
|
|
174
|
+
- MCP server for Claude Desktop
|
|
175
|
+
- Agent skill for OpenCode/Clawdbot
|
|
176
|
+
- Configurable embedding models
|
|
177
|
+
- Incremental indexing
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/index-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,YAAY,SAiIrB,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import cliProgress from 'cli-progress';
|
|
3
|
+
import { loadConfig, ensureInitialized } from '../config/index.js';
|
|
4
|
+
import { openDatabase } from '../db/index.js';
|
|
5
|
+
import { indexSources } from '../indexer/index.js';
|
|
6
|
+
import { writeData, writeMessage, writeSuccess, writeWarning, isTTY } from '../utils/streams.js';
|
|
7
|
+
import { formatCommand, formatDim, formatHighlight } from '../utils/format.js';
|
|
8
|
+
import { getGlobalOpts } from '../utils/cli.js';
|
|
9
|
+
import { SourceNotFoundError } from '../errors/index.js';
|
|
10
|
+
export const indexCommand = new Command('index')
|
|
11
|
+
.description('Index all sources')
|
|
12
|
+
.option('-s, --source <name>', 'Index only a specific source')
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
ensureInitialized();
|
|
15
|
+
const config = loadConfig();
|
|
16
|
+
const opts = getGlobalOpts(indexCommand);
|
|
17
|
+
if (config.sources.length === 0) {
|
|
18
|
+
writeWarning('No sources configured');
|
|
19
|
+
writeMessage(`Add sources first with ${formatCommand('contextkit source add <path>')}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
// Filter sources if --source specified
|
|
23
|
+
let sourcesToIndex = config.sources;
|
|
24
|
+
if (options.source) {
|
|
25
|
+
const source = config.sources.find((s) => s.id === options.source);
|
|
26
|
+
if (!source) {
|
|
27
|
+
throw new SourceNotFoundError(options.source);
|
|
28
|
+
}
|
|
29
|
+
sourcesToIndex = [source];
|
|
30
|
+
}
|
|
31
|
+
// Open database
|
|
32
|
+
const db = openDatabase();
|
|
33
|
+
try {
|
|
34
|
+
if (!opts.quiet) {
|
|
35
|
+
writeMessage('');
|
|
36
|
+
writeMessage('Indexing sources...');
|
|
37
|
+
writeMessage('');
|
|
38
|
+
}
|
|
39
|
+
// Setup progress bar (only in TTY mode)
|
|
40
|
+
let progressBar = null;
|
|
41
|
+
let currentSource = '';
|
|
42
|
+
let currentPhase = '';
|
|
43
|
+
if (isTTY() && !opts.quiet) {
|
|
44
|
+
progressBar = new cliProgress.SingleBar({
|
|
45
|
+
format: `{phase} ${formatHighlight('[{source}]')} {bar} {value}/{total}`,
|
|
46
|
+
barCompleteChar: '█',
|
|
47
|
+
barIncompleteChar: '░',
|
|
48
|
+
hideCursor: true,
|
|
49
|
+
}, cliProgress.Presets.shades_classic);
|
|
50
|
+
}
|
|
51
|
+
// Progress callback
|
|
52
|
+
const onProgress = (progress) => {
|
|
53
|
+
const phaseLabel = {
|
|
54
|
+
discovery: 'Reading files ',
|
|
55
|
+
chunking: 'Chunking ',
|
|
56
|
+
embedding: 'Embedding ',
|
|
57
|
+
storing: 'Storing ',
|
|
58
|
+
}[progress.phase];
|
|
59
|
+
if (progressBar) {
|
|
60
|
+
if (currentSource !== progress.sourceId || currentPhase !== progress.phase) {
|
|
61
|
+
if (currentSource) {
|
|
62
|
+
progressBar.stop();
|
|
63
|
+
}
|
|
64
|
+
currentSource = progress.sourceId;
|
|
65
|
+
currentPhase = progress.phase;
|
|
66
|
+
progressBar.start(progress.total || 1, 0, {
|
|
67
|
+
phase: phaseLabel,
|
|
68
|
+
source: progress.sourceId,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
progressBar.update(progress.current);
|
|
72
|
+
}
|
|
73
|
+
else if (!opts.quiet) {
|
|
74
|
+
// Non-TTY: simple line output
|
|
75
|
+
if (progress.current === progress.total) {
|
|
76
|
+
writeMessage(`${phaseLabel} [${progress.sourceId}]: ${progress.current}/${progress.total}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
// Run indexing
|
|
81
|
+
const stats = await indexSources(sourcesToIndex, process.cwd(), db, {
|
|
82
|
+
chunkSize: config.settings.chunk_size,
|
|
83
|
+
chunkOverlap: config.settings.chunk_overlap,
|
|
84
|
+
}, onProgress);
|
|
85
|
+
// Stop progress bar
|
|
86
|
+
if (progressBar) {
|
|
87
|
+
progressBar.stop();
|
|
88
|
+
}
|
|
89
|
+
// Output results
|
|
90
|
+
if (!opts.quiet) {
|
|
91
|
+
writeMessage('');
|
|
92
|
+
const timeStr = (stats.timeMs / 1000).toFixed(1);
|
|
93
|
+
writeSuccess(`Indexed ${stats.chunks} chunks from ${stats.files} files in ${timeStr}s`);
|
|
94
|
+
if (stats.skipped > 0) {
|
|
95
|
+
writeMessage(formatDim(` (${stats.skipped} files skipped - too large or binary)`));
|
|
96
|
+
}
|
|
97
|
+
writeMessage('');
|
|
98
|
+
}
|
|
99
|
+
// JSON output
|
|
100
|
+
if (opts.json) {
|
|
101
|
+
writeData(JSON.stringify({
|
|
102
|
+
status: 'success',
|
|
103
|
+
stats,
|
|
104
|
+
}, null, 2));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
db.close();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=index-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cmd.js","sourceRoot":"","sources":["../../src/commands/index-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,eAAO,MAAM,WAAW,SAoDpB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync, appendFileSync, readFileSync, rmSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { getDefaultConfig, CONFIG_FILE, INDEX_DB } from '../config/index.js';
|
|
5
|
+
import { initDatabase } from '../db/index.js';
|
|
6
|
+
import { writeSuccess, writeMessage } from '../utils/streams.js';
|
|
7
|
+
import { formatPath, formatCommand, formatBold } from '../utils/format.js';
|
|
8
|
+
import { AlreadyInitializedError } from '../errors/index.js';
|
|
9
|
+
export const initCommand = new Command('init')
|
|
10
|
+
.description('Initialize ContextKit in current directory')
|
|
11
|
+
.option('-f, --force', 'Reinitialize (deletes existing index)')
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const contextKitDir = join(cwd, '.contextkit');
|
|
15
|
+
const configPath = join(contextKitDir, CONFIG_FILE);
|
|
16
|
+
const dbPath = join(contextKitDir, INDEX_DB);
|
|
17
|
+
const gitignorePath = join(cwd, '.gitignore');
|
|
18
|
+
// Check if already initialized
|
|
19
|
+
if (existsSync(contextKitDir) && !options.force) {
|
|
20
|
+
throw new AlreadyInitializedError();
|
|
21
|
+
}
|
|
22
|
+
// Clean existing if --force
|
|
23
|
+
if (existsSync(contextKitDir) && options.force) {
|
|
24
|
+
rmSync(contextKitDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
// Create directory
|
|
27
|
+
mkdirSync(contextKitDir, { recursive: true });
|
|
28
|
+
// Create config file
|
|
29
|
+
const config = getDefaultConfig();
|
|
30
|
+
writeFileSync(configPath, config);
|
|
31
|
+
writeSuccess(`Created ${formatPath('.contextkit/config.yaml')}`);
|
|
32
|
+
// Initialize database
|
|
33
|
+
initDatabase(dbPath);
|
|
34
|
+
writeSuccess(`Created ${formatPath('.contextkit/index.db')}`);
|
|
35
|
+
// Add to .gitignore
|
|
36
|
+
const gitignoreEntry = '\n# ContextKit\n.contextkit/index.db\n';
|
|
37
|
+
if (existsSync(gitignorePath)) {
|
|
38
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
39
|
+
if (!content.includes('.contextkit')) {
|
|
40
|
+
appendFileSync(gitignorePath, gitignoreEntry);
|
|
41
|
+
writeSuccess(`Added ${formatPath('.contextkit')} to .gitignore`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
writeFileSync(gitignorePath, gitignoreEntry.trim() + '\n');
|
|
46
|
+
writeSuccess(`Created .gitignore with ${formatPath('.contextkit')}`);
|
|
47
|
+
}
|
|
48
|
+
// Next steps
|
|
49
|
+
writeMessage('');
|
|
50
|
+
writeMessage(formatBold('Next steps:'));
|
|
51
|
+
writeMessage(` 1. Add sources: ${formatCommand('contextkit source add ./src')}`);
|
|
52
|
+
writeMessage(` 2. Index: ${formatCommand('contextkit index')}`);
|
|
53
|
+
writeMessage(` 3. Select context: ${formatCommand('contextkit select "your query"')}`);
|
|
54
|
+
writeMessage('');
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/commands/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,eAAO,MAAM,aAAa,SA4DtB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { ensureInitialized } from '../config/index.js';
|
|
3
|
+
import { openDatabase } from '../db/index.js';
|
|
4
|
+
import { selectContext } from '../selector/index.js';
|
|
5
|
+
import { writeData, writeMessage, writeWarning } from '../utils/streams.js';
|
|
6
|
+
import { formatCommand, formatDim } from '../utils/format.js';
|
|
7
|
+
import { getGlobalOpts } from '../utils/cli.js';
|
|
8
|
+
import { InvalidUsageError } from '../errors/index.js';
|
|
9
|
+
export const selectCommand = new Command('select')
|
|
10
|
+
.description('Select context for a query')
|
|
11
|
+
.argument('<query>', 'The query to find context for')
|
|
12
|
+
.option('-b, --budget <tokens>', 'Maximum tokens to include', '8000')
|
|
13
|
+
.option('-f, --format <format>', 'Output format: text, json', 'text')
|
|
14
|
+
.option('-s, --sources <sources>', 'Filter sources (comma-separated)')
|
|
15
|
+
.option('--explain', 'Show scoring details')
|
|
16
|
+
.action(async (query, options) => {
|
|
17
|
+
ensureInitialized();
|
|
18
|
+
const opts = getGlobalOpts(selectCommand);
|
|
19
|
+
const budget = parseInt(options.budget, 10);
|
|
20
|
+
if (isNaN(budget) || budget <= 0) {
|
|
21
|
+
throw new InvalidUsageError('Budget must be a positive number.');
|
|
22
|
+
}
|
|
23
|
+
// Parse sources filter
|
|
24
|
+
const sources = options.sources
|
|
25
|
+
? options.sources.split(',').map((s) => s.trim())
|
|
26
|
+
: undefined;
|
|
27
|
+
// Open database
|
|
28
|
+
const db = openDatabase();
|
|
29
|
+
try {
|
|
30
|
+
// Run selection
|
|
31
|
+
const result = await selectContext(db, {
|
|
32
|
+
query,
|
|
33
|
+
budget,
|
|
34
|
+
sources,
|
|
35
|
+
explain: options.explain,
|
|
36
|
+
});
|
|
37
|
+
// Handle empty index
|
|
38
|
+
if (result.isEmpty) {
|
|
39
|
+
writeWarning('No indexed content found');
|
|
40
|
+
writeMessage(`Run ${formatCommand('contextkit index')} first.`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Handle no results
|
|
44
|
+
if (result.output.data.chunks.length === 0) {
|
|
45
|
+
writeMessage('');
|
|
46
|
+
writeMessage(formatDim('No relevant context found for this query.'));
|
|
47
|
+
writeMessage(formatDim('Try a different query or add more sources.'));
|
|
48
|
+
writeMessage('');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Output based on format
|
|
52
|
+
if (options.format === 'json' || opts.json) {
|
|
53
|
+
writeData(JSON.stringify(result.output.data, null, 2));
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Text output goes to stdout (it's the data)
|
|
57
|
+
writeData(result.output.text);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
db.close();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/commands/select.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/commands/source/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,eAAO,MAAM,UAAU,SA2DnB,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { existsSync, statSync } from 'fs';
|
|
3
|
+
import { resolve, relative, basename } from 'path';
|
|
4
|
+
import fg from 'fast-glob';
|
|
5
|
+
import { loadConfig, saveConfig, ensureInitialized } from '../../config/index.js';
|
|
6
|
+
import { writeSuccess, writeMessage } from '../../utils/streams.js';
|
|
7
|
+
import { formatCommand, formatHighlight } from '../../utils/format.js';
|
|
8
|
+
import { PathNotFoundError, SourceExistsError, InvalidUsageError } from '../../errors/index.js';
|
|
9
|
+
/** Default file patterns to include */
|
|
10
|
+
const DEFAULT_INCLUDE = ['**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx', '**/*.md', '**/*.json'];
|
|
11
|
+
/** Default patterns to exclude */
|
|
12
|
+
const DEFAULT_EXCLUDE = ['**/node_modules/**', '**/dist/**', '**/.git/**'];
|
|
13
|
+
export const addCommand = new Command('add')
|
|
14
|
+
.description('Add a directory as a source')
|
|
15
|
+
.argument('<path>', 'Directory path to add')
|
|
16
|
+
.option('-n, --name <name>', 'Custom name for the source')
|
|
17
|
+
.option('-i, --include <patterns...>', 'Include patterns (glob)')
|
|
18
|
+
.option('-e, --exclude <patterns...>', 'Exclude patterns (glob)')
|
|
19
|
+
.action(async (path, options) => {
|
|
20
|
+
ensureInitialized();
|
|
21
|
+
const absolutePath = resolve(process.cwd(), path);
|
|
22
|
+
const relativePath = './' + relative(process.cwd(), absolutePath);
|
|
23
|
+
// Validate path exists
|
|
24
|
+
if (!existsSync(absolutePath)) {
|
|
25
|
+
const suggestion = findSimilarPath(path);
|
|
26
|
+
throw new PathNotFoundError(path, suggestion);
|
|
27
|
+
}
|
|
28
|
+
// Validate it's a directory
|
|
29
|
+
if (!statSync(absolutePath).isDirectory()) {
|
|
30
|
+
throw new InvalidUsageError(`'${path}' is a file, not a directory.`);
|
|
31
|
+
}
|
|
32
|
+
const config = loadConfig();
|
|
33
|
+
const sourceId = options.name || basename(absolutePath);
|
|
34
|
+
// Check for duplicates
|
|
35
|
+
const existing = config.sources.find((s) => s.id === sourceId);
|
|
36
|
+
if (existing) {
|
|
37
|
+
throw new SourceExistsError(sourceId, existing.path);
|
|
38
|
+
}
|
|
39
|
+
// Resolve patterns
|
|
40
|
+
const include = options.include || DEFAULT_INCLUDE;
|
|
41
|
+
const exclude = options.exclude || DEFAULT_EXCLUDE;
|
|
42
|
+
// Count matching files
|
|
43
|
+
const files = fg.sync(include, {
|
|
44
|
+
cwd: absolutePath,
|
|
45
|
+
ignore: exclude,
|
|
46
|
+
onlyFiles: true,
|
|
47
|
+
});
|
|
48
|
+
// Create and save source
|
|
49
|
+
const source = {
|
|
50
|
+
id: sourceId,
|
|
51
|
+
path: relativePath,
|
|
52
|
+
patterns: { include, exclude },
|
|
53
|
+
};
|
|
54
|
+
config.sources.push(source);
|
|
55
|
+
saveConfig(config);
|
|
56
|
+
// Output
|
|
57
|
+
writeSuccess(`Added source '${formatHighlight(sourceId)}'`);
|
|
58
|
+
writeMessage(` Path: ${relativePath}`);
|
|
59
|
+
writeMessage(` Files: ${files.length} (${summarizeExtensions(files)})`);
|
|
60
|
+
writeMessage('');
|
|
61
|
+
writeMessage(`Run ${formatCommand('contextkit index')} to index this source.`);
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Find a similar path to suggest
|
|
65
|
+
*/
|
|
66
|
+
function findSimilarPath(path) {
|
|
67
|
+
const parent = resolve(path, '..');
|
|
68
|
+
if (!existsSync(parent))
|
|
69
|
+
return undefined;
|
|
70
|
+
const entries = fg.sync(['*'], { cwd: parent, onlyDirectories: true });
|
|
71
|
+
const needle = basename(path).toLowerCase();
|
|
72
|
+
return entries.find((e) => e.toLowerCase().includes(needle));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Summarize file extensions for display
|
|
76
|
+
*/
|
|
77
|
+
function summarizeExtensions(files) {
|
|
78
|
+
const exts = new Set();
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
const ext = file.split('.').pop();
|
|
81
|
+
if (ext)
|
|
82
|
+
exts.add(ext);
|
|
83
|
+
}
|
|
84
|
+
const list = Array.from(exts).slice(0, 5).join(', ');
|
|
85
|
+
return exts.size > 5 ? `${list}...` : list;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../../src/commands/source/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SAQtB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { addCommand } from './add.js';
|
|
3
|
+
import { listCommand } from './list.js';
|
|
4
|
+
import { removeCommand } from './remove.js';
|
|
5
|
+
export const sourceCommand = new Command('source')
|
|
6
|
+
.description('Manage sources')
|
|
7
|
+
.addCommand(addCommand)
|
|
8
|
+
.addCommand(listCommand)
|
|
9
|
+
.addCommand(removeCommand)
|
|
10
|
+
.action(() => {
|
|
11
|
+
// Show help when no subcommand given
|
|
12
|
+
sourceCommand.help();
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,gBAAgB,CAAC;KAC7B,UAAU,CAAC,UAAU,CAAC;KACtB,UAAU,CAAC,WAAW,CAAC;KACvB,UAAU,CAAC,aAAa,CAAC;KACzB,MAAM,CAAC,GAAG,EAAE;IACX,qCAAqC;IACrC,aAAa,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/source/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,WAAW,SA6CtB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { loadConfig, ensureInitialized } from '../../config/index.js';
|
|
3
|
+
import { writeData, writeMessage } from '../../utils/streams.js';
|
|
4
|
+
import { formatCommand, formatBold, formatGray } from '../../utils/format.js';
|
|
5
|
+
import { getGlobalOpts } from '../../utils/cli.js';
|
|
6
|
+
export const listCommand = new Command('list').description('List configured sources').action(() => {
|
|
7
|
+
ensureInitialized();
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
const opts = getGlobalOpts(listCommand);
|
|
10
|
+
if (config.sources.length === 0) {
|
|
11
|
+
if (opts.json) {
|
|
12
|
+
writeData(JSON.stringify({ sources: [] }));
|
|
13
|
+
}
|
|
14
|
+
else if (!opts.quiet) {
|
|
15
|
+
writeMessage('No sources configured.');
|
|
16
|
+
writeMessage(`Add one with ${formatCommand('contextkit source add <path>')}`);
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
// JSON output
|
|
21
|
+
if (opts.json) {
|
|
22
|
+
writeData(JSON.stringify({ sources: config.sources }, null, 2));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Plain output (for piping)
|
|
26
|
+
if (opts.plain) {
|
|
27
|
+
for (const source of config.sources) {
|
|
28
|
+
writeData(`${source.id}\t${source.path}`);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Table output
|
|
33
|
+
if (!opts.quiet) {
|
|
34
|
+
writeMessage('');
|
|
35
|
+
writeMessage(formatBold('Sources:'));
|
|
36
|
+
writeMessage(` ${formatGray('NAME'.padEnd(15))} ${formatGray('PATH')}`);
|
|
37
|
+
}
|
|
38
|
+
for (const source of config.sources) {
|
|
39
|
+
writeMessage(` ${source.id.padEnd(15)} ${source.path}`);
|
|
40
|
+
}
|
|
41
|
+
if (!opts.quiet) {
|
|
42
|
+
writeMessage('');
|
|
43
|
+
writeMessage(`Total: ${config.sources.length} source${config.sources.length === 1 ? '' : 's'}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/source/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE;IAChG,iBAAiB,EAAE,CAAC;IAEpB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAExC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACvB,YAAY,CAAC,wBAAwB,CAAC,CAAC;YACvC,YAAY,CAAC,gBAAgB,aAAa,CAAC,8BAA8B,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,OAAO;IACT,CAAC;IAED,cAAc;IACd,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,4BAA4B;IAC5B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,SAAS,CAAC,GAAG,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO;IACT,CAAC;IAED,eAAe;IACf,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,YAAY,CAAC,EAAE,CAAC,CAAC;QACjB,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACrC,YAAY,CAAC,KAAK,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,YAAY,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,YAAY,CAAC,EAAE,CAAC,CAAC;QACjB,YAAY,CAAC,UAAU,MAAM,CAAC,OAAO,CAAC,MAAM,UAAU,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAClG,CAAC;AACH,CAAC,CAAC,CAAC"}
|