Repository navigation
Conversation
- Added a new tool, open_prefilled_doc, to propose opening an unsaved document with pre-filled data. Updated relevant components to support this functionality, including validation and integration into the document planner. Enhanced frontend logic to handle document filling and ensure proper payload structure. Updated translations for the new feature. - **Important**: `_normalize_any_llm_model_id` can go from `_get_document_extraction_model_config` because the provider is already passed separately and the stored value is a bare model id, so stripping a `provider:model` prefix is a no-op for real settings and would corrupt ids that legitimately contain `:` or `/`.
|
- Updated the `frontend_action_result` function to append a message listing omitted fields when the action is successful. - Added a test case to verify the correct handling of omitted fields in the conversation context.
|
Here is a summary of the
Similar Change-Size Groups
|
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | يجب أن يتطابق نوع DOCTYPE للمستند في إجراء الواجهة الأمامية 'open_prefilled_doc'. |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | يجب أن يكون حقل 'doc' في إجراء الواجهة الأمامية 'open_prefilled_doc' كائناً. |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | يتطلب إجراء الواجهة الأمامية 'open_prefilled_doc' نوع DOCTYPE. |
| added | Left blank: {0} | empty | تُرك فارغاً: {0} |
| added | Open document action needs correction. | empty | يحتاج إجراء فتح المستند إلى تصحيح. |
| added | Open unsaved {0} | empty | فتح {0} غير محفوظ |
| added | Opening an unsaved {0} | empty | فتح {0} غير محفوظ |
| added | Prepared unsaved document. | empty | تم تحضير مستند غير محفوظ. |
bn (ask_alyf/locale/bn.po) — 8 entries
bn (ask_alyf/locale/bn.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | ফ্রন্টএন্ড অ্যাকশন 'open_prefilled_doc'-এর ডকুমেন্ট DocType মিলতে হবে। |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | ফ্রন্টএন্ড অ্যাকশন 'open_prefilled_doc'-এর ফিল্ড 'doc' একটি অবজেক্ট হতে হবে। |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | ফ্রন্টএন্ড অ্যাকশন 'open_prefilled_doc'-এর জন্য একটি DocType প্রয়োজন। |
| added | Left blank: {0} | empty | ফাঁকা রাখা হয়েছে: {0} |
| added | Open document action needs correction. | empty | ডকুমেন্ট খোলার অ্যাকশনের সংশোধন প্রয়োজন। |
| added | Open unsaved {0} | empty | অসংরক্ষিত {0} খুলুন |
| added | Opening an unsaved {0} | empty | একটি অসংরক্ষিত {0} খোলা হচ্ছে |
| added | Prepared unsaved document. | empty | অসংরক্ষিত ডকুমেন্ট প্রস্তুত করা হয়েছে। |
de (ask_alyf/locale/de.po) — 8 entries
de (ask_alyf/locale/de.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | Frontend-Aktion 'open_prefilled_doc': DocType des Dokuments muss übereinstimmen. |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | Frontend-Aktion 'open_prefilled_doc' Feld 'doc' muss ein Objekt sein. |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | Frontend-Aktion 'open_prefilled_doc' erfordert einen DocType. |
| added | Left blank: {0} | empty | Leer gelassen: {0} |
| added | Open document action needs correction. | empty | Aktion zum Öffnen eines Dokuments benötigt Korrektur. |
| added | Open unsaved {0} | empty | Nicht gespeichertes {0} öffnen |
| added | Opening an unsaved {0} | empty | Nicht gespeichertes {0} wird geöffnet |
| added | Prepared unsaved document. | empty | Nicht gespeichertes Dokument vorbereitet. |
es (ask_alyf/locale/es.po) — 8 entries
es (ask_alyf/locale/es.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | El DocType del documento de la acción de frontend 'open_prefilled_doc' debe coincidir. |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | El campo 'doc' de la acción de frontend 'open_prefilled_doc' debe ser un objeto. |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | La acción de frontend 'open_prefilled_doc' requiere un DocType. |
| added | Left blank: {0} | empty | Dejado en blanco: {0} |
| added | Open document action needs correction. | empty | La acción de abrir documento necesita corrección. |
| added | Open unsaved {0} | empty | Abrir {0} sin guardar |
| added | Opening an unsaved {0} | empty | Abriendo un {0} sin guardar |
| added | Prepared unsaved document. | empty | Documento sin guardar preparado. |
hi (ask_alyf/locale/hi.po) — 8 entries
hi (ask_alyf/locale/hi.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | फ्रंटएंड क्रिया 'open_prefilled_doc' का दस्तावेज़ DocType मेल खाना चाहिए। |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | फ्रंटएंड क्रिया 'open_prefilled_doc' का फ़ील्ड 'doc' एक ऑब्जेक्ट होना चाहिए। |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | फ्रंटएंड क्रिया 'open_prefilled_doc' के लिए एक DocType आवश्यक है। |
| added | Left blank: {0} | empty | खाली छोड़ दिया गया: {0} |
| added | Open document action needs correction. | empty | दस्तावेज़ खोलने की क्रिया में सुधार की आवश्यकता है। |
| added | Open unsaved {0} | empty | बिना सहेजा गया {0} खोलें |
| added | Opening an unsaved {0} | empty | एक बिना सहेजा गया {0} खोला जा रहा है |
| added | Prepared unsaved document. | empty | बिना सहेजा गया दस्तावेज़ तैयार किया गया। |
ja (ask_alyf/locale/ja.po) — 8 entries
ja (ask_alyf/locale/ja.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | フロントエンドアクション 'open_prefilled_doc' のドキュメントの DocType は一致する必要があります。 |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | フロントエンドアクション 'open_prefilled_doc' のフィールド 'doc' はオブジェクトである必要があります。 |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | フロントエンドアクション 'open_prefilled_doc' には DocType が必要です。 |
| added | Left blank: {0} | empty | 空のまま: {0} |
| added | Open document action needs correction. | empty | ドキュメントを開くアクションを修正する必要があります。 |
| added | Open unsaved {0} | empty | 未保存の{0}を開く |
| added | Opening an unsaved {0} | empty | 未保存の {0} を開いています |
| added | Prepared unsaved document. | empty | 未保存のドキュメントを準備しました。 |
pt (ask_alyf/locale/pt.po) — 8 entries
pt (ask_alyf/locale/pt.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | O DocType do documento na ação de frontend 'open_prefilled_doc' tem de corresponder. |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | O campo 'doc' da ação de frontend 'open_prefilled_doc' deve ser um objeto. |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | A ação de frontend 'open_prefilled_doc' requer um DocType. |
| added | Left blank: {0} | empty | Deixado em branco: {0} |
| added | Open document action needs correction. | empty | A ação de abrir documento precisa de correção. |
| added | Open unsaved {0} | empty | Abrir {0} não guardado |
| added | Opening an unsaved {0} | empty | A abrir um {0} não guardado |
| added | Prepared unsaved document. | empty | Documento não guardado preparado. |
ru (ask_alyf/locale/ru.po) — 8 entries
ru (ask_alyf/locale/ru.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | Тип документа во фронтенд-действии 'open_prefilled_doc' должен совпадать. |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | Поле 'doc' фронтенд-действия 'open_prefilled_doc' должно быть объектом. |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | Фронтенд-действию 'open_prefilled_doc' требуется Тип документа. |
| added | Left blank: {0} | empty | Оставлено пустым: {0} |
| added | Open document action needs correction. | empty | Действие открытия документа требует исправления. |
| added | Open unsaved {0} | empty | Открыть несохранённый {0} |
| added | Opening an unsaved {0} | empty | Открытие несохранённого {0} |
| added | Prepared unsaved document. | empty | Несохранённый документ подготовлен. |
zh_Hans_CN (ask_alyf/locale/zh_CN.po) — 8 entries
zh_Hans_CN (ask_alyf/locale/zh_CN.po)
| Status | Msgid | Previous | Current |
|---|---|---|---|
| added | Frontend action 'open_prefilled_doc' doc DocType must match. | empty | 前端操作 'open_prefilled_doc' 的单据类型必须一致。 |
| added | Frontend action 'open_prefilled_doc' field 'doc' must be an object. | empty | 前端操作 'open_prefilled_doc' 的字段 'doc' 必须是一个对象。 |
| added | Frontend action 'open_prefilled_doc' requires a DocType. | empty | 前端操作 'open_prefilled_doc' 需要一个单据类型。 |
| added | Left blank: {0} | empty | 留空:{0} |
| added | Open document action needs correction. | empty | 打开文档操作需要更正。 |
| added | Open unsaved {0} | empty | 打开未保存的 {0} |
| added | Opening an unsaved {0} | empty | 正在打开未保存的 {0} |
| added | Prepared unsaved document. | empty | 已准备未保存的文档。 |
|
| Status | Previous | Current |
|---|---|---|
| added | empty | Frontend action 'open_prefilled_doc' doc DocType must match. |
| added | empty | Frontend action 'open_prefilled_doc' field 'doc' must be an object. |
| added | empty | Frontend action 'open_prefilled_doc' requires a DocType. |
| added | empty | Left blank: {0} |
| added | empty | Open document action needs correction. |
| added | empty | Open unsaved {0} |
| added | empty | Opening an unsaved {0} |
| added | empty | Prepared unsaved document. |
| api_key=api_key, | ||
| api_base=api_base, | ||
| model_id=_normalize_any_llm_model_id(model_setting), | ||
| model_id=model_setting, |
There was a problem hiding this comment.
This reverts the model ID normalization that was added on develop in #172. It is not related to open_prefilled_doc, and it leaves _normalize_any_llm_model_id defined but unused. Please move this to a separate PR (and delete the function there), or drop it from this one.
| self.toolset.read_skill, | ||
| self.toolset.set_route, | ||
| self.toolset.new_doc, | ||
| self.toolset.open_prefilled_doc, |
There was a problem hiding this comment.
This registers open_prefilled_doc in all modes, and it runs without confirmation (AUTO_FRONTEND_ACTION_TOOLS). But the prompt says "In Ask mode, recommend switching to Agent mode for this flow", and the follow-up tools frm_set_value / frm_add_child exist only in Agent mode. Either register it only in Agent mode, or remove that sentence from the prompt.
| const value = source?.[df.fieldname]; | ||
| if (!hasValue(value)) continue; | ||
| values.set(df.fieldname, value); | ||
| await setField(target, df.fieldname, value, `${pathPrefix}${df.fieldname}`); |
There was a problem hiding this comment.
An invalid Link value is not detected here. For a parent Link field, Frappe's validate_link_and_fetch clears the fetched fields when the link does not exist, but it does not clear the link itself, and it does not fail the request. So a guessed customer or item stays on the form, is not in omitted_fields, and the user sees the error only on save. Maybe check the validate_link_and_fetch response, or validate the links on the server before the action is proposed.
| } | ||
| }; | ||
|
|
||
| const writeBackPayload = (target) => { |
There was a problem hiding this comment.
target[key] = value does not run any triggers. If an async trigger (for example get_item_details) changed rate after it was filled, this restores rate, but amount and the totals are not recalculated until the user edits something. Whether that happens depends on timing (waitForRequests waits at most 5 rounds).
| }; | ||
|
|
||
| let fieldInProgress = null; | ||
| const originalMsgprint = frappe.msgprint; |
There was a problem hiding this comment.
This replaces three Frappe globals (frappe.msgprint, frappe.request.call, frappe.throw) while the form is filled, and uses a shared fieldInProgress flag. Any unrelated request that fails during the fill marks the current field as failed. It is hard to reason about and to maintain. Can this be simpler? If not, please add a short comment for why each patch is necessary.
| for (const row of rows) { | ||
| rowNumber += 1; | ||
| if (!row || typeof row !== "object" || Array.isArray(row)) continue; | ||
| const child = frappe.model.add_child(target, childDoctype, fieldname); |
There was a problem hiding this comment.
The PR description says Link fields still run fetch_from. That is true only for parent fields. Child rows go through grid.set_value, which does not validate links or run the generic fetch_from. ERPNext's own scripts (for example the item_code trigger) still run, so the Sales Invoice example works. But other child DocTypes do not get their fetched values.
| return _("Frontend action 'new_doc' field 'route_options' must be an object.") | ||
| return None | ||
|
|
||
| if tool == "open_prefilled_doc": |
There was a problem hiding this comment.
Please add a unit test for this branch: missing DocType, doc not an object, a different doc.doctype, and a child table given as a string.
| return _("Frontend action 'open_prefilled_doc' field 'doc' must be an object.") | ||
| if doc.get("doctype") not in (None, doctype): | ||
| return _("Frontend action 'open_prefilled_doc' doc DocType must match.") | ||
| return validate_table_field_shapes(doctype, doc) |
There was a problem hiding this comment.
Minor: validate_table_field_shapes checks only Table fields, but the JS also handles Table MultiSelect (frappe.model.table_fields).
open_prefilled_docopens an unsaved form with the given field values, including child tables. The flow is: the agent reads an attached PDF or image withextract_document_data, the document planner checks the DocType withget_metaand returns anopen_prefilled_docpayload, then the agent calls that tool. Nothing is saved, andinsertis not used. Link and Dynamic Link fields still runfetch_from. Afterwards only explicitly set values are restored. A later change on that open form can go throughfrm_set_value.The related prompt stops the agent from calling the tool with a guessed payload. A field stays missing until it is confirmed, and a field that is only valid together with another field stays missing until that other field is included:
Link targets such as items, customers, and accounts are resolved with read tools and are not invented, so the payload only contains confirmed fields and existing records.
resolves #20
Simple Testing in the Browser
Fields missing from the payload keep the default. Here
uom,conversion_factor, andincome_accounton the item stay at whatever the item link fetches:The same fields in the payload override the default and stay in place after
fetch_from: