opencroc 1.4.3 → 1.5.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 +111 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/web/index.html +74 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1270,6 +1270,10 @@ var init_config_validator = __esm({
|
|
|
1270
1270
|
});
|
|
1271
1271
|
|
|
1272
1272
|
// src/pipeline/index.ts
|
|
1273
|
+
var pipeline_exports = {};
|
|
1274
|
+
__export(pipeline_exports, {
|
|
1275
|
+
createPipeline: () => createPipeline
|
|
1276
|
+
});
|
|
1273
1277
|
import * as fs4 from "fs";
|
|
1274
1278
|
import * as path5 from "path";
|
|
1275
1279
|
function createPipeline(config) {
|
|
@@ -3491,6 +3495,39 @@ function registerAgentRoutes(app, office) {
|
|
|
3491
3495
|
agents: office.getAgents()
|
|
3492
3496
|
};
|
|
3493
3497
|
});
|
|
3498
|
+
app.get("/api/files", async () => {
|
|
3499
|
+
const files = office.getGeneratedFiles();
|
|
3500
|
+
return files.map((f) => ({
|
|
3501
|
+
filePath: f.filePath,
|
|
3502
|
+
module: f.module,
|
|
3503
|
+
chain: f.chain,
|
|
3504
|
+
lines: f.content.split("\n").length,
|
|
3505
|
+
size: f.content.length
|
|
3506
|
+
}));
|
|
3507
|
+
});
|
|
3508
|
+
app.get("/api/files/:index", async (req, reply) => {
|
|
3509
|
+
const files = office.getGeneratedFiles();
|
|
3510
|
+
const idx = parseInt(req.params.index, 10);
|
|
3511
|
+
if (isNaN(idx) || idx < 0 || idx >= files.length) {
|
|
3512
|
+
reply.code(404).send({ error: "File not found" });
|
|
3513
|
+
return;
|
|
3514
|
+
}
|
|
3515
|
+
return files[idx];
|
|
3516
|
+
});
|
|
3517
|
+
app.get("/api/pipeline/result", async () => {
|
|
3518
|
+
const result = office.getLastPipelineResult();
|
|
3519
|
+
if (!result) return { ok: false, message: "No pipeline has been run yet" };
|
|
3520
|
+
return {
|
|
3521
|
+
ok: true,
|
|
3522
|
+
modules: result.modules,
|
|
3523
|
+
erDiagramCount: result.erDiagrams.size,
|
|
3524
|
+
chainCount: [...result.chainPlans.values()].reduce((s, p) => s + p.chains.length, 0),
|
|
3525
|
+
totalSteps: [...result.chainPlans.values()].reduce((s, p) => s + p.totalSteps, 0),
|
|
3526
|
+
filesGenerated: result.generatedFiles.length,
|
|
3527
|
+
validationErrors: result.validationErrors.length,
|
|
3528
|
+
duration: result.duration
|
|
3529
|
+
};
|
|
3530
|
+
});
|
|
3494
3531
|
}
|
|
3495
3532
|
var init_agents = __esm({
|
|
3496
3533
|
"src/server/routes/agents.ts"() {
|
|
@@ -3520,6 +3557,8 @@ var init_croc_office = __esm({
|
|
|
3520
3557
|
agents;
|
|
3521
3558
|
cachedGraph = null;
|
|
3522
3559
|
running = false;
|
|
3560
|
+
lastPipelineResult = null;
|
|
3561
|
+
lastGeneratedFiles = [];
|
|
3523
3562
|
constructor(config, cwd) {
|
|
3524
3563
|
this.config = config;
|
|
3525
3564
|
this.cwd = cwd;
|
|
@@ -3589,41 +3628,92 @@ var init_croc_office = __esm({
|
|
|
3589
3628
|
this.running = false;
|
|
3590
3629
|
}
|
|
3591
3630
|
}
|
|
3592
|
-
/** Run the pipeline: scan → er-diagram → api-chain → plan → codegen */
|
|
3631
|
+
/** Run the real pipeline: scan → er-diagram → api-chain → plan → codegen → report */
|
|
3593
3632
|
async runPipeline() {
|
|
3594
3633
|
if (this.running) return { ok: false, task: "pipeline", duration: 0, error: "Another task is running" };
|
|
3595
3634
|
this.running = true;
|
|
3596
3635
|
const start = Date.now();
|
|
3597
3636
|
try {
|
|
3637
|
+
const { resolve: resolvePath } = await import("path");
|
|
3638
|
+
const { createPipeline: createPipeline2 } = await Promise.resolve().then(() => (init_pipeline(), pipeline_exports));
|
|
3639
|
+
const backendRoot = resolvePath(this.cwd, this.config.backendRoot);
|
|
3640
|
+
const pipelineConfig = { ...this.config, backendRoot };
|
|
3641
|
+
const pipeline = createPipeline2(pipelineConfig);
|
|
3598
3642
|
this.updateAgent("parser-croc", { status: "working", currentTask: "Scanning source code...", progress: 10 });
|
|
3599
3643
|
this.log("\u{1F40A} \u89E3\u6790\u9CC4 is scanning source code...");
|
|
3600
3644
|
this.invalidateCache();
|
|
3601
3645
|
await this.buildKnowledgeGraph();
|
|
3602
3646
|
this.updateNodeStatus("module", "testing");
|
|
3603
|
-
this.updateAgent("parser-croc", {
|
|
3647
|
+
this.updateAgent("parser-croc", { currentTask: "Parsing models & ER diagrams...", progress: 40 });
|
|
3648
|
+
const scanResult = await pipeline.run(["scan", "er-diagram"]);
|
|
3649
|
+
const moduleCount = scanResult.modules.length;
|
|
3650
|
+
const erCount = scanResult.erDiagrams.size;
|
|
3651
|
+
this.log(`\u{1F4CA} Found ${moduleCount} modules, ${erCount} ER diagrams`);
|
|
3652
|
+
this.updateAgent("parser-croc", { status: "done", currentTask: `${moduleCount} modules parsed`, progress: 100 });
|
|
3604
3653
|
this.updateAgent("analyzer-croc", { status: "working", currentTask: "Analyzing API chains...", progress: 0 });
|
|
3605
3654
|
this.log("\u{1F40A} \u5206\u6790\u9CC4 is analyzing API dependencies...");
|
|
3606
|
-
await
|
|
3655
|
+
const analyzeResult = await pipeline.run(["api-chain"]);
|
|
3656
|
+
const warnings = analyzeResult.validationErrors.filter((e) => e.severity === "warning");
|
|
3657
|
+
if (warnings.length > 0) {
|
|
3658
|
+
this.log(`\u26A0\uFE0F ${warnings.length} API chain warnings`, "warn");
|
|
3659
|
+
}
|
|
3607
3660
|
this.updateAgent("analyzer-croc", { status: "done", currentTask: "Analysis complete", progress: 100 });
|
|
3608
3661
|
this.updateAgent("planner-croc", { status: "thinking", currentTask: "Planning test chains...", progress: 0 });
|
|
3609
3662
|
this.log("\u{1F40A} \u89C4\u5212\u9CC4 is planning test chains...");
|
|
3610
|
-
await
|
|
3611
|
-
|
|
3663
|
+
const planResult = await pipeline.run(["plan"]);
|
|
3664
|
+
let totalChains = 0, totalSteps = 0;
|
|
3665
|
+
for (const [, plan] of planResult.chainPlans) {
|
|
3666
|
+
totalChains += plan.chains.length;
|
|
3667
|
+
totalSteps += plan.totalSteps;
|
|
3668
|
+
}
|
|
3669
|
+
this.log(`\u{1F4CB} Planned ${totalChains} test chains with ${totalSteps} steps`);
|
|
3670
|
+
this.updateAgent("planner-croc", { status: "done", currentTask: `${totalChains} chains planned`, progress: 100 });
|
|
3612
3671
|
this.updateAgent("tester-croc", { status: "working", currentTask: "Generating test code...", progress: 0 });
|
|
3613
|
-
this.log("\u{1F40A} \u6D4B\u8BD5\u9CC4 is generating test code...");
|
|
3672
|
+
this.log("\u{1F40A} \u6D4B\u8BD5\u9CC4 is generating Playwright test code...");
|
|
3614
3673
|
this.updateNodeStatus("controller", "testing");
|
|
3615
|
-
await
|
|
3674
|
+
const fullResult = await pipeline.run(["scan", "er-diagram", "api-chain", "plan", "codegen"]);
|
|
3675
|
+
this.lastPipelineResult = fullResult;
|
|
3676
|
+
this.lastGeneratedFiles = fullResult.generatedFiles;
|
|
3677
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync10 } = await import("fs");
|
|
3678
|
+
const { dirname: dirname6 } = await import("path");
|
|
3679
|
+
let filesWritten = 0;
|
|
3680
|
+
for (const file of fullResult.generatedFiles) {
|
|
3681
|
+
const fullPath = resolvePath(this.cwd, file.filePath);
|
|
3682
|
+
mkdirSync10(dirname6(fullPath), { recursive: true });
|
|
3683
|
+
writeFileSync10(fullPath, file.content, "utf-8");
|
|
3684
|
+
filesWritten++;
|
|
3685
|
+
}
|
|
3616
3686
|
this.updateNodeStatus("controller", "passed");
|
|
3617
|
-
this.
|
|
3618
|
-
this.updateAgent("
|
|
3687
|
+
this.log(`\u2705 Generated ${filesWritten} test files`);
|
|
3688
|
+
this.updateAgent("tester-croc", { status: "done", currentTask: `${filesWritten} files generated`, progress: 100 });
|
|
3689
|
+
this.broadcast("files:generated", fullResult.generatedFiles.map((f) => ({
|
|
3690
|
+
filePath: f.filePath,
|
|
3691
|
+
module: f.module,
|
|
3692
|
+
chain: f.chain,
|
|
3693
|
+
lines: f.content.split("\n").length
|
|
3694
|
+
})));
|
|
3695
|
+
this.updateAgent("reporter-croc", { status: "working", currentTask: "Compiling report...", progress: 0 });
|
|
3619
3696
|
this.log("\u{1F40A} \u6C47\u62A5\u9CC4 is compiling results...");
|
|
3620
|
-
await
|
|
3697
|
+
const validateResult = await pipeline.run(["validate"]);
|
|
3698
|
+
const errors = validateResult.validationErrors.filter((e) => e.severity === "error");
|
|
3699
|
+
if (errors.length > 0) {
|
|
3700
|
+
this.log(`\u26A0\uFE0F ${errors.length} validation errors`, "warn");
|
|
3701
|
+
}
|
|
3621
3702
|
this.updateNodeStatus("module", "passed");
|
|
3622
3703
|
this.updateAgent("reporter-croc", { status: "done", currentTask: "Report ready", progress: 100 });
|
|
3623
3704
|
const duration = Date.now() - start;
|
|
3624
|
-
this.log(`\u2705 Pipeline complete in ${duration}ms`);
|
|
3625
|
-
this.broadcast("pipeline:complete", {
|
|
3626
|
-
|
|
3705
|
+
this.log(`\u2705 Pipeline complete in ${duration}ms \u2014 ${moduleCount} modules, ${totalChains} chains, ${filesWritten} files`);
|
|
3706
|
+
this.broadcast("pipeline:complete", {
|
|
3707
|
+
duration,
|
|
3708
|
+
status: "success",
|
|
3709
|
+
summary: { modules: moduleCount, chains: totalChains, steps: totalSteps, files: filesWritten }
|
|
3710
|
+
});
|
|
3711
|
+
return { ok: true, task: "pipeline", duration, details: {
|
|
3712
|
+
modules: moduleCount,
|
|
3713
|
+
chains: totalChains,
|
|
3714
|
+
steps: totalSteps,
|
|
3715
|
+
files: filesWritten
|
|
3716
|
+
} };
|
|
3627
3717
|
} catch (err) {
|
|
3628
3718
|
this.updateAgent("tester-croc", { status: "error", currentTask: String(err) });
|
|
3629
3719
|
this.log(`\u274C Pipeline failed: ${err}`, "error");
|
|
@@ -3642,6 +3732,14 @@ var init_croc_office = __esm({
|
|
|
3642
3732
|
}
|
|
3643
3733
|
this.broadcast("agent:update", this.agents);
|
|
3644
3734
|
}
|
|
3735
|
+
/** Get last pipeline result */
|
|
3736
|
+
getLastPipelineResult() {
|
|
3737
|
+
return this.lastPipelineResult;
|
|
3738
|
+
}
|
|
3739
|
+
/** Get generated test files from last pipeline run */
|
|
3740
|
+
getGeneratedFiles() {
|
|
3741
|
+
return this.lastGeneratedFiles;
|
|
3742
|
+
}
|
|
3645
3743
|
// ============ Graph Helpers ============
|
|
3646
3744
|
updateNodeStatus(type, status) {
|
|
3647
3745
|
if (!this.cachedGraph) return;
|
|
@@ -3652,9 +3750,6 @@ var init_croc_office = __esm({
|
|
|
3652
3750
|
}
|
|
3653
3751
|
this.broadcast("graph:update", this.cachedGraph);
|
|
3654
3752
|
}
|
|
3655
|
-
delay(ms) {
|
|
3656
|
-
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
3657
|
-
}
|
|
3658
3753
|
/** Build knowledge graph from project source code */
|
|
3659
3754
|
async buildKnowledgeGraph() {
|
|
3660
3755
|
if (this.cachedGraph) return this.cachedGraph;
|