ai-first-cli 1.1.1 → 1.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.
- package/CHANGELOG.md +78 -0
- package/README.es.md +137 -1
- package/README.md +136 -4
- package/ai/ai_context.md +2 -2
- package/ai/architecture.md +3 -3
- package/ai/cache.json +85 -57
- package/ai/ccp/jira-123/context.json +7 -0
- package/ai/context/repo.json +56 -0
- package/ai/context/utils.json +7 -0
- package/ai/dependencies.json +51 -1026
- package/ai/files.json +195 -3
- package/ai/git/commit-activity.json +8646 -0
- package/ai/git/recent-features.json +1 -0
- package/ai/git/recent-files.json +52 -0
- package/ai/git/recent-flows.json +1 -0
- package/ai/graph/knowledge-graph.json +43643 -0
- package/ai/graph/module-graph.json +4 -0
- package/ai/graph/symbol-graph.json +3307 -879
- package/ai/graph/symbol-references.json +119 -32
- package/ai/index-state.json +843 -188
- package/ai/index.db +0 -0
- package/ai/modules.json +4 -0
- package/ai/repo-map.json +81 -17
- package/ai/repo_map.json +81 -17
- package/ai/repo_map.md +21 -7
- package/ai/summary.md +5 -5
- package/ai/symbols.json +1 -20287
- package/dist/analyzers/androidResources.d.ts +23 -0
- package/dist/analyzers/androidResources.d.ts.map +1 -0
- package/dist/analyzers/androidResources.js +93 -0
- package/dist/analyzers/androidResources.js.map +1 -0
- package/dist/analyzers/dependencies.d.ts.map +1 -1
- package/dist/analyzers/dependencies.js +37 -0
- package/dist/analyzers/dependencies.js.map +1 -1
- package/dist/analyzers/entrypoints.d.ts.map +1 -1
- package/dist/analyzers/entrypoints.js +71 -1
- package/dist/analyzers/entrypoints.js.map +1 -1
- package/dist/analyzers/gradleModules.d.ts +22 -0
- package/dist/analyzers/gradleModules.d.ts.map +1 -0
- package/dist/analyzers/gradleModules.js +75 -0
- package/dist/analyzers/gradleModules.js.map +1 -0
- package/dist/analyzers/techStack.d.ts +7 -0
- package/dist/analyzers/techStack.d.ts.map +1 -1
- package/dist/analyzers/techStack.js +44 -1
- package/dist/analyzers/techStack.js.map +1 -1
- package/dist/commands/ai-first.d.ts +1 -0
- package/dist/commands/ai-first.d.ts.map +1 -1
- package/dist/commands/ai-first.js +312 -1
- package/dist/commands/ai-first.js.map +1 -1
- package/dist/core/adapters/adapterRegistry.d.ts +39 -0
- package/dist/core/adapters/adapterRegistry.d.ts.map +1 -0
- package/dist/core/adapters/adapterRegistry.js +155 -0
- package/dist/core/adapters/adapterRegistry.js.map +1 -0
- package/dist/core/adapters/baseAdapter.d.ts +49 -0
- package/dist/core/adapters/baseAdapter.d.ts.map +1 -0
- package/dist/core/adapters/baseAdapter.js +28 -0
- package/dist/core/adapters/baseAdapter.js.map +1 -0
- package/dist/core/adapters/community/fastapiAdapter.d.ts +7 -0
- package/dist/core/adapters/community/fastapiAdapter.d.ts.map +1 -0
- package/dist/core/adapters/community/fastapiAdapter.js +40 -0
- package/dist/core/adapters/community/fastapiAdapter.js.map +1 -0
- package/dist/core/adapters/community/index.d.ts +11 -0
- package/dist/core/adapters/community/index.d.ts.map +1 -0
- package/dist/core/adapters/community/index.js +11 -0
- package/dist/core/adapters/community/index.js.map +1 -0
- package/dist/core/adapters/community/laravelAdapter.d.ts +7 -0
- package/dist/core/adapters/community/laravelAdapter.d.ts.map +1 -0
- package/dist/core/adapters/community/laravelAdapter.js +47 -0
- package/dist/core/adapters/community/laravelAdapter.js.map +1 -0
- package/dist/core/adapters/community/nestjsAdapter.d.ts +7 -0
- package/dist/core/adapters/community/nestjsAdapter.d.ts.map +1 -0
- package/dist/core/adapters/community/nestjsAdapter.js +48 -0
- package/dist/core/adapters/community/nestjsAdapter.js.map +1 -0
- package/dist/core/adapters/community/phoenixAdapter.d.ts +7 -0
- package/dist/core/adapters/community/phoenixAdapter.d.ts.map +1 -0
- package/dist/core/adapters/community/phoenixAdapter.js +45 -0
- package/dist/core/adapters/community/phoenixAdapter.js.map +1 -0
- package/dist/core/adapters/community/springBootAdapter.d.ts +7 -0
- package/dist/core/adapters/community/springBootAdapter.d.ts.map +1 -0
- package/dist/core/adapters/community/springBootAdapter.js +44 -0
- package/dist/core/adapters/community/springBootAdapter.js.map +1 -0
- package/dist/core/adapters/dotnetAdapter.d.ts +20 -0
- package/dist/core/adapters/dotnetAdapter.d.ts.map +1 -0
- package/dist/core/adapters/dotnetAdapter.js +86 -0
- package/dist/core/adapters/dotnetAdapter.js.map +1 -0
- package/dist/core/adapters/index.d.ts +18 -0
- package/dist/core/adapters/index.d.ts.map +1 -0
- package/dist/core/adapters/index.js +19 -0
- package/dist/core/adapters/index.js.map +1 -0
- package/dist/core/adapters/javascriptAdapter.d.ts +11 -0
- package/dist/core/adapters/javascriptAdapter.d.ts.map +1 -0
- package/dist/core/adapters/javascriptAdapter.js +47 -0
- package/dist/core/adapters/javascriptAdapter.js.map +1 -0
- package/dist/core/adapters/pythonAdapter.d.ts +20 -0
- package/dist/core/adapters/pythonAdapter.d.ts.map +1 -0
- package/dist/core/adapters/pythonAdapter.js +99 -0
- package/dist/core/adapters/pythonAdapter.js.map +1 -0
- package/dist/core/adapters/railsAdapter.d.ts +10 -0
- package/dist/core/adapters/railsAdapter.d.ts.map +1 -0
- package/dist/core/adapters/railsAdapter.js +52 -0
- package/dist/core/adapters/railsAdapter.js.map +1 -0
- package/dist/core/adapters/salesforceAdapter.d.ts +16 -0
- package/dist/core/adapters/salesforceAdapter.d.ts.map +1 -0
- package/dist/core/adapters/salesforceAdapter.js +64 -0
- package/dist/core/adapters/salesforceAdapter.js.map +1 -0
- package/dist/core/adapters/sdk.d.ts +83 -0
- package/dist/core/adapters/sdk.d.ts.map +1 -0
- package/dist/core/adapters/sdk.js +114 -0
- package/dist/core/adapters/sdk.js.map +1 -0
- package/dist/core/ccp.d.ts +37 -0
- package/dist/core/ccp.d.ts.map +1 -0
- package/dist/core/ccp.js +184 -0
- package/dist/core/ccp.js.map +1 -0
- package/dist/core/gitAnalyzer.d.ts +74 -0
- package/dist/core/gitAnalyzer.d.ts.map +1 -0
- package/dist/core/gitAnalyzer.js +298 -0
- package/dist/core/gitAnalyzer.js.map +1 -0
- package/dist/core/incrementalAnalyzer.d.ts +28 -0
- package/dist/core/incrementalAnalyzer.d.ts.map +1 -0
- package/dist/core/incrementalAnalyzer.js +343 -0
- package/dist/core/incrementalAnalyzer.js.map +1 -0
- package/dist/core/knowledgeGraphBuilder.d.ts +31 -0
- package/dist/core/knowledgeGraphBuilder.d.ts.map +1 -0
- package/dist/core/knowledgeGraphBuilder.js +197 -0
- package/dist/core/knowledgeGraphBuilder.js.map +1 -0
- package/dist/core/lazyAnalyzer.d.ts +57 -0
- package/dist/core/lazyAnalyzer.d.ts.map +1 -0
- package/dist/core/lazyAnalyzer.js +204 -0
- package/dist/core/lazyAnalyzer.js.map +1 -0
- package/dist/core/schema.d.ts +57 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +131 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/semanticContexts.d.ts +40 -0
- package/dist/core/semanticContexts.d.ts.map +1 -0
- package/dist/core/semanticContexts.js +454 -0
- package/dist/core/semanticContexts.js.map +1 -0
- package/docs/es/guide/adapters.md +143 -0
- package/docs/es/guide/ai-repository-schema.md +119 -0
- package/docs/es/guide/features.md +67 -0
- package/docs/es/guide/flows.md +134 -0
- package/docs/es/guide/git-intelligence.md +170 -0
- package/docs/es/guide/incremental-analysis.md +131 -0
- package/docs/es/guide/knowledge-graph.md +135 -0
- package/docs/es/guide/lazy-indexing.md +144 -0
- package/docs/es/guide/performance.md +125 -0
- package/docs/guide/adapters.md +225 -0
- package/docs/guide/ai-repository-schema.md +119 -0
- package/docs/guide/architecture.md +69 -1
- package/docs/guide/flows.md +134 -0
- package/docs/guide/git-intelligence.md +170 -0
- package/docs/guide/incremental-analysis.md +131 -0
- package/docs/guide/knowledge-graph.md +135 -0
- package/docs/guide/lazy-indexing.md +144 -0
- package/docs/guide/performance.md +125 -0
- package/package.json +5 -2
- package/src/analyzers/androidResources.ts +113 -0
- package/src/analyzers/dependencies.ts +41 -0
- package/src/analyzers/entrypoints.ts +80 -1
- package/src/analyzers/gradleModules.ts +100 -0
- package/src/analyzers/techStack.ts +56 -0
- package/src/commands/ai-first.ts +343 -1
- package/src/core/adapters/adapterRegistry.ts +187 -0
- package/src/core/adapters/baseAdapter.ts +82 -0
- package/src/core/adapters/community/fastapiAdapter.ts +50 -0
- package/src/core/adapters/community/index.ts +11 -0
- package/src/core/adapters/community/laravelAdapter.ts +56 -0
- package/src/core/adapters/community/nestjsAdapter.ts +57 -0
- package/src/core/adapters/community/phoenixAdapter.ts +54 -0
- package/src/core/adapters/community/springBootAdapter.ts +53 -0
- package/src/core/adapters/dotnetAdapter.ts +104 -0
- package/src/core/adapters/index.ts +24 -0
- package/src/core/adapters/javascriptAdapter.ts +56 -0
- package/src/core/adapters/pythonAdapter.ts +118 -0
- package/src/core/adapters/railsAdapter.ts +65 -0
- package/src/core/adapters/salesforceAdapter.ts +76 -0
- package/src/core/adapters/sdk.ts +172 -0
- package/src/core/ccp.ts +240 -0
- package/src/core/gitAnalyzer.ts +391 -0
- package/src/core/incrementalAnalyzer.ts +382 -0
- package/src/core/knowledgeGraphBuilder.ts +181 -0
- package/src/core/lazyAnalyzer.ts +261 -0
- package/src/core/schema.ts +157 -0
- package/src/core/semanticContexts.ts +575 -0
- package/tests/adapters.test.ts +159 -0
- package/tests/gitAnalyzer.test.ts +133 -0
- package/tests/incrementalAnalyzer.test.ts +83 -0
- package/tests/knowledgeGraph.test.ts +146 -0
- package/tests/lazyAnalyzer.test.ts +230 -0
- package/tests/schema.test.ts +203 -0
- package/tests/semanticContexts.test.ts +435 -0
- package/ai/context/analyzers.Symbol.json +0 -19
- package/ai/context/analyzers.extractSymbols.json +0 -19
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Incremental Analysis
|
|
2
|
+
|
|
3
|
+
AI-First supports incremental updates that refresh only changed files without requiring a full repository analysis. This enables self-healing context for AI agents.
|
|
4
|
+
|
|
5
|
+
## Why Incremental Updates?
|
|
6
|
+
|
|
7
|
+
Running `ai-first init` analyzes the entire repository, which can be slow for large codebases. Incremental updates:
|
|
8
|
+
|
|
9
|
+
- **Fast**: Only analyzes changed files
|
|
10
|
+
- **Efficient**: Updates only affected metadata
|
|
11
|
+
- **Continuous**: Keeps context fresh between analysis runs
|
|
12
|
+
|
|
13
|
+
## How It Works
|
|
14
|
+
|
|
15
|
+
1. **Detect Changes**: Uses `git diff` or filesystem timestamps
|
|
16
|
+
2. **Re-analyze**: Extracts symbols/dependencies from changed files
|
|
17
|
+
3. **Update Metadata**: Updates symbols, dependencies, features, flows
|
|
18
|
+
4. **Rebuild Graph**: Updates knowledge graph with changes
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### CLI Command
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Incremental update (uses git)
|
|
26
|
+
ai-first update
|
|
27
|
+
|
|
28
|
+
# Use filesystem timestamps instead of git
|
|
29
|
+
ai-first update --no-git
|
|
30
|
+
|
|
31
|
+
# Custom root directory
|
|
32
|
+
ai-first update --root /path/to/project
|
|
33
|
+
|
|
34
|
+
# JSON output
|
|
35
|
+
ai-first update --json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Programmatic Usage
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import {
|
|
42
|
+
runIncrementalUpdate,
|
|
43
|
+
detectChangedFiles,
|
|
44
|
+
updateSymbols,
|
|
45
|
+
updateFeatures,
|
|
46
|
+
updateFlows
|
|
47
|
+
} from 'ai-first';
|
|
48
|
+
|
|
49
|
+
// Full incremental update
|
|
50
|
+
const result = runIncrementalUpdate('/path/to/project');
|
|
51
|
+
|
|
52
|
+
console.log(result.changedFiles);
|
|
53
|
+
console.log(result.updatedSymbols);
|
|
54
|
+
console.log(result.updatedFeatures);
|
|
55
|
+
|
|
56
|
+
// Or use individual functions
|
|
57
|
+
const changes = detectChangedFiles('/path/to/project');
|
|
58
|
+
const updated = updateSymbols('/path/to/project', changes, aiDir);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Output
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
🔄 Running incremental update in: /path/to/project
|
|
65
|
+
|
|
66
|
+
📁 Changed files: 5
|
|
67
|
+
modified: src/auth/login.ts
|
|
68
|
+
modified: src/auth/userService.ts
|
|
69
|
+
added: src/payments/checkout.ts
|
|
70
|
+
deleted: src/old/legacy.ts
|
|
71
|
+
|
|
72
|
+
🔧 Updated:
|
|
73
|
+
Symbols: 12
|
|
74
|
+
Dependencies: 2
|
|
75
|
+
Features: auth
|
|
76
|
+
Flows: login
|
|
77
|
+
Knowledge Graph: ✅
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### runIncrementalUpdate(rootDir, aiDir?)
|
|
83
|
+
|
|
84
|
+
Performs full incremental update. Returns:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
{
|
|
88
|
+
changedFiles: ChangedFile[];
|
|
89
|
+
updatedSymbols: number;
|
|
90
|
+
updatedDependencies: number;
|
|
91
|
+
updatedFeatures: string[];
|
|
92
|
+
updatedFlows: string[];
|
|
93
|
+
graphUpdated: boolean;
|
|
94
|
+
errors: string[];
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### detectChangedFiles(rootDir, useGit?)
|
|
99
|
+
|
|
100
|
+
Detects changed files using git (default) or filesystem timestamps.
|
|
101
|
+
|
|
102
|
+
### updateSymbols(rootDir, changes, aiDir)
|
|
103
|
+
|
|
104
|
+
Re-extracts symbols from changed files and updates `ai/symbols.json`.
|
|
105
|
+
|
|
106
|
+
### updateDependencies(rootDir, changes, aiDir)
|
|
107
|
+
|
|
108
|
+
Re-extracts dependencies from changed package files.
|
|
109
|
+
|
|
110
|
+
### updateFeatures(rootDir, changes, aiDir)
|
|
111
|
+
|
|
112
|
+
Updates features that contain changed files.
|
|
113
|
+
|
|
114
|
+
### updateFlows(rootDir, changes, aiDir)
|
|
115
|
+
|
|
116
|
+
Updates flows that contain changed files.
|
|
117
|
+
|
|
118
|
+
### updateKnowledgeGraph(rootDir, aiDir)
|
|
119
|
+
|
|
120
|
+
Rebuilds the knowledge graph with current data.
|
|
121
|
+
|
|
122
|
+
## Self-Healing Context
|
|
123
|
+
|
|
124
|
+
Incremental updates enable self-healing context for AI agents:
|
|
125
|
+
|
|
126
|
+
1. Agent makes changes to codebase
|
|
127
|
+
2. Developer runs `ai-first update`
|
|
128
|
+
3. AI context is refreshed with new/changed files
|
|
129
|
+
4. Agent's next query uses updated context
|
|
130
|
+
|
|
131
|
+
This creates a feedback loop where the AI context stays fresh without manual full re-analysis.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Knowledge Graph
|
|
2
|
+
|
|
3
|
+
The Knowledge Graph unifies all repository intelligence into a single navigable graph that AI agents can use to understand codebase structure and relationships.
|
|
4
|
+
|
|
5
|
+
## Why a Knowledge Graph?
|
|
6
|
+
|
|
7
|
+
Traditional code analysis produces separate outputs (symbols, dependencies, features, flows, git activity). The Knowledge Graph connects everything:
|
|
8
|
+
|
|
9
|
+
- **Feature → Flow → File**: Understand what features exist and how they connect to code
|
|
10
|
+
- **File → Symbol → File**: Navigate code relationships
|
|
11
|
+
- **Commit → File**: See what was changed and by whom
|
|
12
|
+
|
|
13
|
+
## Graph Structure
|
|
14
|
+
|
|
15
|
+
### Nodes
|
|
16
|
+
|
|
17
|
+
| Type | Description | Example |
|
|
18
|
+
|------|-------------|---------|
|
|
19
|
+
| `feature` | Business feature | `auth`, `payments` |
|
|
20
|
+
| `flow` | Execution flow | `login`, `checkout` |
|
|
21
|
+
| `file` | Source file | `src/auth/login.ts` |
|
|
22
|
+
| `symbol` | Code symbol | `src/auth/login.ts#login` |
|
|
23
|
+
| `commit` | Git commit | `commit:src/auth/login.ts` |
|
|
24
|
+
|
|
25
|
+
### Edges
|
|
26
|
+
|
|
27
|
+
| Type | From | To | Description |
|
|
28
|
+
|------|------|-----|-------------|
|
|
29
|
+
| `contains` | feature | flow | Feature contains this flow |
|
|
30
|
+
| `implements` | flow | file | Flow implemented in file |
|
|
31
|
+
| `declares` | file | symbol | File declares symbol |
|
|
32
|
+
| `references` | symbol | file | Symbol references file |
|
|
33
|
+
| `modifies` | commit | file | Commit modified file |
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### CLI Command
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Generate knowledge graph
|
|
41
|
+
ai-first graph
|
|
42
|
+
|
|
43
|
+
# Show statistics
|
|
44
|
+
ai-first graph --stats
|
|
45
|
+
|
|
46
|
+
# Output as JSON
|
|
47
|
+
ai-first graph --json
|
|
48
|
+
|
|
49
|
+
# Custom root directory
|
|
50
|
+
ai-first graph --root /path/to/project
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Programmatic Usage
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import {
|
|
57
|
+
buildKnowledgeGraph,
|
|
58
|
+
loadKnowledgeGraph,
|
|
59
|
+
getNodesByType,
|
|
60
|
+
getEdgesByType,
|
|
61
|
+
getNeighbors
|
|
62
|
+
} from 'ai-first';
|
|
63
|
+
|
|
64
|
+
// Build graph
|
|
65
|
+
const graph = buildKnowledgeGraph('/path/to/project');
|
|
66
|
+
|
|
67
|
+
// Load existing graph
|
|
68
|
+
const graph = loadKnowledgeGraph('/path/to/ai');
|
|
69
|
+
|
|
70
|
+
// Query by type
|
|
71
|
+
const features = getNodesByType(graph, 'feature');
|
|
72
|
+
const flows = getNodesByType(graph, 'flow');
|
|
73
|
+
|
|
74
|
+
// Query by edge type
|
|
75
|
+
const modifications = getEdgesByType(graph, 'modifies');
|
|
76
|
+
|
|
77
|
+
// Navigate neighbors
|
|
78
|
+
const related = getNeighbors(graph, 'auth');
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Output
|
|
82
|
+
|
|
83
|
+
Generates `ai/graph/knowledge-graph.json`:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"nodes": [
|
|
88
|
+
{ "id": "auth", "type": "feature", "label": "auth" },
|
|
89
|
+
{ "id": "login", "type": "flow", "label": "login" },
|
|
90
|
+
{ "id": "src/auth/login.ts", "type": "file", "label": "login.ts" }
|
|
91
|
+
],
|
|
92
|
+
"edges": [
|
|
93
|
+
{ "from": "auth", "to": "login", "type": "contains" },
|
|
94
|
+
{ "from": "login", "to": "src/auth/login.ts", "type": "implements" }
|
|
95
|
+
],
|
|
96
|
+
"metadata": {
|
|
97
|
+
"generated": "2026-03-11T12:00:00.000Z",
|
|
98
|
+
"sources": ["features", "flows", "git", "symbols"],
|
|
99
|
+
"nodeCount": 150,
|
|
100
|
+
"edgeCount": 450
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Integration
|
|
106
|
+
|
|
107
|
+
The Knowledge Graph works with other AI-First outputs:
|
|
108
|
+
|
|
109
|
+
1. **Features** from `ai/context/features/`
|
|
110
|
+
2. **Flows** from `ai/context/flows/`
|
|
111
|
+
3. **Git activity** from `ai/git/`
|
|
112
|
+
4. **Symbols** from `ai/symbols.json`
|
|
113
|
+
5. **Dependencies** from `ai/dependencies.json`
|
|
114
|
+
|
|
115
|
+
## API Reference
|
|
116
|
+
|
|
117
|
+
### buildKnowledgeGraph(rootDir, aiDir?)
|
|
118
|
+
|
|
119
|
+
Builds and saves the knowledge graph.
|
|
120
|
+
|
|
121
|
+
### loadKnowledgeGraph(aiDir)
|
|
122
|
+
|
|
123
|
+
Loads an existing knowledge graph.
|
|
124
|
+
|
|
125
|
+
### getNodesByType(graph, type)
|
|
126
|
+
|
|
127
|
+
Filter nodes by type (feature, flow, file, symbol, commit).
|
|
128
|
+
|
|
129
|
+
### getEdgesByType(graph, type)
|
|
130
|
+
|
|
131
|
+
Filter edges by type (contains, implements, declares, references, modifies).
|
|
132
|
+
|
|
133
|
+
### getNeighbors(graph, nodeId)
|
|
134
|
+
|
|
135
|
+
Find all nodes connected to a given node.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Lazy Context Generation
|
|
2
|
+
|
|
3
|
+
Lazy context generation improves CLI startup time by generating repository context in stages, only analyzing what's needed when it's needed.
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
### Stage 1: Minimal Index (Fast Startup)
|
|
8
|
+
|
|
9
|
+
When you run `ai-first init`, only essential metadata is generated:
|
|
10
|
+
|
|
11
|
+
- **repo-map**: Directory structure
|
|
12
|
+
- **languages**: Detected programming languages
|
|
13
|
+
- **frameworks**: Detected frameworks
|
|
14
|
+
- **entrypoints**: Application entry points
|
|
15
|
+
|
|
16
|
+
This stage is optimized for **fast startup** - typically under 1 second for most repositories.
|
|
17
|
+
|
|
18
|
+
### Stage 2: Full Context (On Demand)
|
|
19
|
+
|
|
20
|
+
Additional context is generated only when requested:
|
|
21
|
+
|
|
22
|
+
- **symbols**: Functions, classes, interfaces
|
|
23
|
+
- **dependencies**: Import relationships
|
|
24
|
+
- **features**: Business feature modules
|
|
25
|
+
- **flows**: Execution chains
|
|
26
|
+
- **knowledge graph**: Full repository graph
|
|
27
|
+
|
|
28
|
+
Trigger conditions:
|
|
29
|
+
- When a specific feature is accessed
|
|
30
|
+
- When the plugin requests detailed context
|
|
31
|
+
- When a CCP (Context Control Pack) is generated
|
|
32
|
+
|
|
33
|
+
## Performance Benefits
|
|
34
|
+
|
|
35
|
+
| Repository Size | Full Index | Lazy Index (Stage 1) |
|
|
36
|
+
|----------------|------------|----------------------|
|
|
37
|
+
| Small (50 files) | ~0.5s | ~0.1s |
|
|
38
|
+
| Medium (200 files) | ~2s | ~0.3s |
|
|
39
|
+
| Large (1000 files) | ~10s | ~1s |
|
|
40
|
+
| Huge (5000 files) | ~30s | ~3s |
|
|
41
|
+
|
|
42
|
+
**Time saved**: 70-90% for initial CLI startup
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
### Default Behavior (Lazy)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ai-first init
|
|
50
|
+
# Generates minimal index only (~1s)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Full Index (When Needed)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Expand full context on demand
|
|
57
|
+
ai-first map
|
|
58
|
+
# or
|
|
59
|
+
ai-first context <symbol>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Check Index State
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
import { getLazyIndexState, hasMinimalIndex } from 'ai-first';
|
|
66
|
+
|
|
67
|
+
const aiDir = './ai';
|
|
68
|
+
console.log('Has minimal:', hasMinimalIndex(aiDir));
|
|
69
|
+
|
|
70
|
+
const state = getLazyIndexState(aiDir);
|
|
71
|
+
console.log('Stage 1:', state?.stage1Complete);
|
|
72
|
+
console.log('Stage 2:', state?.stage2Complete);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## API
|
|
76
|
+
|
|
77
|
+
### buildMinimalIndex(rootDir, aiDir)
|
|
78
|
+
|
|
79
|
+
Build Stage 1 minimal index:
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { buildMinimalIndex } from 'ai-first';
|
|
83
|
+
|
|
84
|
+
const minimal = buildMinimalIndex('/path/to/project', '/path/to/project/ai');
|
|
85
|
+
console.log(minimal.languages); // ['TypeScript', 'JavaScript']
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### expandFeatureContext(rootDir, aiDir, featureName)
|
|
89
|
+
|
|
90
|
+
Expand context for a specific feature:
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
import { expandFeatureContext } from 'ai-first';
|
|
94
|
+
|
|
95
|
+
const result = expandFeatureContext('/path', '/path/ai', 'auth');
|
|
96
|
+
if (result.success) {
|
|
97
|
+
console.log('Feature expanded:', result.files);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### expandFlowContext(rootDir, aiDir, flowName)
|
|
102
|
+
|
|
103
|
+
Expand context for a specific flow:
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
import { expandFlowContext } from 'ai-first';
|
|
107
|
+
|
|
108
|
+
const result = expandFlowContext('/path', '/path/ai', 'login');
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### expandFullContext(rootDir, aiDir)
|
|
112
|
+
|
|
113
|
+
Expand all context (Stage 2):
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
import { expandFullContext } from 'ai-first';
|
|
117
|
+
|
|
118
|
+
const stats = expandFullContext('/path', '/path/ai');
|
|
119
|
+
console.log(stats);
|
|
120
|
+
// { symbols: 150, dependencies: 80, features: 5, flows: 3 }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## State Management
|
|
124
|
+
|
|
125
|
+
Lazy index state is stored in `ai/lazy-index-state.json`:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"stage1Complete": true,
|
|
130
|
+
"stage2Complete": false,
|
|
131
|
+
"featuresExpanded": ["auth", "users"],
|
|
132
|
+
"flowsExpanded": ["login"],
|
|
133
|
+
"lastUpdated": "2024-01-15T10:30:00.000Z"
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Integration
|
|
138
|
+
|
|
139
|
+
The lazy analyzer integrates with existing CLI commands:
|
|
140
|
+
|
|
141
|
+
- `ai-first init` - Stage 1 only (fast)
|
|
142
|
+
- `ai-first map` - Triggers Stage 2
|
|
143
|
+
- `ai-first context` - Expands specific context on demand
|
|
144
|
+
- `ai-first update` - Incremental updates maintain lazy state
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Performance Optimization
|
|
2
|
+
|
|
3
|
+
AI-First is optimized to handle large repositories efficiently through incremental analysis and smart caching.
|
|
4
|
+
|
|
5
|
+
## Incremental Indexing
|
|
6
|
+
|
|
7
|
+
AI-First tracks file changes to avoid reprocessing the entire repository on each run.
|
|
8
|
+
|
|
9
|
+
### How It Works
|
|
10
|
+
|
|
11
|
+
1. **File Hash Tracking**: Each file's content is hashed (MD5)
|
|
12
|
+
2. **State Storage**: Hashes stored in `ai/index-state.json`
|
|
13
|
+
3. **Change Detection**: On each run, only modified files are re-indexed
|
|
14
|
+
|
|
15
|
+
### State File Format
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"version": "1.0.0",
|
|
20
|
+
"lastIndexed": "2026-03-10T12:00:00.000Z",
|
|
21
|
+
"totalFiles": 150,
|
|
22
|
+
"files": {
|
|
23
|
+
"src/auth/AuthService.ts": {
|
|
24
|
+
"path": "src/auth/AuthService.ts",
|
|
25
|
+
"hash": "abc123...",
|
|
26
|
+
"mtime": 1699531200000,
|
|
27
|
+
"size": 1024,
|
|
28
|
+
"indexedAt": "2026-03-10T12:00:00.000Z"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### CLI Output Example
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
🗄️ Generating index for: /project
|
|
38
|
+
|
|
39
|
+
Total files: 150
|
|
40
|
+
To index: 5
|
|
41
|
+
Unchanged: 145
|
|
42
|
+
New: 2
|
|
43
|
+
Deleted: 0
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Semantic Contexts
|
|
47
|
+
|
|
48
|
+
Semantic contexts (features and flows) are regenerated based on the current module structure:
|
|
49
|
+
|
|
50
|
+
- **Features**: Derived from `modules.json` - regenerated when module structure changes
|
|
51
|
+
- **Flows**: Derived from `symbol-graph.json` - regenerated when symbol relationships change
|
|
52
|
+
|
|
53
|
+
These are lightweight computations compared to full symbol extraction.
|
|
54
|
+
|
|
55
|
+
## Performance Tips
|
|
56
|
+
|
|
57
|
+
### 1. Use Incremental Mode
|
|
58
|
+
|
|
59
|
+
The default behavior is incremental. Don't use `--force` unless necessary.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Incremental (default)
|
|
63
|
+
ai-first map
|
|
64
|
+
|
|
65
|
+
# Force full rebuild
|
|
66
|
+
ai-first map --force
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Exclude Unnecessary Files
|
|
70
|
+
|
|
71
|
+
Use `.aiignore` to exclude large or irrelevant directories:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
# .aiignore
|
|
75
|
+
node_modules/
|
|
76
|
+
dist/
|
|
77
|
+
build/
|
|
78
|
+
coverage/
|
|
79
|
+
*.log
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. Large Repositories
|
|
83
|
+
|
|
84
|
+
For repositories with >2000 files, semantic indexing is automatically enabled:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
ai-first map
|
|
88
|
+
# Automatically uses semantic mode for large repos
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 4. Git Integration
|
|
92
|
+
|
|
93
|
+
AI-First can use Git to detect changed files:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Only analyze changed files
|
|
97
|
+
git commit -am "update" && ai-first map
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Benchmarks
|
|
101
|
+
|
|
102
|
+
| Repository Size | Files | Time (First) | Time (Incremental) |
|
|
103
|
+
|----------------|-------|--------------|---------------------|
|
|
104
|
+
| Small | 50 | 0.3s | 0.1s |
|
|
105
|
+
| Medium | 200 | 1.2s | 0.3s |
|
|
106
|
+
| Large | 1000 | 5.5s | 1.2s |
|
|
107
|
+
| Huge | 5000 | 28s | 5s |
|
|
108
|
+
|
|
109
|
+
## Troubleshooting
|
|
110
|
+
|
|
111
|
+
### Slow Performance
|
|
112
|
+
|
|
113
|
+
1. **Check file count**: `ai-first doctor`
|
|
114
|
+
2. **Exclude directories**: Add to `.aiignore`
|
|
115
|
+
3. **Clear cache**: Delete `ai/index-state.json`
|
|
116
|
+
|
|
117
|
+
### Memory Issues
|
|
118
|
+
|
|
119
|
+
For very large repositories (>10k files):
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
ai-first map --semantic
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This uses streaming analysis to reduce memory usage.
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-first-cli",
|
|
3
|
-
|
|
4
|
-
"version": "1.1.1",
|
|
3
|
+
"version": "1.1.3",
|
|
5
4
|
"description": "CLI tool that prepares any repository to be used effectively by AI coding agents",
|
|
6
5
|
"main": "dist/index.js",
|
|
7
6
|
"type": "module",
|
|
@@ -12,6 +11,8 @@
|
|
|
12
11
|
"build": "tsc",
|
|
13
12
|
"run": "node dist/commands/ai-first.js",
|
|
14
13
|
"dev": "node --loader ts-node/esm src/commands/ai-first.ts",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
15
16
|
"docs:dev": "vitepress dev docs",
|
|
16
17
|
"docs:build": "vitepress build docs",
|
|
17
18
|
"docs:preview": "vitepress preview docs",
|
|
@@ -43,10 +44,12 @@
|
|
|
43
44
|
"@vitejs/plugin-vue": "^6.0.4",
|
|
44
45
|
"typescript": "^5.0.0",
|
|
45
46
|
"vitepress": "^1.6.4",
|
|
47
|
+
"vitest": "^2.0.0",
|
|
46
48
|
"vue": "^3.5.30"
|
|
47
49
|
},
|
|
48
50
|
"dependencies": {
|
|
49
51
|
"chokidar": "^5.0.0",
|
|
52
|
+
"ora": "^9.3.0",
|
|
50
53
|
"sql.js": "^1.10.0"
|
|
51
54
|
},
|
|
52
55
|
"optionalDependencies": {
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { FileInfo } from "../core/repoScanner.js";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export interface AndroidResource {
|
|
5
|
+
type: "layout" | "drawable" | "values" | "menu" | "mipmap" | "anim" | "xml" | "other";
|
|
6
|
+
name: string;
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface AndroidResourcesAnalysis {
|
|
11
|
+
isAndroid: boolean;
|
|
12
|
+
resources: AndroidResource[];
|
|
13
|
+
layouts: string[];
|
|
14
|
+
drawables: string[];
|
|
15
|
+
values: string[];
|
|
16
|
+
totalResources: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Analyze Android resources in res/ directory
|
|
21
|
+
*/
|
|
22
|
+
export function analyzeAndroidResources(files: FileInfo[]): AndroidResourcesAnalysis {
|
|
23
|
+
const resFiles = files.filter(f => f.relativePath.startsWith("res/"));
|
|
24
|
+
|
|
25
|
+
if (resFiles.length === 0) {
|
|
26
|
+
return {
|
|
27
|
+
isAndroid: false,
|
|
28
|
+
resources: [],
|
|
29
|
+
layouts: [],
|
|
30
|
+
drawables: [],
|
|
31
|
+
values: [],
|
|
32
|
+
totalResources: 0,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const resources: AndroidResource[] = [];
|
|
37
|
+
const layouts: string[] = [];
|
|
38
|
+
const drawables: string[] = [];
|
|
39
|
+
const values: string[] = [];
|
|
40
|
+
|
|
41
|
+
for (const file of resFiles) {
|
|
42
|
+
const relativePath = file.relativePath;
|
|
43
|
+
const parts = relativePath.split("/");
|
|
44
|
+
|
|
45
|
+
// res/layout/*.xml -> layout
|
|
46
|
+
// res/drawable-*/*.{png,xml} -> drawable
|
|
47
|
+
// res/values/*.xml -> values
|
|
48
|
+
// res/menu/*.xml -> menu
|
|
49
|
+
// res/mipmap-*/*.png -> mipmap
|
|
50
|
+
// res/anim/*.xml -> anim
|
|
51
|
+
// res/xml/*.xml -> xml
|
|
52
|
+
|
|
53
|
+
let type: AndroidResource["type"] = "other";
|
|
54
|
+
let resourceName = file.name;
|
|
55
|
+
|
|
56
|
+
if (parts[1] === "layout") {
|
|
57
|
+
type = "layout";
|
|
58
|
+
layouts.push(resourceName);
|
|
59
|
+
} else if (parts[1]?.startsWith("drawable")) {
|
|
60
|
+
type = "drawable";
|
|
61
|
+
drawables.push(resourceName);
|
|
62
|
+
} else if (parts[1] === "values") {
|
|
63
|
+
type = "values";
|
|
64
|
+
values.push(resourceName);
|
|
65
|
+
} else if (parts[1] === "menu") {
|
|
66
|
+
type = "menu";
|
|
67
|
+
} else if (parts[1]?.startsWith("mipmap")) {
|
|
68
|
+
type = "mipmap";
|
|
69
|
+
} else if (parts[1] === "anim") {
|
|
70
|
+
type = "anim";
|
|
71
|
+
} else if (parts[1] === "xml") {
|
|
72
|
+
type = "xml";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
resources.push({
|
|
76
|
+
type,
|
|
77
|
+
name: resourceName,
|
|
78
|
+
path: relativePath,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
isAndroid: true,
|
|
84
|
+
resources,
|
|
85
|
+
layouts,
|
|
86
|
+
drawables,
|
|
87
|
+
values,
|
|
88
|
+
totalResources: resources.length,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Generate android-resources.json content
|
|
94
|
+
*/
|
|
95
|
+
export function generateAndroidResourcesJson(analysis: AndroidResourcesAnalysis): string {
|
|
96
|
+
const output = {
|
|
97
|
+
isAndroid: analysis.isAndroid,
|
|
98
|
+
totalResources: analysis.totalResources,
|
|
99
|
+
layouts: analysis.layouts,
|
|
100
|
+
drawables: analysis.drawables,
|
|
101
|
+
values: analysis.values,
|
|
102
|
+
byType: {
|
|
103
|
+
layout: analysis.resources.filter(r => r.type === "layout").map(r => r.path),
|
|
104
|
+
drawable: analysis.resources.filter(r => r.type === "drawable").map(r => r.path),
|
|
105
|
+
values: analysis.resources.filter(r => r.type === "values").map(r => r.path),
|
|
106
|
+
menu: analysis.resources.filter(r => r.type === "menu").map(r => r.path),
|
|
107
|
+
mipmap: analysis.resources.filter(r => r.type === "mipmap").map(r => r.path),
|
|
108
|
+
anim: analysis.resources.filter(r => r.type === "anim").map(r => r.path),
|
|
109
|
+
xml: analysis.resources.filter(r => r.type === "xml").map(r => r.path),
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
return JSON.stringify(output, null, 2);
|
|
113
|
+
}
|