feat(agent): 添加AI智能代理功能模块

- 集成Spring AI框架支持大模型对话
- 实现聊天历史记录管理功能
- 添加代码生成功能支持
- 集成MCP协议工具调用
- 实现流式响应和会话管理
- 添加系统提示词和上下文管理
- 支持多租户会话隔离
- 配置自动化装配和依赖注入
- 实现错误处理和异常捕获
- 添加用户权限验证和审计追踪
- 支持对话历史持久化存储
- 实现智能时间上下文识别
This commit is contained in:
will
2026-08-05 16:38:56 +08:00
commit 9d100f9465
320 changed files with 13327 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
›5frzku4ad5girive24os32j44yu‹^Î’VIG�/k9r•(“instrumentedOutputÚ¢HŽ€Ò9&�ôŒ(¥ŒmetadataDirÓ«Ž�ž#4Oõe
ðØ‰œpropertyUpgradeReportOutput²´ÆyàÞœ3Ÿ&þÍË;ŒÕ
@@ -0,0 +1 @@
›5frzku4ad5girive24os32j44yk%wŸáô@*a¿Ñ5þ]¯¯Â“instrumentedOutputW©Ë‡W§ÜY^ÍçÐóOŒmetadataDir�)CÇäe9=É*òs@‘ÈœpropertyUpgradeReportOutput²´ÆyàÞœ3Ÿ&þÍË;ŒÕ
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Gradle.
# For information about cache directory tags, see:
# https://bford.info/cachedir/
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
#Wed Aug 05 00:21:13 CST 2026
inceptionTimestamp=1785860473531
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,446 @@
2026-08-05T00:21:04.804+0800 [DEBUG] [org.gradle.launcher.daemon.bootstrap.DaemonMain] Assuming the daemon was started with following jvm opts: [-XX:MaxMetaspaceSize=384m, -XX:+HeapDumpOnOutOfMemoryError, -Xms256m, -Xmx512m, -Dfile.encoding=UTF-8, -Duser.country=CN, -Duser.language=zh, -Duser.variant]
2026-08-05T00:21:04.958+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface iNode VPN Virtual NIC-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.960+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.960+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface iNode VPN Virtual NIC-QoS Packet Scheduler-0000
2026-08-05T00:21:04.961+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.962+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface iNode VPN Virtual NIC-WFP 802.3 MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.963+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.963+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IP)-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.963+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.963+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IP)-QoS Packet Scheduler-0000
2026-08-05T00:21:04.964+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.964+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IPv6)-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.964+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.964+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IPv6)-QoS Packet Scheduler-0000
2026-08-05T00:21:04.964+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.965+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (Network Monitor)-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.965+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.965+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (Network Monitor)-QoS Packet Scheduler-0000
2026-08-05T00:21:04.965+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.966+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Kernel Debug Network Adapter
2026-08-05T00:21:04.966+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.966+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface ASIX AX88772C USB2.0 to Fast Ethernet Adapter
2026-08-05T00:21:04.966+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.966+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Bluetooth Device (Personal Area Network)
2026-08-05T00:21:04.967+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.967+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:8450:47d:cf7a:cdb5%ethernet_32770
2026-08-05T00:21:04.967+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IP)
2026-08-05T00:21:04.967+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.967+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IPv6)
2026-08-05T00:21:04.967+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.968+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (Network Monitor)
2026-08-05T00:21:04.968+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.968+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Cisco AnyConnect Virtual Miniport Adapter for Windows x64
2026-08-05T00:21:04.968+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.968+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface iNode VPN Virtual NIC
2026-08-05T00:21:04.969+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.970+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:53eb:3262:161:3f0f%ethernet_32775
2026-08-05T00:21:04.970+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (PPPOE)
2026-08-05T00:21:04.970+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.970+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Software Loopback Interface 1
2026-08-05T00:21:04.970+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? true
2026-08-05T00:21:04.970+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback address /0:0:0:0:0:0:0:1
2026-08-05T00:21:04.971+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding loopback address /127.0.0.1
2026-08-05T00:21:04.971+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface TAP-Windows Adapter V9-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.972+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.972+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface TAP-Windows Adapter V9-QoS Packet Scheduler-0000
2026-08-05T00:21:04.972+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.972+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface TAP-Windows Adapter V9-WFP 802.3 MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.972+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.973+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Sangfor aTrust VNIC-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.973+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.973+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Sangfor aTrust VNIC-QoS Packet Scheduler-0000
2026-08-05T00:21:04.973+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.973+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Sangfor aTrust VNIC-WFP 802.3 MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.974+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.974+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface TAP-Windows Adapter V9
2026-08-05T00:21:04.974+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.974+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:c9bb:cc68:e870:45ba%iftype53_32768
2026-08-05T00:21:04.974+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /192.168.255.214
2026-08-05T00:21:04.974+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface OpenVPN Data Channel Offload
2026-08-05T00:21:04.975+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.975+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:54a8:839c:5e41:a357%iftype53_32769
2026-08-05T00:21:04.975+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Sangfor aTrust VNIC
2026-08-05T00:21:04.976+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.976+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:cb45:bb4c:df23:c8af%iftype53_32770
2026-08-05T00:21:04.976+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Intel(R) Wi-Fi 6 AX203-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.976+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.976+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Intel(R) Wi-Fi 6 AX203-Virtual WiFi Filter Driver-0000
2026-08-05T00:21:04.977+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.977+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Intel(R) Wi-Fi 6 AX203-Native WiFi Filter Driver-0000
2026-08-05T00:21:04.977+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.977+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Intel(R) Wi-Fi 6 AX203-QoS Packet Scheduler-0000
2026-08-05T00:21:04.978+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.978+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Intel(R) Wi-Fi 6 AX203-WFP 802.3 MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.978+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.978+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter-QoS Packet Scheduler-0000
2026-08-05T00:21:04.978+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.978+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter-Native WiFi Filter Driver-0000
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter-WFP 802.3 MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter #2-WFP Native MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.979+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter #2-Native WiFi Filter Driver-0000
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter #2-QoS Packet Scheduler-0000
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter #2-WFP 802.3 MAC Layer LightWeight Filter-0000
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.980+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Intel(R) Wi-Fi 6 AX203
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:e7b4:8c35:b44f:aaf2%wireless_32768
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /240e:3a1:569e:f7d1:d17a:f850:422:690c
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /240e:3a1:569e:f7d1:1451:2096:4290:2
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /240e:3a1:569e:f7d1:d0e:75bf:d9f1:ee06
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /192.168.3.18
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter
2026-08-05T00:21:04.981+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:cf5:3e11:24da:b8ea%wireless_32769
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Wi-Fi Direct Virtual Adapter #2
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding remote address /fe80:0:0:0:eaf6:db93:6b4f:9b79%wireless_32770
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft Teredo Tunneling Adapter
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.982+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft IP-HTTPS Platform Adapter
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface Microsoft 6to4 Adapter
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (SSTP)
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (IKEv2)
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (L2TP)
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:04.983+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Adding IP addresses for network interface WAN Miniport (PPTP)
2026-08-05T00:21:04.984+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.InetAddresses] Is this a loopback interface? false
2026-08-05T00:21:05.000+0800 [DEBUG] [org.gradle.internal.nativeintegration.services.NativeServices] Native-platform posix files integration is not available. Continuing with fallback.
2026-08-05T00:21:05.028+0800 [INFO] [org.gradle.launcher.daemon.server.Daemon] start() called on daemon - DefaultDaemonContext[uid=97be2d6a-15b4-4340-995d-c7d8c8274827,javaHome=C:\Program Files\Eclipse Adoptium\jdk-21.0.10.7-hotspot,javaVersion=21,javaVendor=Eclipse Adoptium,daemonRegistryDir=D:\WORK\SELF\willSystem\willSystem\.gradle-codex\daemon,pid=24024,idleTimeout=120000,priority=NORMAL,applyInstrumentationAgent=true,nativeServicesMode=ENABLED,daemonOpts=-XX:MaxMetaspaceSize=384m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=CN,-Duser.language=zh,-Duser.variant]
2026-08-05T00:21:13.064+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.TcpIncomingConnector] Listening on [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]].
2026-08-05T00:21:13.079+0800 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] Daemon starting at: Wed Aug 05 00:21:13 CST 2026, with address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:13.079+0800 [INFO] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Advertising the daemon address to the clients: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:13.079+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Advertised daemon context: DefaultDaemonContext[uid=97be2d6a-15b4-4340-995d-c7d8c8274827,javaHome=C:\Program Files\Eclipse Adoptium\jdk-21.0.10.7-hotspot,javaVersion=21,javaVendor=Eclipse Adoptium,daemonRegistryDir=D:\WORK\SELF\willSystem\willSystem\.gradle-codex\daemon,pid=24024,idleTimeout=120000,priority=NORMAL,applyInstrumentationAgent=true,nativeServicesMode=ENABLED,daemonOpts=-XX:MaxMetaspaceSize=384m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=CN,-Duser.language=zh,-Duser.variant]
2026-08-05T00:21:13.081+0800 [DEBUG] [org.gradle.launcher.daemon.registry.PersistentDaemonRegistry] Storing daemon address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]], context: DefaultDaemonContext[uid=97be2d6a-15b4-4340-995d-c7d8c8274827,javaHome=C:\Program Files\Eclipse Adoptium\jdk-21.0.10.7-hotspot,javaVersion=21,javaVendor=Eclipse Adoptium,daemonRegistryDir=D:\WORK\SELF\willSystem\willSystem\.gradle-codex\daemon,pid=24024,idleTimeout=120000,priority=NORMAL,applyInstrumentationAgent=true,nativeServicesMode=ENABLED,daemonOpts=-XX:MaxMetaspaceSize=384m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=CN,-Duser.language=zh,-Duser.variant]
2026-08-05T00:21:13.096+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire exclusive lock on daemon addresses registry.
2026-08-05T00:21:13.101+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
2026-08-05T00:21:13.102+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
2026-08-05T00:21:13.105+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire exclusive lock on daemon addresses registry.
2026-08-05T00:21:13.106+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
2026-08-05T00:21:13.109+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
2026-08-05T00:21:13.110+0800 [LIFECYCLE] [org.gradle.launcher.daemon.server.Daemon] Daemon server started.
2026-08-05T00:21:13.111+0800 [DEBUG] [org.gradle.launcher.daemon.bootstrap.DaemonStartupCommunication] Completed writing the daemon greeting. Closing streams...
2026-08-05T00:21:13.120+0800 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] stopOnExpiration() called on daemon
2026-08-05T00:21:13.121+0800 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] awaitExpiration() called on daemon
2026-08-05T00:21:13.122+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] daemon is running. Sleeping until state changes.
2026-08-05T00:21:13.129+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.TcpIncomingConnector] Accepted connection from /127.0.0.1:50342 to /127.0.0.1:50340.
2026-08-05T00:21:13.207+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 78: received class org.gradle.launcher.daemon.protocol.Build
2026-08-05T00:21:13.208+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultDaemonConnection] thread 78: Received non-IO message from client: Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}
2026-08-05T00:21:13.208+0800 [INFO] [org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler] Received command: Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}.
2026-08-05T00:21:13.208+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler] Starting executing command: Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem} with connection: socket connection from /127.0.0.1:50340 to /127.0.0.1:50342.
2026-08-05T00:21:13.212+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Command execution: started DaemonCommandExecution[command = Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}, connection = DefaultDaemonConnection: socket connection from /127.0.0.1:50340 to /127.0.0.1:50342] after 0.002533333333333333 minutes of idle
2026-08-05T00:21:13.212+0800 [INFO] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Marking the daemon as busy, address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:13.212+0800 [DEBUG] [org.gradle.launcher.daemon.registry.PersistentDaemonRegistry] Marking busy by address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:13.214+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire exclusive lock on daemon addresses registry.
2026-08-05T00:21:13.214+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
2026-08-05T00:21:13.216+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
2026-08-05T00:21:13.217+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] resetting idle timer
2026-08-05T00:21:13.217+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] daemon is running. Sleeping until state changes.
2026-08-05T00:21:13.218+0800 [INFO] [org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy] Daemon is about to start building Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}. Dispatching build started information...
2026-08-05T00:21:13.218+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 80: dispatching org.gradle.launcher.daemon.protocol.BuildStarted@38452d58
2026-08-05T00:21:13.220+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment] Configuring env variables: [PATH, USERDOMAIN_ROAMINGPROFILE, PROCESSOR_LEVEL, GIT_PAGER, ALLUSERSPROFILE, CODEX_SHELL, PROCESSOR_ARCHITECTURE, GATEWAY_VM_OPTIONS, PSModulePath, SystemDrive, BROWSER_USE_AVAILABLE_BACKENDS, NODE_REPL_TRUSTED_BROWSER_CLIENT_SHA256S, DIRNAME, USERNAME, DEVECOSTUDIO_VM_OPTIONS, STUDIO_VM_OPTIONS, ProgramFiles(x86), CODEX_INTERNAL_ORIGINATOR_OVERRIDE, APP_HOME, CODEX_SANDBOX_NETWORK_DISABLED, DEFAULT_JVM_OPTS, PATHEXT, SHELL, DriverData, OneDriveConsumer, PAGER, NODE_REPL_TRUSTED_CODE_PATHS, CODEX_PERMISSION_PROFILE, LOG_FORMAT, ProgramData, ProgramW6432, HOMEPATH, PROCESSOR_IDENTIFIER, ProgramFiles, PUBLIC, ZSH_TMUX_AUTOSTARTED, LESS, windir, ZES_ENABLE_SYSMAN, LOCALAPPDATA, IntelliJ IDEA, USERDOMAIN, LOGONSERVER, JAVA_HOME, PROMPT, RUST_LOG, JETBRAINSCLIENT_VM_OPTIONS, GRADLE_HOME, OneDrive, APPDATA, GRADLE_USER_HOME, JAVA_EXE, CODEX_THREAD_ID, JETBRAINS_CLIENT_VM_OPTIONS, CommonProgramFiles, Path, DISABLE_AUTO_UPDATE, OS, COMPUTERNAME, PROCESSOR_REVISION, CLASSPATH, CommonProgramW6432, ComSpec, APP_BASE_NAME, ZSH_TMUX_AUTOSTART, =D:, SystemRoot, TEMP, WEBIDE_VM_OPTIONS, HOMEDRIVE, USERPROFILE, TMP, ZHIPU_API_KEY, CommonProgramFiles(x86), NUMBER_OF_PROCESSORS]
2026-08-05T00:21:13.225+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.LogToClient] About to start relaying all logs to the client via the connection.
2026-08-05T00:21:13.226+0800 [INFO] [org.gradle.launcher.daemon.server.exec.LogToClient] The client will now receive all logging from the daemon (pid: 24024). The daemon log file: D:\WORK\SELF\willSystem\willSystem\.gradle-codex\daemon\8.13\daemon-24024.out.log
2026-08-05T00:21:13.227+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon] Requesting daemon stop after processing Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}
2026-08-05T00:21:13.227+0800 [LIFECYCLE] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Daemon will be stopped at the end of the build
2026-08-05T00:21:13.227+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Stop as soon as idle requested. The daemon is busy
2026-08-05T00:21:13.228+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] daemon stop has been requested. Sleeping until state changes.
2026-08-05T00:21:13.228+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] The daemon has started executing the build.
2026-08-05T00:21:13.228+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] Executing build with daemon context: DefaultDaemonContext[uid=97be2d6a-15b4-4340-995d-c7d8c8274827,javaHome=C:\Program Files\Eclipse Adoptium\jdk-21.0.10.7-hotspot,javaVersion=21,javaVendor=Eclipse Adoptium,daemonRegistryDir=D:\WORK\SELF\willSystem\willSystem\.gradle-codex\daemon,pid=24024,idleTimeout=120000,priority=NORMAL,applyInstrumentationAgent=true,nativeServicesMode=ENABLED,daemonOpts=-XX:MaxMetaspaceSize=384m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=CN,-Duser.language=zh,-Duser.variant]
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\WORK\SELF\willSystem\willSystem\build.gradle' line: 3
* What went wrong:
Plugin [id: 'io.spring.dependency-management', version: '1.1.7', apply: false] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Included Builds (No included builds contain this plugin)
- Plugin Repositories (could not resolve plugin artifact 'io.spring.dependency-management:io.spring.dependency-management.gradle.plugin:1.1.7')
Searched in the following repositories:
MavenRepo
Gradle Central Plugin Repository
* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
* Exception is:
org.gradle.api.plugins.UnknownPluginException: Plugin [id: 'io.spring.dependency-management', version: '1.1.7', apply: false] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Included Builds (No included builds contain this plugin)
- Plugin Repositories (could not resolve plugin artifact 'io.spring.dependency-management:io.spring.dependency-management.gradle.plugin:1.1.7')
Searched in the following repositories:
MavenRepo
Gradle Central Plugin Repository
at org.gradle.plugin.use.resolve.internal.PluginResolutionResult.getFound(PluginResolutionResult.java:112)
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.resolvePluginRequest(DefaultPluginRequestApplicator.java:197)
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:101)
at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:123)
at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:68)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:30)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:27)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:48)
at org.gradle.configuration.BuildOperationScriptPlugin.lambda$apply$0(BuildOperationScriptPlugin.java:65)
at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:44)
at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:65)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$1(DefaultProjectStateRegistry.java:435)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:453)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:434)
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:46)
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:27)
at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35)
at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.lambda$run$0(LifecycleProjectEvaluator.java:109)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$1(DefaultProjectStateRegistry.java:435)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$fromMutableState$2(DefaultProjectStateRegistry.java:458)
at org.gradle.internal.work.DefaultWorkerLeaseService.withReplacedLocks(DefaultWorkerLeaseService.java:359)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:458)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:434)
at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:100)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:30)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:27)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:48)
at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:72)
at org.gradle.api.internal.project.DefaultProject.evaluateUnchecked(DefaultProject.java:828)
at org.gradle.api.internal.project.ProjectLifecycleController.lambda$ensureSelfConfigured$2(ProjectLifecycleController.java:89)
at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254)
at org.gradle.internal.model.StateTransitionController.lambda$maybeTransitionIfNotCurrentlyTransitioning$10(StateTransitionController.java:199)
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:36)
at org.gradle.internal.model.StateTransitionController.maybeTransitionIfNotCurrentlyTransitioning(StateTransitionController.java:195)
at org.gradle.api.internal.project.ProjectLifecycleController.ensureSelfConfigured(ProjectLifecycleController.java:89)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.ensureConfigured(DefaultProjectStateRegistry.java:400)
at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:70)
at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:84)
at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:50)
at org.gradle.configuration.BuildTreePreparingProjectsPreparer.prepareProjects(BuildTreePreparingProjectsPreparer.java:65)
at org.gradle.configuration.BuildOperationFiringProjectsPreparer$ConfigureBuild.run(BuildOperationFiringProjectsPreparer.java:52)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:30)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:27)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:48)
at org.gradle.configuration.BuildOperationFiringProjectsPreparer.prepareProjects(BuildOperationFiringProjectsPreparer.java:40)
at org.gradle.initialization.VintageBuildModelController.lambda$prepareProjects$2(VintageBuildModelController.java:84)
at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254)
at org.gradle.internal.model.StateTransitionController.lambda$transitionIfNotPreviously$11(StateTransitionController.java:213)
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:36)
at org.gradle.internal.model.StateTransitionController.transitionIfNotPreviously(StateTransitionController.java:209)
at org.gradle.initialization.VintageBuildModelController.prepareProjects(VintageBuildModelController.java:84)
at org.gradle.initialization.VintageBuildModelController.prepareToScheduleTasks(VintageBuildModelController.java:71)
at org.gradle.internal.build.DefaultBuildLifecycleController.lambda$prepareToScheduleTasks$6(DefaultBuildLifecycleController.java:175)
at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254)
at org.gradle.internal.model.StateTransitionController.lambda$maybeTransition$9(StateTransitionController.java:190)
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:36)
at org.gradle.internal.model.StateTransitionController.maybeTransition(StateTransitionController.java:186)
at org.gradle.internal.build.DefaultBuildLifecycleController.prepareToScheduleTasks(DefaultBuildLifecycleController.java:173)
at org.gradle.internal.buildtree.DefaultBuildTreeWorkPreparer.scheduleRequestedTasks(DefaultBuildTreeWorkPreparer.java:36)
at org.gradle.internal.cc.impl.VintageBuildTreeWorkController$scheduleAndRunRequestedTasks$1.apply(VintageBuildTreeWorkController.kt:36)
at org.gradle.internal.cc.impl.VintageBuildTreeWorkController$scheduleAndRunRequestedTasks$1.apply(VintageBuildTreeWorkController.kt:35)
at org.gradle.composite.internal.DefaultIncludedBuildTaskGraph.withNewWorkGraph(DefaultIncludedBuildTaskGraph.java:112)
at org.gradle.internal.cc.impl.VintageBuildTreeWorkController.scheduleAndRunRequestedTasks(VintageBuildTreeWorkController.kt:35)
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$scheduleAndRunTasks$1(DefaultBuildTreeLifecycleController.java:77)
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$runBuild$4(DefaultBuildTreeLifecycleController.java:120)
at org.gradle.internal.model.StateTransitionController.lambda$transition$6(StateTransitionController.java:169)
at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266)
at org.gradle.internal.model.StateTransitionController.lambda$transition$7(StateTransitionController.java:169)
at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:46)
at org.gradle.internal.model.StateTransitionController.transition(StateTransitionController.java:169)
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.runBuild(DefaultBuildTreeLifecycleController.java:117)
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.scheduleAndRunTasks(DefaultBuildTreeLifecycleController.java:77)
at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.scheduleAndRunTasks(DefaultBuildTreeLifecycleController.java:72)
at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.internal.buildtree.ProblemReportingBuildActionRunner.run(ProblemReportingBuildActionRunner.java:49)
at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:71)
at org.gradle.tooling.internal.provider.FileSystemWatchingBuildActionRunner.run(FileSystemWatchingBuildActionRunner.java:135)
at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:41)
at org.gradle.launcher.exec.RootBuildLifecycleBuildActionExecutor.lambda$execute$0(RootBuildLifecycleBuildActionExecutor.java:54)
at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:130)
at org.gradle.launcher.exec.RootBuildLifecycleBuildActionExecutor.execute(RootBuildLifecycleBuildActionExecutor.java:54)
at org.gradle.internal.buildtree.InitDeprecationLoggingActionExecutor.execute(InitDeprecationLoggingActionExecutor.java:62)
at org.gradle.internal.buildtree.InitProblems.execute(InitProblems.java:36)
at org.gradle.internal.buildtree.DefaultBuildTreeContext.execute(DefaultBuildTreeContext.java:40)
at org.gradle.launcher.exec.BuildTreeLifecycleBuildActionExecutor.lambda$execute$0(BuildTreeLifecycleBuildActionExecutor.java:71)
at org.gradle.internal.buildtree.BuildTreeState.run(BuildTreeState.java:60)
at org.gradle.launcher.exec.BuildTreeLifecycleBuildActionExecutor.execute(BuildTreeLifecycleBuildActionExecutor.java:71)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor$2.call(RunAsBuildOperationBuildActionExecutor.java:67)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor$2.call(RunAsBuildOperationBuildActionExecutor.java:63)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:210)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:205)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:67)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:167)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:60)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:54)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor.execute(RunAsBuildOperationBuildActionExecutor.java:63)
at org.gradle.launcher.exec.RunAsWorkerThreadBuildActionExecutor.lambda$execute$0(RunAsWorkerThreadBuildActionExecutor.java:36)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:263)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127)
at org.gradle.launcher.exec.RunAsWorkerThreadBuildActionExecutor.execute(RunAsWorkerThreadBuildActionExecutor.java:36)
at org.gradle.tooling.internal.provider.continuous.ContinuousBuildActionExecutor.execute(ContinuousBuildActionExecutor.java:110)
at org.gradle.tooling.internal.provider.SubscribableBuildActionExecutor.execute(SubscribableBuildActionExecutor.java:64)
at org.gradle.internal.session.DefaultBuildSessionContext.execute(DefaultBuildSessionContext.java:46)
at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor$ActionImpl.apply(BuildSessionLifecycleBuildActionExecutor.java:92)
at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor$ActionImpl.apply(BuildSessionLifecycleBuildActionExecutor.java:80)
at org.gradle.internal.session.BuildSessionState.run(BuildSessionState.java:73)
at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor.execute(BuildSessionLifecycleBuildActionExecutor.java:62)
at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor.execute(BuildSessionLifecycleBuildActionExecutor.java:41)
at org.gradle.internal.buildprocess.execution.StartParamsValidatingActionExecutor.execute(StartParamsValidatingActionExecutor.java:64)
at org.gradle.internal.buildprocess.execution.StartParamsValidatingActionExecutor.execute(StartParamsValidatingActionExecutor.java:32)
at org.gradle.internal.buildprocess.execution.SessionFailureReportingActionExecutor.execute(SessionFailureReportingActionExecutor.java:51)
at org.gradle.internal.buildprocess.execution.SessionFailureReportingActionExecutor.execute(SessionFailureReportingActionExecutor.java:39)
at org.gradle.internal.buildprocess.execution.SetupLoggingActionExecutor.execute(SetupLoggingActionExecutor.java:47)
at org.gradle.internal.buildprocess.execution.SetupLoggingActionExecutor.execute(SetupLoggingActionExecutor.java:31)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:70)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:29)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.lambda$execute$0(ForwardClientInput.java:40)
at org.gradle.internal.daemon.clientinput.ClientInputForwarder.forwardInput(ClientInputForwarder.java:80)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:53)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:84)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator.lambda$runCommand$0(DaemonStateCoordinator.java:321)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
BUILD FAILED in 30s
2026-08-05T00:21:25.537+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.ExecuteBuild] The daemon has finished executing the build.
2026-08-05T00:21:25.555+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] daemon stop has been requested. Sleeping until state changes.
2026-08-05T00:21:25.555+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Command execution: finished waiting for DaemonCommandExecution[command = Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}, connection = DefaultDaemonConnection: socket connection from /127.0.0.1:50340 to /127.0.0.1:50342]. Result org.gradle.launcher.daemon.server.DaemonStateCoordinator@6f9cb928 with state StopRequested
2026-08-05T00:21:25.556+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Command execution: completed DaemonCommandExecution[command = Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}, connection = DefaultDaemonConnection: socket connection from /127.0.0.1:50340 to /127.0.0.1:50342]
2026-08-05T00:21:25.556+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] resetting idle timer
2026-08-05T00:21:25.556+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] Marking daemon stopped due to command completed and stop requested. The daemon is not running a build
2026-08-05T00:21:25.556+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonStateCoordinator] daemon has stopped.
2026-08-05T00:21:25.556+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.ReturnResult] Daemon is dispatching the build result: Success[value=org.gradle.launcher.exec.BuildActionResult@5fd92a48]
2026-08-05T00:21:25.557+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 77: dispatching Success[value=org.gradle.launcher.exec.BuildActionResult@5fd92a48]
2026-08-05T00:21:25.557+0800 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] stop() called on daemon
2026-08-05T00:21:25.558+0800 [INFO] [org.gradle.launcher.daemon.server.Daemon] Stop requested. Daemon is removing its presence from the registry...
2026-08-05T00:21:25.558+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Removing our presence to clients, eg. removing this address from the registry: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:25.558+0800 [DEBUG] [org.gradle.launcher.daemon.registry.PersistentDaemonRegistry] Removing daemon address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:25.561+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire exclusive lock on daemon addresses registry.
2026-08-05T00:21:25.562+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
2026-08-05T00:21:25.563+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
2026-08-05T00:21:25.564+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Address removed from registry.
2026-08-05T00:21:25.581+0800 [DEBUG] [org.gradle.launcher.daemon.server.exec.CleanUpVirtualFileSystemAfterBuild] Cleaning virtual file system after build finished
2026-08-05T00:21:25.582+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler] Finishing executing command: Build{id=8f003848-cb45-44c8-a349-abd959060618, currentDir=D:\WORK\SELF\willSystem\willSystem}
2026-08-05T00:21:25.624+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 78: received class org.gradle.launcher.daemon.protocol.CloseInput
2026-08-05T00:21:25.625+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultDaemonConnection] thread 78: Received IO message from client: org.gradle.launcher.daemon.protocol.CloseInput@517ed5dc
2026-08-05T00:21:25.625+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 78: received class org.gradle.launcher.daemon.protocol.Finished
2026-08-05T00:21:25.625+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultDaemonConnection] thread 78: Received non-IO message from client: org.gradle.launcher.daemon.protocol.Finished@31144112
2026-08-05T00:21:25.626+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultIncomingConnectionHandler] Received finished message: org.gradle.launcher.daemon.protocol.Finished@31144112
2026-08-05T00:21:25.626+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 77: stopping connection
2026-08-05T00:21:25.628+0800 [DEBUG] [org.gradle.internal.remote.internal.inet.SocketConnection] Discarding EOFException: java.io.EOFException
2026-08-05T00:21:25.628+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 78: received null
2026-08-05T00:21:25.628+0800 [DEBUG] [org.gradle.launcher.daemon.server.DefaultDaemonConnection] thread 78: Received end-of-input from client.
2026-08-05T00:21:25.628+0800 [DEBUG] [org.gradle.launcher.daemon.server.SynchronizedDispatchConnection] thread 77: stopping connection
2026-08-05T00:21:25.630+0800 [DEBUG] [org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess] Releasing file lock for jars (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\jars-9)
2026-08-05T00:21:25.630+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on jars (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\jars-9).
2026-08-05T00:21:25.633+0800 [DEBUG] [org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess] Releasing file lock for file content cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\fileContent)
2026-08-05T00:21:25.633+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on file content cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\fileContent).
2026-08-05T00:21:25.634+0800 [DEBUG] [org.gradle.internal.watch.vfs.impl.WatchingVirtualFileSystem] Closing VFS, dropping state
2026-08-05T00:21:25.636+0800 [DEBUG] [org.gradle.internal.watch.registry.impl.DefaultFileWatcherRegistry] Finished listening to file system change events
2026-08-05T00:21:25.636+0800 [DEBUG] [org.gradle.cache.internal.DefaultCacheCoordinator] Cache Generated Gradle JARs cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\generated-gradle-jars) was closed 0 times.
2026-08-05T00:21:25.636+0800 [DEBUG] [org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess] Releasing file lock for artifact cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\modules-2)
2026-08-05T00:21:25.637+0800 [DEBUG] [org.gradle.cache.internal.btree.BTreePersistentIndexedCache] Closing cache module-metadata.bin (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\modules-2\metadata-2.107\module-metadata.bin)
2026-08-05T00:21:25.637+0800 [DEBUG] [org.gradle.cache.internal.btree.BTreePersistentIndexedCache] Closing cache resource-at-url.bin (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\modules-2\metadata-2.107\resource-at-url.bin)
2026-08-05T00:21:25.638+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on artifact cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\modules-2).
2026-08-05T00:21:25.641+0800 [DEBUG] [org.gradle.cache.internal.DefaultCacheCoordinator] Cache groovy-dsl (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\groovy-dsl) was closed 0 times.
2026-08-05T00:21:25.642+0800 [DEBUG] [org.gradle.cache.internal.DefaultCacheCoordinator] Cache Artifact transforms cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\transforms) was closed 0 times.
2026-08-05T00:21:25.643+0800 [DEBUG] [org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess] Releasing file lock for journal cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\journal-1)
2026-08-05T00:21:25.643+0800 [DEBUG] [org.gradle.cache.internal.btree.BTreePersistentIndexedCache] Closing cache file-access.bin (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\journal-1\file-access.bin)
2026-08-05T00:21:25.644+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on journal cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\journal-1).
2026-08-05T00:21:25.644+0800 [DEBUG] [org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess] Releasing file lock for file hash cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\fileHashes)
2026-08-05T00:21:25.645+0800 [DEBUG] [org.gradle.cache.internal.btree.BTreePersistentIndexedCache] Closing cache fileHashes.bin (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\fileHashes\fileHashes.bin)
2026-08-05T00:21:25.646+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on file hash cache (D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches\8.13\fileHashes).
2026-08-05T00:21:25.647+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Deleting unused version-specific caches in D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches' started
2026-08-05T00:21:25.667+0800 [DEBUG] [org.gradle.cache.internal.VersionSpecificCacheCleanupAction] Processed version-specific caches at D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches for cleanup in 0.018 secs
2026-08-05T00:21:25.667+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Deleting unused version-specific caches in D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches'
2026-08-05T00:21:25.667+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Deleting unused version-specific caches in D:\WORK\SELF\willSystem\willSystem\.gradle-codex\caches' completed
2026-08-05T00:21:25.669+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Deleting unused Gradle distributions in D:\WORK\SELF\willSystem\willSystem\.gradle-codex\wrapper\dists' started
2026-08-05T00:21:25.670+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Deleting unused Gradle distributions in D:\WORK\SELF\willSystem\willSystem\.gradle-codex\wrapper\dists'
2026-08-05T00:21:25.671+0800 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Deleting unused Gradle distributions in D:\WORK\SELF\willSystem\willSystem\.gradle-codex\wrapper\dists' completed
2026-08-05T00:21:25.671+0800 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] stop() called on daemon
2026-08-05T00:21:25.671+0800 [INFO] [org.gradle.launcher.daemon.server.Daemon] Stop requested. Daemon is removing its presence from the registry...
2026-08-05T00:21:25.671+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Removing our presence to clients, eg. removing this address from the registry: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:25.672+0800 [DEBUG] [org.gradle.launcher.daemon.registry.PersistentDaemonRegistry] Removing daemon address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:25.674+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire exclusive lock on daemon addresses registry.
2026-08-05T00:21:25.674+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
2026-08-05T00:21:25.676+0800 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
2026-08-05T00:21:25.677+0800 [DEBUG] [org.gradle.launcher.daemon.server.DaemonRegistryUpdater] Address removed from registry.
2026-08-05T00:21:25.678+0800 [DEBUG] [org.gradle.cache.internal.locklistener.DefaultFileLockContentionHandler] File lock listener thread completed.
2026-08-05T00:21:25.680+0800 [DEBUG] [java.lang.Runtime] Runtime.exit() called with status: 0
java.lang.Throwable: Runtime.exit(0)
at java.base/java.lang.Shutdown.logRuntimeExit(Shutdown.java:179)
at java.base/java.lang.Shutdown.exit(Shutdown.java:160)
at java.base/java.lang.Runtime.exit(Runtime.java:188)
at java.base/java.lang.System.exit(System.java:1920)
at org.gradle.launcher.bootstrap.ProcessCompleter.complete(ProcessCompleter.java:21)
at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:61)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:72)
at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:39)
at org.gradle.launcher.daemon.bootstrap.GradleDaemon.main(GradleDaemon.java:22)
Daemon vm is shutting down... The daemon has exited normally or was terminated in response to a user interrupt.
2026-08-05T00:21:25.682+0800 [DEBUG] [org.gradle.launcher.daemon.registry.PersistentDaemonRegistry] Removing daemon address: [395e3ed3-d3f4-4c92-b3c0-52cf4a71fc27 port:50340, addresses:[localhost/127.0.0.1]]
2026-08-05T00:21:25.683+0800 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] VM shutdown hook was unable to remove the daemon address from the registry. It will be cleaned up later.
java.lang.IllegalStateException: Cannot start managing file contention because this handler has been closed.
at org.gradle.cache.internal.locklistener.DefaultFileLockContentionHandler.assertNotStopped(DefaultFileLockContentionHandler.java:248)
at org.gradle.cache.internal.locklistener.DefaultFileLockContentionHandler.reservePort(DefaultFileLockContentionHandler.java:286)
at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:124)
at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:106)
at org.gradle.cache.internal.DefaultFileLockManager.lock(DefaultFileLockManager.java:101)
at org.gradle.cache.internal.OnDemandFileAccess.updateFile(OnDemandFileAccess.java:51)
at org.gradle.cache.internal.FileBackedObjectHolder.update(FileBackedObjectHolder.java:77)
at org.gradle.cache.internal.FileIntegrityViolationSuppressingObjectHolderDecorator.lambda$update$0(FileIntegrityViolationSuppressingObjectHolderDecorator.java:48)
at org.gradle.cache.internal.FileIntegrityViolationSuppressingObjectHolderDecorator.doUpdate(FileIntegrityViolationSuppressingObjectHolderDecorator.java:58)
at org.gradle.cache.internal.FileIntegrityViolationSuppressingObjectHolderDecorator.update(FileIntegrityViolationSuppressingObjectHolderDecorator.java:48)
at org.gradle.launcher.daemon.registry.PersistentDaemonRegistry.remove(PersistentDaemonRegistry.java:133)
at org.gradle.launcher.daemon.server.Daemon$1.run(Daemon.java:133)
at java.base/java.lang.Thread.run(Thread.java:1583)
Binary file not shown.
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Gradle.
# For information about cache directory tags, see:
# https://bford.info/cachedir/
Binary file not shown.
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/businessAgent" />
<option value="$PROJECT_DIR$/businessJob" />
<option value="$PROJECT_DIR$/coreAgent" />
<option value="$PROJECT_DIR$/coreApi" />
<option value="$PROJECT_DIR$/coreAuth" />
<option value="$PROJECT_DIR$/coreCommon" />
<option value="$PROJECT_DIR$/coreData" />
<option value="$PROJECT_DIR$/coreJob" />
<option value="$PROJECT_DIR$/coreQueue" />
<option value="$PROJECT_DIR$/coreRedis" />
<option value="$PROJECT_DIR$/coreService" />
<option value="$PROJECT_DIR$/wcsApp" />
<option value="$PROJECT_DIR$/wcsService" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,org.springframework.amqp.rabbit.connection.CachingConnectionFactory,createConnection" />
</inspection_tool>
</profile>
</component>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
+124
View File
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
Generated
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/will_server" vcs="Git" />
</component>
</project>
+2
View File
@@ -0,0 +1,2 @@
logging.level.org.springframework.context.annotation=DEBUG
logging.level.org.springframework.beans.factory=DEBUG
+65
View File
@@ -0,0 +1,65 @@
plugins {
id 'java'
id 'io.spring.dependency-management' version '1.1.7' apply false
}
allprojects {
group = 'com.will'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
gradlePluginPortal()
}
}
subprojects {
apply plugin: 'java' // 明确为每个子项目应用 java 插件
apply plugin: 'io.spring.dependency-management' // 复用上面声明的版本
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
compileJava {
options.compilerArgs << '-parameters'
}
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:3.5.7"
mavenBom "org.springframework.ai:spring-ai-bom:1.0.0"
mavenBom "org.bsc.langgraph4j:langgraph4j-bom:1.8.19"
}
}
dependencies {
implementation 'org.springframework:spring-context'
implementation 'org.springframework:spring-aop'
implementation("org.springframework.boot:spring-boot-starter-data-redis")
implementation("org.springframework.boot:spring-boot-starter-json")
implementation 'org.springframework.boot:spring-boot-autoconfigure'
implementation 'org.slf4j:slf4j-api'
implementation("com.fasterxml.jackson.core:jackson-databind:2.20.1")
implementation("cn.hutool:hutool-all:5.8.41")
implementation 'org.aspectj:aspectjweaver:1.9.25'
implementation("org.apache.commons:commons-pool2:2.12.1")
implementation enforcedPlatform('org.junit:junit-bom:5.10.0')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
compileOnly 'org.projectlombok:lombok:1.18.34'
annotationProcessor 'org.projectlombok:lombok:1.18.34'
testCompileOnly 'org.projectlombok:lombok:1.18.34'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.34'
}
test {
useJUnitPlatform()
}
}
+19
View File
@@ -0,0 +1,19 @@
plugins {
id 'java'
}
dependencies {
implementation project(':coreCommon')
implementation project(':coreService')
implementation project(':coreAgent')
implementation project(':coreAuth')
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.ai:spring-ai-client-chat'
implementation 'org.springframework.ai:spring-ai-starter-mcp-client'
implementation 'org.bsc.langgraph4j:langgraph4j-core'
implementation 'org.bsc.langgraph4j:langgraph4j-spring-ai'
}
@@ -0,0 +1,90 @@
package com.will.businessAgent.codegen;
import com.will.businessAgent.codegen.CodeArtifact;
import com.will.businessAgent.codegen.CodeGenRequest;
import com.will.businessAgent.codegen.CodeGenResult;
import com.will.businessAgent.codegen.CodeGenState;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bsc.langgraph4j.CompiledGraph;
import org.bsc.langgraph4j.NodeOutput;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "will.agent", name = "enabled", havingValue = "true")
public class BusinessCodeGenAgentService {
private final CompiledGraph<CodeGenState> businessCodeGenCompiledGraph;
public CodeGenResult generate(CodeGenRequest request) {
if (request == null || !StringUtils.hasText(request.getRequirement())) {
throw new IllegalArgumentException("requirement 不能为空");
}
String moduleName = StringUtils.hasText(request.getModuleName()) ? request.getModuleName() : "demo";
String entityName = StringUtils.hasText(request.getEntityName())
? request.getEntityName()
: capitalize(moduleName);
Map<String, Object> inputs = Map.of(
CodeGenState.REQUIREMENT, request.getRequirement(),
CodeGenState.MODULE_NAME, moduleName,
CodeGenState.ENTITY_NAME, entityName
);
CodeGenState finalState = null;
for (NodeOutput<CodeGenState> output : businessCodeGenCompiledGraph.stream(inputs)) {
log.debug("[Agent] node={}", output.node());
if (output.state() != null) {
finalState = output.state();
}
}
if (finalState == null) {
throw new IllegalStateException("Agent 执行失败:未产生最终状态");
}
List<CodeArtifact> artifacts = new ArrayList<>();
addArtifact(artifacts, "entity", entityName + ".java", finalState.entityCode().orElse(""));
addArtifact(artifacts, "mapper", entityName + "Mapper.java", finalState.mapperCode().orElse(""));
addArtifact(artifacts, "dto", entityName + "DTO.java", finalState.dtoCode().orElse(""));
addArtifact(artifacts, "service", entityName + "Service.java", finalState.serviceCode().orElse(""));
addArtifact(artifacts, "controller", "Auth" + entityName + "Controller.java",
finalState.controllerCode().orElse(""));
return CodeGenResult.builder()
.moduleName(finalState.moduleName().orElse(moduleName))
.entityName(finalState.entityName().orElse(entityName))
.plan(finalState.plan().orElse(""))
.summary(finalState.summary().orElse(""))
.mcpContext(finalState.mcpContext().orElse(""))
.artifacts(artifacts)
.build();
}
private void addArtifact(List<CodeArtifact> artifacts, String layer, String fileName, String content) {
if (!StringUtils.hasText(content)) {
return;
}
artifacts.add(CodeArtifact.builder()
.layer(layer)
.fileName(fileName)
.content(content)
.build());
}
private static String capitalize(String value) {
if (value.length() == 1) {
return value.toUpperCase();
}
return Character.toUpperCase(value.charAt(0)) + value.substring(1);
}
}
@@ -0,0 +1,165 @@
package com.will.businessAgent.codegen;
import com.will.coreAgent.framework.mcp.McpContextService;
import com.will.coreAgent.agent.prompt.WillSystemPrompts;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bsc.langgraph4j.CompiledGraph;
import org.bsc.langgraph4j.GraphStateException;
import org.bsc.langgraph4j.StateGraph;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import java.util.Map;
import static org.bsc.langgraph4j.StateGraph.END;
import static org.bsc.langgraph4j.StateGraph.START;
import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async;
/**
* LangGraph4j 工作流:解析需求 → MCP 上下文增强 → 生成计划 → 生成各层代码 → 总结。
*
* <pre>
* START → init → enrichMcp → plan → generate → summary → END
* </pre>
*/
@Slf4j
@Configuration
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "will.agent", name = "enabled", havingValue = "true")
public class BusinessCodeGenGraph {
private final McpContextService mcpContextService;
@Bean
public CompiledGraph<CodeGenState> businessCodeGenCompiledGraph(ChatClient agentChatClient)
throws GraphStateException {
var initNode = node_async((CodeGenState state) -> {
String module = state.moduleName().filter(StringUtils::hasText).orElse("demo");
String entity = state.entityName().filter(StringUtils::hasText)
.orElse(capitalize(module));
log.info("[Agent] init module={}, entity={}", module, entity);
return Map.of(
CodeGenState.MODULE_NAME, module,
CodeGenState.ENTITY_NAME, entity
);
});
var enrichMcpNode = node_async((CodeGenState state) -> {
String context = mcpContextService.buildContextSnippet(
state.requirement().orElse(""),
state.moduleName().orElse("demo"));
if (mcpContextService.isEnabled()) {
log.info("[Agent][MCP] context enriched, tools={}, servers={}",
mcpContextService.listToolNames().size(),
mcpContextService.connectedServerCount());
}
return Map.of(CodeGenState.MCP_CONTEXT, context);
});
var planNode = node_async((CodeGenState state) -> {
String plan = agentChatClient.prompt()
.user(WillSystemPrompts.planPrompt(
state.requirement().orElse(""),
state.moduleName().orElse("demo"),
state.entityName().orElse("Demo"),
state.mcpContext().orElse("")))
.call()
.content();
log.info("[Agent] plan generated");
return Map.of(CodeGenState.PLAN, plan == null ? "" : plan);
});
var generateNode = node_async((CodeGenState state) -> {
String module = state.moduleName().orElse("demo");
String entity = state.entityName().orElse("Demo");
String plan = state.plan().orElse("");
String mcpContext = state.mcpContext().orElse("");
String entityCode = generateLayer(agentChatClient, "entity", module, entity, plan, mcpContext);
String mapperCode = generateLayer(agentChatClient, "mapper", module, entity, plan, mcpContext);
String dtoCode = generateLayer(agentChatClient, "dto", module, entity, plan, mcpContext);
String serviceCode = generateLayer(agentChatClient, "service", module, entity, plan, mcpContext);
String controllerCode = generateLayer(agentChatClient, "controller", module, entity, plan, mcpContext);
log.info("[Agent] code layers generated");
return Map.of(
CodeGenState.ENTITY_CODE, entityCode,
CodeGenState.MAPPER_CODE, mapperCode,
CodeGenState.DTO_CODE, dtoCode,
CodeGenState.SERVICE_CODE, serviceCode,
CodeGenState.CONTROLLER_CODE, controllerCode
);
});
var summaryNode = node_async((CodeGenState state) -> {
String summary = agentChatClient.prompt()
.user(WillSystemPrompts.summaryPrompt(
state.moduleName().orElse("demo"),
state.entityName().orElse("Demo"),
state.plan().orElse(""),
state.mcpContext().orElse("")))
.call()
.content();
return Map.of(CodeGenState.SUMMARY, summary == null ? "" : summary);
});
StateGraph<CodeGenState> graph = new StateGraph<>(CodeGenState.SCHEMA, CodeGenState::new)
.addNode("init", initNode)
.addNode("enrichMcp", enrichMcpNode)
.addNode("plan", planNode)
.addNode("generate", generateNode)
.addNode("summary", summaryNode)
.addEdge(START, "init")
.addEdge("init", "enrichMcp")
.addEdge("enrichMcp", "plan")
.addEdge("plan", "generate")
.addEdge("generate", "summary")
.addEdge("summary", END);
return graph.compile();
}
private static String generateLayer(
ChatClient chatClient,
String layer,
String module,
String entity,
String plan,
String mcpContext) {
String content = chatClient.prompt()
.user(WillSystemPrompts.codePrompt(layer, module, entity, plan, mcpContext))
.call()
.content();
return stripMarkdownFence(content);
}
private static String stripMarkdownFence(String content) {
if (content == null) {
return "";
}
String trimmed = content.trim();
if (trimmed.startsWith("```")) {
int firstNewline = trimmed.indexOf('\n');
int lastFence = trimmed.lastIndexOf("```");
if (firstNewline > 0 && lastFence > firstNewline) {
return trimmed.substring(firstNewline + 1, lastFence).trim();
}
}
return trimmed;
}
private static String capitalize(String value) {
if (!StringUtils.hasText(value)) {
return "Demo";
}
if (value.length() == 1) {
return value.toUpperCase();
}
return Character.toUpperCase(value.charAt(0)) + value.substring(1);
}
}
@@ -0,0 +1,12 @@
package com.will.businessAgent.codegen;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class CodeArtifact {
private String fileName;
private String layer;
private String content;
}
@@ -0,0 +1,13 @@
package com.will.businessAgent.codegen;
import lombok.Data;
@Data
public class CodeGenRequest {
/** 自然语言业务需求,如:商品管理,含名称、价格、库存 CRUD */
private String requirement;
/** 业务模块名(英文小写),如 product、order,默认 demo */
private String moduleName;
/** 实体类名(PascalCase),如 Product,默认根据 moduleName 推导 */
private String entityName;
}
@@ -0,0 +1,17 @@
package com.will.businessAgent.codegen;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
@Builder
public class CodeGenResult {
private String moduleName;
private String entityName;
private String plan;
private String summary;
private String mcpContext;
private List<CodeArtifact> artifacts;
}
@@ -0,0 +1,88 @@
package com.will.businessAgent.codegen;
import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.state.Channel;
import org.bsc.langgraph4j.state.Channels;
import java.util.Map;
import java.util.Optional;
/**
* LangGraph4j 业务代码生成状态。
*/
public class CodeGenState extends AgentState {
public static final String REQUIREMENT = "requirement";
public static final String MODULE_NAME = "moduleName";
public static final String ENTITY_NAME = "entityName";
public static final String PLAN = "plan";
public static final String ENTITY_CODE = "entityCode";
public static final String MAPPER_CODE = "mapperCode";
public static final String DTO_CODE = "dtoCode";
public static final String SERVICE_CODE = "serviceCode";
public static final String CONTROLLER_CODE = "controllerCode";
public static final String SUMMARY = "summary";
public static final String MCP_CONTEXT = "mcpContext";
public static final Map<String, Channel<?>> SCHEMA = Map.ofEntries(
Map.entry(REQUIREMENT, Channels.base(() -> "")),
Map.entry(MODULE_NAME, Channels.base(() -> "")),
Map.entry(ENTITY_NAME, Channels.base(() -> "")),
Map.entry(PLAN, Channels.base(() -> "")),
Map.entry(ENTITY_CODE, Channels.base(() -> "")),
Map.entry(MAPPER_CODE, Channels.base(() -> "")),
Map.entry(DTO_CODE, Channels.base(() -> "")),
Map.entry(SERVICE_CODE, Channels.base(() -> "")),
Map.entry(CONTROLLER_CODE, Channels.base(() -> "")),
Map.entry(SUMMARY, Channels.base(() -> "")),
Map.entry(MCP_CONTEXT, Channels.base(() -> ""))
);
public CodeGenState(Map<String, Object> initData) {
super(initData);
}
public Optional<String> requirement() {
return value(REQUIREMENT);
}
public Optional<String> moduleName() {
return value(MODULE_NAME);
}
public Optional<String> entityName() {
return value(ENTITY_NAME);
}
public Optional<String> plan() {
return value(PLAN);
}
public Optional<String> entityCode() {
return value(ENTITY_CODE);
}
public Optional<String> mapperCode() {
return value(MAPPER_CODE);
}
public Optional<String> dtoCode() {
return value(DTO_CODE);
}
public Optional<String> serviceCode() {
return value(SERVICE_CODE);
}
public Optional<String> controllerCode() {
return value(CONTROLLER_CODE);
}
public Optional<String> summary() {
return value(SUMMARY);
}
public Optional<String> mcpContext() {
return value(MCP_CONTEXT);
}
}
@@ -0,0 +1,27 @@
package com.will.businessAgent.config;
import com.will.businessAgent.codegen.BusinessCodeGenAgentService;
import com.will.businessAgent.codegen.BusinessCodeGenGraph;
import com.will.businessAgent.controller.AgentCodeController;
import com.will.businessAgent.controller.AgentZentaoController;
import com.will.businessAgent.tool.WillSystemAgentTools;
import com.will.businessAgent.tool.WillSystemOrgTools;
import com.will.businessAgent.tool.ZentaoReportTools;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@ConditionalOnProperty(prefix = "will.agent", name = "enabled", havingValue = "true")
@Import({
BusinessAgentToolConfiguration.class,
BusinessCodeGenGraph.class,
BusinessCodeGenAgentService.class,
WillSystemAgentTools.class,
WillSystemOrgTools.class,
ZentaoReportTools.class,
AgentCodeController.class,
AgentZentaoController.class
})
public class BusinessAgentAutoConfiguration {
}
@@ -0,0 +1,35 @@
package com.will.businessAgent.config;
import com.will.coreAgent.framework.tool.UserContextAwareToolCallbackProvider;
import com.will.businessAgent.tool.WillSystemAgentTools;
import com.will.businessAgent.tool.WillSystemOrgTools;
import com.will.businessAgent.tool.ZentaoReportTools;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ConditionalOnProperty(prefix = "will.agent", name = "enabled", havingValue = "true")
public class BusinessAgentToolConfiguration {
@Bean
public ToolCallbackProvider willSystemAgentToolProvider(
WillSystemAgentTools agentTools,
WillSystemOrgTools orgTools,
ObjectProvider<ZentaoReportTools> zentaoReportTools) {
List<Object> tools = new ArrayList<>();
tools.add(agentTools);
tools.add(orgTools);
zentaoReportTools.ifAvailable(tools::add);
ToolCallbackProvider methodProvider = MethodToolCallbackProvider.builder()
.toolObjects(tools.toArray())
.build();
return new UserContextAwareToolCallbackProvider(methodProvider);
}
}
@@ -0,0 +1,34 @@
package com.will.businessAgent.controller;
import com.will.auth.annotation.RequirePermission;
import com.will.businessAgent.codegen.CodeGenRequest;
import com.will.businessAgent.codegen.CodeGenResult;
import com.will.businessAgent.codegen.BusinessCodeGenAgentService;
import com.will.coreCommon.auth.ApiPermissions;
import com.will.coreCommon.general.ResponseMessage;
import com.will.coreCommon.general.ResponseMessageFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/agent/code")
@RequiredArgsConstructor
public class AgentCodeController {
private final ObjectProvider<BusinessCodeGenAgentService> businessCodeGenAgentService;
@RequirePermission(ApiPermissions.AGENT_CODE_GEN)
@PostMapping("/generate")
public ResponseMessage<CodeGenResult> generate(@RequestBody CodeGenRequest request) {
BusinessCodeGenAgentService service = businessCodeGenAgentService.getIfAvailable();
if (service == null) {
return ResponseMessageFactory.error(
"AI Agent 未启用,请在 application.yml 中设置 will.agent.enabled=true 并配置大模型");
}
return ResponseMessageFactory.success(service.generate(request));
}
}
@@ -0,0 +1,39 @@
package com.will.businessAgent.controller;
import com.will.auth.annotation.RequirePermission;
import com.will.businessAgent.tool.ZentaoReportTools;
import com.will.coreCommon.auth.ApiPermissions;
import com.will.coreCommon.general.ResponseMessage;
import com.will.coreCommon.general.ResponseMessageFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
@RestController
@RequestMapping("/api/agent/zentao")
@RequiredArgsConstructor
public class AgentZentaoController {
private final ObjectProvider<ZentaoReportTools> zentaoReportTools;
@RequirePermission(ApiPermissions.AGENT_LIST)
@GetMapping("/tso/effort/week")
public ResponseMessage<String> zentaoTsoEffortThisWeek() {
ZentaoReportTools tools = zentaoReportTools.getIfAvailable();
if (tools == null) {
return ResponseMessageFactory.error("禅道工具未启用");
}
LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
LocalDate weekStart = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
LocalDate weekEnd = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
return ResponseMessageFactory.success(
tools.getZentaoGroupTaskEffortStats(weekStart.toString(), weekEnd.toString(), "TSO"));
}
}
@@ -0,0 +1,29 @@
package com.will.businessAgent.tool;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* 智能体内置工具(非 MCP 进程,直接注册到 ChatClient)。
*/
@Component
public class WillSystemAgentTools {
@Tool(description = "获取 willSystem 项目模块说明")
public String getWillSystemModuleInfo(
@ToolParam(description = "模块名:user、department、role、menu、agent") String module) {
if (!StringUtils.hasText(module)) {
return "请提供模块名";
}
return switch (module.trim().toLowerCase()) {
case "user" -> "用户管理:/api/sys/user,权限 sys:user:list|save|delete";
case "department", "dept" -> "部门管理:/api/sys/department,权限 sys:department:*";
case "role" -> "角色管理:/api/sys/role,权限 sys:role:*";
case "menu" -> "菜单管理:/api/sys/menu,权限 sys:menu:*";
case "agent" -> "AI 智能体:/api/agent/chat、/api/agent/code/generate";
default -> "未知模块:" + module + "。可选:user、department、role、menu、agent";
};
}
}
@@ -0,0 +1,212 @@
package com.will.businessAgent.tool;
import com.will.coreAgent.agent.context.AgentOperatorContext;
import com.will.coreCommon.BaseListDTO;
import com.will.coreCommon.BasePage;
import com.will.coreCommon.context.UserContext;
import com.will.coreCommon.general.ResponseMessage;
import com.will.coreService.dto.DepartmentDTO;
import com.will.coreService.dto.UserDTO;
import com.will.coreService.dto.UserSaveDTO;
import com.will.coreService.service.DepartmentService;
import com.will.coreService.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* willSystem 组织架构查询工具:部门 / 用户(遵循数据权限)。
* 通过 ChatClient ToolCallback 暴露给大模型,等价于业务 MCP 能力。
*/
@Component
@RequiredArgsConstructor
public class WillSystemOrgTools {
private final DepartmentService departmentService;
private final UserService userService;
@Tool(description = "查询 willSystem 部门树(含编码、名称、状态)。用于了解组织架构。")
public String listDepartments() {
ensureUserContext();
ResponseMessage<BaseListDTO<DepartmentDTO>> result = departmentService.getDepartmentListDto();
if (result.hasError()) {
return "查询部门失败:" + result.getMessage();
}
List<DepartmentDTO> list = result.getData() == null ? List.of() : result.getData().getList();
if (list == null || list.isEmpty()) {
return "当前用户可见部门为空";
}
StringBuilder sb = new StringBuilder("部门树(共 ").append(countNodes(list)).append(" 个):\n");
appendDeptTree(sb, list, 0);
return sb.toString();
}
@Tool(description = "按部门名称关键字搜索部门,返回匹配的部门列表")
public String searchDepartments(
@ToolParam(description = "部门名称关键字,例如:研发、销售") String departmentName) {
ensureUserContext();
if (!StringUtils.hasText(departmentName)) {
return "请提供部门名称关键字";
}
DepartmentDTO condition = new DepartmentDTO();
condition.setDepartmentName(departmentName.trim());
ResponseMessage<BasePage<DepartmentDTO>> result =
departmentService.getDepartmentPageDto(condition, 1, 50);
if (result.hasError()) {
return "搜索部门失败:" + result.getMessage();
}
BasePage<DepartmentDTO> page = result.getData();
if (page == null || page.getList() == null || page.getList().isEmpty()) {
return "未找到名称包含「" + departmentName + "」的部门";
}
StringBuilder sb = new StringBuilder("匹配部门(").append(page.getTotal()).append("):\n");
appendDeptTree(sb, page.getList(), 0);
return sb.toString();
}
@Tool(description = "按部门 ID 分页查询该部门及子部门下的用户列表")
public String listUsersByDepartment(
@ToolParam(description = "部门 ID") String departmentId,
@ToolParam(description = "页码,从 1 开始,默认 1", required = false) Integer pageIndex,
@ToolParam(description = "每页条数,默认 10,最大 50", required = false) Integer pageSize) {
ensureUserContext();
if (!StringUtils.hasText(departmentId)) {
return "请提供部门 ID(可先调用 listDepartments 或 searchDepartments 获取)";
}
int page = pageIndex == null || pageIndex < 1 ? 1 : pageIndex;
int size = pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 50);
ResponseMessage<BasePage<UserDTO>> result =
departmentService.getPageUsersByDepartmentId(departmentId.trim(), page, size);
if (result.hasError()) {
return "查询部门用户失败:" + result.getMessage();
}
return formatUserPage(result.getData(), "部门 " + departmentId + " 用户");
}
@Tool(description = "按登录账号或姓名关键字分页搜索 willSystem 用户;用户询问用户信息、人员信息、账号列表时优先调用")
public String searchUsers(
@ToolParam(description = "登录账号或姓名关键字,可为空表示查全部可见用户", required = false) String account,
@ToolParam(description = "页码,从 1 开始,默认 1", required = false) Integer pageIndex,
@ToolParam(description = "每页条数,默认 10,最大 50", required = false) Integer pageSize) {
ensureUserContext();
int page = pageIndex == null || pageIndex < 1 ? 1 : pageIndex;
int size = pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 50);
String keyword = StringUtils.hasText(account) ? account.trim() : null;
ResponseMessage<BasePage<UserDTO>> result = userService.page(keyword, page, size);
if (result.hasError()) {
return "搜索用户失败:" + result.getMessage();
}
String title = keyword == null ? "用户列表" : "账号或姓名包含「" + keyword + "」的用户";
return formatUserPage(result.getData(), title);
}
@Tool(description = "按用户 ID 查询用户详情(账号、姓名、邮箱、角色等,不含密码)")
public String getUserDetail(
@ToolParam(description = "用户 ID") String userId) {
ensureUserContext();
if (!StringUtils.hasText(userId)) {
return "请提供用户 ID(可先调用 searchUsers 获取)";
}
ResponseMessage<UserSaveDTO> result = userService.detail(userId.trim());
if (result.hasError()) {
return "查询用户详情失败:" + result.getMessage();
}
UserSaveDTO user = result.getData();
if (user == null) {
return "用户不存在";
}
return """
用户详情:
- ID:%s
- 账号:%s
- 姓名:%s
- 邮箱:%s
- 手机:%s
- 状态:%s
- 角色ID:%s
""".formatted(
nullToDash(user.getId()),
nullToDash(user.getAccount()),
nullToDash(user.getUserName()),
nullToDash(user.getEmail()),
user.getPhoneNumber() == null ? "-" : user.getPhoneNumber(),
Boolean.FALSE.equals(user.getStatus()) ? "禁用" : "启用",
user.getRoleIds() == null || user.getRoleIds().isEmpty()
? "-"
: String.join(", ", user.getRoleIds())
);
}
private void ensureUserContext() {
String userId = UserContext.getCurrentUserId();
if (!StringUtils.hasText(userId)) {
userId = AgentOperatorContext.get();
if (StringUtils.hasText(userId)) {
UserContext.setCurrentUserId(userId);
}
}
if (!StringUtils.hasText(userId)) {
throw new IllegalStateException("未获取到当前登录用户,请重新登录后再试");
}
}
private static String formatUserPage(BasePage<UserDTO> page, String title) {
if (page == null || page.getList() == null || page.getList().isEmpty()) {
return title + ":无数据";
}
StringBuilder sb = new StringBuilder(title)
.append("(共 ").append(page.getTotal()).append(" 人):\n");
for (UserDTO user : page.getList()) {
sb.append("- ID=").append(user.getId())
.append(" | 账号=").append(nullToDash(user.getAccount()))
.append(" | 姓名=").append(nullToDash(user.getUserName()))
.append(" | 状态=").append(Boolean.FALSE.equals(user.getStatus()) ? "禁用" : "启用")
.append(" | 邮箱=").append(nullToDash(user.getEmail()))
.append('\n');
}
return sb.toString();
}
private static void appendDeptTree(StringBuilder sb, List<DepartmentDTO> nodes, int depth) {
if (nodes == null) {
return;
}
String indent = " ".repeat(Math.max(0, depth));
for (DepartmentDTO dept : nodes) {
sb.append(indent)
.append("- ID=").append(nullToDash(dept.getId()))
.append(" | 名称=").append(nullToDash(dept.getDepartmentName()))
.append(" | 编码=").append(nullToDash(dept.getDepartmentCode()))
.append(" | 状态=").append(dept.getStatus() == null ? "-" : dept.getStatus())
.append('\n');
if (dept.getChildren() != null && !dept.getChildren().isEmpty()) {
appendDeptTree(sb, dept.getChildren(), depth + 1);
}
}
}
private static int countNodes(List<DepartmentDTO> nodes) {
if (nodes == null || nodes.isEmpty()) {
return 0;
}
int count = 0;
List<DepartmentDTO> queue = new ArrayList<>(nodes);
while (!queue.isEmpty()) {
DepartmentDTO node = queue.remove(queue.size() - 1);
count++;
if (node.getChildren() != null) {
queue.addAll(node.getChildren());
}
}
return count;
}
private static String nullToDash(String value) {
return StringUtils.hasText(value) ? value : "-";
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
com.will.businessAgent.config.BusinessAgentAutoConfiguration
+21
View File
@@ -0,0 +1,21 @@
plugins {
id 'java'
}
dependencies {
implementation project(':coreCommon')
implementation project(':coreService')
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'com.fasterxml.jackson.core:jackson-databind'
}
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
}
}
@@ -0,0 +1,51 @@
package com.will.businessJob.mail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
@Slf4j
@Component
@RequiredArgsConstructor
public class MailMessageClient {
private final ObjectProvider<JavaMailSender> mailSenderProvider;
private final ObjectProvider<MailProperties> mailPropertiesProvider;
public void sendMarkdown(String mailTo, String subject, String content) {
if (!StringUtils.hasText(mailTo)) {
throw new IllegalStateException("邮件收件人未配置");
}
JavaMailSender mailSender = mailSenderProvider.getIfAvailable();
if (mailSender == null) {
throw new IllegalStateException("邮件发送服务未配置,请配置 spring.mail.*");
}
try {
MimeMessage message = mailSender.createMimeMessage();
MailProperties mailProperties = mailPropertiesProvider.getIfAvailable(MailProperties::new);
String from = defaultString(mailProperties.getProperties().get("mail.from"), mailProperties.getUsername());
if (StringUtils.hasText(from)) {
message.setFrom(new InternetAddress(from.trim()));
}
message.setRecipients(MimeMessage.RecipientType.TO, mailTo.trim());
message.setSubject(defaultString(subject, "计划任务通知"), "UTF-8");
message.setText(content == null ? "" : content, "UTF-8");
mailSender.send(message);
log.info("[MailMessage] markdown sent, mailTo={}, length={}", mailTo, content == null ? 0 : content.length());
} catch (Exception ex) {
log.warn("[MailMessage] send failed, mailTo={}", mailTo, ex);
throw new IllegalStateException("邮件发送失败:" + ex.getMessage(), ex);
}
}
private String defaultString(String value, String defaultValue) {
return StringUtils.hasText(value) ? value.trim() : defaultValue;
}
}
@@ -0,0 +1,102 @@
package com.will.businessJob.robot;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.will.coreService.enums.RobotType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class RobotMessageClient {
private static final String DEFAULT_TITLE = "报表通知";
private final ObjectMapper objectMapper;
private final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
public void sendMarkdown(String robotType, String content, String webhookUrl) {
RobotType type = RobotType.valueOf(RobotType.defaultName(robotType));
if (!StringUtils.hasText(webhookUrl)) {
throw new IllegalStateException(type.getLabel() + "机器人 webhookUrl 未配置");
}
if (!StringUtils.hasText(content)) {
throw new IllegalArgumentException(type.getLabel() + "机器人消息内容不能为空");
}
try {
HttpRequest request = HttpRequest.newBuilder(URI.create(webhookUrl.trim()))
.timeout(Duration.ofSeconds(20))
.header("Content-Type", "application/json; charset=utf-8")
.POST(HttpRequest.BodyPublishers.ofString(
objectMapper.writeValueAsString(buildPayload(type, content)), StandardCharsets.UTF_8))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException(type.getLabel() + "机器人 HTTP 状态异常:" + response.statusCode());
}
validateResponse(type, response.body());
log.info("[RobotMessage] markdown sent, robotType={}, length={}", type.name(), content.length());
} catch (Exception ex) {
log.warn("[RobotMessage] send failed, robotType={}", type.name(), ex);
throw new IllegalStateException(type.getLabel() + "机器人发送失败:" + ex.getMessage(), ex);
}
}
private Map<String, Object> buildPayload(RobotType type, String content) {
return switch (type) {
case WE_COM -> Map.of(
"msgtype", "markdown",
"markdown", Map.of("content", content)
);
case FEISHU -> Map.of(
"msg_type", "interactive",
"card", Map.of(
"elements", java.util.List.of(Map.of(
"tag", "markdown",
"content", content
))
)
);
case DINGTALK -> Map.of(
"msgtype", "markdown",
"markdown", Map.of(
"title", DEFAULT_TITLE,
"text", content
)
);
case EMAIL -> throw new IllegalArgumentException("EMAIL is not a robot message type");
};
}
private void validateResponse(RobotType type, String responseBody) throws Exception {
JsonNode body = objectMapper.readTree(responseBody);
switch (type) {
case WE_COM, DINGTALK -> {
int errcode = body.path("errcode").asInt(-1);
if (errcode != 0) {
throw new IllegalStateException(type.getLabel() + "机器人返回失败:" + responseBody);
}
}
case FEISHU -> {
int code = body.path("code").asInt(body.path("StatusCode").asInt(-1));
if (code != 0) {
throw new IllegalStateException(type.getLabel() + "机器人返回失败:" + responseBody);
}
}
case EMAIL -> throw new IllegalArgumentException("EMAIL is not a robot message type");
}
}
}
@@ -0,0 +1,144 @@
package com.will.businessJob.zentao;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
@ConditionalOnBean(name = "zentaoJdbcTemplate")
public class ZentaoEffortReportQueryService {
private final JdbcTemplate zentaoJdbcTemplate;
public ZentaoEffortReportQueryService(@Qualifier("zentaoJdbcTemplate") JdbcTemplate zentaoJdbcTemplate) {
this.zentaoJdbcTemplate = zentaoJdbcTemplate;
}
@PostConstruct
public void logZentaoJdbcTemplate() {
Object dataSource = zentaoJdbcTemplate.getDataSource();
if (dataSource instanceof HikariDataSource hikariDataSource) {
log.info("[Job][Zentao] effort report bound jdbcUrl={}, username={}",
hikariDataSource.getJdbcUrl(), hikariDataSource.getUsername());
} else {
log.info("[Job][Zentao] effort report bound datasource={}",
dataSource == null ? "null" : dataSource.getClass().getName());
}
}
public String getGroupTaskEffortRobotSummary(String startDate, String endDate, String groupName) {
LocalDate start = parseDate(startDate);
LocalDate end = parseDate(endDate);
if (start == null || end == null) {
return "禅道用户组任务工时统计:日期格式错误,请使用 yyyy-MM-dd,例如 2026-08-01";
}
if (start.isAfter(end)) {
return "禅道用户组任务工时统计:开始日期不能晚于结束日期";
}
String actualGroupName = StringUtils.hasText(groupName) ? groupName.trim() : "TSO";
List<Object> params = List.of(start.toString(), end.toString(), actualGroupName);
List<Map<String, Object>> rows = queryList("""
SELECT u.account account,
COALESCE(NULLIF(u.realname, ''), u.account) realname,
COALESCE(effort.consumed, 0) consumed
FROM zt_user u
INNER JOIN zt_usergroup ug ON ug.account = u.account
INNER JOIN zt_group g ON g.id = ug.`group`
LEFT JOIN (
SELECT e.account, ROUND(SUM(e.consumed), 2) consumed
FROM zt_effort e
WHERE e.objectType = 'task'
AND e.`date` >= ?
AND e.`date` <= ?
GROUP BY e.account
) effort ON effort.account = u.account
WHERE g.`name` = ?
AND u.deleted = '0'
AND u.account <> 'sygu'
ORDER BY consumed ASC, u.account ASC
""", params.toArray());
if (isQueryFailed(rows)) {
return "禅道用户组任务工时统计:查询失败," + rows.get(0).get("count");
}
if (rows.isEmpty()) {
return "禅道用户组任务工时统计:无成员数据";
}
long days = end.toEpochDay() - start.toEpochDay() + 1;
double threshold = Math.max(days - 1, 0) * 7D;
double totalConsumed = rows.stream()
.map(row -> row.get("consumed"))
.filter(Number.class::isInstance)
.map(Number.class::cast)
.mapToDouble(Number::doubleValue)
.sum();
String users = rows.stream()
.map(row -> {
Object realname = row.getOrDefault("realname", "-");
Object consumedValue = row.getOrDefault("consumed", 0);
double consumed = consumedValue instanceof Number number ? number.doubleValue() : 0D;
String line = "姓名=%s | 消耗工时=%s".formatted(realname, consumedValue);
String color = consumed < threshold ? "warning" : "info";
return "- <font color=\"" + color + "\">" + line + "</font>";
})
.collect(Collectors.joining("\n"));
return """
禅道 %s 组任务工时统计:
- 时间范围:%s 至 %s
- 人员数:%s
- 工时预警阈值:%.2f
- 总消耗工时:%.2f
按成员:
%s
""".formatted(actualGroupName, start, end, rows.size(), threshold, totalConsumed, users);
}
private LocalDate parseDate(String value) {
if (!StringUtils.hasText(value)) {
return null;
}
try {
return LocalDate.parse(value.trim());
} catch (DateTimeParseException ex) {
return null;
}
}
private List<Map<String, Object>> queryList(String sql, Object... args) {
try {
logSql(sql, args);
return zentaoJdbcTemplate.queryForList(sql, args);
} catch (Exception ex) {
log.warn("[Job][Zentao][SQL] query failed: {}", ex.getMessage(), ex);
return List.of(Map.of("count", ex.getMessage() == null ? "bad SQL grammar" : ex.getMessage()));
}
}
private boolean isQueryFailed(List<Map<String, Object>> rows) {
return rows.size() == 1 && rows.get(0).containsKey("count") && rows.get(0).size() == 1
&& rows.get(0).get("count") instanceof String;
}
private void logSql(String sql, Object... args) {
log.info("[Job][Zentao][SQL] {} | args={}", normalizeSql(sql), List.of(args));
}
private String normalizeSql(String sql) {
return sql == null ? "" : sql.replaceAll("\\s+", " ").trim();
}
}
@@ -0,0 +1,163 @@
package com.will.businessJob.zentao;
import com.will.businessJob.mail.MailMessageClient;
import com.will.businessJob.robot.RobotMessageClient;
import com.will.coreService.dto.AgentReportConfigDTO;
import com.will.coreService.dto.AgentReportJobConfigDTO;
import com.will.coreService.enums.RobotType;
import com.will.coreService.service.AgentReportConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
@Slf4j
@Service
@RequiredArgsConstructor
public class ZentaoWeComReportService {
private static final String DEFAULT_GROUP_NAME = "TSO";
private static final String DEFAULT_REPORT_TITLE = "禅道工时完成情况";
private static final String DEFAULT_ZONE = "Asia/Shanghai";
private static final int WE_COM_MARKDOWN_MAX_LENGTH = 3900;
private final ObjectProvider<ZentaoEffortReportQueryService> effortReportQueryService;
private final RobotMessageClient robotMessageClient;
private final MailMessageClient mailMessageClient;
private final AgentReportConfigService reportConfigService;
public String sendDailyEffortReport(AgentReportJobConfigDTO jobConfig) {
AgentReportConfigDTO config = reportConfigService.getConfig();
String disabledReason = validateJobConfig(config, jobConfig);
if (disabledReason != null) {
return disabledReason;
}
ReportRequest request = buildRequest(config, jobConfig);
return sendReport(request, jobConfig.getId());
}
private String validateJobConfig(AgentReportConfigDTO config, AgentReportJobConfigDTO jobConfig) {
if (!Boolean.TRUE.equals(config.getEnabled()) || !Boolean.TRUE.equals(jobConfig.getEnabled())) {
return "计划任务未启用";
}
return null;
}
private ReportRequest buildRequest(AgentReportConfigDTO config, AgentReportJobConfigDTO jobConfig) {
ZoneId zoneId = resolveZone(jobConfig.getZone());
LocalDate today = LocalDate.now(zoneId);
LocalDate weekStart = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
return new ReportRequest(
defaultString(jobConfig.getName(), DEFAULT_REPORT_TITLE),
weekStart,
today,
defaultGroupName(config.getGroupName()),
defaultString(jobConfig.getRobotType(), RobotType.defaultName(config.getRobotType())),
defaultString(jobConfig.getWebhookUrl(), config.getWebhookUrl()),
defaultString(jobConfig.getMailTo(), config.getMailTo()),
defaultString(jobConfig.getMailSubject(), defaultString(config.getMailSubject(), defaultString(jobConfig.getName(), DEFAULT_REPORT_TITLE)))
);
}
private String sendReport(ReportRequest request, String jobId) {
ZentaoEffortReportQueryService queryService = getEffortReportQueryService();
String report = queryService.getGroupTaskEffortRobotSummary(
request.startDate().toString(),
request.endDate().toString(),
request.groupName()
);
String content = truncateMarkdown(request.robotType(), buildMarkdown(request, report));
if (RobotType.EMAIL.name().equals(RobotType.defaultName(request.robotType()))) {
mailMessageClient.sendMarkdown(request.mailTo(), request.mailSubject(), content);
} else {
robotMessageClient.sendMarkdown(request.robotType(), content, request.webhookUrl());
}
if (StringUtils.hasText(jobId)) {
log.info("[Zentao][Robot] job report sent, jobId={}, robotType={}, startDate={}, endDate={}, groupName={}",
jobId, request.robotType(), request.startDate(), request.endDate(), request.groupName());
} else {
log.info("[Zentao][Robot] daily effort report sent, robotType={}, startDate={}, endDate={}, groupName={}",
request.robotType(), request.startDate(), request.endDate(), request.groupName());
}
return content;
}
private ZentaoEffortReportQueryService getEffortReportQueryService() {
ZentaoEffortReportQueryService queryService = effortReportQueryService.getIfAvailable();
if (queryService == null) {
throw new IllegalStateException("禅道工时报表通知查询服务未启用");
}
return queryService;
}
private String buildMarkdown(ReportRequest request, String report) {
return """
## %s
> 日期:%s - %s
> 执行范围:%s
%s
""".formatted(
request.title(),
request.startDate(),
request.endDate(),
request.groupName(),
normalizeMarkdown(report)
);
}
private ZoneId resolveZone(String zone) {
return ZoneId.of(defaultString(zone, DEFAULT_ZONE));
}
private String defaultGroupName(String groupName) {
return defaultString(groupName, DEFAULT_GROUP_NAME);
}
private String defaultString(String value, String defaultValue) {
return StringUtils.hasText(value) ? value.trim() : defaultValue;
}
private String normalizeMarkdown(String report) {
if (!StringUtils.hasText(report)) {
return "无数据";
}
return report.replace("\\n", "\n").trim();
}
private String truncateMarkdown(String robotType, String content) {
if (!RobotType.WE_COM.name().equals(RobotType.defaultName(robotType)) || content.length() <= WE_COM_MARKDOWN_MAX_LENGTH) {
return content;
}
String suffix = "\n\n> 内容过长,已截断。";
int maxBodyLength = WE_COM_MARKDOWN_MAX_LENGTH - suffix.length();
if (maxBodyLength <= 0) {
return content.substring(0, WE_COM_MARKDOWN_MAX_LENGTH);
}
int cutIndex = content.lastIndexOf('\n', maxBodyLength);
if (cutIndex < 0) {
cutIndex = maxBodyLength;
}
return content.substring(0, cutIndex).trim() + suffix;
}
private record ReportRequest(
String title,
LocalDate startDate,
LocalDate endDate,
String groupName,
String robotType,
String webhookUrl,
String mailTo,
String mailSubject
) {
}
}
+3
View File
@@ -0,0 +1,3 @@
plugins { id 'java' }
dependencyManagement { imports { mavenBom 'org.springframework.ai:spring-ai-bom:1.0.0' } }
dependencies { implementation 'org.springframework.ai:spring-ai-starter-mcp-client' }
+19
View File
@@ -0,0 +1,19 @@
plugins {
id 'java'
}
dependencies {
implementation project(':coreCommon')
implementation project(':coreService')
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.ai:spring-ai-client-chat'
implementation 'org.springframework.ai:spring-ai-ollama'
implementation 'org.springframework.ai:spring-ai-openai'
implementation 'org.springframework.ai:spring-ai-zhipuai'
implementation 'org.springframework.ai:spring-ai-starter-mcp-client'
implementation 'org.bsc.langgraph4j:langgraph4j-core'
implementation 'org.bsc.langgraph4j:langgraph4j-spring-ai'
}
@@ -0,0 +1,32 @@
package com.will.coreAgent.agent.context;
import org.springframework.util.StringUtils;
/**
* Agent 调用期间的操作人上下文(跨工具回调线程传递)。
*/
public final class AgentOperatorContext {
public static final String TOOL_CONTEXT_USER_ID = "operatorUserId";
private static final InheritableThreadLocal<String> CURRENT_USER_ID = new InheritableThreadLocal<>();
private AgentOperatorContext() {
}
public static void set(String userId) {
if (StringUtils.hasText(userId)) {
CURRENT_USER_ID.set(userId);
} else {
CURRENT_USER_ID.remove();
}
}
public static String get() {
return CURRENT_USER_ID.get();
}
public static void clear() {
CURRENT_USER_ID.remove();
}
}
@@ -0,0 +1,13 @@
package com.will.coreAgent.agent.dto;
import lombok.Data;
@Data
public class AgentChatRequest {
/** 用户消息 */
private String message;
/** 会话 ID,留空则自动生成 */
private String sessionId;
}
@@ -0,0 +1,12 @@
package com.will.coreAgent.agent.dto;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class AgentChatResult {
private String sessionId;
private String reply;
}
@@ -0,0 +1,15 @@
package com.will.coreAgent.agent.dto;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class AgentDefinition {
private String id;
private String name;
private String description;
private String endpoint;
private boolean streamingSupported;
}
@@ -0,0 +1,19 @@
package com.will.coreAgent.agent.dto;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
@Builder
public class AgentMetaResult {
private boolean enabled;
private String provider;
private String model;
private boolean mcpEnabled;
private int mcpToolCount;
private List<String> mcpToolNames;
private List<AgentDefinition> agents;
}
@@ -0,0 +1,14 @@
package com.will.coreAgent.agent.dto;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
@Builder
public class McpStatusResult {
private boolean enabled;
private int connectedServers;
private List<String> toolNames;
}

Some files were not shown because too many files have changed in this diff Show More