Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/12894-copilot-draft-card.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@object-ui/plugin-chatbot': minor
'@object-ui/i18n': minor
---

**The copilot's change card says when a change will be saved as a draft, and the applied card offers review and undo** (objectui#12894).

- **The change card.** When the copilot proposes a change, the card is headed 「修改方案 · 2 项」 / "Change plan · 2 changes" and lists one row per change: a + / ✎ / - symbol, the kind (字段 / 视图 …), the object and field it touches, and its type and parameters in small type (「number · 续借次数 · 默认 0 · 不必填」). For an app that is already live and holds records, the change is saved as a Studio draft: the card says so in an amber note, and its main button reads 「存为草稿」 / "Save as draft".
- **The applied card.** After you confirm, the card shows what happened, for example 「已存为草稿 · 2 项未发布」 with 「已有 12 条记录的续借次数为空」 and 「核对:结构 ✓」. It offers 「查看变更并发布」 / "Review changes and publish" and 「撤销」 / "Undo" when the host provides them. Undo discards every unpublished draft of the app package, so when other drafts are pending the button says how many, and the card asks before it runs.

Each of these reads a field the copilot's tools now send. When an older version does not send it, the card looks as it did before.

`@object-ui/plugin-chatbot`: `ProposedChanges` gains optional `posture` and `primaryAction`; `ReplayOutcome` gains optional `draftState`, `existingRows` and `appliedCard`; `ChatbotEnhancedToolInvocation` now references both types instead of repeating them; `ChatbotEnhancedProps` gains optional `onReviewDrafts` and `onDiscardDrafts`. `@object-ui/i18n`: new `chatbot.changes.*` keys in every pack.
18 changes: 18 additions & 0 deletions content/docs/plugins/plugin-chatbot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,24 @@ turn) reads `checklist`: a passed/total chip, the verified lines in two
columns, and the app and package that "Open app" and "View in Studio" open.
A result without those keys keeps the simpler rows the cards drew before.

The change card (a `changes_proposed` result) draws what the copilot's tools
say about how a change will land. When the result carries a `posture`, the
card is headed "Change plan · N changes" and draws one row per change: a
symbol for add, change or remove, the kind (field, view, object), the
`object · field` it touches, and its type and parameters in small type. A
change to an app that is live and holds records (`posture.mode: 'draft'`) is
saved as a Studio draft: the card's note says so in amber, and the primary
button reads "Save as draft" when `primaryAction` is `save_draft` (the message
it sends is still `changesConfirmMessage`). Once applied, the card shows the
result's `appliedCard` title and lines, "Review changes and publish" through
`onReviewDrafts(packageId)`, and "Undo" through `onDiscardDrafts(packageId)`.
Undo is meant for `POST /api/v1/packages/:id/discard-drafts`, which discards
every pending draft of the package, so the card asks first whenever other
drafts are pending: it reads `draftState.others` from the result, and the live
count from `fetchPendingDraftCount` when the host provides one. A host without
`onReviewDrafts` keeps the inline Publish button; a result without these keys
draws the card as before.

