feat(fusion_helpdesk_central): findings-first wizard, explicit Generate button

The old flow fired OpenAI on wizard open with just ticket + chatter,
so the AI summary was just a paraphrase of what the user originally
reported — your engineering analysis (scope, limitations, recommended
approach) never made it to the owner. Restructure to a two-step flow:

  1. Open wizard → empty findings + empty summary, NO OpenAI call
  2. You write findings: scope / effort / approach / risk
  3. Click 'Generate Summary from Findings' → OpenAI runs with
     ticket + chatter + findings, where the prompt explicitly tells
     the model to weight findings MORE THAN the original report
  4. Review/edit, then Send

Bulk wizard mirrors the flow per line: each row gets its own
findings + summary, one 'Generate All Summaries' button fans out
parallel OpenAI calls using each line's own findings.

Updated SUMMARY_PROMPT to:
- Tell the model the support engineer's findings are authoritative
- Emit a bullet structure that leads with the recommendation, not
  the user's restated ask
- Side with findings over the original report when they conflict

New tests cover:
- default_get does NOT fire OpenAI (regression guard for auto-AI)
- Findings text actually reaches the OpenAI prompt
- Send works with a manually-typed summary (no AI in the loop)
- Existing bulk + validation paths still pass with the new shape

Also folds in the deferred code-review #7: ThreadPoolExecutor now
explicitly cancels pending futures on timeout via
shutdown(wait=False, cancel_futures=True) so a slow OpenAI day can't
hold the wizard open for ceil(N/workers)*15s.

Bumps fusion_helpdesk_central to 19.0.2.3.0.

Smoke-tested live on nexa: opening the wizard makes zero OpenAI calls;
clicking Generate with findings='My findings: scope is XL, ~8h' makes
exactly one call and the findings text is verifiably in the prompt
body received by call_openai_chat.
This commit is contained in:
gsinghpal
2026-05-27 13:49:02 -04:00
parent 7349f3180d
commit c520803c84
6 changed files with 303 additions and 85 deletions

View File

@@ -29,28 +29,65 @@
invisible="not ai_unavailable">
<strong>AI summary unavailable.</strong>
OpenAI didn't return a summary (no API key set, rate limit,
or network error). Write a quick brief below before sending —
everything else still works.
or network error). Write a quick brief in the Summary
field below before sending — everything else still works.
</div>
<!-- Single mode: one summary field for the one ticket. -->
<!--
Single mode. The user fills findings first, clicks
Generate Summary, reviews the AI output, edits if needed,
then Sends. We deliberately don't auto-fire OpenAI on
open — the AI needs the engineer's analysis to be useful.
-->
<group invisible="mode != 'single'">
<field name="personal_note"
placeholder="One-line note that appears above the summary in the email…"/>
<field name="ai_summary" string="Summary to send"
placeholder="Bullet-point summary that the owner will read first." />
</group>
<group invisible="mode != 'single'" string="1. Your Findings">
<field name="findings" nolabel="1"
placeholder="What did your investigation surface? Scope, limitations, recommended approach, effort, risks — anything the owner needs to know that the original reporter wouldn't have."/>
</group>
<group invisible="mode != 'single'" string="2. Summary to Send">
<div class="o_row" colspan="2">
<button name="action_generate_summary" type="object"
string="Generate Summary from Findings"
icon="fa-magic"
class="btn-secondary"/>
<span class="o_form_label text-muted ms-2">
← click after writing your findings, then review &amp; edit below
</span>
</div>
<field name="ai_summary" nolabel="1"
placeholder="Click Generate Summary above, or write the brief yourself. The owner reads this first."/>
</group>
<!-- Bulk mode: per-ticket lines, each with its own summary. -->
<!--
Bulk mode: same two-step flow per ticket. Findings +
Summary editable inline; a single Generate All button
fans out OpenAI in parallel using each line's findings.
-->
<group invisible="mode != 'bulk'">
<field name="personal_note"
placeholder="One-line note that appears once at the top of the combined email…"/>
</group>
<div class="o_row" colspan="2"
invisible="mode != 'bulk'">
<button name="action_generate_all_summaries" type="object"
string="Generate All Summaries"
icon="fa-magic"
class="btn-secondary"/>
<span class="o_form_label text-muted ms-2">
← fill in findings per row first, then click to regenerate all summaries in parallel
</span>
</div>
<field name="line_ids" invisible="mode != 'bulk'" nolabel="1">
<list editable="bottom" create="0" delete="0">
<field name="ticket_id" readonly="1"/>
<field name="ticket_name" readonly="1"/>
<field name="ai_summary"/>
<field name="findings"
placeholder="Your engineering findings for this ticket…"/>
<field name="ai_summary"
placeholder="(empty — click Generate All above, or write by hand)"/>
</list>
</field>