archbyte 0.4.0 → 0.4.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/bin/archbyte.js +2 -20
- package/dist/agents/pipeline/merger.d.ts +2 -2
- package/dist/agents/pipeline/merger.js +152 -27
- package/dist/agents/pipeline/types.d.ts +29 -1
- package/dist/agents/pipeline/types.js +0 -1
- package/dist/agents/providers/claude-sdk.js +32 -8
- package/dist/agents/runtime/types.d.ts +4 -0
- package/dist/agents/runtime/types.js +2 -2
- package/dist/agents/static/component-detector.js +35 -3
- package/dist/agents/static/connection-mapper.d.ts +1 -1
- package/dist/agents/static/connection-mapper.js +74 -1
- package/dist/agents/static/index.js +5 -2
- package/dist/agents/static/types.d.ts +26 -0
- package/dist/cli/analyze.js +62 -19
- package/dist/cli/arch-diff.d.ts +38 -0
- package/dist/cli/arch-diff.js +61 -0
- package/dist/cli/patrol.d.ts +5 -3
- package/dist/cli/patrol.js +417 -65
- package/dist/cli/setup.js +2 -7
- package/dist/cli/shared.d.ts +11 -0
- package/dist/cli/shared.js +61 -0
- package/dist/cli/validate.d.ts +0 -1
- package/dist/cli/validate.js +0 -16
- package/dist/server/src/index.js +537 -17
- package/package.json +1 -1
- package/templates/archbyte.yaml +8 -0
- package/ui/dist/assets/index-DDCNauh7.css +1 -0
- package/ui/dist/assets/index-DO4t5Xu1.js +72 -0
- package/ui/dist/index.html +2 -2
- package/dist/cli/mcp-server.d.ts +0 -1
- package/dist/cli/mcp-server.js +0 -443
- package/dist/cli/mcp.d.ts +0 -1
- package/dist/cli/mcp.js +0 -98
- package/ui/dist/assets/index-0_XpUUZQ.css +0 -1
- package/ui/dist/assets/index-DmO1qYan.js +0 -70
package/dist/cli/analyze.js
CHANGED
|
@@ -79,25 +79,28 @@ export async function handleAnalyze(options) {
|
|
|
79
79
|
config.apiKey = options.apiKey;
|
|
80
80
|
}
|
|
81
81
|
if (!config) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
82
|
+
const msg = [
|
|
83
|
+
chalk.red("No model provider configured."),
|
|
84
|
+
"",
|
|
85
|
+
chalk.bold("Zero-config (Claude Code users):"),
|
|
86
|
+
chalk.gray(" Install Claude Code → archbyte analyze just works"),
|
|
87
|
+
"",
|
|
88
|
+
chalk.bold("Or set up with:"),
|
|
89
|
+
chalk.gray(" archbyte config set provider anthropic"),
|
|
90
|
+
chalk.gray(" archbyte config set api-key sk-ant-..."),
|
|
91
|
+
"",
|
|
92
|
+
chalk.bold("Or use environment variables:"),
|
|
93
|
+
chalk.gray(" export ARCHBYTE_PROVIDER=anthropic"),
|
|
94
|
+
chalk.gray(" export ARCHBYTE_API_KEY=sk-ant-..."),
|
|
95
|
+
"",
|
|
96
|
+
chalk.bold("Or run without a model:"),
|
|
97
|
+
chalk.gray(" archbyte analyze --static"),
|
|
98
|
+
"",
|
|
99
|
+
chalk.bold("Supported providers:"),
|
|
100
|
+
chalk.gray(" anthropic, openai, google, claude-sdk"),
|
|
101
|
+
].join("\n");
|
|
102
|
+
console.error(msg);
|
|
103
|
+
throw new Error("No model provider configured");
|
|
101
104
|
}
|
|
102
105
|
const providerLabel = config.provider === "claude-sdk" ? "Claude Code (SDK)" : config.provider;
|
|
103
106
|
console.log(chalk.gray(`Provider: ${chalk.white(providerLabel)}`));
|
|
@@ -177,6 +180,19 @@ export async function handleAnalyze(options) {
|
|
|
177
180
|
console.log();
|
|
178
181
|
}
|
|
179
182
|
}
|
|
183
|
+
// 3b. File-tree drift detection (catches zero-commit and major project growth)
|
|
184
|
+
if (priorMeta && !options.force && !incrementalContext) {
|
|
185
|
+
const currentFileCount = countProjectFiles(rootDir);
|
|
186
|
+
const priorCount = priorMeta.filesScanned ?? 0;
|
|
187
|
+
if (currentFileCount > 0 && priorCount > 0 && currentFileCount <= priorCount * 1.5) {
|
|
188
|
+
// File count hasn't grown significantly — skip re-scan
|
|
189
|
+
console.log(chalk.green("No significant changes detected since last scan. Use --force to re-scan."));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (currentFileCount > priorCount) {
|
|
193
|
+
console.log(chalk.yellow(`File tree grew from ${priorCount} to ${currentFileCount} files — running full scan.`));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
180
196
|
// 4. Run static context collection → LLM pipeline
|
|
181
197
|
const progress = progressBar(7);
|
|
182
198
|
progress.update(0, "Collecting static context...");
|
|
@@ -328,6 +344,33 @@ function getGitCommit() {
|
|
|
328
344
|
return undefined;
|
|
329
345
|
}
|
|
330
346
|
}
|
|
347
|
+
function countProjectFiles(rootDir) {
|
|
348
|
+
let count = 0;
|
|
349
|
+
const skip = new Set(["node_modules", ".git", ".archbyte", ".next", "dist", "build", ".cache"]);
|
|
350
|
+
function walk(dir, depth) {
|
|
351
|
+
if (depth > 4)
|
|
352
|
+
return;
|
|
353
|
+
try {
|
|
354
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
355
|
+
for (const entry of entries) {
|
|
356
|
+
if (entry.name.startsWith(".") && entry.name !== ".github")
|
|
357
|
+
continue;
|
|
358
|
+
if (skip.has(entry.name))
|
|
359
|
+
continue;
|
|
360
|
+
const full = path.join(dir, entry.name);
|
|
361
|
+
if (entry.isDirectory()) {
|
|
362
|
+
walk(full, depth + 1);
|
|
363
|
+
}
|
|
364
|
+
else if (/\.(ts|tsx|js|jsx|py|go|rs|java|kt|rb|cs|php|swift|dart)$/i.test(entry.name)) {
|
|
365
|
+
count++;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
catch { /* permission errors, etc. */ }
|
|
370
|
+
}
|
|
371
|
+
walk(rootDir, 0);
|
|
372
|
+
return count;
|
|
373
|
+
}
|
|
331
374
|
function writeScanMetadata(rootDir, durationMs, mode, filesScanned, tokenUsage, incrementalMode, skippedAgents) {
|
|
332
375
|
const meta = {
|
|
333
376
|
analyzedAt: new Date().toISOString(),
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture diff — computes structural changes between two architecture snapshots.
|
|
3
|
+
* Used by patrol for change detection and by diff command for comparison.
|
|
4
|
+
*/
|
|
5
|
+
import type { Architecture } from "../server/src/generator/index.js";
|
|
6
|
+
export interface StructuralDiff {
|
|
7
|
+
addedNodes: Array<{
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
type: string;
|
|
11
|
+
layer: string;
|
|
12
|
+
}>;
|
|
13
|
+
removedNodes: Array<{
|
|
14
|
+
id: string;
|
|
15
|
+
label: string;
|
|
16
|
+
type: string;
|
|
17
|
+
layer: string;
|
|
18
|
+
}>;
|
|
19
|
+
modifiedNodes: Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
field: string;
|
|
22
|
+
from: string;
|
|
23
|
+
to: string;
|
|
24
|
+
}>;
|
|
25
|
+
addedEdges: Array<{
|
|
26
|
+
source: string;
|
|
27
|
+
target: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
}>;
|
|
30
|
+
removedEdges: Array<{
|
|
31
|
+
source: string;
|
|
32
|
+
target: string;
|
|
33
|
+
label?: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export declare function diffArchitectures(prev: Architecture, curr: Architecture): StructuralDiff;
|
|
37
|
+
export declare function loadArchitectureJSON(rootDir: string): Architecture | null;
|
|
38
|
+
export declare function hasStructuralChanges(diff: StructuralDiff): boolean;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture diff — computes structural changes between two architecture snapshots.
|
|
3
|
+
* Used by patrol for change detection and by diff command for comparison.
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
export function diffArchitectures(prev, curr) {
|
|
8
|
+
const prevNodeMap = new Map();
|
|
9
|
+
for (const n of prev.nodes)
|
|
10
|
+
prevNodeMap.set(n.id, n);
|
|
11
|
+
const currNodeMap = new Map();
|
|
12
|
+
for (const n of curr.nodes)
|
|
13
|
+
currNodeMap.set(n.id, n);
|
|
14
|
+
const prevNodeIds = new Set(prev.nodes.map((n) => n.id));
|
|
15
|
+
const currNodeIds = new Set(curr.nodes.map((n) => n.id));
|
|
16
|
+
const addedNodes = curr.nodes
|
|
17
|
+
.filter((n) => !prevNodeIds.has(n.id))
|
|
18
|
+
.map((n) => ({ id: n.id, label: n.label, type: n.type, layer: n.layer }));
|
|
19
|
+
const removedNodes = prev.nodes
|
|
20
|
+
.filter((n) => !currNodeIds.has(n.id))
|
|
21
|
+
.map((n) => ({ id: n.id, label: n.label, type: n.type, layer: n.layer }));
|
|
22
|
+
const modifiedNodes = [];
|
|
23
|
+
for (const n of curr.nodes) {
|
|
24
|
+
const old = prevNodeMap.get(n.id);
|
|
25
|
+
if (!old)
|
|
26
|
+
continue;
|
|
27
|
+
for (const field of ["label", "type", "layer"]) {
|
|
28
|
+
if (old[field] !== n[field]) {
|
|
29
|
+
modifiedNodes.push({ id: n.id, field, from: old[field], to: n[field] });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const edgeKey = (e) => `${e.source}->${e.target}`;
|
|
34
|
+
const prevEdgeKeys = new Set(prev.edges.map(edgeKey));
|
|
35
|
+
const currEdgeKeys = new Set(curr.edges.map(edgeKey));
|
|
36
|
+
const addedEdges = curr.edges
|
|
37
|
+
.filter((e) => !prevEdgeKeys.has(edgeKey(e)))
|
|
38
|
+
.map((e) => ({ source: e.source, target: e.target, label: e.label }));
|
|
39
|
+
const removedEdges = prev.edges
|
|
40
|
+
.filter((e) => !currEdgeKeys.has(edgeKey(e)))
|
|
41
|
+
.map((e) => ({ source: e.source, target: e.target, label: e.label }));
|
|
42
|
+
return { addedNodes, removedNodes, modifiedNodes, addedEdges, removedEdges };
|
|
43
|
+
}
|
|
44
|
+
export function loadArchitectureJSON(rootDir) {
|
|
45
|
+
const archPath = path.join(rootDir, ".archbyte", "architecture.json");
|
|
46
|
+
if (!fs.existsSync(archPath))
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(fs.readFileSync(archPath, "utf-8"));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function hasStructuralChanges(diff) {
|
|
56
|
+
return (diff.addedNodes.length > 0 ||
|
|
57
|
+
diff.removedNodes.length > 0 ||
|
|
58
|
+
diff.modifiedNodes.length > 0 ||
|
|
59
|
+
diff.addedEdges.length > 0 ||
|
|
60
|
+
diff.removedEdges.length > 0);
|
|
61
|
+
}
|
package/dist/cli/patrol.d.ts
CHANGED
|
@@ -4,13 +4,15 @@ interface PatrolOptions {
|
|
|
4
4
|
interval?: string;
|
|
5
5
|
onViolation?: string;
|
|
6
6
|
daemon?: boolean;
|
|
7
|
+
once?: boolean;
|
|
8
|
+
watch?: boolean;
|
|
7
9
|
history?: boolean;
|
|
8
|
-
rescan?: boolean;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* Run the architecture patrol daemon.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* Each cycle: snapshot → analyze (incremental) → generate → validate → diff
|
|
14
|
+
*
|
|
15
|
+
* --once: run a single cycle then exit (used by UI "Run Now")
|
|
14
16
|
*/
|
|
15
17
|
export declare function handlePatrol(options: PatrolOptions): Promise<void>;
|
|
16
18
|
export {};
|