Skip to content

Commit 03edd22

Browse files
committed
fix: 统一初始化时序,修复卡顿及记忆加载,新增 autoload 校验
- 新增 setting_ready 信号替代各处 await/while 轮询,面板统一等待 manager 就绪 - 修复初始化阶段 while 轮询和信号递归导致的编辑器卡顿 - 修复记忆面板首次无内容(删除无意义 await physics_frame) - set_singleton 新增 class_name 冲突检测和 extends Node 校验 - 更新 help 及官网链接
1 parent 4c48450 commit 03edd22

14 files changed

Lines changed: 151 additions & 47 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
/android/
44
.trae/rules
55
.vscode/
6-
test/
6+
test/.reasonix/

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [0.5.0] - 2026-06-05
5+
## [0.5.0] - 2026-06-15
66

77
### ✨ New Features (新增功能)
88
- **供应商与模型**:
@@ -25,14 +25,21 @@ All notable changes to this project will be documented in this file.
2525
- **性能优化**:
2626
- 设置页、技能页、记忆页改为首次可见时才初始化,减少插件启动时的加载压力。
2727
- message_item._process 改为按需启停,空闲时不再每帧运行。
28+
- **Tools**:
29+
- set_singleton 新增 class_name 冲突检测和 extends Node 校验。
2830

