|
81 | 81 | // React to agent.id changes to reload agent-specific trigger options |
82 | 82 | $effect(() => { |
83 | 83 | if (agent?.id) { |
| 84 | + // Capture current agent.id to prevent race conditions |
| 85 | + const requestedAgentId = agent.id; |
| 86 | +
|
84 | 87 | // Reset state when agent changes |
85 | 88 | ruleOptions = []; |
86 | 89 | innerRules = []; |
87 | 90 |
|
88 | | - // Load agent-specific data |
89 | | - Promise.all([ |
90 | | - loadAgentRuleOptions(), |
91 | | - loadAgentRuleConfigOptions() |
92 | | - ]); |
| 91 | + // Load agent-specific data with error handling |
| 92 | + void (async () => { |
| 93 | + try { |
| 94 | + await Promise.all([ |
| 95 | + loadAgentRuleOptions(requestedAgentId), |
| 96 | + loadAgentRuleConfigOptions(requestedAgentId) |
| 97 | + ]); |
| 98 | + } catch (error) { |
| 99 | + // Error already logged in individual loaders |
| 100 | + // Ensure init() is called even if options fail to load |
| 101 | + // so existing agent rules still render |
| 102 | + if (agent.id === requestedAgentId && innerRules.length === 0) { |
| 103 | + init(); |
| 104 | + } |
| 105 | + } |
| 106 | + })(); |
93 | 107 | } |
94 | 108 | }); |
95 | 109 |
|
|
98 | 112 | resizeWindow(); |
99 | 113 | }); |
100 | 114 |
|
101 | | - function loadAgentRuleOptions() { |
| 115 | + /** |
| 116 | + * @param {string} requestedAgentId - The agent ID for which we're loading options |
| 117 | + */ |
| 118 | + function loadAgentRuleOptions(requestedAgentId) { |
102 | 119 | return new Promise((resolve, reject) => { |
103 | | - getAgentRuleOptionsById(agent.id).then(data => { |
| 120 | + getAgentRuleOptionsById(requestedAgentId).then(data => { |
| 121 | + // Guard: only apply results if agent hasn't changed |
| 122 | + if (agent.id !== requestedAgentId) { |
| 123 | + resolve('stale'); |
| 124 | + return; |
| 125 | + } |
| 126 | +
|
104 | 127 | const list = data?.map(x => { |
105 | 128 | return { |
106 | 129 | name: x.trigger_name, |
|
118 | 141 | resolve('done'); |
119 | 142 | }).catch(error => { |
120 | 143 | console.error('Failed to load agent rule options:', error); |
121 | | - ruleOptions = [{ name: "", displayName: "" }]; |
| 144 | + // Guard: only apply error state if agent hasn't changed |
| 145 | + if (agent.id === requestedAgentId) { |
| 146 | + ruleOptions = [{ name: "", displayName: "" }]; |
| 147 | + } |
122 | 148 | reject(error); |
123 | 149 | }); |
124 | 150 | }); |
|
134 | 160 | innerRefresh(list); |
135 | 161 | } |
136 | 162 |
|
137 | | - function loadAgentRuleConfigOptions() { |
| 163 | + /** |
| 164 | + * @param {string} requestedAgentId - The agent ID for which we're loading config options |
| 165 | + */ |
| 166 | + function loadAgentRuleConfigOptions(requestedAgentId) { |
138 | 167 | return new Promise((resolve, reject) => { |
139 | 168 | getAgentRuleConfigOptions().then(data => { |
| 169 | + // Guard: only apply results if agent hasn't changed |
| 170 | + if (agent.id !== requestedAgentId) { |
| 171 | + resolve('stale'); |
| 172 | + return; |
| 173 | + } |
| 174 | +
|
140 | 175 | ruleConfigs = data || {}; |
141 | 176 | const keys = Object.keys(data || {}); |
142 | 177 | const list = keys?.map(x => ({ name: x })) || []; |
|
147 | 182 | resolve('done'); |
148 | 183 | }).catch(error => { |
149 | 184 | console.error('Failed to load agent rule config options:', error); |
150 | | - ruleConfigs = {}; |
151 | | - configOptions = [{ name: '' }]; |
| 185 | + // Guard: only apply error state if agent hasn't changed |
| 186 | + if (agent.id === requestedAgentId) { |
| 187 | + ruleConfigs = {}; |
| 188 | + configOptions = [{ name: '' }]; |
| 189 | + } |
152 | 190 | reject(error); |
153 | 191 | }); |
154 | 192 | }); |
|
0 commit comments