mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 16:56:56 +08:00
fix(agent): add TargetRef nil guards and ensureHistory for robustness
- Add nil checks for session.TargetRef in all four execute*Action handlers (Trader/Exchange/Model/Strategy) to prevent panic on corrupted sessions; bulk-delete and query actions are excluded - Add ensureHistory() helper and call it in runPlannedAgentWithContextMode to prevent nil panic when history is not initialized Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,12 @@ func New(tm *manager.TraderManager, st *store.Store, cfg *Config, logger *slog.L
|
|||||||
|
|
||||||
func (a *Agent) SetAIClient(c mcp.AIClient) { a.aiClient = c }
|
func (a *Agent) SetAIClient(c mcp.AIClient) { a.aiClient = c }
|
||||||
|
|
||||||
|
func (a *Agent) ensureHistory() {
|
||||||
|
if a.history == nil {
|
||||||
|
a.history = newChatHistory(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Agent) log() *slog.Logger {
|
func (a *Agent) log() *slog.Logger {
|
||||||
if a != nil && a.logger != nil {
|
if a != nil && a.logger != nil {
|
||||||
return a.logger
|
return a.logger
|
||||||
|
|||||||
@@ -2551,6 +2551,7 @@ func (a *Agent) runPlannedAgentWithContextMode(ctx context.Context, storeUserID
|
|||||||
answer, _, err := a.driveActiveSession(ctx, storeUserID, userID, lang, text, session, onEvent)
|
answer, _, err := a.driveActiveSession(ctx, storeUserID, userID, lang, text, session, onEvent)
|
||||||
return answer, err
|
return answer, err
|
||||||
}
|
}
|
||||||
|
a.ensureHistory()
|
||||||
a.history.Add(userID, "user", text)
|
a.history.Add(userID, "user", text)
|
||||||
if onEvent != nil {
|
if onEvent != nil {
|
||||||
onEvent(StreamEventPlanning, a.planningStatusText(lang))
|
onEvent(StreamEventPlanning, a.planningStatusText(lang))
|
||||||
|
|||||||
@@ -1479,6 +1479,12 @@ func (a *Agent) executeTraderManagementAction(storeUserID string, userID int64,
|
|||||||
}
|
}
|
||||||
return formatReadFastPathResponse(lang, "list_traders", a.toolListTraders(storeUserID))
|
return formatReadFastPathResponse(lang, "list_traders", a.toolListTraders(storeUserID))
|
||||||
case "start", "stop", "delete":
|
case "start", "stop", "delete":
|
||||||
|
if session.TargetRef == nil && !(session.Action == "delete" && fieldValue(session, "bulk_scope") == "all") {
|
||||||
|
if lang == "zh" {
|
||||||
|
return "请先指定要操作的交易员。"
|
||||||
|
}
|
||||||
|
return "Please specify which trader to operate on."
|
||||||
|
}
|
||||||
if fieldValue(session, skillDAGStepField) == "" {
|
if fieldValue(session, skillDAGStepField) == "" {
|
||||||
setSkillDAGStep(&session, "await_confirmation")
|
setSkillDAGStep(&session, "await_confirmation")
|
||||||
}
|
}
|
||||||
@@ -1894,6 +1900,17 @@ func (a *Agent) executeBulkTraderDelete(storeUserID string, userID int64, lang,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) executeExchangeManagementAction(storeUserID string, userID int64, lang, text string, session skillSession) string {
|
func (a *Agent) executeExchangeManagementAction(storeUserID string, userID int64, lang, text string, session skillSession) string {
|
||||||
|
switch session.Action {
|
||||||
|
case "query", "query_list", "create":
|
||||||
|
// These actions don't need a target — fall through.
|
||||||
|
default:
|
||||||
|
if session.TargetRef == nil {
|
||||||
|
if lang == "zh" {
|
||||||
|
return "请先指定要操作的交易所配置。"
|
||||||
|
}
|
||||||
|
return "Please specify which exchange config to operate on."
|
||||||
|
}
|
||||||
|
}
|
||||||
switch session.Action {
|
switch session.Action {
|
||||||
case "query_detail":
|
case "query_detail":
|
||||||
if detail, ok := a.describeExchange(storeUserID, lang, session.TargetRef); ok {
|
if detail, ok := a.describeExchange(storeUserID, lang, session.TargetRef); ok {
|
||||||
@@ -2069,6 +2086,17 @@ func (a *Agent) executeExchangeManagementAction(storeUserID string, userID int64
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) executeModelManagementAction(storeUserID string, userID int64, lang, text string, session skillSession) string {
|
func (a *Agent) executeModelManagementAction(storeUserID string, userID int64, lang, text string, session skillSession) string {
|
||||||
|
switch session.Action {
|
||||||
|
case "query", "query_list", "create":
|
||||||
|
// These actions don't need a target — fall through.
|
||||||
|
default:
|
||||||
|
if session.TargetRef == nil {
|
||||||
|
if lang == "zh" {
|
||||||
|
return "请先指定要操作的模型。"
|
||||||
|
}
|
||||||
|
return "Please specify which model to operate on."
|
||||||
|
}
|
||||||
|
}
|
||||||
switch session.Action {
|
switch session.Action {
|
||||||
case "query_detail":
|
case "query_detail":
|
||||||
if detail, ok := a.describeModel(storeUserID, lang, session.TargetRef); ok {
|
if detail, ok := a.describeModel(storeUserID, lang, session.TargetRef); ok {
|
||||||
@@ -2228,6 +2256,18 @@ func (a *Agent) executeModelManagementAction(storeUserID string, userID int64, l
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) executeStrategyManagementAction(storeUserID string, userID int64, lang, text string, session skillSession) string {
|
func (a *Agent) executeStrategyManagementAction(storeUserID string, userID int64, lang, text string, session skillSession) string {
|
||||||
|
switch session.Action {
|
||||||
|
case "query", "query_list", "create":
|
||||||
|
// These actions don't need a target — fall through.
|
||||||
|
default:
|
||||||
|
isBulkDelete := session.Action == "delete" && fieldValue(session, "bulk_scope") == "all"
|
||||||
|
if session.TargetRef == nil && !isBulkDelete {
|
||||||
|
if lang == "zh" {
|
||||||
|
return "请先指定要操作的策略。"
|
||||||
|
}
|
||||||
|
return "Please specify which strategy to operate on."
|
||||||
|
}
|
||||||
|
}
|
||||||
switch session.Action {
|
switch session.Action {
|
||||||
case "query", "query_list":
|
case "query", "query_list":
|
||||||
return formatReadFastPathResponse(lang, "get_strategies", a.toolGetStrategies(storeUserID))
|
return formatReadFastPathResponse(lang, "get_strategies", a.toolGetStrategies(storeUserID))
|
||||||
|
|||||||
Reference in New Issue
Block a user