-
Notifications
You must be signed in to change notification settings - Fork 4
Fix resume contact inference and LinkedIn field handling #129
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1345,6 +1345,10 @@ async def confirm_create( | |||||||||||||||
| create_payload = self.crm_cog._build_resume_create_contact_payload( | ||||||||||||||||
| file_content=self.file_content | ||||||||||||||||
| ) | ||||||||||||||||
| self.crm_cog._populate_name_fields( | ||||||||||||||||
| create_payload, | ||||||||||||||||
| source_name=str(create_payload.get("name", "")).strip(), | ||||||||||||||||
| ) | ||||||||||||||||
| target_contact = self.crm_cog.espo_api.request( | ||||||||||||||||
| "POST", "Contact", create_payload | ||||||||||||||||
| ) | ||||||||||||||||
|
|
@@ -1375,6 +1379,8 @@ async def confirm_create( | |||||||||||||||
| ) | ||||||||||||||||
| except Exception as exc: | ||||||||||||||||
| status_code = getattr(self.crm_cog.espo_api, "status_code", None) | ||||||||||||||||
| error_detail = str(exc).strip() or "Unknown error" | ||||||||||||||||
| status_note = f" (status {status_code})" if status_code else "" | ||||||||||||||||
| logger.exception( | ||||||||||||||||
| "Failed to create contact from resume filename=%s target_scope=%s inferred_meta=%s status_code=%s payload=%s", | ||||||||||||||||
| self.filename, | ||||||||||||||||
|
|
@@ -1399,7 +1405,7 @@ async def confirm_create( | |||||||||||||||
| metadata=audit_metadata, | ||||||||||||||||
| ) | ||||||||||||||||
| await interaction.followup.send( | ||||||||||||||||
| "⚠️ Could not create a contact from this resume. " | ||||||||||||||||
| f"⚠️ Could not create a contact from this resume: `{error_detail}`{status_note}. " | ||||||||||||||||
| "Please provide `search_term` or `link_user`.", | ||||||||||||||||
| ephemeral=True, | ||||||||||||||||
| ) | ||||||||||||||||
|
|
@@ -1532,6 +1538,11 @@ def __init__(self, bot: commands.Bot) -> None: | |||||||||||||||
| discord_logs_webhook_wait=settings.discord_logs_webhook_wait, | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| @staticmethod | ||||||||||||||||
| def _configured_linkedin_field() -> str: | ||||||||||||||||
| """Return the configured field for LinkedIn profile values.""" | ||||||||||||||||
| return str(getattr(settings, "crm_linkedin_field", "cLinkedInUrl")) | ||||||||||||||||
|
||||||||||||||||
| return str(getattr(settings, "crm_linkedin_field", "cLinkedInUrl")) | |
| default_field = "cLinkedInUrl" | |
| raw_value = getattr(settings, "crm_linkedin_field", None) | |
| if not isinstance(raw_value, str): | |
| return default_field | |
| value = raw_value.strip() | |
| return value or default_field |
Copilot
AI
Mar 3, 2026
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.
The parsed name/email are interpolated directly into inline-code backticks. If the extracted name/email contains a backtick, it can break formatting and potentially hide/alter surrounding text. Consider sanitizing (e.g., replace/backslash-escape backticks and truncate to a safe length) before embedding user/LLM-derived values into Discord messages.
Copilot
AI
Mar 3, 2026
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.
_populate_name_fields() calls resume_extractor.split_name(), which will invoke an additional LLM call whenever the OpenAI client is configured. In the resume-upload path you already may have done an LLM extraction, so this can introduce an extra API request (latency/cost/failure surface) just to split the name. Consider using heuristic-only splitting here, or plumbing through extracted first_name/last_name hints from the resume profile to avoid triggering another model call.
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.
The user-facing failure message embeds
error_detail = str(exc)verbatim. ForEspoAPIErrorraised by the shared client, this may include boilerplate (e.g., "Wrong request, status code is …") and can duplicate the separately-appended status note, making the message noisy. Consider special-casingEspoAPIErrorto extract/display just the server reason (and escape/truncate any backticks/newlines) while keeping the full exception details only in logs/audit metadata.