Skip to content

refactor: 自动倒货改为自动售卖#1646

Open
zmdyy0318 wants to merge 10 commits intov2from
refactor/autosell
Open

refactor: 自动倒货改为自动售卖#1646
zmdyy0318 wants to merge 10 commits intov2from
refactor/autosell

Conversation

@zmdyy0318
Copy link
Copy Markdown
Contributor

@zmdyy0318 zmdyy0318 commented Mar 27, 2026

1、去除自动倒货中购买物品功能,由已有自动囤货代替
2、节点重构,用wait_freeze代替循环自身
3、部分节点接入万能跳转

Summary by Sourcery

重构自动补货/转移流程,以支持通过新的流水线配置实现自动售卖。

新功能:

  • 引入新的 AutoSell 流水线配置,在现有补货逻辑的基础上自动化售卖行为。

改进:

  • 从自动转移流程中移除购买物品的行为,改为使用现有的自动补货功能。
  • 重构节点流程控制,使用 wait_freeze 代替自循环,并将选定节点接入通用跳转机制,以实现更灵活的流转。
Original summary in English

Summary by Sourcery

Refactor the automatic restocking/transfer flow to support automatic selling via a new pipeline configuration.

New Features:

  • Introduce a new AutoSell pipeline configuration to automate selling behavior based on existing stocking logic.

Enhancements:

  • Remove item-purchasing behavior from the auto-transfer flow in favor of using the existing auto-stock feature.
  • Refactor node flow control to use wait_freeze instead of self-looping and wire selected nodes into the universal jump mechanism for more flexible transitions.

Summary by Sourcery

将旧的自动转售流程替换为集成到现有任务系统中的全新自动售卖(autosell)流水线。

新功能:

  • 引入自动售卖任务和流水线配置,根据库存再分配和价格规则自动出售物品。

改进:

  • 注册新的、特定于自动售卖的自定义识别和操作,用于物品文本/价格处理以及扫描去重,并复用通用流水线机制。
  • 移除旧的转售模块及其流水线和预设,全面采用新的自动售卖流程。
Original summary in English

Summary by Sourcery

Replace the legacy auto-resell flow with a new autosell pipeline integrated into the existing task system.

New Features:

  • Introduce an autosell task and pipeline configuration to automate item selling based on stock redistribution and price rules.

Enhancements:

  • Register new autosell-specific custom recognitions and actions for item text/price handling and scanning de-duplication, reusing generic pipeline mechanisms.
  • Remove the old resell module, its pipelines, and presets in favor of the new autosell flow.

Copilot AI review requested due to automatic review settings March 27, 2026 06:55
@zmdyy0318 zmdyy0318 marked this pull request as draft March 27, 2026 06:55
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嘿,我已经审查了你的改动,一切看起来都很棒!


Sourcery 对开源项目是免费的——如果你喜欢我们的评审,请考虑帮忙分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈来改进后续评审。
Original comment in English

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 新增并重构 AutoSell(自动售卖) 的流水线资源,目标是用现有“自动囤货”替代原“自动倒货”中的购买逻辑,并在流程中引入 wait_freezes 与部分“万能跳转”节点以提升稳定性。

Changes:

  • 新增 AutoSell 主流程 pipeline(进入好友飞船 → 导航 → 进入物资调度 → 识别出售物资入口等)
  • 为 AutoSell 流程补充若干模板图片资源(物资调度按钮、票据 item 等)
  • 在关键步骤使用 pre_wait_freezes[JumpBack]SceneWaitLoadingExit 来处理加载/冻结等待

Reviewed changes

