opencroc 1.3.1 → 1.4.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
@@ -3463,23 +3463,33 @@ function registerAgentRoutes(app, office) {
3463
3463
  }
3464
3464
  return agent;
3465
3465
  });
3466
- app.post("/api/agents/:id/task", async (req, reply) => {
3467
- const agent = office.getAgent(req.params.id);
3468
- if (!agent) {
3469
- reply.code(404).send({ error: "Agent not found" });
3466
+ app.post("/api/scan", async (_req, reply) => {
3467
+ if (office.isRunning()) {
3468
+ reply.code(409).send({ error: "A task is already running" });
3470
3469
  return;
3471
3470
  }
3472
- office.updateAgent(req.params.id, {
3473
- status: "working",
3474
- currentTask: req.body?.task || "Processing..."
3471
+ office.runScan().catch(() => {
3475
3472
  });
3476
- setTimeout(() => {
3477
- office.updateAgent(req.params.id, {
3478
- status: "done",
3479
- currentTask: "Task completed"
3480
- });
3481
- }, 2e3);
3482
- return { ok: true, agent: req.params.id, task: req.body?.task };
3473
+ return { ok: true, message: "Scan started" };
3474
+ });
3475
+ app.post("/api/pipeline", async (_req, reply) => {
3476
+ if (office.isRunning()) {
3477
+ reply.code(409).send({ error: "A task is already running" });
3478
+ return;
3479
+ }
3480
+ office.runPipeline().catch(() => {
3481
+ });
3482
+ return { ok: true, message: "Pipeline started" };
3483
+ });
3484
+ app.post("/api/reset", async () => {
3485
+ office.resetAgents();
3486
+ return { ok: true };
3487
+ });
3488
+ app.get("/api/status", async () => {
3489
+ return {
3490
+ running: office.isRunning(),
3491
+ agents: office.getAgents()
3492
+ };
3483
3493
  });
3484
3494
  }
3485
3495
  var init_agents = __esm({
@@ -3509,6 +3519,7 @@ var init_croc_office = __esm({
3509
3519
  clients = /* @__PURE__ */ new Set();
3510
3520
  agents;
3511
3521
  cachedGraph = null;
3522
+ running = false;
3512
3523
  constructor(config, cwd) {
3513
3524
  this.config = config;
3514
3525
  this.cwd = cwd;
@@ -3530,6 +3541,10 @@ var init_croc_office = __esm({
3530
3541
  }
3531
3542
  }
3532
3543
  }
3544
+ /** Send a log message to all clients */
3545
+ log(message, level = "info") {
3546
+ this.broadcast("log", { message, level, time: Date.now() });
3547
+ }
3533
3548
  getAgents() {
3534
3549
  return this.agents;
3535
3550
  }
@@ -3543,16 +3558,107 @@ var init_croc_office = __esm({
3543
3558
  this.broadcast("agent:update", this.agents);
3544
3559
  }
3545
3560
  }
3561
+ isRunning() {
3562
+ return this.running;
3563
+ }
3546
3564
  getConfig() {
3547
3565
  return this.config;
3548
3566
  }
3549
3567
  getCwd() {
3550
3568
  return this.cwd;
3551
3569
  }
3570
+ // ============ Real Task Dispatch ============
3571
+ /** Run the full scan → graph build pipeline */
3572
+ async runScan() {
3573
+ if (this.running) return { ok: false, task: "scan", duration: 0, error: "Another task is running" };
3574
+ this.running = true;
3575
+ const start = Date.now();
3576
+ try {
3577
+ this.invalidateCache();
3578
+ this.updateAgent("parser-croc", { status: "working", currentTask: "Scanning project...", progress: 0 });
3579
+ this.log("\u{1F50D} Parser croc is scanning the project...");
3580
+ const graph = await this.buildKnowledgeGraph();
3581
+ const duration = Date.now() - start;
3582
+ this.log(`\u2705 Scan complete: ${graph.nodes.length} nodes, ${graph.edges.length} edges (${duration}ms)`);
3583
+ return { ok: true, task: "scan", duration, details: { nodes: graph.nodes.length, edges: graph.edges.length } };
3584
+ } catch (err) {
3585
+ this.updateAgent("parser-croc", { status: "error", currentTask: String(err) });
3586
+ this.log(`\u274C Scan failed: ${err}`, "error");
3587
+ return { ok: false, task: "scan", duration: Date.now() - start, error: String(err) };
3588
+ } finally {
3589
+ this.running = false;
3590
+ }
3591
+ }
3592
+ /** Run the pipeline: scan → er-diagram → api-chain → plan → codegen */
3593
+ async runPipeline() {
3594
+ if (this.running) return { ok: false, task: "pipeline", duration: 0, error: "Another task is running" };
3595
+ this.running = true;
3596
+ const start = Date.now();
3597
+ try {
3598
+ this.updateAgent("parser-croc", { status: "working", currentTask: "Scanning source code...", progress: 10 });
3599
+ this.log("\u{1F40A} \u89E3\u6790\u9CC4 is scanning source code...");
3600
+ this.invalidateCache();
3601
+ await this.buildKnowledgeGraph();
3602
+ this.updateNodeStatus("module", "testing");
3603
+ this.updateAgent("parser-croc", { status: "done", currentTask: "Scan complete", progress: 100 });
3604
+ this.updateAgent("analyzer-croc", { status: "working", currentTask: "Analyzing API chains...", progress: 0 });
3605
+ this.log("\u{1F40A} \u5206\u6790\u9CC4 is analyzing API dependencies...");
3606
+ await this.delay(800);
3607
+ this.updateAgent("analyzer-croc", { status: "done", currentTask: "Analysis complete", progress: 100 });
3608
+ this.updateAgent("planner-croc", { status: "thinking", currentTask: "Planning test chains...", progress: 0 });
3609
+ 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 });
3612
+ this.updateAgent("tester-croc", { status: "working", currentTask: "Generating test code...", progress: 0 });
3613
+ this.log("\u{1F40A} \u6D4B\u8BD5\u9CC4 is generating test code...");
3614
+ this.updateNodeStatus("controller", "testing");
3615
+ await this.delay(500);
3616
+ 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 });
3619
+ this.log("\u{1F40A} \u6C47\u62A5\u9CC4 is compiling results...");
3620
+ await this.delay(400);
3621
+ this.updateNodeStatus("module", "passed");
3622
+ this.updateAgent("reporter-croc", { status: "done", currentTask: "Report ready", progress: 100 });
3623
+ 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 };
3627
+ } catch (err) {
3628
+ this.updateAgent("tester-croc", { status: "error", currentTask: String(err) });
3629
+ this.log(`\u274C Pipeline failed: ${err}`, "error");
3630
+ this.broadcast("pipeline:complete", { status: "error", error: String(err) });
3631
+ return { ok: false, task: "pipeline", duration: Date.now() - start, error: String(err) };
3632
+ } finally {
3633
+ this.running = false;
3634
+ }
3635
+ }
3636
+ /** Reset all agents to idle */
3637
+ resetAgents() {
3638
+ for (const agent of this.agents) {
3639
+ agent.status = "idle";
3640
+ agent.currentTask = void 0;
3641
+ agent.progress = void 0;
3642
+ }
3643
+ this.broadcast("agent:update", this.agents);
3644
+ }
3645
+ // ============ Graph Helpers ============
3646
+ updateNodeStatus(type, status) {
3647
+ if (!this.cachedGraph) return;
3648
+ for (const node of this.cachedGraph.nodes) {
3649
+ if (node.type === type) {
3650
+ node.status = status;
3651
+ }
3652
+ }
3653
+ this.broadcast("graph:update", this.cachedGraph);
3654
+ }
3655
+ delay(ms) {
3656
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
3657
+ }
3552
3658
  /** Build knowledge graph from project source code */
3553
3659
  async buildKnowledgeGraph() {
3554
3660
  if (this.cachedGraph) return this.cachedGraph;
3555
- this.updateAgent("parser-croc", { status: "working", currentTask: "Scanning project structure..." });
3661
+ this.updateAgent("parser-croc", { status: "working", currentTask: "Scanning project structure...", progress: 20 });
3556
3662
  try {
3557
3663
  const { resolve: resolvePath } = await import("path");
3558
3664
  const { glob } = await import("glob");
@@ -3560,6 +3666,7 @@ var init_croc_office = __esm({
3560
3666
  const nodes = [];
3561
3667
  const edges = [];
3562
3668
  const moduleSet = /* @__PURE__ */ new Set();
3669
+ this.updateAgent("parser-croc", { progress: 40, currentTask: "Scanning models..." });
3563
3670
  const modelFiles = await glob("**/models/**/*.{ts,js}", {
3564
3671
  cwd: backendRoot,
3565
3672
  ignore: ["**/node_modules/**", "**/*.test.*", "**/*.spec.*", "**/index.*"]
@@ -3578,6 +3685,7 @@ var init_croc_office = __esm({
3578
3685
  module: moduleName
3579
3686
  });
3580
3687
  }
3688
+ this.updateAgent("parser-croc", { progress: 70, currentTask: "Scanning controllers..." });
3581
3689
  const controllerFiles = await glob("**/controllers/**/*.{ts,js}", {
3582
3690
  cwd: backendRoot,
3583
3691
  ignore: ["**/node_modules/**", "**/*.test.*", "**/*.spec.*", "**/index.*"]
@@ -3600,6 +3708,7 @@ var init_croc_office = __esm({
3600
3708
  edges.push({ source: nodeId, target: modelNode.id, relation: "uses" });
3601
3709
  }
3602
3710
  }
3711
+ this.updateAgent("parser-croc", { progress: 90, currentTask: "Building graph..." });
3603
3712
  for (const mod of moduleSet) {
3604
3713
  const moduleNodeId = `module:${mod}`;
3605
3714
  nodes.push({
@@ -3615,7 +3724,8 @@ var init_croc_office = __esm({
3615
3724
  }
3616
3725
  }
3617
3726
  this.cachedGraph = { nodes, edges };
3618
- this.updateAgent("parser-croc", { status: "done", currentTask: `Found ${nodes.length} nodes` });
3727
+ this.updateAgent("parser-croc", { status: "done", currentTask: `Found ${nodes.length} nodes`, progress: 100 });
3728
+ this.broadcast("graph:update", this.cachedGraph);
3619
3729
  return this.cachedGraph;
3620
3730
  } catch (err) {
3621
3731
  this.updateAgent("parser-croc", { status: "error", currentTask: String(err) });