opencode-swarm 6.62.0 → 6.64.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/dist/cli/index.js +220 -95
- package/dist/evidence/manager.d.ts +2 -12
- package/dist/gate-evidence.d.ts +2 -9
- package/dist/graph/graph-builder.d.ts +39 -0
- package/dist/graph/graph-query.d.ts +42 -0
- package/dist/graph/graph-store.d.ts +27 -0
- package/dist/graph/import-extractor.d.ts +44 -0
- package/dist/graph/index.d.ts +16 -0
- package/dist/graph/symbol-extractor.d.ts +17 -0
- package/dist/graph/types.d.ts +84 -0
- package/dist/hooks/repo-graph-injection.d.ts +45 -0
- package/dist/index.js +2591 -1185
- package/dist/plan/ledger.d.ts +2 -2
- package/dist/plan/manager.d.ts +8 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/repo-map.d.ts +2 -0
- package/dist/tools/tool-names.d.ts +1 -1
- package/dist/validation/task-id.d.ts +43 -0
- package/package.json +1 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type FileNode, type RepoGraph } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Build a full repository graph by walking the workspace, parsing source files
|
|
4
|
+
* for imports and exported symbols, and assembling them into a `RepoGraph`.
|
|
5
|
+
*
|
|
6
|
+
* Performance:
|
|
7
|
+
* - File scanning skips well-known build/dep directories (node_modules, dist, .git, etc.)
|
|
8
|
+
* - Per-file parsing runs with a concurrency limit to avoid overwhelming I/O.
|
|
9
|
+
* - Files larger than `MAX_FILE_SIZE_BYTES` are skipped (would also fail downstream extractors).
|
|
10
|
+
*
|
|
11
|
+
* Targets ~5s for a 50k LOC repo (~500 files) on commodity hardware.
|
|
12
|
+
*/
|
|
13
|
+
export interface BuildOptions {
|
|
14
|
+
/** Optional cap on file count to bound runtime on huge repos. */
|
|
15
|
+
maxFiles?: number;
|
|
16
|
+
/** Concurrency for per-file parsing. Defaults to 16. */
|
|
17
|
+
concurrency?: number;
|
|
18
|
+
/** Additional directory names to skip (merged with defaults). */
|
|
19
|
+
skipDirs?: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Hard upper bound on file count if the caller does not supply one. Protects
|
|
23
|
+
* against unbounded memory growth on extremely large monorepos. Callers can
|
|
24
|
+
* pass an explicit `maxFiles` (including a larger one) to override.
|
|
25
|
+
*/
|
|
26
|
+
export declare const DEFAULT_MAX_FILES = 10000;
|
|
27
|
+
/**
|
|
28
|
+
* Walk the workspace and return absolute paths of all supported source files.
|
|
29
|
+
* Cross-platform: emits absolute paths using the host's path separator.
|
|
30
|
+
*/
|
|
31
|
+
export declare function findSourceFiles(workspaceRoot: string, skipDirs?: Set<string>): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Build the repo graph from scratch.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildRepoGraph(workspaceRoot: string, options?: BuildOptions): Promise<RepoGraph>;
|
|
36
|
+
/**
|
|
37
|
+
* Process a single file into a FileNode. Returns null if the file cannot be processed.
|
|
38
|
+
*/
|
|
39
|
+
export declare function processFile(absoluteFilePath: string, workspaceRoot: string): Promise<FileNode | null>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { BlastRadiusResult, FileNode, FileReference, LocalizationBlock, RepoGraph, SymbolReference } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Query API for the repo graph.
|
|
4
|
+
*
|
|
5
|
+
* All functions accept normalized RELATIVE forward-slash paths and return the
|
|
6
|
+
* same. Callers responsible for normalizing input paths (helper provided).
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeGraphPath(p: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Files that import the given file (direct dependents).
|
|
11
|
+
*/
|
|
12
|
+
export declare function getImporters(graph: RepoGraph, filePath: string): FileReference[];
|
|
13
|
+
/**
|
|
14
|
+
* Files this file imports (direct dependencies, resolved targets only).
|
|
15
|
+
*/
|
|
16
|
+
export declare function getDependencies(graph: RepoGraph, filePath: string): FileReference[];
|
|
17
|
+
/**
|
|
18
|
+
* Find all importers of a specific exported symbol from a file.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getSymbolConsumers(graph: RepoGraph, filePath: string, symbolName: string): SymbolReference[];
|
|
21
|
+
/**
|
|
22
|
+
* Compute the transitive blast radius of changing one or more files.
|
|
23
|
+
*
|
|
24
|
+
* Performs a BFS over the reverse-edge index up to `maxDepth` levels.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getBlastRadius(graph: RepoGraph, filePaths: string[], maxDepth?: number): BlastRadiusResult;
|
|
27
|
+
/**
|
|
28
|
+
* Top-N most-imported files (by in-degree) — useful for surfacing
|
|
29
|
+
* architectural pillars.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getKeyFiles(graph: RepoGraph, topN?: number): FileNode[];
|
|
32
|
+
/**
|
|
33
|
+
* Build a compact localization block for a single file. This is the primary
|
|
34
|
+
* payload injected into the coder agent's pre-edit context.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getLocalizationContext(graph: RepoGraph, filePath: string, options?: {
|
|
37
|
+
maxImporters?: number;
|
|
38
|
+
maxDeps?: number;
|
|
39
|
+
maxDepth?: number;
|
|
40
|
+
}): LocalizationBlock;
|
|
41
|
+
/** Reset the cached reverse index. Call this when a graph is mutated in place. */
|
|
42
|
+
export declare function resetQueryCache(): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type RepoGraph } from './types';
|
|
2
|
+
export declare function getGraphPath(workspaceRoot: string): string;
|
|
3
|
+
export declare function loadGraph(workspaceRoot: string): RepoGraph | null;
|
|
4
|
+
export declare function saveGraph(workspaceRoot: string, graph: RepoGraph): void;
|
|
5
|
+
/**
|
|
6
|
+
* Build the graph from scratch and persist it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildAndSaveGraph(workspaceRoot: string): Promise<RepoGraph>;
|
|
9
|
+
/**
|
|
10
|
+
* Apply incremental updates for a list of changed (or potentially-changed) files.
|
|
11
|
+
*
|
|
12
|
+
* For each file:
|
|
13
|
+
* - If the file no longer exists, its node is removed.
|
|
14
|
+
* - Otherwise its node is re-parsed and replaced.
|
|
15
|
+
*
|
|
16
|
+
* Returns the updated graph (mutated in place AND returned for convenience).
|
|
17
|
+
* Caller must call `saveGraph` to persist if desired.
|
|
18
|
+
*/
|
|
19
|
+
export declare function updateGraphIncremental(workspaceRoot: string, changedRelativePaths: string[], graph: RepoGraph): Promise<RepoGraph>;
|
|
20
|
+
/**
|
|
21
|
+
* Determine if a stored graph is fresh enough to reuse.
|
|
22
|
+
*
|
|
23
|
+
* Default freshness window: 5 minutes. Files added/removed outside this
|
|
24
|
+
* window are not detected without an explicit incremental update — callers
|
|
25
|
+
* that care about up-to-the-second accuracy should rebuild.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isGraphFresh(graph: RepoGraph | null, maxAgeMs?: number): boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ImportEdge } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Extract import edges from a source file.
|
|
4
|
+
*
|
|
5
|
+
* Uses regex-based parsing (the same proven approach as `src/tools/imports.ts`
|
|
6
|
+
* and `src/tools/co-change-analyzer.ts`). Tree-sitter is intentionally not used
|
|
7
|
+
* here because:
|
|
8
|
+
* 1. The existing regex patterns are battle-tested across the codebase.
|
|
9
|
+
* 2. Import statements have stable, simple syntax that regex handles reliably.
|
|
10
|
+
* 3. Avoiding the per-file Tree-sitter parse keeps full-graph builds fast
|
|
11
|
+
* enough to be interactive (target: <5s for 50k LOC).
|
|
12
|
+
*
|
|
13
|
+
* Supported languages:
|
|
14
|
+
* - TypeScript / JavaScript (.ts/.tsx/.js/.jsx/.mjs/.cjs) — ES modules + CJS require
|
|
15
|
+
* - Python (.py) — `import x` and `from x import y`
|
|
16
|
+
* - Go (.go) — `import "path"` and `import (...)` blocks
|
|
17
|
+
* - Rust (.rs) — `use path::module`
|
|
18
|
+
*
|
|
19
|
+
* Only RELATIVE imports are tracked as graph edges. External package imports
|
|
20
|
+
* (e.g. 'react', 'fmt', 'std::fs') are skipped — they are not part of the
|
|
21
|
+
* intra-repo dependency graph.
|
|
22
|
+
*/
|
|
23
|
+
export interface ExtractImportsOptions {
|
|
24
|
+
/** Absolute path to the source file (used for relative resolution). */
|
|
25
|
+
absoluteFilePath: string;
|
|
26
|
+
/** Absolute workspace root (used for relative path computation). */
|
|
27
|
+
workspaceRoot: string;
|
|
28
|
+
/** Optional pre-read content; if omitted the file is read from disk. */
|
|
29
|
+
content?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Source file extensions we know how to scan. */
|
|
32
|
+
export declare const SOURCE_EXTENSIONS: readonly [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py", ".go", ".rs"];
|
|
33
|
+
export declare function getLanguageFromExtension(ext: string): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Extract import edges for a single file. Returns an empty array when the
|
|
36
|
+
* language is unsupported or the file cannot be parsed.
|
|
37
|
+
*
|
|
38
|
+
* Resolution strategy for edge.target:
|
|
39
|
+
* - TS/JS: probe extensions (.ts, .tsx, .js, .jsx, .mjs, .cjs, /index.*).
|
|
40
|
+
* - Python: probe .py and /__init__.py for relative imports only.
|
|
41
|
+
* - Go/Rust: target left empty (intra-repo resolution requires module/crate
|
|
42
|
+
* metadata that is out of scope for Phase 1). The raw module is preserved.
|
|
43
|
+
*/
|
|
44
|
+
export declare function extractImports(opts: ExtractImportsOptions): ImportEdge[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo graph: structural codebase awareness for swarm agents.
|
|
3
|
+
*
|
|
4
|
+
* Public surface:
|
|
5
|
+
* - Types (RepoGraph, FileNode, ImportEdge, ExportedSymbol, ...)
|
|
6
|
+
* - Builders (buildRepoGraph, processFile, findSourceFiles)
|
|
7
|
+
* - Store (loadGraph, saveGraph, buildAndSaveGraph, updateGraphIncremental, isGraphFresh, getGraphPath)
|
|
8
|
+
* - Query (getImporters, getDependencies, getSymbolConsumers, getBlastRadius,
|
|
9
|
+
* getKeyFiles, getLocalizationContext, normalizeGraphPath, resetQueryCache)
|
|
10
|
+
*/
|
|
11
|
+
export { type BuildOptions, buildRepoGraph, findSourceFiles, processFile, } from './graph-builder';
|
|
12
|
+
export { getBlastRadius, getDependencies, getImporters, getKeyFiles, getLocalizationContext, getSymbolConsumers, normalizeGraphPath, resetQueryCache, } from './graph-query';
|
|
13
|
+
export { buildAndSaveGraph, getGraphPath, isGraphFresh, loadGraph, saveGraph, updateGraphIncremental, } from './graph-store';
|
|
14
|
+
export { extractImports, getLanguageFromExtension, SOURCE_EXTENSIONS, } from './import-extractor';
|
|
15
|
+
export { extractExportedSymbols } from './symbol-extractor';
|
|
16
|
+
export * from './types';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ExportedSymbol } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Extract exported symbols from a single file.
|
|
4
|
+
*
|
|
5
|
+
* Reuses the proven regex-based extractors from `src/tools/symbols.ts`
|
|
6
|
+
* (`extractTSSymbols` / `extractPythonSymbols`) and maps their internal
|
|
7
|
+
* SymbolInfo shape to our `ExportedSymbol` type.
|
|
8
|
+
*
|
|
9
|
+
* For Go and Rust, exported-symbol extraction is best-effort (out of scope
|
|
10
|
+
* for Phase 1) — empty arrays are returned. The graph still tracks file-level
|
|
11
|
+
* import edges for these languages.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* @param relativeFilePath - file path relative to workspace root (forward-slash)
|
|
15
|
+
* @param workspaceRoot - absolute workspace root
|
|
16
|
+
*/
|
|
17
|
+
export declare function extractExportedSymbols(relativeFilePath: string, workspaceRoot: string): ExportedSymbol[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo graph data structures.
|
|
3
|
+
*
|
|
4
|
+
* The graph captures structural relationships between source files
|
|
5
|
+
* (imports/exports) so agents can reason about blast radius before editing.
|
|
6
|
+
*
|
|
7
|
+
* All paths are RELATIVE to the workspace root and FORWARD-SLASH normalized
|
|
8
|
+
* for cross-platform comparison.
|
|
9
|
+
*/
|
|
10
|
+
export type ImportType = 'named' | 'default' | 'namespace' | 'sideeffect' | 'require';
|
|
11
|
+
export interface ImportEdge {
|
|
12
|
+
/** Importing file (relative, forward-slash). */
|
|
13
|
+
source: string;
|
|
14
|
+
/** Resolved imported file (relative, forward-slash). May be empty for unresolved imports. */
|
|
15
|
+
target: string;
|
|
16
|
+
/** Raw module specifier as written in the source (e.g. '../utils/path-security'). */
|
|
17
|
+
rawModule: string;
|
|
18
|
+
/** Named imports brought in (empty for sideeffect/namespace/default). */
|
|
19
|
+
importedSymbols: string[];
|
|
20
|
+
/** What kind of import statement this is. */
|
|
21
|
+
importType: ImportType;
|
|
22
|
+
/** 1-indexed line number where the import appears. */
|
|
23
|
+
line: number;
|
|
24
|
+
}
|
|
25
|
+
export type SymbolKind = 'function' | 'class' | 'interface' | 'type' | 'enum' | 'const' | 'variable' | 'method' | 'property';
|
|
26
|
+
export interface ExportedSymbol {
|
|
27
|
+
name: string;
|
|
28
|
+
kind: SymbolKind;
|
|
29
|
+
signature?: string;
|
|
30
|
+
line: number;
|
|
31
|
+
}
|
|
32
|
+
export interface FileNode {
|
|
33
|
+
/** Relative, forward-slash path. */
|
|
34
|
+
path: string;
|
|
35
|
+
/** Detected language id (e.g. 'typescript', 'python', 'go', 'rust'). */
|
|
36
|
+
language: string;
|
|
37
|
+
/** Symbols this file exports (or top-level definitions for languages without explicit exports). */
|
|
38
|
+
exports: ExportedSymbol[];
|
|
39
|
+
/** Outgoing import edges from this file. */
|
|
40
|
+
imports: ImportEdge[];
|
|
41
|
+
/** mtime of the source file (ms epoch) for incremental updates. */
|
|
42
|
+
mtimeMs: number;
|
|
43
|
+
}
|
|
44
|
+
export interface RepoGraph {
|
|
45
|
+
/** Schema version for migration. */
|
|
46
|
+
version: number;
|
|
47
|
+
/** ISO timestamp when this graph was built. */
|
|
48
|
+
buildTimestamp: string;
|
|
49
|
+
/** Workspace root used at build time (absolute, for diagnostics only). */
|
|
50
|
+
rootDir: string;
|
|
51
|
+
/** Files keyed by their relative forward-slash path. */
|
|
52
|
+
files: Record<string, FileNode>;
|
|
53
|
+
}
|
|
54
|
+
export interface FileReference {
|
|
55
|
+
file: string;
|
|
56
|
+
line?: number;
|
|
57
|
+
importType?: ImportType;
|
|
58
|
+
}
|
|
59
|
+
export interface SymbolReference {
|
|
60
|
+
file: string;
|
|
61
|
+
line: number;
|
|
62
|
+
importedAs: string;
|
|
63
|
+
}
|
|
64
|
+
export interface BlastRadiusResult {
|
|
65
|
+
target: string[];
|
|
66
|
+
directDependents: string[];
|
|
67
|
+
transitiveDependents: string[];
|
|
68
|
+
depthReached: number;
|
|
69
|
+
totalDependents: number;
|
|
70
|
+
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
71
|
+
}
|
|
72
|
+
export interface LocalizationBlock {
|
|
73
|
+
target: string;
|
|
74
|
+
importerCount: number;
|
|
75
|
+
importers: FileReference[];
|
|
76
|
+
dependencyCount: number;
|
|
77
|
+
dependencies: FileReference[];
|
|
78
|
+
exportedSymbolsUsedExternally: string[];
|
|
79
|
+
blastRadius: BlastRadiusResult;
|
|
80
|
+
/** Compact human/LLM-readable summary suitable for context injection. */
|
|
81
|
+
summary: string;
|
|
82
|
+
}
|
|
83
|
+
export declare const REPO_GRAPH_SCHEMA_VERSION = 1;
|
|
84
|
+
export declare const REPO_GRAPH_FILENAME = "repo-graph.json";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo graph context injection for the system-enhancer hook.
|
|
3
|
+
*
|
|
4
|
+
* Produces compact text blocks that surface structural information
|
|
5
|
+
* (importers, dependents, blast radius) for the file the agent is about
|
|
6
|
+
* to edit. Designed to fit within the system-enhancer's per-block budget
|
|
7
|
+
* (~300-500 chars).
|
|
8
|
+
*
|
|
9
|
+
* Failure mode: silent. If no graph exists (`.swarm/repo-graph.json`
|
|
10
|
+
* absent or invalid), this module returns `null` for every helper —
|
|
11
|
+
* the agent simply doesn't get the extra context. The graph is built
|
|
12
|
+
* on-demand by the agent calling `repo_map` with action="build".
|
|
13
|
+
*
|
|
14
|
+
* Caching: the loaded graph is cached per-directory in module scope to
|
|
15
|
+
* avoid re-reading the JSON on every system prompt construction. The
|
|
16
|
+
* cache is bypassed if the file's mtime advances.
|
|
17
|
+
*/
|
|
18
|
+
import { type RepoGraph } from '../graph';
|
|
19
|
+
/**
|
|
20
|
+
* Load the repo graph for `directory`, using a per-directory cache that
|
|
21
|
+
* invalidates on file mtime change. Returns null if no graph exists.
|
|
22
|
+
*
|
|
23
|
+
* Exported only for tests; production callers use the buildXxxBlock helpers below.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCachedGraph(directory: string): RepoGraph | null;
|
|
26
|
+
/** Test-only: clear the per-directory cache. */
|
|
27
|
+
export declare function resetGraphInjectionCache(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Build a localization block for a target file. Used by the coder agent
|
|
30
|
+
* to surface importers/dependencies/blast-radius before editing.
|
|
31
|
+
*
|
|
32
|
+
* Returns null when:
|
|
33
|
+
* - No graph exists.
|
|
34
|
+
* - The target isn't tracked in the graph (file too new, language unsupported).
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildCoderLocalizationBlock(directory: string, targetFile: string): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Build a blast-radius block for a list of changed files. Used by the
|
|
39
|
+
* reviewer agent to spot-check whether unseen consumers might break.
|
|
40
|
+
*
|
|
41
|
+
* Returns null when no graph exists or when none of the files are in the
|
|
42
|
+
* graph. The result is bounded to the top 8 dependents to stay within
|
|
43
|
+
* the per-block context budget.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildReviewerBlastRadiusBlock(directory: string, changedFiles: string[]): string | null;
|