Copilot reviewed 1 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
assets/resource/pipeline/AutoSell/Main.json 新增自动售卖主流程节点编排(含进入好友、导航、进入物资调度与后续售卖相关节点骨架)
assets/resource/image/AutoSell/StockRedistributionButton.png 新增“物资调度”按钮模板图
assets/resource/image/AutoSell/SellTicketItemWuling.png 新增票据 item 模板图(武陵)
assets/resource/image/AutoSell/SellTicketItemValleyIV.png 新增票据 item 模板图(谷地IV)
assets/resource/image/AutoSell/SellTicketFriendWuling.png 新增好友票据模板图(武陵)
assets/resource/image/AutoSell/SellTicketFirendValleyIV.png 新增好友票据模板图(谷地IV,文件名疑似拼写问题)

@zmdyy0318 zmdyy0318 marked this pull request as ready for review April 5, 2026 07:33
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 4 个问题,并给出了一些整体性的反馈:

  • 全局切片 scanedItemNameList 在多个 action 中被修改,但没有任何同步机制,在并发运行时可能产生数据竞争;建议将这段状态按任务隔离,或者使用互斥锁进行保护。
  • autosell 逻辑中的多处代码依赖魔法常量和硬编码子串(例如默认的 targetPrice = 4600AutoSellStockRedistributionOpenItemTextAction 里的中文名称片段);建议把这些集中到可配置的数据结构(如表或配置文件)中,以便更容易扩展和维护行为。
  • 一些新的 autosell handler 假定入参和图像非空(例如 AutoSellStockRedistributionOpenItemTextRecognition.RunAutoSellItemRecordAction.Run),并复用了拷贝粘贴的日志信息(例如 "from AutoSellFriendsPriceRecognition");增加 nil 检查并使用更准确的日志信息,可以让失败更安全、调试更清晰。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The global `scanedItemNameList` slice is mutated from multiple actions without any synchronization, which could lead to data races in concurrent runs; consider encapsulating this state per-task or protecting it with a mutex.
- Several places in the autosell logic rely on magic constants and hard-coded substrings (e.g., default `targetPrice = 4600`, Chinese name fragments in `AutoSellStockRedistributionOpenItemTextAction`); centralizing these into configurable data (e.g., a table or config file) would make the behavior easier to extend and maintain.
- Some new autosell handlers assume non-nil args and images (e.g., `AutoSellStockRedistributionOpenItemTextRecognition.Run`, `AutoSellItemRecordAction.Run`) and reuse copy-pasted log messages (e.g., 'from AutoSellFriendsPriceRecognition'); adding nil checks and more precise log messages would make failures safer and debugging clearer.

## Individual Comments

### Comment 1
<location path="agent/go-service/autosell/autosell.go" line_range="111-113" />
<code_context>
+
+type AutoSellStockRedistributionOpenItemTextRecognition struct{}
+
+func (r *AutoSellStockRedistributionOpenItemTextRecognition) Run(ctx *maa.Context, arg *maa.CustomRecognitionArg) (*maa.CustomRecognitionResult, bool) {
+
+	detail, recoErr := ctx.RunRecognition("AutoSellStockRedistributionOpenItemText", arg.Img)
+	if recoErr != nil || detail == nil {
+		log.Error().Err(recoErr).Msg("Failed to run AutoSellStockRedistributionOpenItemText")
</code_context>
<issue_to_address>
**issue:** Missing argument nil checks in recognition handler can cause panics.

This method assumes `arg` and `arg.Img` are non-nil, unlike `AutoSellPriceCompareRecognition.Run`. If the framework passes a nil arg or image (e.g., after an upstream failure), `ctx.RunRecognition` will panic. Please add the same defensive nil checks here to match the other recognition handler.
</issue_to_address>

### Comment 2
<location path="agent/go-service/autosell/autosell.go" line_range="52" />
<code_context>
+		} `json:"filtered"`
+	}
+	// Results.Best是空,暂时只能这样获取
+	if detailJsonErr := json.Unmarshal([]byte(detail.CombinedResult[2].DetailJson), &detailJson); detailJsonErr != nil {
+		log.Error().Err(detailJsonErr).Msg("Failed to parse DetailJson from AutoSellFriendsPriceRecognition")
+		return nil, false
+	}
</code_context>
<issue_to_address>
**suggestion:** Log message references the wrong recognition name, which can hinder debugging.

