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 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", { status: "done", currentTask: "Scan complete", progress: 100 });
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 this.delay(800);
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 this.delay(600);
3611
- this.updateAgent("planner-croc", { status: "done", currentTask: "Plan ready", progress: 100 });
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 this.delay(500);
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.updateAgent("tester-croc", { status: "done", currentTask: "Tests generated", progress: 100 });
3618
- this.updateAgent("reporter-croc", { status: "working", currentTask: "Building report...", progress: 0 });
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 this.delay(400);
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", { duration, status: "success" });
3626
- return { ok: true, task: "pipeline", duration };
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;