Repository navigation
fix: [AI-Generated Earnings] The AI-generated earnings feature modifies earnings directly, without first presenting the proposed adjustments to the user for their review and confirmation. #7743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| <script setup lang="ts"> | ||
| import { computed, inject, nextTick, onBeforeUnmount, ref, useTemplateRef } from 'vue' | ||
| import { computed, inject, nextTick, onBeforeUnmount, ref, useTemplateRef ,provide} from 'vue' | ||
| import { useRoute } from 'vue-router' | ||
| import { cloneDeep } from 'lodash' | ||
| import type LogicFlow from '@logicflow/core' | ||
|
|
@@ -18,7 +18,8 @@ import { clearDebugLog } from '../common' | |
| import { createAgent } from '../create-agent' | ||
| import type { AgentEvent, AgentHandle } from '../type' | ||
| import { createActivity } from './activity' | ||
|
|
||
| import { VIEW_KEY,VIEW_TYPE } from '@/conversation-panel/view' | ||
| provide(VIEW_KEY,VIEW_TYPE.DEBUG) | ||
| defineOptions({ name: 'WorkflowAiGeneratePanel' }) | ||
| const props = withDefaults( | ||
| defineProps<{ | ||
|
|
@@ -90,8 +91,13 @@ function scrollToBottom() { | |
| nextTick(() => scrollbarRef.value?.setScrollTop(Number.MAX_SAFE_INTEGER)) | ||
| } | ||
|
|
||
| /** 会改动画布的顶层工具;本轮未调用时视为仅规划 / 答复(如等待用户确认方案),不提示生成完成 */ | ||
| const CANVAS_MUTATING_TOOLS = new Set(['add_node', 'add_edge', 'delete_node', 'delete_edge', 'configure_node', 'layout']) | ||
| let canvasChanged = false | ||
|
|
||
| /** 顶层 agent 的总结已作为正文流入活动,失败作为 FAILURE 项展示 */ | ||
| function onEvent(event: AgentEvent) { | ||
| if (event.type === 'tool_start' && !event.position.length && CANVAS_MUTATING_TOOLS.has(event.name)) canvasChanged = true | ||
| activity.pushEvent(event) | ||
| scrollToBottom() | ||
| } | ||
|
|
@@ -117,9 +123,11 @@ async function run(text: string) { | |
| ) | ||
| } | ||
| status.value = 'running' | ||
| canvasChanged = false | ||
| const result = await agent.run(text) | ||
| if (result.status === 'done') { | ||
| status.value = 'done' | ||
| if (!canvasChanged) return | ||
| await layoutCanvas(lf) | ||
| lf.fitView() | ||
| MsgSuccess('工作流已生成,请检查后保存') | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Summary of Issues and Suggestions:
✅ Recommended Fixed Code Snippet (Diff Style) @@ -1,5 +1,5 @@
<script setup lang="ts">
-import { computed, inject, nextTick, onBeforeUnmount, ref, useTemplateRef } from 'vue'
+import { computed, inject, provide, nextTick, onBeforeUnmount, ref, useTemplateRef } from 'vue' // Alphabetical order
import { useRoute } from 'vue-router'
import { cloneDeep } from 'lodash'
import type LogicFlow from '@logicflow/core'
@@ -18,8 +18,9 @@ import { clearDebugLog } from '../common'
import { createAgent } from '../create-agent'
import type { AgentEvent, AgentHandle } from '../type'
import { createActivity } from './activity'
-
+// Add blank line if required by linter, fix spacing
+import { VIEW_KEY, VIEW_TYPE } from '@/conversation-panel/view'
// Provide view key for debugging context (ensure parent-child relationship exists)
provide(VIEW_KEY, VIEW_TYPE.DEBUG)
defineOptions({ name: 'WorkflowAiGeneratePanel' })
const props = withDefaults(
defineProps<{
@@ -90,9 +91,9 @@ function scrollToBottom() {
nextTick(() => scrollbarRef.value?.setScrollTop(Number.MAX_SAFE_INTEGER))
}
-/** 会改动画布的顶层工具;本轮未调用时视为仅规划 / 答复(如等待用户确认方案),不提示生成完成 */
+/** Tools that mutate canvas. If none are called, skip layout/fitView (e.g., planning-only mode) */
const CANVAS_MUTATING_TOOLS = new Set(['add_node', 'add_edge', 'delete_node', 'delete_edge', 'configure_node', 'layout'])
let canvasChanged = false
/** Top-level agent summary flows into activity as text; failures shown as FAILURE items */
function onEvent(event: AgentEvent) {
- if (event.type === 'tool_start' && !event.position.length && CANVAS_MUTATING_TOOLS.has(event.name)) canvasChanged = true
+ // Safe check: handle if position is undefined/null
+ const isTopLevel = !event.position || event.position.length === 0
+ if (event.type === 'tool_start' && isTopLevel && CANVAS_MUTATING_TOOLS.has(event.name)) {
+ canvasChanged = true
+ }
activity.pushEvent(event)
scrollToBottom()
}
@@ -117,12 +123,14 @@ async function run(text: string) {
)
}
status.value = 'running'
canvasChanged = false
const result = await agent.run(text)
if (result.status === 'done') {
status.value = 'done'
// Only fit view and show success if canvas actually changed
- if (!canvasChanged) return
+ if (!canvasChanged) {
+ // Optional: Show a different message or do nothing silently if only planning occurred
+ return
+ }
await layoutCanvas(lf)
lf.fitView()
MsgSuccess('工作流已生成,请检查后保存') |
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review of the diff
1. Potential
None/ empty-string issueschat_record.question.get("content")— ifquestionisNone, or the dict has no"content"key, this raisesAttributeError/KeyError. Use defensive access:"".join([r.get("content") for r in chat_record.messages if r.get("type") == "TEXT"])—r.get("content")can returnNone, which will raiseTypeError: sequence item N: expected str instance, NoneType found. Filter or coerce:2. Behavior change worth confirming
chat_record.answer_text/chat_record.problem_text(presumably denormalized fields or properties on the model). The new code recomputes them frommessages/question. Make sure:chat_record.messagesis always populated and ordered correctly.TEXTmessages without a separator ("") is intentional — otherwise use"\n".3. Performance
messagestwice per chat record. Minor, but could be collapsed if both fields are needed. Not critical here.Problem.objects.get_or_create(content=problem_text, ...)will now run with potentially differentproblem_textthan before. Ifproblem_textcomputation differs from what's stored inchat_record.problem_text, deduplication behavior changes. Ensure DB uniqueness constraints includeknowledge_id.get_or_createandParagraphconstruction mean N+1 writes; considerbulk_createforParagraph/ProblemParagraphMappingbatches and pre-fetching existingProblemrows withcontent__in=[...]to avoid repeated queries.4. Empty data handling
answer_textorproblem_textends up as"", you'll create emptyParagraph/Problemrows. Consider skipping records whereanswer_text.strip() == ""(or raising) to avoid polluting DB.5. Style / type safety
chat_record.messagesasList[Dict[str, str]]and letting mypy flagOptional[str]joins.uuid.uuid7()— confirm your Python/dependency version actually providesuuid7(not in stdlib until recently); otherwise this is a latent runtime error unrelated to this diff.6. Recommend refactor
Summary: Main risks are
Nonepropagation into"".join, possible unintended semantics change (concatenation without separator), and DB-level empty rows / dedup regressions from recomputedproblem_text. The core logic is sound; harden input handling and verify uniqueness assumptions.