This error is logged in `AutoSellStockRedistributionOpenItemTextRecognition`, but the message still mentions `AutoSellFriendsPriceRecognition`. Please update the log string to reference the correct recognition source for clearer debugging.

```suggestion
		log.Error().Err(detailJsonErr).Msg("Failed to parse DetailJson from AutoSellStockRedistributionOpenItemTextRecognition")
```
</issue_to_address>

### Comment 3
<location path="agent/go-service/autosell/autosell.go" line_range="222-223" />
<code_context>
+		maafocus.Print(ctx, i18n.T("autosell.check_item_price_unknown", resultItem.Text))
+	}
+
+	override := map[string]any{
+		"AutoSellStockRedistributionItemOpen": map[string]any{
+			"target": maa.Rect{
+				resultItem.Box[0],
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `resultItem.Box[0..3]` without validating length risks panics on malformed OCR results.

This assumes `resultItem.Box` has at least 4 elements, but OCR JSON may yield an empty or shorter slice. Please guard this with a length check (e.g., `if len(resultItem.Box) < 4 { /* log and return */ }`) to prevent index-out-of-range panics.
</issue_to_address>

### Comment 4
<location path="agent/go-service/autosell/autosell.go" line_range="168" />
<code_context>
+type AutoSellStockRedistributionOpenItemTextAction struct{}
+
+func (a *AutoSellStockRedistributionOpenItemTextAction) Run(ctx *maa.Context, arg *maa.CustomActionArg) bool {
+	customResult, ok := arg.RecognitionDetail.Results.Best.AsCustom()
+	if !ok {
+		log.Error().Msg("Failed to get custom recognition result")
</code_context>
<issue_to_address>
**issue (bug_risk):** Assuming nested fields on `arg.RecognitionDetail` exist may cause nil dereferences.

This dereferences `arg`, `arg.RecognitionDetail`, `arg.RecognitionDetail.Results`, and `Results.Best` without nil checks. If recognition fails or the result shape changes, this will panic before `AsCustom()` is reached. Consider adding nil guards for each step and logging + returning false when the expected structure is missing.
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的代码评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的代码评审。
Original comment in English

Hey - I've found 4 issues, and left some high level feedback:

  • The global scanedItemNameList slice is mutated from multiple actions without any synchronization, which could lead to data races in concurrent runs; consider encapsulating this state per-task or protecting it with a mutex.
  • Several places in the autosell logic rely on magic constants and hard-coded substrings (e.g., default targetPrice = 4600, Chinese name fragments in AutoSellStockRedistributionOpenItemTextAction); centralizing these into configurable data (e.g., a table or config file) would make the behavior easier to extend and maintain.
  • Some new autosell handlers assume non-nil args and images (e.g., AutoSellStockRedistributionOpenItemTextRecognition.Run, AutoSellItemRecordAction.Run) and reuse copy-pasted log messages (e.g., 'from AutoSellFriendsPriceRecognition'); adding nil checks and more precise log messages would make failures safer and debugging clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The global `scanedItemNameList` slice is mutated from multiple actions without any synchronization, which could lead to data races in concurrent runs; consider encapsulating this state per-task or protecting it with a mutex.
- Several places in the autosell logic rely on magic constants and hard-coded substrings (e.g., default `targetPrice = 4600`, Chinese name fragments in `AutoSellStockRedistributionOpenItemTextAction`); centralizing these into configurable data (e.g., a table or config file) would make the behavior easier to extend and maintain.
- Some new autosell handlers assume non-nil args and images (e.g., `AutoSellStockRedistributionOpenItemTextRecognition.Run`, `AutoSellItemRecordAction.Run`) and reuse copy-pasted log messages (e.g., 'from AutoSellFriendsPriceRecognition'); adding nil checks and more precise log messages would make failures safer and debugging clearer.

## Individual Comments

### Comment 1
<location path="agent/go-service/autosell/autosell.go" line_range="111-113" />
<code_context>
+
+type AutoSellStockRedistributionOpenItemTextRecognition struct{}
+
+func (r *AutoSellStockRedistributionOpenItemTextRecognition) Run(ctx *maa.Context, arg *maa.CustomRecognitionArg) (*maa.CustomRecognitionResult, bool) {
+
+	detail, recoErr := ctx.RunRecognition("AutoSellStockRedistributionOpenItemText", arg.Img)
+	if recoErr != nil || detail == nil {
+		log.Error().Err(recoErr).Msg("Failed to run AutoSellStockRedistributionOpenItemText")
</code_context>
<issue_to_address>
**issue:** Missing argument nil checks in recognition handler can cause panics.

This method assumes `arg` and `arg.Img` are non-nil, unlike `AutoSellPriceCompareRecognition.Run`. If the framework passes a nil arg or image (e.g., after an upstream failure), `ctx.RunRecognition` will panic. Please add the same defensive nil checks here to match the other recognition handler.
</issue_to_address>

### Comment 2
<location path="agent/go-service/autosell/autosell.go" line_range="52" />
<code_context>
+		} `json:"filtered"`
+	}
+	// Results.Best是空,暂时只能这样获取
+	if detailJsonErr := json.Unmarshal([]byte(detail.CombinedResult[2].DetailJson), &detailJson); detailJsonErr != nil {
+		log.Error().Err(detailJsonErr).Msg("Failed to parse DetailJson from AutoSellFriendsPriceRecognition")
+		return nil, false
+	}
</code_context>
<issue_to_address>
**suggestion:** Log message references the wrong recognition name, which can hinder debugging.

This error is logged in `AutoSellStockRedistributionOpenItemTextRecognition`, but the message still mentions `AutoSellFriendsPriceRecognition`. Please update the log string to reference the correct recognition source for clearer debugging.

```suggestion
		log.Error().Err(detailJsonErr).Msg("Failed to parse DetailJson from AutoSellStockRedistributionOpenItemTextRecognition")
```
</issue_to_address>

### Comment 3
<location path="agent/go-service/autosell/autosell.go" line_range="222-223" />
<code_context>
+		maafocus.Print(ctx, i18n.T("autosell.check_item_price_unknown", resultItem.Text))
+	}
+
+	override := map[string]any{
+		"AutoSellStockRedistributionItemOpen": map[string]any{
+			"target": maa.Rect{
+				resultItem.Box[0],
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `resultItem.Box[0..3]` without validating length risks panics on malformed OCR results.

This assumes `resultItem.Box` has at least 4 elements, but OCR JSON may yield an empty or shorter slice. Please guard this with a length check (e.g., `if len(resultItem.Box) < 4 { /* log and return */ }`) to prevent index-out-of-range panics.
</issue_to_address>

### Comment 4
<location path="agent/go-service/autosell/autosell.go" line_range="168" />
<code_context>
+type AutoSellStockRedistributionOpenItemTextAction struct{}
+
+func (a *AutoSellStockRedistributionOpenItemTextAction) Run(ctx *maa.Context, arg *maa.CustomActionArg) bool {
+	customResult, ok := arg.RecognitionDetail.Results.Best.AsCustom()
+	if !ok {
+		log.Error().Msg("Failed to get custom recognition result")
</code_context>
<issue_to_address>
**issue (bug_risk):** Assuming nested fields on `arg.RecognitionDetail` exist may cause nil dereferences.

This dereferences `arg`, `arg.RecognitionDetail`, `arg.RecognitionDetail.Results`, and `Results.Best` without nil checks. If recognition fails or the result shape changes, this will panic before `AsCustom()` is reached. Consider adding nil guards for each step and logging + returning false when the expected structure is missing.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 68 changed files in this pull request and generated 7 comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants