@getmikk/ai-context 1.7.1 → 1.9.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 +59 -288
- package/package.json +3 -3
- package/src/claude-md-generator.ts +69 -73
- package/src/context-builder.ts +196 -22
- package/src/providers.ts +42 -1
- package/src/token-counter.ts +224 -0
- package/src/types.ts +15 -1
- package/tests/claude-md.test.ts +88 -8
- package/tests/context-builder.test.ts +159 -0
package/README.md
CHANGED
|
@@ -1,329 +1,100 @@
|
|
|
1
|
-
# @getmikk/ai-context
|
|
1
|
+
# @getmikk/ai-context
|
|
2
2
|
|
|
3
|
-
> Token-budgeted
|
|
3
|
+
> Token-budgeted AI context builder and claude.md / AGENTS.md generator.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@getmikk/ai-context)
|
|
6
6
|
[](../../LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Two things: a graph-traced context builder that packs the most relevant functions into a token budget for any given task, and a documentation generator that produces always-accurate `claude.md` and `AGENTS.md` files from the lock file.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
> Part of [Mikk](../../README.md) — the codebase nervous system for AI-assisted development.
|
|
10
|
+
> Part of [Mikk](../../README.md) — live architectural context for your AI agent.
|
|
13
11
|
|
|
14
12
|
---
|
|
15
13
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install @getmikk/ai-context
|
|
20
|
-
# or
|
|
21
|
-
bun add @getmikk/ai-context
|
|
22
|
-
```
|
|
14
|
+
## Context Builder
|
|
23
15
|
|
|
24
|
-
|
|
16
|
+
Given a task description, BFS-traces the dependency graph from matched seed functions and returns the most relevant context within a configurable token budget.
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
## Quick Start
|
|
29
|
-
|
|
30
|
-
### Context Queries
|
|
18
|
+
### Usage
|
|
31
19
|
|
|
32
20
|
```typescript
|
|
33
21
|
import { ContextBuilder, getProvider } from '@getmikk/ai-context'
|
|
34
|
-
import { ContractReader, LockReader } from '@getmikk/core'
|
|
35
|
-
|
|
36
|
-
const contract = await new ContractReader().read('./mikk.json')
|
|
37
|
-
const lock = await new LockReader().read('./mikk.lock.json')
|
|
38
22
|
|
|
39
23
|
const builder = new ContextBuilder(contract, lock)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
maxHops:
|
|
24
|
+
|
|
25
|
+
const ctx = builder.build({
|
|
26
|
+
task: 'Add rate limiting to all API routes',
|
|
27
|
+
maxHops: 4,
|
|
28
|
+
tokenBudget: 6000,
|
|
29
|
+
focusModules: ['api-gateway'],
|
|
44
30
|
includeCallGraph: true,
|
|
31
|
+
includeBodies: true,
|
|
32
|
+
projectRoot: '/path/to/project',
|
|
45
33
|
})
|
|
46
34
|
|
|
47
|
-
// Format for
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
//
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Claude.md / AGENTS.md Generation
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { ClaudeMdGenerator } from '@getmikk/ai-context'
|
|
57
|
-
|
|
58
|
-
const generator = new ClaudeMdGenerator(contract, lock, /* tokenBudget */ 4000)
|
|
59
|
-
const markdown = generator.generate()
|
|
35
|
+
// Format for your AI client
|
|
36
|
+
const formatter = getProvider('claude') // XML tags
|
|
37
|
+
// const formatter = getProvider('generic') // plain text
|
|
38
|
+
// const formatter = getProvider('compact') // minimal tokens
|
|
60
39
|
|
|
61
|
-
|
|
62
|
-
await writeFile('./claude.md', markdown)
|
|
63
|
-
await writeFile('./AGENTS.md', markdown)
|
|
40
|
+
const output = formatter.formatContext(ctx)
|
|
64
41
|
```
|
|
65
42
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
## How Context Building Works
|
|
69
|
-
|
|
70
|
-
The `ContextBuilder` uses a 6-step algorithm:
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
1. Resolve Seeds
|
|
74
|
-
└─ Parse task → extract keywords → match against lock file functions/modules
|
|
43
|
+
### How context is built
|
|
75
44
|
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
1. **Seed** — match task keywords against function names, module descriptions, and file paths
|
|
46
|
+
2. **Walk** — BFS from seed nodes, following call graph edges outward up to `maxHops` depth
|
|
47
|
+
3. **Score** — each function scored by: proximity to seed (depth penalty), keyword match bonus, entry-point bonus
|
|
48
|
+
4. **Budget** — greedy knapsack: highest-scoring functions added until token budget is consumed
|
|
49
|
+
5. **Format** — serialized with function bodies, params, return types, call graph, and file locations
|
|
78
50
|
|
|
79
|
-
|
|
80
|
-
└─ Each function gets a relevance score:
|
|
81
|
-
• Proximity score (closer to seed = higher)
|
|
82
|
-
• Keyword match score (task keywords in function name)
|
|
83
|
-
• Entry-point bonus (exported functions score higher)
|
|
84
|
-
|
|
85
|
-
4. Sort by Score
|
|
86
|
-
└─ Descending relevance
|
|
87
|
-
|
|
88
|
-
5. Fill Token Budget
|
|
89
|
-
└─ Greedily add functions until budget is exhausted
|
|
90
|
-
(each function's token cost ≈ line count × 4)
|
|
91
|
-
|
|
92
|
-
6. Group by Module
|
|
93
|
-
└─ Organize selected functions into module-level context
|
|
94
|
-
```
|
|
51
|
+
The result is surgical — agents get exactly the functions relevant to their task, not the entire codebase.
|
|
95
52
|
|
|
96
53
|
---
|
|
97
54
|
|
|
98
|
-
##
|
|
55
|
+
## claude.md / AGENTS.md Generator
|
|
99
56
|
|
|
100
|
-
|
|
57
|
+
Generates `claude.md` and `AGENTS.md` automatically during `mikk init` and `mikk analyze`. Every piece of content is derived from the AST-parsed lock file — never hand-authored, never stale.
|
|
101
58
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { ContextBuilder } from '@getmikk/ai-context'
|
|
106
|
-
|
|
107
|
-
const builder = new ContextBuilder(contract, lock)
|
|
108
|
-
const context = builder.build(query)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**`ContextQuery`:**
|
|
112
|
-
|
|
113
|
-
| Field | Type | Default | Description |
|
|
114
|
-
|-------|------|---------|-------------|
|
|
115
|
-
| `task` | `string` | — | Natural-language description of the task |
|
|
116
|
-
| `focusFiles` | `string[]` | `[]` | Specific files to prioritize |
|
|
117
|
-
| `focusModules` | `string[]` | `[]` | Specific modules to prioritize |
|
|
118
|
-
| `maxFunctions` | `number` | `50` | Maximum functions to include |
|
|
119
|
-
| `maxHops` | `number` | `3` | BFS depth limit from seed functions |
|
|
120
|
-
| `tokenBudget` | `number` | `8000` | Maximum estimated tokens |
|
|
121
|
-
| `includeCallGraph` | `boolean` | `true` | Include `calls[]` and `calledBy[]` per function |
|
|
122
|
-
|
|
123
|
-
**`AIContext` (returned):**
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
type AIContext = {
|
|
127
|
-
project: string // Project name from contract
|
|
128
|
-
modules: ContextModule[] // Relevant modules with their functions
|
|
129
|
-
constraints: string[] // Active architectural constraints
|
|
130
|
-
decisions: string[] // Relevant ADRs
|
|
131
|
-
prompt: string // Original task
|
|
132
|
-
meta: {
|
|
133
|
-
seedCount: number // How many seed functions were found
|
|
134
|
-
totalFunctionsConsidered: number
|
|
135
|
-
selectedFunctions: number // Functions that fit in the budget
|
|
136
|
-
estimatedTokens: number // Approximate token count
|
|
137
|
-
keywords: string[] // Extracted keywords from the task
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**`ContextModule`:**
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
type ContextModule = {
|
|
146
|
-
id: string
|
|
147
|
-
name: string
|
|
148
|
-
description?: string
|
|
149
|
-
intent?: string // Module's purpose from mikk.json
|
|
150
|
-
functions: ContextFunction[]
|
|
151
|
-
files: string[]
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
**`ContextFunction`:**
|
|
156
|
-
|
|
157
|
-
```typescript
|
|
158
|
-
type ContextFunction = {
|
|
159
|
-
name: string
|
|
160
|
-
file: string
|
|
161
|
-
startLine: number
|
|
162
|
-
endLine: number
|
|
163
|
-
calls: string[] // Functions this one calls
|
|
164
|
-
calledBy: string[] // Functions that call this one
|
|
165
|
-
purpose?: string // Inferred purpose
|
|
166
|
-
errorHandling?: string // Error patterns detected
|
|
167
|
-
edgeCases?: string // Edge cases noted
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
### ClaudeMdGenerator
|
|
174
|
-
|
|
175
|
-
Generates tiered markdown documentation files for AI agents.
|
|
59
|
+
### Usage
|
|
176
60
|
|
|
177
61
|
```typescript
|
|
178
62
|
import { ClaudeMdGenerator } from '@getmikk/ai-context'
|
|
179
63
|
|
|
180
|
-
const generator = new ClaudeMdGenerator(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
**All data is sourced from the AST-derived lock file** — no hallucinated descriptions. Module intents come from `mikk.json`, function lists and call graphs come from `mikk.lock.json`.
|
|
64
|
+
const generator = new ClaudeMdGenerator(
|
|
65
|
+
contract,
|
|
66
|
+
lock,
|
|
67
|
+
12000, // token budget
|
|
68
|
+
{ // from package.json
|
|
69
|
+
description: 'Multi-channel AI gateway',
|
|
70
|
+
scripts: { build: 'bun run build', test: 'vitest' },
|
|
71
|
+
dependencies: { ... },
|
|
72
|
+
},
|
|
73
|
+
projectRoot
|
|
74
|
+
)
|
|
193
75
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
```markdown
|
|
197
|
-
# Project: my-app
|
|
198
|
-
|
|
199
|
-
## Architecture Overview
|
|
200
|
-
- **Modules:** 5
|
|
201
|
-
- **Total Functions:** 87
|
|
202
|
-
- **Total Files:** 23
|
|
203
|
-
|
|
204
|
-
## Modules
|
|
205
|
-
|
|
206
|
-
### auth
|
|
207
|
-
**Intent:** Handle user authentication and session management
|
|
208
|
-
**Public API:** `login`, `logout`, `validateToken`, `refreshSession`
|
|
209
|
-
**Files:** auth/login.ts, auth/session.ts, auth/middleware.ts
|
|
210
|
-
**Key Functions:**
|
|
211
|
-
- `validateToken` (auth/middleware.ts:15-42) → calls: `decodeJWT`, `checkExpiry`
|
|
212
|
-
- `login` (auth/login.ts:8-35) → calls: `validateCredentials`, `createSession`
|
|
213
|
-
|
|
214
|
-
### payments
|
|
215
|
-
...
|
|
216
|
-
|
|
217
|
-
## Constraints
|
|
218
|
-
- auth: no-import from payments
|
|
219
|
-
- payments: must-use stripe-sdk
|
|
220
|
-
|
|
221
|
-
## Decisions
|
|
222
|
-
- ADR-001: Use JWT for stateless auth (2024-01-15)
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
### Providers
|
|
228
|
-
|
|
229
|
-
Providers format the `AIContext` object into a string optimized for a specific AI model.
|
|
230
|
-
|
|
231
|
-
```typescript
|
|
232
|
-
import { getProvider, ClaudeProvider, GenericProvider } from '@getmikk/ai-context'
|
|
233
|
-
|
|
234
|
-
// Factory
|
|
235
|
-
const provider = getProvider('claude') // or 'generic'
|
|
236
|
-
|
|
237
|
-
// Format context for the provider
|
|
238
|
-
const formatted = provider.formatContext(context)
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
#### ClaudeProvider
|
|
242
|
-
|
|
243
|
-
Formats with structured XML tags optimized for Anthropic Claude:
|
|
244
|
-
|
|
245
|
-
```xml
|
|
246
|
-
<architecture>
|
|
247
|
-
<module name="auth" intent="Handle authentication">
|
|
248
|
-
<function name="validateToken" file="auth/middleware.ts" lines="15-42">
|
|
249
|
-
<calls>decodeJWT, checkExpiry</calls>
|
|
250
|
-
<calledBy>authMiddleware</calledBy>
|
|
251
|
-
</function>
|
|
252
|
-
</module>
|
|
253
|
-
</architecture>
|
|
254
|
-
<constraints>
|
|
255
|
-
auth: no-import from payments
|
|
256
|
-
</constraints>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
#### GenericProvider
|
|
260
|
-
|
|
261
|
-
Clean plain-text format for any AI model:
|
|
262
|
-
|
|
263
|
-
```
|
|
264
|
-
## Module: auth
|
|
265
|
-
Intent: Handle authentication
|
|
266
|
-
|
|
267
|
-
### validateToken (auth/middleware.ts:15-42)
|
|
268
|
-
Calls: decodeJWT, checkExpiry
|
|
269
|
-
Called by: authMiddleware
|
|
76
|
+
const content = generator.generate()
|
|
77
|
+
// Write to claude.md and AGENTS.md
|
|
270
78
|
```
|
|
271
79
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
## Usage Examples
|
|
275
|
-
|
|
276
|
-
### "What breaks if I change this file?"
|
|
80
|
+
### Tiered output
|
|
277
81
|
|
|
278
|
-
|
|
279
|
-
const context = builder.build({
|
|
280
|
-
task: `Impact analysis for changes to src/auth/login.ts`,
|
|
281
|
-
focusFiles: ['src/auth/login.ts'],
|
|
282
|
-
maxHops: 5,
|
|
283
|
-
tokenBudget: 4000,
|
|
284
|
-
})
|
|
285
|
-
// Returns all functions transitively affected by login.ts
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### "Get context for adding a feature"
|
|
289
|
-
|
|
290
|
-
```typescript
|
|
291
|
-
const context = builder.build({
|
|
292
|
-
task: 'Add two-factor authentication to the login flow',
|
|
293
|
-
focusModules: ['auth'],
|
|
294
|
-
tokenBudget: 12000,
|
|
295
|
-
includeCallGraph: true,
|
|
296
|
-
})
|
|
297
|
-
// Returns auth module functions + related cross-module calls
|
|
298
|
-
```
|
|
82
|
+
Content is generated in priority order until the token budget (default 12,000) is consumed:
|
|
299
83
|
|
|
300
|
-
|
|
84
|
+
| Tier | Content | Always included? |
|
|
85
|
+
|------|---------|-----------------|
|
|
86
|
+
| 1 | Project summary — name, description, module list with function counts, stats, critical constraints | Yes |
|
|
87
|
+
| — | Tech stack — detected frameworks, runtime, build tool | If detectable |
|
|
88
|
+
| — | Build/test/run commands — from package.json scripts | If present |
|
|
89
|
+
| 2 | Per-module detail — exported API, key functions, internal call summary (~300 tokens/module) | Until budget |
|
|
90
|
+
| — | Context files — discovered schemas, configs, data models | If budget allows |
|
|
91
|
+
| — | Import graph — cross-file import relationships per module | If budget allows |
|
|
92
|
+
| — | HTTP routes — detected routes with method, path, handler | If budget allows |
|
|
93
|
+
| 3 | Constraints — all declared constraint rules | If budget allows |
|
|
94
|
+
| — | ADR decisions — architectural decisions with reasons | If budget allows |
|
|
301
95
|
|
|
302
|
-
|
|
303
|
-
const context = builder.build({
|
|
304
|
-
task: 'Refactor the payment processing pipeline',
|
|
305
|
-
focusModules: ['payments'],
|
|
306
|
-
maxFunctions: 30,
|
|
307
|
-
tokenBudget: 6000,
|
|
308
|
-
})
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
|
-
## Types
|
|
314
|
-
|
|
315
|
-
```typescript
|
|
316
|
-
import type {
|
|
317
|
-
AIContext,
|
|
318
|
-
ContextModule,
|
|
319
|
-
ContextFunction,
|
|
320
|
-
ContextQuery,
|
|
321
|
-
ContextProvider,
|
|
322
|
-
} from '@getmikk/ai-context'
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
---
|
|
96
|
+
Modules with zero functions are skipped entirely.
|
|
326
97
|
|
|
327
|
-
|
|
98
|
+
### Token estimation
|
|
328
99
|
|
|
329
|
-
|
|
100
|
+
Uses a ~4 chars/token approximation. The generator stops adding sections the moment adding the next section would exceed the budget, so the output always fits within the specified window.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getmikk/ai-context",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dev": "tsc --watch"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@getmikk/core": "^1.
|
|
25
|
-
"@getmikk/intent-engine": "^1.
|
|
24
|
+
"@getmikk/core": "^1.9.0",
|
|
25
|
+
"@getmikk/intent-engine": "^1.9.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"typescript": "^5.7.0",
|