Use `surface="plain"` for full-page chat workspaces where the surrounding app
already provides navigation chrome. The default `surface="card"` remains a
better fit for embedded dashboards, side panels, and floating chat windows.
Expand Down
41 changes: 41 additions & 0 deletions packages/i18n/src/locales/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3751,6 +3751,47 @@ const ar = {
draftPosture: "تُحفظ التغييرات اللاحقة كمسودات، وأنت من ينشرها في Studio.",
checksPassed: "اجتازت الفحوصات {{passed}}/{{total}}",
},
changes: {
planTitle: "خطة التغييرات · {{count}} تغييرات",
planTitle_zero: "خطة التغييرات · {{count}} تغيير",
planTitle_one: "خطة التغييرات · {{count}} تغيير",
planTitle_two: "خطة التغييرات · تغييران ({{count}})",
planTitle_few: "خطة التغييرات · {{count}} تغييرات",
planTitle_many: "خطة التغييرات · {{count}} تغييرًا",
planTitle_other: "خطة التغييرات · {{count}} تغيير",
saveDraft: "حفظ كمسودة",
reviewAndPublish: "مراجعة التغييرات ونشرها",
undo: "تراجع",
undoWithOthers: "تراجع (مع {{count}} مسودات أخرى)",
undoWithOthers_zero: "تراجع (مع {{count}} مسودة أخرى)",
undoWithOthers_one: "تراجع (مع {{count}} مسودة أخرى)",
undoWithOthers_two: "تراجع (مع مسودتين أخريين: {{count}})",
undoWithOthers_few: "تراجع (مع {{count}} مسودات أخرى)",
undoWithOthers_many: "تراجع (مع {{count}} مسودة أخرى)",
undoWithOthers_other: "تراجع (مع {{count}} مسودة أخرى)",
undoConfirm: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirm_zero: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirm_one: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirm_two: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirm_few: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirm_many: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirm_other: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة وعددها {{total}}، منها {{count}} لا تخص هذا التغيير.",
undoConfirmUnknown: "يؤدي التراجع إلى حذف جميع المسودات غير المنشورة في هذه الحزمة، وليس هذا التغيير فقط.",
undoConfirmAction: "تراجع عن الكل",
undoCancel: "إلغاء",
undoing: "جارٍ التراجع…",
undone: "تم التراجع",
undoFailed: "تعذّر التراجع",
kind: {
field: "حقل",
object: "كائن",
view: "طريقة عرض",
dashboard: "لوحة معلومات",
app: "تطبيق",
seed: "بيانات تجريبية",
package: "حزمة التطبيق",
},
},
},
chatbotError: {
title: "فشل الرد",
Expand Down
29 changes: 29 additions & 0 deletions packages/i18n/src/locales/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3468,6 +3468,35 @@ const de = {
draftPosture: "Spätere Änderungen werden als Entwurf gespeichert, und Sie veröffentlichen sie in Studio.",
checksPassed: "Prüfungen bestanden {{passed}}/{{total}}",
},
changes: {
planTitle: "Änderungsplan · {{count}} Änderungen",
planTitle_one: "Änderungsplan · {{count}} Änderung",
planTitle_other: "Änderungsplan · {{count}} Änderungen",
saveDraft: "Als Entwurf speichern",
reviewAndPublish: "Änderungen prüfen und veröffentlichen",
undo: "Rückgängig",
undoWithOthers: "Rückgängig (mit {{count}} weiteren Entwürfen)",
undoWithOthers_one: "Rückgängig (mit {{count}} weiteren Entwurf)",
undoWithOthers_other: "Rückgängig (mit {{count}} weiteren Entwürfen)",
undoConfirm: "Rückgängig verwirft alle {{total}} unveröffentlichten Entwürfe dieses Pakets, davon {{count}}, die nicht zu dieser Änderung gehören.",
undoConfirm_one: "Rückgängig verwirft alle {{total}} unveröffentlichten Entwürfe dieses Pakets, davon {{count}}, der nicht zu dieser Änderung gehört.",
undoConfirm_other: "Rückgängig verwirft alle {{total}} unveröffentlichten Entwürfe dieses Pakets, davon {{count}}, die nicht zu dieser Änderung gehören.",
undoConfirmUnknown: "Rückgängig verwirft alle unveröffentlichten Entwürfe dieses Pakets, nicht nur diese Änderung.",
undoConfirmAction: "Alle verwerfen",
undoCancel: "Abbrechen",
undoing: "Wird rückgängig gemacht…",
undone: "Rückgängig gemacht",
undoFailed: "Rückgängig machen fehlgeschlagen",
kind: {
field: "Feld",
object: "Objekt",
view: "Ansicht",
dashboard: "Dashboard",
app: "App",
seed: "Beispieldaten",
package: "App-Paket",
},
},
},
chatbotError: {
title: "Antwort fehlgeschlagen",
Expand Down
29 changes: 29 additions & 0 deletions packages/i18n/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4145,6 +4145,35 @@ const en = {
draftPosture: 'Later changes are saved as drafts, and you publish them in Studio.',
checksPassed: 'Checks passed {{passed}}/{{total}}',
},
changes: {
planTitle: 'Change plan · {{count}} changes',
planTitle_one: 'Change plan · {{count}} change',
planTitle_other: 'Change plan · {{count}} changes',
saveDraft: 'Save as draft',
reviewAndPublish: 'Review changes and publish',
undo: 'Undo',
undoWithOthers: 'Undo (and {{count}} other drafts)',
undoWithOthers_one: 'Undo (and {{count}} other draft)',
undoWithOthers_other: 'Undo (and {{count}} other drafts)',
undoConfirm: 'Undo discards all {{total}} unpublished drafts of this package, including {{count}} that are not part of this change.',
undoConfirm_one: 'Undo discards all {{total}} unpublished drafts of this package, including {{count}} that is not part of this change.',
undoConfirm_other: 'Undo discards all {{total}} unpublished drafts of this package, including {{count}} that are not part of this change.',
undoConfirmUnknown: 'Undo discards every unpublished draft of this package, not only this change.',
undoConfirmAction: 'Undo all',
undoCancel: 'Cancel',
undoing: 'Undoing…',
undone: 'Undone',
undoFailed: 'Undo failed',
kind: {
field: 'Field',
object: 'Object',
view: 'View',
dashboard: 'Dashboard',
app: 'App',
seed: 'Sample data',
package: 'App package',
},
},
},
chatbotError: {
title: 'Response failed',
Expand Down
32 changes: 32 additions & 0 deletions packages/i18n/src/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3537,6 +3537,38 @@ const es = {
draftPosture: "Los cambios posteriores se guardan como borrador y usted los publica en Studio.",
checksPassed: "Comprobaciones superadas {{passed}}/{{total}}",
},
changes: {
planTitle: "Plan de cambios · {{count}} cambios",
planTitle_one: "Plan de cambios · {{count}} cambio",
planTitle_many: "Plan de cambios · {{count}} de cambios",
planTitle_other: "Plan de cambios · {{count}} cambios",
saveDraft: "Guardar como borrador",
reviewAndPublish: "Revisar cambios y publicar",
undo: "Deshacer",
undoWithOthers: "Deshacer (y {{count}} borradores más)",
undoWithOthers_one: "Deshacer (y {{count}} borrador más)",
undoWithOthers_many: "Deshacer (y {{count}} de borradores más)",
undoWithOthers_other: "Deshacer (y {{count}} borradores más)",
undoConfirm: "Deshacer descarta los {{total}} borradores sin publicar de este paquete, incluidos {{count}} que no forman parte de este cambio.",
undoConfirm_one: "Deshacer descarta los {{total}} borradores sin publicar de este paquete, incluido {{count}} que no forma parte de este cambio.",
undoConfirm_many: "Deshacer descarta los {{total}} borradores sin publicar de este paquete, incluidos {{count}} de borradores que no forman parte de este cambio.",
undoConfirm_other: "Deshacer descarta los {{total}} borradores sin publicar de este paquete, incluidos {{count}} que no forman parte de este cambio.",
undoConfirmUnknown: "Deshacer descarta todos los borradores sin publicar de este paquete, no solo este cambio.",
undoConfirmAction: "Deshacer todo",
undoCancel: "Cancelar",
undoing: "Deshaciendo…",
undone: "Deshecho",
undoFailed: "No se pudo deshacer",
kind: {
field: "Campo",
object: "Objeto",
view: "Vista",
dashboard: "Panel",
app: "Aplicación",
seed: "Datos de ejemplo",
package: "Paquete de aplicación",
},
},
},
chatbotError: {
title: "Error en la respuesta",
Expand Down
32 changes: 32 additions & 0 deletions packages/i18n/src/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3534,6 +3534,38 @@ const fr = {
draftPosture: "Les modifications suivantes sont enregistrées comme brouillons, et vous les publiez dans Studio.",
checksPassed: "Vérifications réussies {{passed}}/{{total}}",
},
changes: {
planTitle: "Plan de modifications · {{count}} modifications",
planTitle_one: "Plan de modifications · {{count}} modification",
planTitle_many: "Plan de modifications · {{count}} de modifications",
planTitle_other: "Plan de modifications · {{count}} modifications",
saveDraft: "Enregistrer comme brouillon",
reviewAndPublish: "Vérifier les modifications et publier",
undo: "Annuler",
undoWithOthers: "Annuler (avec {{count}} autres brouillons)",
undoWithOthers_one: "Annuler (avec {{count}} autre brouillon)",
undoWithOthers_many: "Annuler (avec {{count}} d'autres brouillons)",
undoWithOthers_other: "Annuler (avec {{count}} autres brouillons)",
undoConfirm: "Annuler supprime les {{total}} brouillons non publiés de ce package, dont {{count}} qui ne font pas partie de cette modification.",
undoConfirm_one: "Annuler supprime les {{total}} brouillons non publiés de ce package, dont {{count}} qui ne fait pas partie de cette modification.",
undoConfirm_many: "Annuler supprime les {{total}} brouillons non publiés de ce package, dont {{count}} de brouillons qui ne font pas partie de cette modification.",
undoConfirm_other: "Annuler supprime les {{total}} brouillons non publiés de ce package, dont {{count}} qui ne font pas partie de cette modification.",
undoConfirmUnknown: "Annuler supprime tous les brouillons non publiés de ce package, pas seulement cette modification.",
undoConfirmAction: "Tout annuler",
undoCancel: "Conserver",
undoing: "Annulation…",
undone: "Annulé",
undoFailed: "Échec de l'annulation",
kind: {
field: "Champ",
object: "Objet",
view: "Vue",
dashboard: "Tableau de bord",
app: "Application",
seed: "Données d'exemple",
package: "Package d'application",
},
},
},
chatbotError: {
title: "Échec de la réponse",
Expand Down
29 changes: 29 additions & 0 deletions packages/i18n/src/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3470,6 +3470,35 @@ const ja = {
draftPosture: "以降の変更は下書きとして保存され、Studio で公開します。",
checksPassed: "照合済み {{passed}}/{{total}}",
},
changes: {
planTitle: "変更案 · {{count}} 件",
planTitle_one: "変更案 · {{count}} 件",
planTitle_other: "変更案 · {{count}} 件",
saveDraft: "下書きとして保存",
reviewAndPublish: "変更を確認して公開",
undo: "取り消す",
undoWithOthers: "取り消す(ほかの下書き {{count}} 件も含む)",
undoWithOthers_one: "取り消す(ほかの下書き {{count}} 件も含む)",
undoWithOthers_other: "取り消す(ほかの下書き {{count}} 件も含む)",
undoConfirm: "取り消すと、このアプリパッケージの未公開の下書き {{total}} 件がすべて破棄されます。うち {{count}} 件は今回の変更ではありません。",
undoConfirm_one: "取り消すと、このアプリパッケージの未公開の下書き {{total}} 件がすべて破棄されます。うち {{count}} 件は今回の変更ではありません。",
undoConfirm_other: "取り消すと、このアプリパッケージの未公開の下書き {{total}} 件がすべて破棄されます。うち {{count}} 件は今回の変更ではありません。",
undoConfirmUnknown: "取り消すと、今回の変更だけでなく、このアプリパッケージの未公開の下書きがすべて破棄されます。",
undoConfirmAction: "すべて取り消す",
undoCancel: "キャンセル",
undoing: "取り消し中…",
undone: "取り消しました",
undoFailed: "取り消せませんでした",
kind: {
field: "フィールド",
object: "オブジェクト",
view: "ビュー",
dashboard: "ダッシュボード",
app: "アプリ",
seed: "サンプルデータ",
package: "アプリパッケージ",
},
},
},
chatbotError: {
title: "応答に失敗しました",
Expand Down
29 changes: 29 additions & 0 deletions packages/i18n/src/locales/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3467,6 +3467,35 @@ const ko = {
draftPosture: "이후 변경 사항은 초안으로 저장되며, Studio에서 직접 게시합니다.",
checksPassed: "검증 통과 {{passed}}/{{total}}",
},
changes: {
planTitle: "변경안 · {{count}}개",
planTitle_one: "변경안 · {{count}}개",
planTitle_other: "변경안 · {{count}}개",
saveDraft: "초안으로 저장",
reviewAndPublish: "변경 사항 확인 후 게시",
undo: "되돌리기",
undoWithOthers: "되돌리기(다른 초안 {{count}}개 포함)",
undoWithOthers_one: "되돌리기(다른 초안 {{count}}개 포함)",
undoWithOthers_other: "되돌리기(다른 초안 {{count}}개 포함)",
undoConfirm: "되돌리면 이 앱 패키지의 게시되지 않은 초안 {{total}}개가 모두 폐기되며, 그중 {{count}}개는 이번 변경이 아닙니다.",
undoConfirm_one: "되돌리면 이 앱 패키지의 게시되지 않은 초안 {{total}}개가 모두 폐기되며, 그중 {{count}}개는 이번 변경이 아닙니다.",
undoConfirm_other: "되돌리면 이 앱 패키지의 게시되지 않은 초안 {{total}}개가 모두 폐기되며, 그중 {{count}}개는 이번 변경이 아닙니다.",
undoConfirmUnknown: "되돌리면 이번 변경뿐 아니라 이 앱 패키지의 게시되지 않은 초안이 모두 폐기됩니다.",
undoConfirmAction: "모두 되돌리기",
undoCancel: "취소",
undoing: "되돌리는 중…",
undone: "되돌림",
undoFailed: "되돌리지 못했습니다",
kind: {
field: "필드",
object: "오브젝트",
view: "뷰",
dashboard: "대시보드",
app: "앱",
seed: "샘플 데이터",
package: "앱 패키지",
},
},
},
chatbotError: {
title: "응답 실패",
Expand Down
Loading
Loading