codehere 0.2.2 → 0.3.0-rc.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/README.md +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +253 -1219
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +272 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +9 -38
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +321 -30
- package/dist/presentation/cli/commands/trust-command.js +84 -72
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/ui.js +11 -11
- package/package.json +24 -62
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -534
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -704
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Query Result Cache
|
|
3
|
-
* Caches search query results
|
|
4
|
-
*
|
|
5
|
-
* Phase 1: v0.5.0-alpha.0
|
|
6
|
-
*/
|
|
7
|
-
import { createHash } from 'crypto';
|
|
8
|
-
class QueryResultCache {
|
|
9
|
-
cache = new Map();
|
|
10
|
-
hits = 0;
|
|
11
|
-
misses = 0;
|
|
12
|
-
ttl = 3600000; // 1 hour
|
|
13
|
-
get(query, maxResults) {
|
|
14
|
-
const key = this.getCacheKey(query, maxResults);
|
|
15
|
-
const cached = this.cache.get(key);
|
|
16
|
-
if (cached) {
|
|
17
|
-
const age = Date.now() - cached.timestamp;
|
|
18
|
-
if (age < this.ttl) {
|
|
19
|
-
return cached.chunks;
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
this.cache.delete(key);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
set(query, maxResults, chunks) {
|
|
28
|
-
const key = this.getCacheKey(query, maxResults);
|
|
29
|
-
this.cache.set(key, {
|
|
30
|
-
chunks,
|
|
31
|
-
timestamp: Date.now(),
|
|
32
|
-
query,
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
recordHit() {
|
|
36
|
-
this.hits++;
|
|
37
|
-
}
|
|
38
|
-
recordMiss() {
|
|
39
|
-
this.misses++;
|
|
40
|
-
}
|
|
41
|
-
getStats() {
|
|
42
|
-
const total = this.hits + this.misses;
|
|
43
|
-
return {
|
|
44
|
-
hitRate: total > 0 ? this.hits / total : 0,
|
|
45
|
-
totalHits: this.hits,
|
|
46
|
-
totalMisses: this.misses,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
clear() {
|
|
50
|
-
this.cache.clear();
|
|
51
|
-
this.hits = 0;
|
|
52
|
-
this.misses = 0;
|
|
53
|
-
}
|
|
54
|
-
getCacheKey(query, maxResults) {
|
|
55
|
-
const normalized = query.trim().toLowerCase();
|
|
56
|
-
return createHash('sha256').update(`${normalized}:${maxResults}`).digest('hex');
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
let instance = null;
|
|
60
|
-
export function getQueryResultCache() {
|
|
61
|
-
if (!instance) {
|
|
62
|
-
instance = new QueryResultCache();
|
|
63
|
-
}
|
|
64
|
-
return instance;
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=query-result-cache.js.map
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Response Cache
|
|
3
|
-
* Caches AI-generated responses
|
|
4
|
-
*
|
|
5
|
-
* Phase 1: v0.5.0-alpha.0
|
|
6
|
-
*/
|
|
7
|
-
import { createHash } from 'crypto';
|
|
8
|
-
class ResponseCache {
|
|
9
|
-
cache = new Map();
|
|
10
|
-
ttl = 3600000; // 1 hour
|
|
11
|
-
generateContextHash(chunks) {
|
|
12
|
-
const chunkIds = chunks.map(c => c.id || c.filepath).sort().join(',');
|
|
13
|
-
return createHash('sha256').update(chunkIds).digest('hex');
|
|
14
|
-
}
|
|
15
|
-
get(query, contextHash, checkStale = false) {
|
|
16
|
-
const key = this.getCacheKey(query, contextHash);
|
|
17
|
-
const cached = this.cache.get(key);
|
|
18
|
-
if (cached) {
|
|
19
|
-
if (!checkStale || (Date.now() - cached.timestamp) < this.ttl) {
|
|
20
|
-
return cached.response;
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
this.cache.delete(key);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
set(query, response, contextHash) {
|
|
29
|
-
const key = this.getCacheKey(query, contextHash);
|
|
30
|
-
this.cache.set(key, {
|
|
31
|
-
response,
|
|
32
|
-
timestamp: Date.now(),
|
|
33
|
-
contextHash,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
getCacheKey(query, contextHash) {
|
|
37
|
-
const normalized = query.trim().toLowerCase();
|
|
38
|
-
return createHash('sha256').update(`${normalized}:${contextHash}`).digest('hex');
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
let instance = null;
|
|
42
|
-
export function getResponseCache() {
|
|
43
|
-
if (!instance) {
|
|
44
|
-
instance = new ResponseCache();
|
|
45
|
-
}
|
|
46
|
-
return instance;
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=response-cache.js.map
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security Scan Cache
|
|
3
|
-
* Caches security scan results
|
|
4
|
-
*
|
|
5
|
-
* Phase 1: v0.5.0-alpha.0
|
|
6
|
-
*/
|
|
7
|
-
import { createHash } from 'crypto';
|
|
8
|
-
class SecurityScanCache {
|
|
9
|
-
cache = new Map();
|
|
10
|
-
ttl = 3600000; // 1 hour
|
|
11
|
-
get(filepath, contentHash) {
|
|
12
|
-
const key = `${filepath}:${contentHash}`;
|
|
13
|
-
const cached = this.cache.get(key);
|
|
14
|
-
if (cached) {
|
|
15
|
-
const age = Date.now() - cached.timestamp;
|
|
16
|
-
if (age < this.ttl) {
|
|
17
|
-
return cached.results;
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
this.cache.delete(key);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
set(filepath, code, sast, license, providerBias) {
|
|
26
|
-
// Create hash from code content
|
|
27
|
-
const contentHash = createHash('sha256').update(code).digest('hex');
|
|
28
|
-
const key = `${filepath}:${contentHash}`;
|
|
29
|
-
this.cache.set(key, {
|
|
30
|
-
filepath,
|
|
31
|
-
hash: contentHash,
|
|
32
|
-
results: { sast, license, providerBias },
|
|
33
|
-
timestamp: Date.now(),
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
clear() {
|
|
37
|
-
this.cache.clear();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
let instance = null;
|
|
41
|
-
export function getSecurityScanCache() {
|
|
42
|
-
if (!instance) {
|
|
43
|
-
instance = new SecurityScanCache();
|
|
44
|
-
}
|
|
45
|
-
return instance;
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=security-scan-cache.js.map
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure: AST-Based Code Chunker
|
|
3
|
-
* Implements ICodeChunker using code-aware chunking
|
|
4
|
-
*/
|
|
5
|
-
import { CodeAwareChunker } from './code-aware-chunker.js';
|
|
6
|
-
export class ASTCodeChunker {
|
|
7
|
-
chunker;
|
|
8
|
-
constructor() {
|
|
9
|
-
this.chunker = new CodeAwareChunker();
|
|
10
|
-
}
|
|
11
|
-
async chunk(filepath) {
|
|
12
|
-
return await this.chunker.chunk(filepath, {
|
|
13
|
-
preserveSyntax: true,
|
|
14
|
-
hierarchical: true,
|
|
15
|
-
maxChunkSize: 2000, // tokens
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=ast-code-chunker.js.map
|
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure: Code-Aware Chunker
|
|
3
|
-
* Implements enterprise-grade code chunking that respects code structure
|
|
4
|
-
*
|
|
5
|
-
* Based on enterprise architecture requirements:
|
|
6
|
-
* - Split by logical units (functions, classes, modules)
|
|
7
|
-
* - Preserve syntactic integrity
|
|
8
|
-
* - Hierarchical strategy (high-level docs → functions → lines)
|
|
9
|
-
*/
|
|
10
|
-
import { readFileSync, existsSync } from 'fs';
|
|
11
|
-
import { parseFile } from '../../ast-parser.js';
|
|
12
|
-
export class CodeAwareChunker {
|
|
13
|
-
/**
|
|
14
|
-
* Chunk code file by logical units (functions, classes, modules)
|
|
15
|
-
* Preserves syntactic integrity - all chunks are valid code blocks
|
|
16
|
-
*/
|
|
17
|
-
async chunk(filepath, options = {}) {
|
|
18
|
-
const { preserveSyntax = true, hierarchical = true, maxChunkSize = 2000, // tokens (roughly 8000 chars)
|
|
19
|
-
} = options;
|
|
20
|
-
if (!existsSync(filepath)) {
|
|
21
|
-
throw new Error(`File not found: ${filepath}`);
|
|
22
|
-
}
|
|
23
|
-
const content = readFileSync(filepath, 'utf-8');
|
|
24
|
-
const ext = filepath.split('.').pop()?.toLowerCase() || '';
|
|
25
|
-
// For non-code files, use document-based chunking
|
|
26
|
-
if (!['ts', 'tsx', 'js', 'jsx', 'py', 'java', 'go', 'rs', 'cpp', 'c'].includes(ext)) {
|
|
27
|
-
return this.chunkDocument(content, filepath, maxChunkSize);
|
|
28
|
-
}
|
|
29
|
-
// For code files, use AST-based chunking
|
|
30
|
-
try {
|
|
31
|
-
const analysis = await parseFile(filepath);
|
|
32
|
-
if (!analysis) {
|
|
33
|
-
// Fallback to function-based chunking if AST parsing returns null
|
|
34
|
-
return this.chunkByFunctions(content, filepath, maxChunkSize);
|
|
35
|
-
}
|
|
36
|
-
return this.chunkByAST(analysis, content, filepath, hierarchical, maxChunkSize);
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
// Fallback to function-based chunking if AST parsing fails
|
|
40
|
-
console.warn(`AST parsing failed for ${filepath}, using function-based chunking:`, error);
|
|
41
|
-
return this.chunkByFunctions(content, filepath, maxChunkSize);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Map symbol kind to chunk metadata type
|
|
46
|
-
*/
|
|
47
|
-
mapSymbolKindToChunkType(kind) {
|
|
48
|
-
const kindMap = {
|
|
49
|
-
'function': 'function',
|
|
50
|
-
'method': 'function',
|
|
51
|
-
'class': 'class',
|
|
52
|
-
'interface': 'interface',
|
|
53
|
-
'type': 'code-block',
|
|
54
|
-
'variable': 'code-block',
|
|
55
|
-
'enum': 'code-block',
|
|
56
|
-
'property': 'code-block',
|
|
57
|
-
};
|
|
58
|
-
return kindMap[kind] || 'code-block';
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Chunk using AST analysis - most precise method
|
|
62
|
-
*/
|
|
63
|
-
chunkByAST(analysis, content, filepath, hierarchical, maxChunkSize) {
|
|
64
|
-
const chunks = [];
|
|
65
|
-
const lines = content.split('\n');
|
|
66
|
-
// Hierarchical strategy: classes → functions → statements
|
|
67
|
-
if (hierarchical) {
|
|
68
|
-
// Level 1: Chunk by classes/interfaces
|
|
69
|
-
for (const symbol of analysis.symbols) {
|
|
70
|
-
if (symbol.kind === 'class' || symbol.kind === 'interface') {
|
|
71
|
-
const classChunk = this.extractSymbolContent(symbol, lines, content);
|
|
72
|
-
if (classChunk && classChunk.length <= maxChunkSize) {
|
|
73
|
-
chunks.push({
|
|
74
|
-
filepath,
|
|
75
|
-
content: classChunk,
|
|
76
|
-
score: 1.0,
|
|
77
|
-
lineStart: symbol.line,
|
|
78
|
-
lineEnd: symbol.line + classChunk.split('\n').length,
|
|
79
|
-
metadata: {
|
|
80
|
-
symbols: [symbol.name],
|
|
81
|
-
type: this.mapSymbolKindToChunkType(symbol.kind),
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
else if (classChunk) {
|
|
86
|
-
// Class too large, chunk by methods
|
|
87
|
-
const methodChunks = this.chunkLargeClass(symbol, analysis, lines, content, maxChunkSize);
|
|
88
|
-
chunks.push(...methodChunks);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// Level 2: Chunk standalone functions
|
|
93
|
-
for (const symbol of analysis.symbols) {
|
|
94
|
-
if (symbol.kind === 'function' && !this.isMethodOfClass(symbol, analysis)) {
|
|
95
|
-
const funcChunk = this.extractSymbolContent(symbol, lines, content);
|
|
96
|
-
if (funcChunk && funcChunk.length <= maxChunkSize) {
|
|
97
|
-
chunks.push({
|
|
98
|
-
filepath,
|
|
99
|
-
content: funcChunk,
|
|
100
|
-
score: 1.0,
|
|
101
|
-
lineStart: symbol.line,
|
|
102
|
-
lineEnd: symbol.line + funcChunk.split('\n').length,
|
|
103
|
-
metadata: {
|
|
104
|
-
symbols: [symbol.name],
|
|
105
|
-
type: 'function',
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
// Non-hierarchical: chunk all symbols
|
|
114
|
-
for (const symbol of analysis.symbols) {
|
|
115
|
-
const symbolChunk = this.extractSymbolContent(symbol, lines, content);
|
|
116
|
-
if (symbolChunk) {
|
|
117
|
-
chunks.push({
|
|
118
|
-
filepath,
|
|
119
|
-
content: symbolChunk,
|
|
120
|
-
score: 1.0,
|
|
121
|
-
lineStart: symbol.line,
|
|
122
|
-
lineEnd: symbol.line + symbolChunk.split('\n').length,
|
|
123
|
-
metadata: {
|
|
124
|
-
symbols: [symbol.name],
|
|
125
|
-
type: this.mapSymbolKindToChunkType(symbol.kind),
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// If no chunks created (no symbols found), fallback to function-based
|
|
132
|
-
if (chunks.length === 0) {
|
|
133
|
-
return this.chunkByFunctions(content, filepath, maxChunkSize);
|
|
134
|
-
}
|
|
135
|
-
return chunks;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Chunk large class by its methods
|
|
139
|
-
*/
|
|
140
|
-
chunkLargeClass(classSymbol, analysis, lines, content, maxChunkSize) {
|
|
141
|
-
const chunks = [];
|
|
142
|
-
const classStart = classSymbol.line;
|
|
143
|
-
const classEnd = this.findClassEnd(classSymbol, lines);
|
|
144
|
-
// Find methods within this class
|
|
145
|
-
const methods = analysis.symbols.filter(s => s.kind === 'function' && s.line > classStart && s.line < classEnd);
|
|
146
|
-
// Create chunk for class header + first few methods
|
|
147
|
-
let currentChunk = lines.slice(classStart - 1, classStart + 10).join('\n');
|
|
148
|
-
let currentLineStart = classStart;
|
|
149
|
-
for (const method of methods) {
|
|
150
|
-
const methodContent = this.extractSymbolContent(method, lines, content);
|
|
151
|
-
if (!methodContent)
|
|
152
|
-
continue;
|
|
153
|
-
const potentialChunk = currentChunk + '\n\n' + methodContent;
|
|
154
|
-
if (potentialChunk.length <= maxChunkSize) {
|
|
155
|
-
currentChunk = potentialChunk;
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
// Save current chunk and start new one
|
|
159
|
-
chunks.push({
|
|
160
|
-
filepath: classSymbol.filepath,
|
|
161
|
-
content: currentChunk,
|
|
162
|
-
score: 1.0,
|
|
163
|
-
lineStart: currentLineStart,
|
|
164
|
-
lineEnd: method.line - 1,
|
|
165
|
-
metadata: {
|
|
166
|
-
symbols: [classSymbol.name],
|
|
167
|
-
type: 'class-partial',
|
|
168
|
-
},
|
|
169
|
-
});
|
|
170
|
-
currentChunk = methodContent;
|
|
171
|
-
currentLineStart = method.line;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
// Add final chunk
|
|
175
|
-
if (currentChunk) {
|
|
176
|
-
chunks.push({
|
|
177
|
-
filepath: classSymbol.filepath,
|
|
178
|
-
content: currentChunk,
|
|
179
|
-
score: 1.0,
|
|
180
|
-
lineStart: currentLineStart,
|
|
181
|
-
lineEnd: classEnd,
|
|
182
|
-
metadata: {
|
|
183
|
-
symbols: [classSymbol.name],
|
|
184
|
-
type: 'class-partial',
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return chunks;
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Chunk by function boundaries (fallback method)
|
|
192
|
-
*/
|
|
193
|
-
chunkByFunctions(content, filepath, maxChunkSize) {
|
|
194
|
-
const chunks = [];
|
|
195
|
-
const lines = content.split('\n');
|
|
196
|
-
// Regex patterns for different languages
|
|
197
|
-
const functionPatterns = [
|
|
198
|
-
/^(export\s+)?(async\s+)?function\s+(\w+)/, // JavaScript/TypeScript
|
|
199
|
-
/^(export\s+)?(async\s+)?const\s+(\w+)\s*=\s*(async\s*)?\(/, // Arrow functions
|
|
200
|
-
/^(export\s+)?class\s+(\w+)/, // Classes
|
|
201
|
-
/^(export\s+)?interface\s+(\w+)/, // Interfaces
|
|
202
|
-
/^def\s+(\w+)/, // Python
|
|
203
|
-
];
|
|
204
|
-
let currentChunk = [];
|
|
205
|
-
let currentLineStart = 1;
|
|
206
|
-
let braceCount = 0;
|
|
207
|
-
let inFunction = false;
|
|
208
|
-
for (let i = 0; i < lines.length; i++) {
|
|
209
|
-
const line = lines[i];
|
|
210
|
-
const isFunctionStart = functionPatterns.some(pattern => pattern.test(line));
|
|
211
|
-
if (isFunctionStart && currentChunk.length > 0) {
|
|
212
|
-
// Save previous chunk
|
|
213
|
-
const chunkContent = currentChunk.join('\n');
|
|
214
|
-
if (chunkContent.trim().length > 0) {
|
|
215
|
-
chunks.push({
|
|
216
|
-
filepath,
|
|
217
|
-
content: chunkContent,
|
|
218
|
-
score: 1.0,
|
|
219
|
-
lineStart: currentLineStart,
|
|
220
|
-
lineEnd: i - 1,
|
|
221
|
-
metadata: {
|
|
222
|
-
type: 'function',
|
|
223
|
-
},
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
currentChunk = [line];
|
|
227
|
-
currentLineStart = i + 1;
|
|
228
|
-
inFunction = true;
|
|
229
|
-
braceCount = this.countBraces(line);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
currentChunk.push(line);
|
|
233
|
-
if (inFunction) {
|
|
234
|
-
braceCount += this.countBraces(line);
|
|
235
|
-
if (braceCount === 0 && line.trim().length > 0) {
|
|
236
|
-
inFunction = false;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
// If chunk gets too large, split it
|
|
240
|
-
if (currentChunk.join('\n').length > maxChunkSize && currentChunk.length > 10) {
|
|
241
|
-
const chunkContent = currentChunk.slice(0, -5).join('\n');
|
|
242
|
-
chunks.push({
|
|
243
|
-
filepath,
|
|
244
|
-
content: chunkContent,
|
|
245
|
-
score: 1.0,
|
|
246
|
-
lineStart: currentLineStart,
|
|
247
|
-
lineEnd: i - 5,
|
|
248
|
-
metadata: {
|
|
249
|
-
type: 'code-block',
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
currentChunk = currentChunk.slice(-5);
|
|
253
|
-
currentLineStart = i - 4;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
// Add final chunk
|
|
258
|
-
if (currentChunk.length > 0) {
|
|
259
|
-
chunks.push({
|
|
260
|
-
filepath,
|
|
261
|
-
content: currentChunk.join('\n'),
|
|
262
|
-
score: 1.0,
|
|
263
|
-
lineStart: currentLineStart,
|
|
264
|
-
lineEnd: lines.length,
|
|
265
|
-
metadata: {
|
|
266
|
-
type: 'code-block',
|
|
267
|
-
},
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
return chunks.length > 0 ? chunks : [{
|
|
271
|
-
filepath,
|
|
272
|
-
content,
|
|
273
|
-
score: 1.0,
|
|
274
|
-
lineStart: 1,
|
|
275
|
-
lineEnd: lines.length,
|
|
276
|
-
metadata: {
|
|
277
|
-
type: 'file',
|
|
278
|
-
},
|
|
279
|
-
}];
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Chunk document files (markdown, text, etc.)
|
|
283
|
-
*/
|
|
284
|
-
chunkDocument(content, filepath, maxChunkSize) {
|
|
285
|
-
const chunks = [];
|
|
286
|
-
const paragraphs = content.split(/\n\s*\n/);
|
|
287
|
-
let currentChunk = [];
|
|
288
|
-
let currentLineStart = 1;
|
|
289
|
-
for (const paragraph of paragraphs) {
|
|
290
|
-
const potentialChunk = [...currentChunk, paragraph].join('\n\n');
|
|
291
|
-
if (potentialChunk.length <= maxChunkSize) {
|
|
292
|
-
currentChunk.push(paragraph);
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
if (currentChunk.length > 0) {
|
|
296
|
-
chunks.push({
|
|
297
|
-
filepath,
|
|
298
|
-
content: currentChunk.join('\n\n'),
|
|
299
|
-
score: 1.0,
|
|
300
|
-
lineStart: currentLineStart,
|
|
301
|
-
lineEnd: currentLineStart + currentChunk.join('\n\n').split('\n').length,
|
|
302
|
-
metadata: {
|
|
303
|
-
type: 'document',
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
currentChunk = [paragraph];
|
|
308
|
-
currentLineStart += currentChunk.join('\n\n').split('\n').length;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (currentChunk.length > 0) {
|
|
312
|
-
chunks.push({
|
|
313
|
-
filepath,
|
|
314
|
-
content: currentChunk.join('\n\n'),
|
|
315
|
-
score: 1.0,
|
|
316
|
-
lineStart: currentLineStart,
|
|
317
|
-
lineEnd: content.split('\n').length,
|
|
318
|
-
metadata: {
|
|
319
|
-
type: 'document',
|
|
320
|
-
},
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
return chunks.length > 0 ? chunks : [{
|
|
324
|
-
filepath,
|
|
325
|
-
content,
|
|
326
|
-
score: 1.0,
|
|
327
|
-
lineStart: 1,
|
|
328
|
-
lineEnd: content.split('\n').length,
|
|
329
|
-
metadata: {
|
|
330
|
-
type: 'document',
|
|
331
|
-
},
|
|
332
|
-
}];
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Extract content for a symbol from AST
|
|
336
|
-
*/
|
|
337
|
-
extractSymbolContent(symbol, lines, content) {
|
|
338
|
-
if (!symbol.line)
|
|
339
|
-
return null;
|
|
340
|
-
const startLine = symbol.line - 1; // 0-indexed
|
|
341
|
-
const endLine = this.findSymbolEnd(symbol, lines, startLine);
|
|
342
|
-
if (endLine <= startLine)
|
|
343
|
-
return null;
|
|
344
|
-
return lines.slice(startLine, endLine).join('\n');
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Find end of symbol (class, function, etc.)
|
|
348
|
-
*/
|
|
349
|
-
findSymbolEnd(symbol, lines, startLine) {
|
|
350
|
-
// Simple heuristic: find matching braces
|
|
351
|
-
let braceCount = 0;
|
|
352
|
-
let foundStart = false;
|
|
353
|
-
for (let i = startLine; i < lines.length; i++) {
|
|
354
|
-
const line = lines[i];
|
|
355
|
-
if (!foundStart) {
|
|
356
|
-
if (line.includes('{') || line.includes('class') || line.includes('function')) {
|
|
357
|
-
foundStart = true;
|
|
358
|
-
braceCount = this.countBraces(line);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
braceCount += this.countBraces(line);
|
|
363
|
-
if (braceCount === 0 && line.trim().length > 0) {
|
|
364
|
-
return i + 1;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return lines.length;
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Find end of class
|
|
372
|
-
*/
|
|
373
|
-
findClassEnd(classSymbol, lines) {
|
|
374
|
-
return this.findSymbolEnd(classSymbol, lines, classSymbol.line - 1);
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Count braces in line
|
|
378
|
-
*/
|
|
379
|
-
countBraces(line) {
|
|
380
|
-
return (line.match(/{/g) || []).length - (line.match(/}/g) || []).length;
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Check if function is a method of a class
|
|
384
|
-
*/
|
|
385
|
-
isMethodOfClass(funcSymbol, analysis) {
|
|
386
|
-
// Find classes before this function
|
|
387
|
-
const classes = analysis.symbols.filter(s => s.kind === 'class' && s.line < funcSymbol.line);
|
|
388
|
-
// Find the closest class
|
|
389
|
-
const closestClass = classes.reduce((prev, curr) => curr.line > prev.line ? curr : prev, classes[0] || { line: 0 });
|
|
390
|
-
if (!closestClass)
|
|
391
|
-
return false;
|
|
392
|
-
// Check if function is within class bounds (simple heuristic)
|
|
393
|
-
const classEnd = this.findClassEnd(closestClass, analysis.symbols.map(() => ''));
|
|
394
|
-
return funcSymbol.line > closestClass.line && funcSymbol.line < classEnd;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
//# sourceMappingURL=code-aware-chunker.js.map
|