2931
### 🐛 Bug Fixes (问题修复)
32+
- 修复插件加载后编辑器持续卡顿(消除 while 轮询和信号递归死循环)。
33+
- 修复模型开关触发 signal → update_model_selector 递归死循环导致卡死。
34+
- 修复记忆面板首次切换无内容。
35+
- 修复插件重新启用时 setting_ready 标志残留导致面板跳过初始化。
3036
- 修复 CheckScriptError 工具在脚本含有 `class_name` 定义时静态检查始终失败的问题。([#9](https://github.com/925236118/AlphaAgent/pull/9))
3137
- 优化标题生成逻辑和思考内容展示。
3238
- 修复 Anthropic 兼容 API 适配问题。
3339
- 限制输入框最大高度,防止内容过多撑破 UI 布局。
3440

3541
### 🔧 Improvements (优化改进)
42+
- 统一初始化时序:新增 setting_ready 信号,所有面板通过信号等待 manager 就绪。
3643
- 修改代码文件层级,优化项目结构。
3744
- 清理 OpenAI 聊天包装器中耦合的 DeepSeek 特殊处理逻辑。
3845

addons/agent/agent.gd

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ func _disable_plugin() -> void:
1414
pass
1515

1616
func _enter_tree() -> void:
17+
# 每次启用插件时复位就绪标志,确保面板通过信号等待新的 load_global_setting 完成
18+
global_setting.setting_is_ready = false
19+
1720
print_greetings()
1821

1922
# 初始化临时文件管理器
@@ -33,7 +36,7 @@ func _enter_tree() -> void:
3336
# 所有初始化完成后打印结束语
3437
print_alpha_message("==$==*----*===*----*===*----*==$==")
3538
print_alpha_message("初始化结束,欢迎使用 [b]Alpha[/b],始于初心,无限可能。")
36-
print_alpha_message("更多详细信息请查看:[url href='https://godotvillage.github.io/alpha/']Alpha 官方网站[/url]")
39+
print_alpha_message("更多详细信息请查看:[url href='https://godotvillage.com/#/project/8665befd-9b55-46dd-9126-5d9bffdbc006']Alpha 官方网站[/url]")
3740

3841

3942
func _exit_tree() -> void:
@@ -69,6 +72,9 @@ enum SendShotcut {
6972
}
7073

7174
class GlobalSetting:
75+
signal setting_ready
76+
var setting_is_ready: bool = false
77+
7278
var setting_dir = ""
7379

7480
var setting_file: String = ""
@@ -139,6 +145,9 @@ class GlobalSetting:
139145
# 初始化技能管理器
140146
skill_manager = AgentSkillConfig.SkillManager.new(skill_directory)
141147

148+
setting_is_ready = true
149+
setting_ready.emit()
150+
142151
func save_global_setting():
143152
var dict = {
144153
"auto_clear": self.auto_clear,

addons/agent/tools/tools_nodes/set_singleton_tool.gd

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,45 @@
22
class_name SetSingletonTool
33
extends AgentToolBase
44

5+
## 获取脚本的 class_name。先查 ProjectSettings 已注册全局类,未注册则解析文件。
6+
func _get_script_class_name(path: String) -> String:
7+
if not path.ends_with(".gd"):
8+
return ""
9+
10+
# 优先查 ProjectSettings:Godot 已解析过的脚本这里最准最快
11+
var class_list: Array = ProjectSettings.get_global_class_list()
12+
for entry in class_list:
13+
if entry.path == path:
14+
return entry.get("class", "")
15+
16+
# 未注册则读文件解析 class_name 行
17+
var file = FileAccess.open(path, FileAccess.READ)
18+
if file == null:
19+
return ""
20+
var text = file.get_as_string()
21+
for line in text.split("\n"):
22+
var s = line.strip_edges()
23+
if s.is_empty() or s.begins_with("#"):
24+
continue
25+
if s.begins_with("class_name "):
26+
return s.substr(11).strip_edges().split(" ")[0] # 取 extends 前的部分
27+
return ""
28+
29+
## 检查脚本是否继承自 Node(autoload 必要条件)
30+
func _script_extends_node(path: String) -> bool:
31+
if not path.ends_with(".gd"):
32+
return true # .tscn 场景必然是 Node
33+
34+
var script = load(path)
35+
if not script is GDScript:
36+
return false
37+
38+
var base: StringName = script.get_instance_base_type()
39+
if base.is_empty() or not ClassDB.class_exists(base):
40+
return false
41+
42+
return ClassDB.is_parent_class(base, "Node")
43+
544
func _get_tool_name() -> String:
645
return "set_singleton"
746

@@ -39,6 +78,11 @@ func do_action(tool_call: AgentModelUtils.ToolCallsInfo) -> Dictionary:
3978
var singleton_name = json.name
4079
var singleton_path = json.get("path", "")
4180
if singleton_path:
81+
var script_class := _get_script_class_name(singleton_path)
82+
if script_class != "" and script_class == singleton_name:
83+
return {"error": "自动加载名 '%s' 与脚本 class_name '%s' 冲突,不可挂载。请使用不同的自动加载名称。" % [singleton_name, script_class]}
84+
if not _script_extends_node(singleton_path):
85+
return {"error": "脚本 '%s' 不继承自 Node,无法设为自动加载。" % singleton_path}
4286
var singleton = AlphaAgentSingleton.get_instance()
4387
singleton.add_autoload_singleton(singleton_name, singleton_path)
4488
return {

addons/agent/ui/chat/input_container.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ func update_model_selector(suppliers: Array, current_model_id: String, current_m
137137
# 设置当前选中的模型
138138
if not model_id_list.has(current_idx):
139139
current_idx = first_model_idx
140+
model_button.set_block_signals(true)
140141
model_button.selected = current_idx
142+
model_button.set_block_signals(false)
141143
if current_idx != -1:
142144
_on_model_selected(current_idx)
143145

addons/agent/ui/help/help.tscn

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ vertical_alignment = 1
4545
[node name="TabContainer" type="TabContainer" parent="MarginContainer/VBoxContainer"]
4646
layout_mode = 2
4747
size_flags_vertical = 3
48-
current_tab = 4
48+
current_tab = 0
4949

5050
[node name="设计哲学" type="ScrollContainer" parent="MarginContainer/VBoxContainer/TabContainer"]
51-
visible = false
5251
layout_mode = 2
5352
size_flags_vertical = 3
5453
metadata/_tab_index = 0
@@ -218,6 +217,7 @@ text = "Alpha有可以记录用户输入的记忆的功能。
218217
fit_content = true
219218

220219
[node name="关于" type="ScrollContainer" parent="MarginContainer/VBoxContainer/TabContainer"]
220+
visible = false
221221
layout_mode = 2
222222
size_flags_vertical = 3
223223
metadata/_tab_index = 4
@@ -259,5 +259,7 @@ Jaxson(1253318213)
259259
PR贡献者:
260260
[ul]
261261
TonyZhao(https://github.com/tonyzhao-jt)
262+
Smalldy(https://github.com/Smalldy)
263+
TsubakiLoL(https://github.com/TsubakiLoL)
262264
[/ul]"
263265
fit_content = true

addons/agent/ui/main_panel.gd

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ func _ready() -> void:
8686
welcome_message.show()
8787
message_container.hide()
8888

89-
# 初始化模型选择
90-
_init_model_selector()
91-
92-
# 初始化角色选择
93-
_init_role_selector()
89+
# 初始化模型选择和角色选择(等待 setting_ready)
90+
if AlphaAgentPlugin.global_setting.setting_is_ready:
91+
_on_setting_ready()
92+
else:
93+
AlphaAgentPlugin.global_setting.setting_ready.connect(_on_setting_ready, CONNECT_ONE_SHOT)
9494
_bind_message_scroll_events()
9595

9696
back_chat_button.pressed.connect(on_click_back_chat_button)
@@ -119,9 +119,12 @@ func _connect_plugin_signals():
119119
singleton.models_changed.connect(_on_models_changed)
120120
singleton.roles_changed.connect(_on_roles_changed)
121121

122+
func _on_setting_ready():
123+
_init_model_selector()
124+
_init_role_selector()
125+
122126
# 初始化模型选择器
123127
func _init_model_selector():
124-
await AlphaAgentPlugin.wait_for_scene_tree_frame()
125128
var model_manager = AlphaAgentPlugin.global_setting.model_manager
126129
if model_manager == null:
127130
return
@@ -137,7 +140,6 @@ func _init_model_selector():
137140
)
138141

139142
func _init_role_selector():
140-
await AlphaAgentPlugin.wait_for_scene_tree_frame()
141143
var role_manager = AlphaAgentPlugin.global_setting.role_manager
142144
if role_manager == null:
143145
return
@@ -154,6 +156,10 @@ func _on_model_selected(supplier_id: String, model_id: String):
154156
if model_manager == null:
155157
return
156158

159+
# 模型未变则跳过,打断 signal → update_model_selector → _on_model_selected 递归链
160+
if model_manager.current_supplier_id == supplier_id and model_manager.current_model_id == model_id:
161+
return
162+
157163
model_manager.set_current_model(supplier_id, model_id)
158164

159165
# 更新输入容器的模型选择器显示
@@ -166,6 +172,7 @@ func _on_models_changed():
166172
func _on_roles_changed():
167173
_init_role_selector()
168174

175+
169176
func reset_message_info():
170177
current_message_item = null
171178
current_think = ""

addons/agent/ui/main_panel.tscn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ size_flags_vertical = 4
427427
tooltip_text = "打开Alpha官网"
428428
text = "Alpha官网"
429429
underline = 1
430-
uri = "https://godotvillage.github.io/alpha/"
430+
uri = "https://godotvillage.com/#/project/8665befd-9b55-46dd-9126-5d9bffdbc006"
431431

432432
[node name="Tools" parent="." instance=ExtResource("3_2usmi")]
433433

addons/agent/ui/memory/memory_container.gd

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,41 @@ extends VBoxContainer
1313
const MEMORY_ITEM = preload("uid://cr2sav6by4tal")
1414
const CONFIG = preload("uid://b4bcww0bmnxt0")
1515

16-
var _initialized: bool = false
16+
var _did_load: bool = false
17+
var _setting_ready_connected: bool = false
1718
func _ready() -> void:
1819
visibility_changed.connect(on_visibility_changed)
1920
add_global_memory.pressed.connect(on_add_global_memory)
2021
add_project_memory.pressed.connect(on_add_project_memory)
2122

23+
# 等待 setting_ready 后再加载和渲染记忆
24+
if not _setting_ready_connected:
25+
_setting_ready_connected = true
26+
AlphaAgentPlugin.global_setting.setting_ready.connect(_on_setting_ready, CONNECT_ONE_SHOT)
27+
28+
func _on_setting_ready():
29+
if visible:
30+
_try_render()
31+
32+
func _try_render():
33+
if not AlphaAgentPlugin.global_setting.setting_is_ready:
34+
return
35+
if not _did_load:
36+
_did_load = true
37+
load_from_project()
38+
load_from_global()
39+
clear_memory_nodes()
40+
add_memory_nodes()
41+
2242
func on_visibility_changed():
2343
if visible:
24-
if not _initialized:
25-
_initialized = true
26-
load_from_project()
27-
clear_memory_nodes()
28-
add_memory_nodes()
44+
_try_render()
2945
else:
3046
clear_memory_nodes()
3147

3248
func load_from_project():
3349
var CONFIG := load("uid://b4bcww0bmnxt0") as AgentConfig
34-
var memory = CONFIG.memory
35-
await get_tree().physics_frame
36-
AlphaAgentPlugin.project_memory = memory
50+
AlphaAgentPlugin.project_memory = CONFIG.memory
3751

3852
func load_from_global():
3953
var memory_string = FileAccess.get_file_as_string(global_memory_file)
@@ -44,8 +58,7 @@ func load_from_global():
4458
if memory_string != "":
4559
json = JSON.parse_string(memory_string)
4660

47-
await get_tree().physics_frame
48-
AlphaAgentPlugin.global_memory = json as Array[String]
61+
AlphaAgentPlugin.global_memory.assign(json)
4962

5063
func add_memory_nodes():
5164
for i in AlphaAgentPlugin.global_memory.size():

addons/agent/ui/models/setting_model_item.gd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ func set_setting_model_info(model: ModelConfig.ModelInfo):
2727
model_id.text = model_info.model_name
2828
support_reasoner.visible = model_info.supports_thinking
2929
support_tool.visible = model_info.supports_tools
30+
is_active.set_block_signals(true)
3031
is_active.button_pressed = model_info.active
32+
is_active.set_block_signals(false)
3133

3234
func on_toggled_is_active_button(toggled_on: bool):
3335
model_info.active = toggled_on

0 commit comments

Comments
 (0)