opencroc 1.8.1 → 1.8.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/dist/cli/index.js +755 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +128 -1
- package/dist/index.js +548 -0
- package/dist/index.js.map +1 -1
- package/dist/web/dist/assets/main-Ccg3eDNK.js +1 -0
- package/dist/web/dist/assets/office-runtime-B3iNctxE.css +1 -0
- package/dist/web/dist/assets/office-runtime-BsCh82Pj.js +183 -0
- package/dist/web/dist/assets/pixel-page-3BYGm7dH.js +470 -0
- package/dist/web/dist/assets/react-vendor-C8RhVn0h.js +49 -0
- package/dist/web/dist/assets/studio-page-BInoyoV2.css +1 -0
- package/dist/web/dist/assets/studio-page-o3SCvE_v.js +351 -0
- package/dist/web/dist/assets/three-addons-BdrPp04O.js +470 -0
- package/dist/web/dist/assets/three-core-CsxM1PCY.js +4057 -0
- package/dist/web/dist/index.html +15 -0
- package/dist/web/index.html +11 -572
- package/dist/web/public/botreview/char_0.png +0 -0
- package/dist/web/public/botreview/char_1.png +0 -0
- package/dist/web/public/botreview/char_2.png +0 -0
- package/dist/web/public/botreview/coffee-machine.gif +0 -0
- package/dist/web/public/botreview/server.gif +0 -0
- package/dist/web/public/botreview/walls.png +0 -0
- package/dist/web/public/star/desk-v3.webp +0 -0
- package/dist/web/public/star/office_bg_small.webp +0 -0
- package/dist/web/public/star/star-idle-v5.png +0 -0
- package/dist/web/public/star/star-working-spritesheet-grid.webp +0 -0
- package/dist/web/src/app/AppLayout.tsx +34 -0
- package/dist/web/src/app/AppRouter.tsx +46 -0
- package/dist/web/src/app/bootstrap.tsx +22 -0
- package/dist/web/src/app/routes.tsx +52 -0
- package/dist/web/src/features/office/runtime/index.ts +1 -0
- package/dist/web/src/features/office/runtime/mount.ts +809 -0
- package/dist/web/src/features/pixel/runtime/index.ts +1 -0
- package/dist/web/src/features/pixel/runtime/mount.ts +728 -0
- package/dist/web/src/features/studio/runtime/index.ts +1 -0
- package/dist/web/src/features/studio/runtime/mount.ts +664 -0
- package/dist/web/src/features/three/engine/index.ts +1 -0
- package/dist/web/src/main.tsx +7 -0
- package/dist/web/src/pages/office/index.ts +1 -0
- package/dist/web/src/pages/office/page.tsx +283 -0
- package/dist/web/src/pages/pixel/index.ts +1 -0
- package/dist/web/src/pages/pixel/page.tsx +564 -0
- package/dist/web/src/pages/studio/index.ts +1 -0
- package/dist/web/src/pages/studio/page.tsx +446 -0
- package/dist/web/{js/agents.js → src/runtime/agents.ts} +304 -31
- package/dist/web/{js/camera.js → src/runtime/camera.ts} +12 -5
- package/dist/web/{js/dataviz.js → src/runtime/dataviz.ts} +38 -14
- package/dist/web/{js/effects.js → src/runtime/effects.ts} +139 -2
- package/dist/web/{js/engine.js → src/runtime/engine.ts} +45 -6
- package/dist/web/{js/office.js → src/runtime/office.ts} +136 -20
- package/dist/web/{js/ui.js → src/runtime/ui.ts} +11 -7
- package/dist/web/src/shared/assets.ts +4 -0
- package/dist/web/src/shared/navigation.ts +47 -0
- package/dist/web/src/styles/app-layout.css +19 -0
- package/dist/web/src/styles/office.css +268 -0
- package/dist/web/tsconfig.json +28 -0
- package/dist/web/vite.config.ts +93 -0
- package/package.json +11 -2
- package/dist/web/index-studio.html +0 -1644
- package/dist/web/index-v2-pixel.html +0 -1571
- /package/dist/web/{assets → dist}/botreview/char_0.png +0 -0
- /package/dist/web/{assets → dist}/botreview/char_1.png +0 -0
- /package/dist/web/{assets → dist}/botreview/char_2.png +0 -0
- /package/dist/web/{assets → dist}/botreview/coffee-machine.gif +0 -0
- /package/dist/web/{assets → dist}/botreview/server.gif +0 -0
- /package/dist/web/{assets → dist}/botreview/walls.png +0 -0
- /package/dist/web/{assets → dist}/star/desk-v3.webp +0 -0
- /package/dist/web/{assets → dist}/star/office_bg_small.webp +0 -0
- /package/dist/web/{assets → dist}/star/star-idle-v5.png +0 -0
- /package/dist/web/{assets → dist}/star/star-working-spritesheet-grid.webp +0 -0
- /package/dist/web/{js/state.js → src/runtime/state.ts} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -6511,12 +6511,430 @@ var init_studio_store = __esm({
|
|
|
6511
6511
|
}
|
|
6512
6512
|
});
|
|
6513
6513
|
|
|
6514
|
+
// src/agents/role-registry.ts
|
|
6515
|
+
var role_registry_exports = {};
|
|
6516
|
+
__export(role_registry_exports, {
|
|
6517
|
+
RoleRegistry: () => RoleRegistry,
|
|
6518
|
+
getRoleRegistry: () => getRoleRegistry
|
|
6519
|
+
});
|
|
6520
|
+
function getRoleRegistry() {
|
|
6521
|
+
if (!_registry) {
|
|
6522
|
+
_registry = new RoleRegistry();
|
|
6523
|
+
}
|
|
6524
|
+
return _registry;
|
|
6525
|
+
}
|
|
6526
|
+
var CORE_ROLES, LANGUAGE_ROLES, FRAMEWORK_ROLES, DOMAIN_ROLES, RoleRegistry, _registry;
|
|
6527
|
+
var init_role_registry = __esm({
|
|
6528
|
+
"src/agents/role-registry.ts"() {
|
|
6529
|
+
"use strict";
|
|
6530
|
+
init_esm_shims();
|
|
6531
|
+
CORE_ROLES = [
|
|
6532
|
+
{
|
|
6533
|
+
id: "parser-croc",
|
|
6534
|
+
name: "\u89E3\u6790\u9CC4",
|
|
6535
|
+
nameEn: "Parser Croc",
|
|
6536
|
+
category: "core",
|
|
6537
|
+
description: "\u89E3\u6790\u9879\u76EE\u7ED3\u6784\u3001\u63D0\u53D6\u5B9E\u4F53\u548C\u5173\u7CFB",
|
|
6538
|
+
sprite: "parser",
|
|
6539
|
+
color: "#34d399",
|
|
6540
|
+
priority: 0,
|
|
6541
|
+
triggers: { custom: () => true },
|
|
6542
|
+
// Always summoned
|
|
6543
|
+
systemPrompt: "You are an expert code parser. Analyze the project structure, extract all entities (classes, functions, APIs, models) and their relationships.",
|
|
6544
|
+
outputType: "analysis",
|
|
6545
|
+
tags: ["core", "parser", "structure"]
|
|
6546
|
+
},
|
|
6547
|
+
{
|
|
6548
|
+
id: "analyzer-croc",
|
|
6549
|
+
name: "\u5206\u6790\u9CC4",
|
|
6550
|
+
nameEn: "Analyzer Croc",
|
|
6551
|
+
category: "core",
|
|
6552
|
+
description: "\u6784\u5EFA\u77E5\u8BC6\u56FE\u8C31\u3001\u5206\u6790\u4F9D\u8D56\u5173\u7CFB",
|
|
6553
|
+
sprite: "analyzer",
|
|
6554
|
+
color: "#60a5fa",
|
|
6555
|
+
priority: 1,
|
|
6556
|
+
triggers: { custom: () => true },
|
|
6557
|
+
systemPrompt: "You are an expert software architect. Build a knowledge graph of the project, analyze dependencies, coupling, and cohesion.",
|
|
6558
|
+
outputType: "diagram",
|
|
6559
|
+
tags: ["core", "graph", "architecture"]
|
|
6560
|
+
},
|
|
6561
|
+
{
|
|
6562
|
+
id: "tester-croc",
|
|
6563
|
+
name: "\u6D4B\u8BD5\u9CC4",
|
|
6564
|
+
nameEn: "Tester Croc",
|
|
6565
|
+
category: "core",
|
|
6566
|
+
description: "\u751F\u6210\u548C\u6267\u884C E2E \u6D4B\u8BD5",
|
|
6567
|
+
sprite: "tester",
|
|
6568
|
+
color: "#a78bfa",
|
|
6569
|
+
priority: 2,
|
|
6570
|
+
triggers: { custom: () => true },
|
|
6571
|
+
systemPrompt: "You are an expert test engineer. Generate comprehensive E2E test cases covering all critical paths, edge cases, and error scenarios.",
|
|
6572
|
+
outputType: "analysis",
|
|
6573
|
+
tags: ["core", "testing", "e2e"]
|
|
6574
|
+
},
|
|
6575
|
+
{
|
|
6576
|
+
id: "healer-croc",
|
|
6577
|
+
name: "\u4FEE\u590D\u9CC4",
|
|
6578
|
+
nameEn: "Healer Croc",
|
|
6579
|
+
category: "core",
|
|
6580
|
+
description: "\u81EA\u52A8\u4FEE\u590D\u6D4B\u8BD5\u5931\u8D25\u548C\u4EE3\u7801\u95EE\u9898",
|
|
6581
|
+
sprite: "healer",
|
|
6582
|
+
color: "#f87171",
|
|
6583
|
+
priority: 3,
|
|
6584
|
+
triggers: { custom: () => true },
|
|
6585
|
+
systemPrompt: "You are an expert debugger and code fixer. Analyze test failures, diagnose root causes, and propose minimal targeted fixes.",
|
|
6586
|
+
outputType: "fix",
|
|
6587
|
+
tags: ["core", "healing", "debug"]
|
|
6588
|
+
},
|
|
6589
|
+
{
|
|
6590
|
+
id: "planner-croc",
|
|
6591
|
+
name: "\u89C4\u5212\u9CC4",
|
|
6592
|
+
nameEn: "Planner Croc",
|
|
6593
|
+
category: "core",
|
|
6594
|
+
description: "\u5236\u5B9A\u6D4B\u8BD5\u7B56\u7565\u548C\u6267\u884C\u8BA1\u5212",
|
|
6595
|
+
sprite: "planner",
|
|
6596
|
+
color: "#fbbf24",
|
|
6597
|
+
priority: 4,
|
|
6598
|
+
triggers: { custom: () => true },
|
|
6599
|
+
systemPrompt: "You are an expert project planner. Create test strategies, prioritize test execution order, and optimize the testing pipeline.",
|
|
6600
|
+
outputType: "analysis",
|
|
6601
|
+
tags: ["core", "planning", "strategy"]
|
|
6602
|
+
},
|
|
6603
|
+
{
|
|
6604
|
+
id: "reporter-croc",
|
|
6605
|
+
name: "\u6C47\u62A5\u9CC4",
|
|
6606
|
+
nameEn: "Reporter Croc",
|
|
6607
|
+
category: "core",
|
|
6608
|
+
description: "\u751F\u6210\u591A\u89C6\u89D2\u5206\u6790\u62A5\u544A",
|
|
6609
|
+
sprite: "reporter",
|
|
6610
|
+
color: "#22d3ee",
|
|
6611
|
+
priority: 5,
|
|
6612
|
+
triggers: { custom: () => true },
|
|
6613
|
+
systemPrompt: "You are an expert technical writer. Generate clear, actionable reports from multiple perspectives (developer, architect, tester, product, executive).",
|
|
6614
|
+
outputType: "report",
|
|
6615
|
+
tags: ["core", "reporting", "documentation"]
|
|
6616
|
+
}
|
|
6617
|
+
];
|
|
6618
|
+
LANGUAGE_ROLES = [
|
|
6619
|
+
{
|
|
6620
|
+
id: "python-croc",
|
|
6621
|
+
name: "Python\u4E13\u5BB6\u9CC4",
|
|
6622
|
+
nameEn: "Python Expert Croc",
|
|
6623
|
+
category: "language",
|
|
6624
|
+
description: "Python \u751F\u6001\u4E13\u5BB6\uFF1ADjango/Flask/FastAPI/SQLAlchemy",
|
|
6625
|
+
sprite: "language",
|
|
6626
|
+
color: "#3776ab",
|
|
6627
|
+
priority: 10,
|
|
6628
|
+
triggers: { languages: ["python"] },
|
|
6629
|
+
systemPrompt: "You are a Python ecosystem expert. Analyze Python code for best practices, type safety, async patterns, Django/Flask/FastAPI conventions, SQLAlchemy usage, and Python-specific security issues.",
|
|
6630
|
+
outputType: "review",
|
|
6631
|
+
tags: ["language", "python", "django", "flask", "fastapi"]
|
|
6632
|
+
},
|
|
6633
|
+
{
|
|
6634
|
+
id: "go-croc",
|
|
6635
|
+
name: "Go\u4E13\u5BB6\u9CC4",
|
|
6636
|
+
nameEn: "Go Expert Croc",
|
|
6637
|
+
category: "language",
|
|
6638
|
+
description: "Go \u751F\u6001\u4E13\u5BB6\uFF1Agoroutine/channel/\u63A5\u53E3\u8BBE\u8BA1",
|
|
6639
|
+
sprite: "language",
|
|
6640
|
+
color: "#00add8",
|
|
6641
|
+
priority: 10,
|
|
6642
|
+
triggers: { languages: ["go"] },
|
|
6643
|
+
systemPrompt: "You are a Go ecosystem expert. Analyze Go code for goroutine safety, channel patterns, interface design, error handling, and Go-specific performance concerns.",
|
|
6644
|
+
outputType: "review",
|
|
6645
|
+
tags: ["language", "go", "golang", "concurrency"]
|
|
6646
|
+
},
|
|
6647
|
+
{
|
|
6648
|
+
id: "java-croc",
|
|
6649
|
+
name: "Java\u4E13\u5BB6\u9CC4",
|
|
6650
|
+
nameEn: "Java Expert Croc",
|
|
6651
|
+
category: "language",
|
|
6652
|
+
description: "Java/Kotlin \u751F\u6001\u4E13\u5BB6\uFF1ASpring Boot/JPA/\u5FAE\u670D\u52A1",
|
|
6653
|
+
sprite: "language",
|
|
6654
|
+
color: "#ed8b00",
|
|
6655
|
+
priority: 10,
|
|
6656
|
+
triggers: { languages: ["java", "kotlin"] },
|
|
6657
|
+
systemPrompt: "You are a Java/Kotlin ecosystem expert. Analyze Spring Boot applications for bean lifecycle issues, JPA N+1 queries, transaction management, and microservice patterns.",
|
|
6658
|
+
outputType: "review",
|
|
6659
|
+
tags: ["language", "java", "kotlin", "spring"]
|
|
6660
|
+
},
|
|
6661
|
+
{
|
|
6662
|
+
id: "rust-croc",
|
|
6663
|
+
name: "Rust\u4E13\u5BB6\u9CC4",
|
|
6664
|
+
nameEn: "Rust Expert Croc",
|
|
6665
|
+
category: "language",
|
|
6666
|
+
description: "Rust \u751F\u6001\u4E13\u5BB6\uFF1A\u6240\u6709\u6743/\u751F\u547D\u5468\u671F/unsafe",
|
|
6667
|
+
sprite: "language",
|
|
6668
|
+
color: "#dea584",
|
|
6669
|
+
priority: 10,
|
|
6670
|
+
triggers: { languages: ["rust"] },
|
|
6671
|
+
systemPrompt: "You are a Rust ecosystem expert. Analyze Rust code for ownership patterns, lifetime issues, unsafe code safety, and performance optimization.",
|
|
6672
|
+
outputType: "review",
|
|
6673
|
+
tags: ["language", "rust", "ownership", "safety"]
|
|
6674
|
+
}
|
|
6675
|
+
];
|
|
6676
|
+
FRAMEWORK_ROLES = [
|
|
6677
|
+
{
|
|
6678
|
+
id: "react-croc",
|
|
6679
|
+
name: "React\u4E13\u5BB6\u9CC4",
|
|
6680
|
+
nameEn: "React Expert Croc",
|
|
6681
|
+
category: "framework",
|
|
6682
|
+
description: "React/Next.js \u524D\u7AEF\u6027\u80FD\u548C\u67B6\u6784\u4E13\u5BB6",
|
|
6683
|
+
sprite: "framework",
|
|
6684
|
+
color: "#61dafb",
|
|
6685
|
+
priority: 15,
|
|
6686
|
+
triggers: { frameworks: ["React", "Next.js"] },
|
|
6687
|
+
systemPrompt: "You are a React/Next.js expert. Analyze component architecture, render performance, state management, SSR/SSG patterns, and React-specific anti-patterns.",
|
|
6688
|
+
outputType: "review",
|
|
6689
|
+
tags: ["framework", "react", "nextjs", "frontend"]
|
|
6690
|
+
},
|
|
6691
|
+
{
|
|
6692
|
+
id: "vue-croc",
|
|
6693
|
+
name: "Vue\u4E13\u5BB6\u9CC4",
|
|
6694
|
+
nameEn: "Vue Expert Croc",
|
|
6695
|
+
category: "framework",
|
|
6696
|
+
description: "Vue/Nuxt \u4E13\u5BB6\uFF1A\u7EC4\u5408\u5F0FAPI/\u54CD\u5E94\u5F0F/SSR",
|
|
6697
|
+
sprite: "framework",
|
|
6698
|
+
color: "#42b883",
|
|
6699
|
+
priority: 15,
|
|
6700
|
+
triggers: { frameworks: ["Vue", "Nuxt"] },
|
|
6701
|
+
systemPrompt: "You are a Vue/Nuxt expert. Analyze Composition API usage, reactivity patterns, Pinia stores, SSR hydration, and Vue-specific best practices.",
|
|
6702
|
+
outputType: "review",
|
|
6703
|
+
tags: ["framework", "vue", "nuxt", "frontend"]
|
|
6704
|
+
},
|
|
6705
|
+
{
|
|
6706
|
+
id: "express-croc",
|
|
6707
|
+
name: "Express\u4E13\u5BB6\u9CC4",
|
|
6708
|
+
nameEn: "Express Expert Croc",
|
|
6709
|
+
category: "framework",
|
|
6710
|
+
description: "Express/Koa/Fastify \u8DEF\u7531\u548C\u4E2D\u95F4\u4EF6\u4E13\u5BB6",
|
|
6711
|
+
sprite: "framework",
|
|
6712
|
+
color: "#68a063",
|
|
6713
|
+
priority: 15,
|
|
6714
|
+
triggers: { frameworks: ["Express", "Koa", "Fastify"] },
|
|
6715
|
+
systemPrompt: "You are a Node.js backend expert. Analyze Express/Koa/Fastify middleware chains, route organization, error handling, authentication patterns, and performance.",
|
|
6716
|
+
outputType: "review",
|
|
6717
|
+
tags: ["framework", "express", "koa", "fastify", "nodejs"]
|
|
6718
|
+
},
|
|
6719
|
+
{
|
|
6720
|
+
id: "django-croc",
|
|
6721
|
+
name: "Django\u4E13\u5BB6\u9CC4",
|
|
6722
|
+
nameEn: "Django Expert Croc",
|
|
6723
|
+
category: "framework",
|
|
6724
|
+
description: "Django/DRF \u4E13\u5BB6\uFF1AORM/\u5E8F\u5217\u5316/\u6743\u9650",
|
|
6725
|
+
sprite: "framework",
|
|
6726
|
+
color: "#092e20",
|
|
6727
|
+
priority: 15,
|
|
6728
|
+
triggers: { frameworks: ["Django", "DRF"] },
|
|
6729
|
+
systemPrompt: "You are a Django/DRF expert. Analyze ORM query efficiency, serializer design, view permissions, middleware, and Django-specific security practices.",
|
|
6730
|
+
outputType: "review",
|
|
6731
|
+
tags: ["framework", "django", "drf", "python"]
|
|
6732
|
+
},
|
|
6733
|
+
{
|
|
6734
|
+
id: "spring-croc",
|
|
6735
|
+
name: "SpringBoot\u4E13\u5BB6\u9CC4",
|
|
6736
|
+
nameEn: "Spring Boot Expert Croc",
|
|
6737
|
+
category: "framework",
|
|
6738
|
+
description: "Spring Boot/Cloud \u5FAE\u670D\u52A1\u67B6\u6784\u4E13\u5BB6",
|
|
6739
|
+
sprite: "framework",
|
|
6740
|
+
color: "#6db33f",
|
|
6741
|
+
priority: 15,
|
|
6742
|
+
triggers: { frameworks: ["Spring Boot", "Spring Cloud"] },
|
|
6743
|
+
systemPrompt: "You are a Spring Boot/Cloud expert. Analyze bean configurations, transaction management, service discovery, circuit breakers, and microservice communication patterns.",
|
|
6744
|
+
outputType: "review",
|
|
6745
|
+
tags: ["framework", "spring", "springboot", "microservice"]
|
|
6746
|
+
}
|
|
6747
|
+
];
|
|
6748
|
+
DOMAIN_ROLES = [
|
|
6749
|
+
{
|
|
6750
|
+
id: "security-croc",
|
|
6751
|
+
name: "\u5B89\u5168\u5BA1\u8BA1\u9CC4",
|
|
6752
|
+
nameEn: "Security Auditor Croc",
|
|
6753
|
+
category: "domain",
|
|
6754
|
+
description: "\u5B89\u5168\u6F0F\u6D1E\u68C0\u6D4B\uFF1A\u6CE8\u5165/XSS/CSRF/\u8BA4\u8BC1/\u6388\u6743",
|
|
6755
|
+
sprite: "security",
|
|
6756
|
+
color: "#ef4444",
|
|
6757
|
+
priority: 8,
|
|
6758
|
+
triggers: {
|
|
6759
|
+
riskCategories: ["security"],
|
|
6760
|
+
custom: (ctx) => ctx.hasAPIs
|
|
6761
|
+
},
|
|
6762
|
+
systemPrompt: "You are a security auditor. Scan for OWASP Top 10 vulnerabilities: SQL injection, XSS, CSRF, broken authentication, sensitive data exposure, insecure deserialization, and missing access controls.",
|
|
6763
|
+
outputType: "report",
|
|
6764
|
+
tags: ["domain", "security", "owasp", "audit"]
|
|
6765
|
+
},
|
|
6766
|
+
{
|
|
6767
|
+
id: "performance-croc",
|
|
6768
|
+
name: "\u6027\u80FD\u5206\u6790\u9CC4",
|
|
6769
|
+
nameEn: "Performance Analyst Croc",
|
|
6770
|
+
category: "domain",
|
|
6771
|
+
description: "\u6027\u80FD\u74F6\u9888\u68C0\u6D4B\uFF1AN+1\u67E5\u8BE2/\u5185\u5B58\u6CC4\u6F0F/\u6162\u63A5\u53E3",
|
|
6772
|
+
sprite: "performance",
|
|
6773
|
+
color: "#f59e0b",
|
|
6774
|
+
priority: 9,
|
|
6775
|
+
triggers: {
|
|
6776
|
+
minEntities: 50,
|
|
6777
|
+
custom: (ctx) => ctx.hasModels && ctx.hasAPIs
|
|
6778
|
+
},
|
|
6779
|
+
systemPrompt: "You are a performance analyst. Detect N+1 queries, memory leaks, slow API endpoints, missing indexes, unnecessary data loading, and recommend caching strategies.",
|
|
6780
|
+
outputType: "report",
|
|
6781
|
+
tags: ["domain", "performance", "optimization", "n+1"]
|
|
6782
|
+
},
|
|
6783
|
+
{
|
|
6784
|
+
id: "architecture-croc",
|
|
6785
|
+
name: "\u67B6\u6784\u8BC4\u5BA1\u9CC4",
|
|
6786
|
+
nameEn: "Architecture Reviewer Croc",
|
|
6787
|
+
category: "domain",
|
|
6788
|
+
description: "\u67B6\u6784\u8D28\u91CF\u8BC4\u5BA1\uFF1A\u8026\u5408\u5EA6/\u5185\u805A\u6027/\u5206\u5C42/DDD",
|
|
6789
|
+
sprite: "architecture",
|
|
6790
|
+
color: "#8b5cf6",
|
|
6791
|
+
priority: 7,
|
|
6792
|
+
triggers: {
|
|
6793
|
+
minEntities: 30
|
|
6794
|
+
},
|
|
6795
|
+
systemPrompt: "You are a software architect. Evaluate coupling, cohesion, layering, dependency injection, SOLID principles, DDD patterns, and recommend architectural improvements.",
|
|
6796
|
+
outputType: "review",
|
|
6797
|
+
tags: ["domain", "architecture", "solid", "ddd"]
|
|
6798
|
+
},
|
|
6799
|
+
{
|
|
6800
|
+
id: "data-modeling-croc",
|
|
6801
|
+
name: "\u6570\u636E\u5EFA\u6A21\u9CC4",
|
|
6802
|
+
nameEn: "Data Modeling Croc",
|
|
6803
|
+
category: "domain",
|
|
6804
|
+
description: "\u6570\u636E\u6A21\u578B\u8BC4\u5BA1\uFF1A\u8303\u5F0F/\u7D22\u5F15/\u5173\u8054/\u8FC1\u79FB",
|
|
6805
|
+
sprite: "database",
|
|
6806
|
+
color: "#06b6d4",
|
|
6807
|
+
priority: 9,
|
|
6808
|
+
triggers: {
|
|
6809
|
+
custom: (ctx) => ctx.hasModels,
|
|
6810
|
+
frameworks: ["Sequelize", "Prisma", "TypeORM", "Drizzle", "SQLAlchemy", "Django"]
|
|
6811
|
+
},
|
|
6812
|
+
systemPrompt: "You are a database expert. Review data models for normalization, index design, relationship integrity, migration safety, cascade delete risks, and query optimization.",
|
|
6813
|
+
outputType: "review",
|
|
6814
|
+
tags: ["domain", "database", "modeling", "orm"]
|
|
6815
|
+
},
|
|
6816
|
+
{
|
|
6817
|
+
id: "devops-croc",
|
|
6818
|
+
name: "\u8FD0\u7EF4\u90E8\u7F72\u9CC4",
|
|
6819
|
+
nameEn: "DevOps Croc",
|
|
6820
|
+
category: "domain",
|
|
6821
|
+
description: "CI/CD\u3001Docker\u3001K8s \u90E8\u7F72\u548C\u8FD0\u7EF4\u4E13\u5BB6",
|
|
6822
|
+
sprite: "devops",
|
|
6823
|
+
color: "#2563eb",
|
|
6824
|
+
priority: 12,
|
|
6825
|
+
triggers: {
|
|
6826
|
+
custom: (ctx) => ctx.hasDocker || ctx.hasCI,
|
|
6827
|
+
filePatterns: ["Dockerfile", "docker-compose*", ".github/workflows/*", ".gitlab-ci*", "Jenkinsfile"]
|
|
6828
|
+
},
|
|
6829
|
+
systemPrompt: "You are a DevOps expert. Analyze Dockerfile efficiency, compose orchestration, CI/CD pipeline design, secret management, health checks, and deployment strategies.",
|
|
6830
|
+
outputType: "review",
|
|
6831
|
+
tags: ["domain", "devops", "docker", "ci/cd", "kubernetes"]
|
|
6832
|
+
},
|
|
6833
|
+
{
|
|
6834
|
+
id: "api-design-croc",
|
|
6835
|
+
name: "API\u8BBE\u8BA1\u9CC4",
|
|
6836
|
+
nameEn: "API Design Croc",
|
|
6837
|
+
category: "domain",
|
|
6838
|
+
description: "RESTful API \u8BBE\u8BA1\u8BC4\u5BA1\uFF1A\u547D\u540D/\u7248\u672C/\u5206\u9875/\u9519\u8BEF\u5904\u7406",
|
|
6839
|
+
sprite: "api",
|
|
6840
|
+
color: "#10b981",
|
|
6841
|
+
priority: 11,
|
|
6842
|
+
triggers: {
|
|
6843
|
+
custom: (ctx) => ctx.hasAPIs,
|
|
6844
|
+
minEntities: 10
|
|
6845
|
+
},
|
|
6846
|
+
systemPrompt: "You are an API design expert. Review REST API naming conventions, versioning strategy, pagination, filtering, error response format, rate limiting, and documentation completeness.",
|
|
6847
|
+
outputType: "review",
|
|
6848
|
+
tags: ["domain", "api", "rest", "design"]
|
|
6849
|
+
},
|
|
6850
|
+
{
|
|
6851
|
+
id: "refactor-croc",
|
|
6852
|
+
name: "\u91CD\u6784\u5EFA\u8BAE\u9CC4",
|
|
6853
|
+
nameEn: "Refactoring Croc",
|
|
6854
|
+
category: "domain",
|
|
6855
|
+
description: "\u4EE3\u7801\u8D28\u91CF\u8BC4\u4F30\uFF1A\u6280\u672F\u503A/\u590D\u6742\u5EA6/\u91CD\u590D\u4EE3\u7801",
|
|
6856
|
+
sprite: "refactor",
|
|
6857
|
+
color: "#ec4899",
|
|
6858
|
+
priority: 13,
|
|
6859
|
+
triggers: {
|
|
6860
|
+
riskCategories: ["maintainability"],
|
|
6861
|
+
minEntities: 40
|
|
6862
|
+
},
|
|
6863
|
+
systemPrompt: "You are a refactoring expert. Identify code smells, duplicated logic, high cyclomatic complexity, god classes, feature envy, and suggest targeted refactoring strategies with minimal risk.",
|
|
6864
|
+
outputType: "review",
|
|
6865
|
+
tags: ["domain", "refactoring", "quality", "tech-debt"]
|
|
6866
|
+
},
|
|
6867
|
+
{
|
|
6868
|
+
id: "microservice-croc",
|
|
6869
|
+
name: "\u670D\u52A1\u6CBB\u7406\u9CC4",
|
|
6870
|
+
nameEn: "Microservice Governance Croc",
|
|
6871
|
+
category: "domain",
|
|
6872
|
+
description: "\u5FAE\u670D\u52A1\u67B6\u6784\u6CBB\u7406\uFF1A\u670D\u52A1\u8FB9\u754C/\u7194\u65AD/\u94FE\u8DEF\u8FFD\u8E2A",
|
|
6873
|
+
sprite: "microservice",
|
|
6874
|
+
color: "#7c3aed",
|
|
6875
|
+
priority: 14,
|
|
6876
|
+
triggers: {
|
|
6877
|
+
projectTypes: ["microservice", "monorepo"],
|
|
6878
|
+
custom: (ctx) => ctx.entityCount > 100
|
|
6879
|
+
},
|
|
6880
|
+
systemPrompt: "You are a microservice governance expert. Analyze service boundaries, inter-service communication, circuit breakers, distributed tracing, service mesh, and API gateway patterns.",
|
|
6881
|
+
outputType: "review",
|
|
6882
|
+
tags: ["domain", "microservice", "governance", "distributed"]
|
|
6883
|
+
}
|
|
6884
|
+
];
|
|
6885
|
+
RoleRegistry = class {
|
|
6886
|
+
roles = /* @__PURE__ */ new Map();
|
|
6887
|
+
constructor() {
|
|
6888
|
+
for (const role of [...CORE_ROLES, ...LANGUAGE_ROLES, ...FRAMEWORK_ROLES, ...DOMAIN_ROLES]) {
|
|
6889
|
+
this.roles.set(role.id, role);
|
|
6890
|
+
}
|
|
6891
|
+
}
|
|
6892
|
+
/** Register a new role (community or custom) */
|
|
6893
|
+
register(role) {
|
|
6894
|
+
if (this.roles.has(role.id)) {
|
|
6895
|
+
throw new Error(`Role "${role.id}" is already registered`);
|
|
6896
|
+
}
|
|
6897
|
+
this.roles.set(role.id, role);
|
|
6898
|
+
}
|
|
6899
|
+
/** Unregister a role */
|
|
6900
|
+
unregister(id) {
|
|
6901
|
+
return this.roles.delete(id);
|
|
6902
|
+
}
|
|
6903
|
+
/** Get a role by ID */
|
|
6904
|
+
get(id) {
|
|
6905
|
+
return this.roles.get(id);
|
|
6906
|
+
}
|
|
6907
|
+
/** List all registered roles */
|
|
6908
|
+
list() {
|
|
6909
|
+
return Array.from(this.roles.values());
|
|
6910
|
+
}
|
|
6911
|
+
/** List roles by category */
|
|
6912
|
+
listByCategory(category) {
|
|
6913
|
+
return this.list().filter((r) => r.category === category);
|
|
6914
|
+
}
|
|
6915
|
+
/** Search roles by tags */
|
|
6916
|
+
search(query) {
|
|
6917
|
+
const q = query.toLowerCase();
|
|
6918
|
+
return this.list().filter(
|
|
6919
|
+
(r) => r.name.toLowerCase().includes(q) || r.nameEn.toLowerCase().includes(q) || r.description.toLowerCase().includes(q) || r.tags.some((t) => t.includes(q))
|
|
6920
|
+
);
|
|
6921
|
+
}
|
|
6922
|
+
/** Total number of registered roles */
|
|
6923
|
+
get size() {
|
|
6924
|
+
return this.roles.size;
|
|
6925
|
+
}
|
|
6926
|
+
};
|
|
6927
|
+
_registry = null;
|
|
6928
|
+
}
|
|
6929
|
+
});
|
|
6930
|
+
|
|
6514
6931
|
// src/server/routes/studio.ts
|
|
6515
6932
|
function restoreStore(snapshotStore) {
|
|
6516
6933
|
return snapshotStore?.load() ?? { ...EMPTY_STUDIO_STORE };
|
|
6517
6934
|
}
|
|
6518
6935
|
function registerStudioRoutes(app, office, snapshotStore) {
|
|
6519
6936
|
const store = restoreStore(snapshotStore);
|
|
6937
|
+
let lastScanResult = null;
|
|
6520
6938
|
if (store.graph) {
|
|
6521
6939
|
office.log(`\u267B\uFE0F Restored Studio snapshot: ${store.graph.nodes.length} nodes, ${store.risks.length} risks`, "info");
|
|
6522
6940
|
}
|
|
@@ -6578,6 +6996,7 @@ function registerStudioRoutes(app, office, snapshotStore) {
|
|
|
6578
6996
|
store.risks = risks;
|
|
6579
6997
|
store.scanTime = Date.now();
|
|
6580
6998
|
store.source = target;
|
|
6999
|
+
lastScanResult = scanResult;
|
|
6581
7000
|
persistStore();
|
|
6582
7001
|
broadcastGraph();
|
|
6583
7002
|
return {
|
|
@@ -6826,6 +7245,90 @@ function registerStudioRoutes(app, office, snapshotStore) {
|
|
|
6826
7245
|
snapshots: snapshotStore.list()
|
|
6827
7246
|
};
|
|
6828
7247
|
});
|
|
7248
|
+
app.get("/api/studio/roles", async (req) => {
|
|
7249
|
+
const { getRoleRegistry: getRoleRegistry2 } = await Promise.resolve().then(() => (init_role_registry(), role_registry_exports));
|
|
7250
|
+
const registry = getRoleRegistry2();
|
|
7251
|
+
const category = req.query.category;
|
|
7252
|
+
const search = req.query.search;
|
|
7253
|
+
let roles = registry.list();
|
|
7254
|
+
if (category) roles = roles.filter((r) => r.category === category);
|
|
7255
|
+
if (search) roles = registry.search(search);
|
|
7256
|
+
return {
|
|
7257
|
+
total: roles.length,
|
|
7258
|
+
categories: {
|
|
7259
|
+
core: roles.filter((r) => r.category === "core").length,
|
|
7260
|
+
language: roles.filter((r) => r.category === "language").length,
|
|
7261
|
+
framework: roles.filter((r) => r.category === "framework").length,
|
|
7262
|
+
domain: roles.filter((r) => r.category === "domain").length,
|
|
7263
|
+
community: roles.filter((r) => r.category === "community").length
|
|
7264
|
+
},
|
|
7265
|
+
roles: roles.map((r) => ({
|
|
7266
|
+
id: r.id,
|
|
7267
|
+
name: r.name,
|
|
7268
|
+
nameEn: r.nameEn,
|
|
7269
|
+
category: r.category,
|
|
7270
|
+
description: r.description,
|
|
7271
|
+
color: r.color,
|
|
7272
|
+
sprite: r.sprite,
|
|
7273
|
+
priority: r.priority,
|
|
7274
|
+
tags: r.tags,
|
|
7275
|
+
outputType: r.outputType
|
|
7276
|
+
}))
|
|
7277
|
+
};
|
|
7278
|
+
});
|
|
7279
|
+
app.post("/api/studio/summon", async (_req, reply) => {
|
|
7280
|
+
if (!lastScanResult) {
|
|
7281
|
+
reply.code(400).send({ error: "No project scanned. Run /api/studio/scan first." });
|
|
7282
|
+
return;
|
|
7283
|
+
}
|
|
7284
|
+
const riskCategories = [...new Set(store.risks.map((r) => r.category))];
|
|
7285
|
+
const plan = await office.summonForProject(lastScanResult, riskCategories);
|
|
7286
|
+
return {
|
|
7287
|
+
ok: true,
|
|
7288
|
+
totalAgents: office.getAgents().length,
|
|
7289
|
+
coreAgents: 6,
|
|
7290
|
+
dynamicAgents: office.getAgents().length - 6,
|
|
7291
|
+
reasoning: plan.reasoning,
|
|
7292
|
+
agents: office.getAgents().map((a) => ({
|
|
7293
|
+
id: a.id,
|
|
7294
|
+
name: a.name,
|
|
7295
|
+
role: a.role,
|
|
7296
|
+
sprite: a.sprite,
|
|
7297
|
+
status: a.status,
|
|
7298
|
+
category: a.category,
|
|
7299
|
+
color: a.color,
|
|
7300
|
+
description: a.description
|
|
7301
|
+
})),
|
|
7302
|
+
context: {
|
|
7303
|
+
languages: plan.context.languages,
|
|
7304
|
+
frameworks: plan.context.frameworks,
|
|
7305
|
+
projectType: plan.context.projectType,
|
|
7306
|
+
entityCount: plan.context.entityCount,
|
|
7307
|
+
hasAPIs: plan.context.hasAPIs,
|
|
7308
|
+
hasModels: plan.context.hasModels,
|
|
7309
|
+
hasFrontend: plan.context.hasFrontend,
|
|
7310
|
+
hasDocker: plan.context.hasDocker,
|
|
7311
|
+
hasCI: plan.context.hasCI
|
|
7312
|
+
}
|
|
7313
|
+
};
|
|
7314
|
+
});
|
|
7315
|
+
app.get("/api/studio/agents", async () => {
|
|
7316
|
+
const info = office.getSummonPlan();
|
|
7317
|
+
return {
|
|
7318
|
+
...info,
|
|
7319
|
+
agents: info.agents.map((a) => ({
|
|
7320
|
+
id: a.id,
|
|
7321
|
+
name: a.name,
|
|
7322
|
+
role: a.role,
|
|
7323
|
+
sprite: a.sprite,
|
|
7324
|
+
status: a.status,
|
|
7325
|
+
currentTask: a.currentTask,
|
|
7326
|
+
category: a.category,
|
|
7327
|
+
color: a.color,
|
|
7328
|
+
description: a.description
|
|
7329
|
+
}))
|
|
7330
|
+
};
|
|
7331
|
+
});
|
|
6829
7332
|
}
|
|
6830
7333
|
var init_studio = __esm({
|
|
6831
7334
|
"src/server/routes/studio.ts"() {
|
|
@@ -6838,6 +7341,155 @@ var init_studio = __esm({
|
|
|
6838
7341
|
}
|
|
6839
7342
|
});
|
|
6840
7343
|
|
|
7344
|
+
// src/agents/task-router.ts
|
|
7345
|
+
var task_router_exports = {};
|
|
7346
|
+
__export(task_router_exports, {
|
|
7347
|
+
buildMatchContext: () => buildMatchContext,
|
|
7348
|
+
planSummon: () => planSummon
|
|
7349
|
+
});
|
|
7350
|
+
function buildMatchContext(scan2) {
|
|
7351
|
+
const languages = scan2.languages;
|
|
7352
|
+
const frameworks = scan2.frameworks.map((f) => f.name);
|
|
7353
|
+
const frontendFrameworks = ["React", "Vue", "Angular", "Svelte", "Next.js", "Nuxt"];
|
|
7354
|
+
const backendFrameworks = ["Express", "Fastify", "NestJS", "Django", "Flask", "Spring Boot", "Gin", "Actix"];
|
|
7355
|
+
const hasFE = frameworks.some((f) => frontendFrameworks.includes(f));
|
|
7356
|
+
const hasBE = frameworks.some((f) => backendFrameworks.includes(f));
|
|
7357
|
+
const projectType = hasFE && hasBE ? "fullstack" : hasFE ? "frontend" : hasBE ? "backend" : "unknown";
|
|
7358
|
+
const entityTypes = new Set(scan2.entities.map((e) => e.type));
|
|
7359
|
+
const hasModels = entityTypes.has("model") || entityTypes.has("class");
|
|
7360
|
+
const hasAPIs = entityTypes.has("api") || entityTypes.has("route");
|
|
7361
|
+
const hasFrontend = hasFE || (languages["html"] ?? 0) > 10 || (languages["css"] ?? 0) > 5;
|
|
7362
|
+
const allPaths = scan2.files.map((f) => f.path);
|
|
7363
|
+
const hasDocker = allPaths.some(
|
|
7364
|
+
(p) => p.includes("Dockerfile") || p.includes("docker-compose")
|
|
7365
|
+
);
|
|
7366
|
+
const hasCI = allPaths.some(
|
|
7367
|
+
(p) => p.includes(".github/workflows") || p.includes(".gitlab-ci") || p.includes("Jenkinsfile")
|
|
7368
|
+
);
|
|
7369
|
+
const riskCategories = [];
|
|
7370
|
+
return {
|
|
7371
|
+
languages,
|
|
7372
|
+
frameworks,
|
|
7373
|
+
projectType,
|
|
7374
|
+
fileCount: scan2.files.length,
|
|
7375
|
+
entityCount: scan2.entities.length,
|
|
7376
|
+
riskCategories,
|
|
7377
|
+
hasModels,
|
|
7378
|
+
hasAPIs,
|
|
7379
|
+
hasFrontend,
|
|
7380
|
+
hasDocker,
|
|
7381
|
+
hasCI
|
|
7382
|
+
};
|
|
7383
|
+
}
|
|
7384
|
+
function matchesTriggers(trigger, ctx) {
|
|
7385
|
+
const reasons = [];
|
|
7386
|
+
let score = 0;
|
|
7387
|
+
let checks = 0;
|
|
7388
|
+
if (trigger.languages && trigger.languages.length > 0) {
|
|
7389
|
+
checks++;
|
|
7390
|
+
const matched = trigger.languages.filter((l) => (ctx.languages[l] ?? 0) > 0);
|
|
7391
|
+
if (matched.length > 0) {
|
|
7392
|
+
score++;
|
|
7393
|
+
reasons.push(`\u8BED\u8A00\u5339\u914D: ${matched.join(", ")}`);
|
|
7394
|
+
}
|
|
7395
|
+
}
|
|
7396
|
+
if (trigger.frameworks && trigger.frameworks.length > 0) {
|
|
7397
|
+
checks++;
|
|
7398
|
+
const matched = trigger.frameworks.filter(
|
|
7399
|
+
(f) => ctx.frameworks.some((cf) => cf.toLowerCase() === f.toLowerCase())
|
|
7400
|
+
);
|
|
7401
|
+
if (matched.length > 0) {
|
|
7402
|
+
score++;
|
|
7403
|
+
reasons.push(`\u6846\u67B6\u5339\u914D: ${matched.join(", ")}`);
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
if (trigger.projectTypes && trigger.projectTypes.length > 0) {
|
|
7407
|
+
checks++;
|
|
7408
|
+
if (trigger.projectTypes.includes(ctx.projectType)) {
|
|
7409
|
+
score++;
|
|
7410
|
+
reasons.push(`\u9879\u76EE\u7C7B\u578B\u5339\u914D: ${ctx.projectType}`);
|
|
7411
|
+
}
|
|
7412
|
+
}
|
|
7413
|
+
if (trigger.minEntities !== void 0) {
|
|
7414
|
+
checks++;
|
|
7415
|
+
if (ctx.entityCount >= trigger.minEntities) {
|
|
7416
|
+
score++;
|
|
7417
|
+
reasons.push(`\u5B9E\u4F53\u6570\u91CF\u6EE1\u8DB3: ${ctx.entityCount} \u2265 ${trigger.minEntities}`);
|
|
7418
|
+
}
|
|
7419
|
+
}
|
|
7420
|
+
if (trigger.riskCategories && trigger.riskCategories.length > 0) {
|
|
7421
|
+
checks++;
|
|
7422
|
+
const matched = trigger.riskCategories.filter((r) => ctx.riskCategories.includes(r));
|
|
7423
|
+
if (matched.length > 0) {
|
|
7424
|
+
score++;
|
|
7425
|
+
reasons.push(`\u98CE\u9669\u7C7B\u522B\u5339\u914D: ${matched.join(", ")}`);
|
|
7426
|
+
}
|
|
7427
|
+
}
|
|
7428
|
+
if (trigger.custom) {
|
|
7429
|
+
checks++;
|
|
7430
|
+
try {
|
|
7431
|
+
if (trigger.custom(ctx)) {
|
|
7432
|
+
score++;
|
|
7433
|
+
reasons.push("\u81EA\u5B9A\u4E49\u6761\u4EF6\u6EE1\u8DB3");
|
|
7434
|
+
}
|
|
7435
|
+
} catch {
|
|
7436
|
+
}
|
|
7437
|
+
}
|
|
7438
|
+
const matches = checks === 0 ? false : score > 0;
|
|
7439
|
+
const confidence = checks > 0 ? score / checks : 0;
|
|
7440
|
+
return {
|
|
7441
|
+
matches,
|
|
7442
|
+
reason: reasons.join("; ") || "\u65E0\u5339\u914D",
|
|
7443
|
+
confidence
|
|
7444
|
+
};
|
|
7445
|
+
}
|
|
7446
|
+
function planSummon(scan2, maxRoles = 8, riskCategories = []) {
|
|
7447
|
+
const registry = getRoleRegistry();
|
|
7448
|
+
const ctx = buildMatchContext(scan2);
|
|
7449
|
+
ctx.riskCategories = riskCategories;
|
|
7450
|
+
const summoned = [];
|
|
7451
|
+
const reasoning = [];
|
|
7452
|
+
const allRoles = registry.list();
|
|
7453
|
+
const coreRoles = allRoles.filter((r) => r.category === "core");
|
|
7454
|
+
for (const role of coreRoles) {
|
|
7455
|
+
summoned.push({ role, reason: "\u6838\u5FC3\u89D2\u8272(\u59CB\u7EC8\u53EC\u5524)", confidence: 1 });
|
|
7456
|
+
reasoning.push(`\u2705 ${role.name} \u2014 \u6838\u5FC3\u89D2\u8272`);
|
|
7457
|
+
}
|
|
7458
|
+
const nonCore = allRoles.filter((r) => r.category !== "core");
|
|
7459
|
+
const candidates = [];
|
|
7460
|
+
for (const role of nonCore) {
|
|
7461
|
+
const result = matchesTriggers(role.triggers, ctx);
|
|
7462
|
+
if (result.matches) {
|
|
7463
|
+
candidates.push({
|
|
7464
|
+
role,
|
|
7465
|
+
reason: result.reason,
|
|
7466
|
+
confidence: result.confidence
|
|
7467
|
+
});
|
|
7468
|
+
}
|
|
7469
|
+
}
|
|
7470
|
+
candidates.sort((a, b) => {
|
|
7471
|
+
if (a.role.priority !== b.role.priority) return a.role.priority - b.role.priority;
|
|
7472
|
+
return b.confidence - a.confidence;
|
|
7473
|
+
});
|
|
7474
|
+
const selected = candidates.slice(0, maxRoles);
|
|
7475
|
+
for (const s of selected) {
|
|
7476
|
+
summoned.push(s);
|
|
7477
|
+
reasoning.push(`\u{1F40A} ${s.role.name} \u2014 ${s.reason} (\u7F6E\u4FE1\u5EA6: ${(s.confidence * 100).toFixed(0)}%)`);
|
|
7478
|
+
}
|
|
7479
|
+
const skipped = candidates.slice(maxRoles);
|
|
7480
|
+
for (const s of skipped) {
|
|
7481
|
+
reasoning.push(`\u23ED\uFE0F ${s.role.name} \u2014 \u5339\u914D\u4F46\u8D85\u51FA\u9650\u5236 (\u7F6E\u4FE1\u5EA6: ${(s.confidence * 100).toFixed(0)}%)`);
|
|
7482
|
+
}
|
|
7483
|
+
return { roles: summoned, reasoning, context: ctx };
|
|
7484
|
+
}
|
|
7485
|
+
var init_task_router = __esm({
|
|
7486
|
+
"src/agents/task-router.ts"() {
|
|
7487
|
+
"use strict";
|
|
7488
|
+
init_esm_shims();
|
|
7489
|
+
init_role_registry();
|
|
7490
|
+
}
|
|
7491
|
+
});
|
|
7492
|
+
|
|
6841
7493
|
// src/execution/coordinator.ts
|
|
6842
7494
|
var coordinator_exports = {};
|
|
6843
7495
|
__export(coordinator_exports, {
|
|
@@ -7216,7 +7868,7 @@ var init_croc_office = __esm({
|
|
|
7216
7868
|
{ id: "planner-croc", name: "\u89C4\u5212\u9CC4", role: "planner", sprite: "planner", status: "idle", tokensUsed: 0 },
|
|
7217
7869
|
{ id: "reporter-croc", name: "\u6C47\u62A5\u9CC4", role: "reporter", sprite: "reporter", status: "idle", tokensUsed: 0 }
|
|
7218
7870
|
];
|
|
7219
|
-
CrocOffice = class {
|
|
7871
|
+
CrocOffice = class _CrocOffice {
|
|
7220
7872
|
config;
|
|
7221
7873
|
cwd;
|
|
7222
7874
|
clients = /* @__PURE__ */ new Set();
|
|
@@ -7228,6 +7880,10 @@ var init_croc_office = __esm({
|
|
|
7228
7880
|
lastExecutionMetrics = null;
|
|
7229
7881
|
lastExecutionQuality = null;
|
|
7230
7882
|
lastReports = [];
|
|
7883
|
+
static ACTIVE_AGENT_STATUSES = /* @__PURE__ */ new Set([
|
|
7884
|
+
"working",
|
|
7885
|
+
"thinking"
|
|
7886
|
+
]);
|
|
7231
7887
|
constructor(config, cwd) {
|
|
7232
7888
|
this.config = config;
|
|
7233
7889
|
this.cwd = cwd;
|
|
@@ -7262,10 +7918,34 @@ var init_croc_office = __esm({
|
|
|
7262
7918
|
updateAgent(id, update) {
|
|
7263
7919
|
const agent = this.agents.find((a) => a.id === id);
|
|
7264
7920
|
if (agent) {
|
|
7921
|
+
const wasActive = this.isAgentActive(agent.status);
|
|
7265
7922
|
Object.assign(agent, update);
|
|
7923
|
+
const isActive = this.isAgentActive(agent.status);
|
|
7266
7924
|
this.broadcast("agent:update", this.agents);
|
|
7925
|
+
if (!wasActive && isActive) {
|
|
7926
|
+
this.broadcast("agent:assigned", {
|
|
7927
|
+
id: agent.id,
|
|
7928
|
+
name: agent.name,
|
|
7929
|
+
role: agent.role,
|
|
7930
|
+
status: agent.status,
|
|
7931
|
+
currentTask: agent.currentTask ?? null,
|
|
7932
|
+
at: Date.now()
|
|
7933
|
+
});
|
|
7934
|
+
} else if (wasActive && !isActive) {
|
|
7935
|
+
this.broadcast("agent:released", {
|
|
7936
|
+
id: agent.id,
|
|
7937
|
+
name: agent.name,
|
|
7938
|
+
role: agent.role,
|
|
7939
|
+
status: agent.status,
|
|
7940
|
+
currentTask: agent.currentTask ?? null,
|
|
7941
|
+
at: Date.now()
|
|
7942
|
+
});
|
|
7943
|
+
}
|
|
7267
7944
|
}
|
|
7268
7945
|
}
|
|
7946
|
+
isAgentActive(status) {
|
|
7947
|
+
return _CrocOffice.ACTIVE_AGENT_STATUSES.has(status);
|
|
7948
|
+
}
|
|
7269
7949
|
isRunning() {
|
|
7270
7950
|
return this.running;
|
|
7271
7951
|
}
|
|
@@ -7395,12 +8075,75 @@ var init_croc_office = __esm({
|
|
|
7395
8075
|
/** Reset all agents to idle */
|
|
7396
8076
|
resetAgents() {
|
|
7397
8077
|
for (const agent of this.agents) {
|
|
8078
|
+
const wasActive = this.isAgentActive(agent.status);
|
|
7398
8079
|
agent.status = "idle";
|
|
7399
8080
|
agent.currentTask = void 0;
|
|
7400
8081
|
agent.progress = void 0;
|
|
8082
|
+
if (wasActive) {
|
|
8083
|
+
this.broadcast("agent:released", {
|
|
8084
|
+
id: agent.id,
|
|
8085
|
+
name: agent.name,
|
|
8086
|
+
role: agent.role,
|
|
8087
|
+
status: agent.status,
|
|
8088
|
+
currentTask: null,
|
|
8089
|
+
at: Date.now()
|
|
8090
|
+
});
|
|
8091
|
+
}
|
|
7401
8092
|
}
|
|
7402
8093
|
this.broadcast("agent:update", this.agents);
|
|
7403
8094
|
}
|
|
8095
|
+
/**
|
|
8096
|
+
* Dynamically summon crocs based on a project scan result.
|
|
8097
|
+
* Core 6 are always present; additional expert crocs are added based on project characteristics.
|
|
8098
|
+
*/
|
|
8099
|
+
async summonForProject(scan2, riskCategories = []) {
|
|
8100
|
+
const { planSummon: planSummon2 } = await Promise.resolve().then(() => (init_task_router(), task_router_exports));
|
|
8101
|
+
const plan = planSummon2(scan2, 8, riskCategories);
|
|
8102
|
+
const coreIds = new Set(DEFAULT_AGENTS.map((a) => a.id));
|
|
8103
|
+
this.agents = DEFAULT_AGENTS.map((a) => ({ ...a }));
|
|
8104
|
+
for (const summoned of plan.roles) {
|
|
8105
|
+
if (coreIds.has(summoned.role.id)) continue;
|
|
8106
|
+
const agent = {
|
|
8107
|
+
id: summoned.role.id,
|
|
8108
|
+
name: summoned.role.name,
|
|
8109
|
+
role: summoned.role.id.replace(/-croc$/, ""),
|
|
8110
|
+
sprite: summoned.role.sprite,
|
|
8111
|
+
status: "idle",
|
|
8112
|
+
tokensUsed: 0,
|
|
8113
|
+
category: summoned.role.category,
|
|
8114
|
+
color: summoned.role.color,
|
|
8115
|
+
description: summoned.role.description
|
|
8116
|
+
};
|
|
8117
|
+
this.agents.push(agent);
|
|
8118
|
+
}
|
|
8119
|
+
this.broadcast("agent:update", this.agents);
|
|
8120
|
+
for (const line of plan.reasoning) {
|
|
8121
|
+
this.log(line);
|
|
8122
|
+
}
|
|
8123
|
+
this.log(`\u{1F40A} \u5171\u53EC\u5524 ${this.agents.length} \u4E2A\u9CC4\u9C7C\u4E13\u5BB6 (${plan.roles.length - DEFAULT_AGENTS.length} \u4E2A\u52A8\u6001\u89D2\u8272)`);
|
|
8124
|
+
const dynamicAgents = this.agents.filter((a) => !coreIds.has(a.id));
|
|
8125
|
+
for (let i = 0; i < dynamicAgents.length; i++) {
|
|
8126
|
+
const agent = dynamicAgents[i];
|
|
8127
|
+
setTimeout(() => {
|
|
8128
|
+
this.updateAgent(agent.id, { status: "working", currentTask: "\u5206\u6790\u9879\u76EE\u4E2D\u2026" });
|
|
8129
|
+
setTimeout(() => {
|
|
8130
|
+
this.updateAgent(agent.id, { status: "idle", currentTask: void 0 });
|
|
8131
|
+
}, 2e3 + Math.random() * 1e3);
|
|
8132
|
+
}, 300 * i);
|
|
8133
|
+
}
|
|
8134
|
+
return plan;
|
|
8135
|
+
}
|
|
8136
|
+
/** Get the current summon plan context */
|
|
8137
|
+
getSummonPlan() {
|
|
8138
|
+
const coreIds = new Set(DEFAULT_AGENTS.map((a) => a.id));
|
|
8139
|
+
const coreCount = this.agents.filter((a) => coreIds.has(a.id)).length;
|
|
8140
|
+
return {
|
|
8141
|
+
agentCount: this.agents.length,
|
|
8142
|
+
coreCount,
|
|
8143
|
+
dynamicCount: this.agents.length - coreCount,
|
|
8144
|
+
agents: this.agents
|
|
8145
|
+
};
|
|
8146
|
+
}
|
|
7404
8147
|
/** Get last pipeline result */
|
|
7405
8148
|
getLastPipelineResult() {
|
|
7406
8149
|
return this.lastPipelineResult;
|
|
@@ -7827,7 +8570,8 @@ async function startServer(opts) {
|
|
|
7827
8570
|
await app.register(fastifyStatic, {
|
|
7828
8571
|
root: webDir,
|
|
7829
8572
|
prefix: "/",
|
|
7830
|
-
decorateReply: false
|
|
8573
|
+
decorateReply: false,
|
|
8574
|
+
index: false
|
|
7831
8575
|
});
|
|
7832
8576
|
}
|
|
7833
8577
|
const office = new CrocOffice(opts.config, opts.cwd);
|
|
@@ -7841,17 +8585,20 @@ async function startServer(opts) {
|
|
|
7841
8585
|
socket.on("close", () => office.removeClient(socket));
|
|
7842
8586
|
});
|
|
7843
8587
|
});
|
|
8588
|
+
app.get("/index-studio.html", (_req, reply) => {
|
|
8589
|
+
reply.redirect("/studio");
|
|
8590
|
+
});
|
|
8591
|
+
app.get("/index-v2-pixel.html", (_req, reply) => {
|
|
8592
|
+
reply.redirect("/pixel");
|
|
8593
|
+
});
|
|
7844
8594
|
app.setNotFoundHandler((req, reply) => {
|
|
7845
8595
|
if (req.url.startsWith("/api/")) {
|
|
7846
8596
|
reply.code(404).send({ error: "Not found" });
|
|
7847
8597
|
return;
|
|
7848
8598
|
}
|
|
7849
|
-
const
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
reply.sendFile("index-studio.html");
|
|
7853
|
-
} else if (existsSync20(indexPath)) {
|
|
7854
|
-
reply.sendFile("index.html");
|
|
8599
|
+
const builtIndexPath = join17(webDir, "dist", "index.html");
|
|
8600
|
+
if (existsSync20(builtIndexPath)) {
|
|
8601
|
+
reply.sendFile("dist/index.html");
|
|
7855
8602
|
} else {
|
|
7856
8603
|
reply.code(200).header("content-type", "text/html").send(getEmbeddedHtml());
|
|
7857
8604
|
}
|