@blinkk/root-cms 3.0.5 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +77 -0
  2. package/dist/app.js +7 -4
  3. package/dist/browser-client/browser-client.d.ts +148 -0
  4. package/dist/browser-client/embed-window.d.ts +66 -0
  5. package/dist/browser-client/emitter.d.ts +11 -0
  6. package/dist/browser-client.js +377 -0
  7. package/dist/{chunk-RXWDB3K4.js → chunk-4VZTYUQ7.js} +1 -1
  8. package/dist/{chunk-N4K6ICFR.js → chunk-AFBSITEO.js} +4 -6
  9. package/dist/{chunk-PNLLZXVY.js → chunk-AJDMNTZQ.js} +2 -2
  10. package/dist/{chunk-VSPPZPMP.js → chunk-GXV4UQ6Z.js} +15 -11
  11. package/dist/chunk-J72JK4KR.js +8 -0
  12. package/dist/cli.js +2 -1
  13. package/dist/client.js +2 -1
  14. package/dist/core/client.d.ts +5 -0
  15. package/dist/core/plugin.d.ts +17 -0
  16. package/dist/core.js +4 -2
  17. package/dist/functions.js +4 -3
  18. package/dist/plugin.js +16 -4
  19. package/dist/shared/embed-protocol.d.ts +72 -0
  20. package/dist/ui/AIPage-EL6DQYII.js +1 -0
  21. package/dist/ui/AssetsPage-5S6PNMF6.js +1 -0
  22. package/dist/ui/CollectionPage-CU3VDEXA.js +1 -0
  23. package/dist/ui/ComparePage-FTZLYO2O.js +1 -0
  24. package/dist/ui/DataPage-XIXFKXDN.js +1 -0
  25. package/dist/ui/DataSourcePage-ORIEQH3Y.js +1 -0
  26. package/dist/ui/DocTranslationsPage-4OVBIPSG.js +1 -0
  27. package/dist/ui/DocumentPage-3JPFJF3E.js +1 -0
  28. package/dist/ui/EditDataSourcePage-HIGZZQJC.js +1 -0
  29. package/dist/ui/EditReleasePage-KUHBU2HQ.js +1 -0
  30. package/dist/ui/EmbeddedAIPage-CJWZE5FC.js +1 -0
  31. package/dist/ui/EmbeddedDocumentPage-6XQHYIAO.js +1 -0
  32. package/dist/ui/{ImageEditorDialog-4H665KK2.js → ImageEditorDialog-GGS4VFEA.js} +2 -2
  33. package/dist/ui/LogsPage-4DVGYXZY.js +1 -0
  34. package/dist/ui/NewDataSourcePage-7TUUE6ZL.js +1 -0
  35. package/dist/ui/NewReleasePage-6UT36HDW.js +1 -0
  36. package/dist/ui/NotFoundPage-AW6UC6II.js +1 -0
  37. package/dist/ui/ProjectPage-US5FJGFK.js +1 -0
  38. package/dist/ui/ReleasePage-W2R3DIFX.js +1 -0
  39. package/dist/ui/ReleasesPage-HBBUGE7D.js +1 -0
  40. package/dist/ui/SettingsPage-7JQQILUV.js +1 -0
  41. package/dist/ui/SidebarToolsPage-MIYXKHF2.js +1 -0
  42. package/dist/ui/TaskPage-JYUQEGRB.js +1 -0
  43. package/dist/ui/TasksPage-4VFQF243.js +1 -0
  44. package/dist/ui/TranslationsArbPage-AJLM5VSD.js +2 -0
  45. package/dist/ui/TranslationsEditPage-RTTGTIGI.js +1 -0
  46. package/dist/ui/{TranslationsPage-WIDVSTYF.js → TranslationsPage-HPYAJQ4Q.js} +31 -31
  47. package/dist/ui/{ai-tools-5E5ELLZX.js → ai-tools-4DWMFQS6.js} +1 -1
  48. package/dist/ui/{chunk-JYFLU7DM.js → chunk-2KSMCQ6H.js} +2 -2
  49. package/dist/ui/{chunk-HKINZLMW.js → chunk-344GZOGG.js} +45 -45
  50. package/dist/ui/{chunk-CGCKJFL4.js → chunk-3E6CASIN.js} +1 -1
  51. package/dist/ui/chunk-3T4ZWQR4.js +7 -0
  52. package/dist/ui/chunk-4ISFTE2G.js +5 -0
  53. package/dist/ui/chunk-5AVRMJVW.js +1 -0
  54. package/dist/ui/chunk-764W6634.js +1 -0
  55. package/dist/ui/chunk-76ZGLKLT.js +1 -0
  56. package/dist/ui/{chunk-SKEP5WYH.js → chunk-7SK47HHZ.js} +3 -3
  57. package/dist/ui/chunk-AZCGXQTL.js +1 -0
  58. package/dist/ui/{chunk-W3BJ2EZX.js → chunk-B6M55OFE.js} +1 -1
  59. package/dist/ui/{chunk-KYDOSLTO.js → chunk-CAY5NM4Z.js} +1 -1
  60. package/dist/ui/{chunk-4KE2SZKH.js → chunk-D3UIZHRK.js} +1 -1
  61. package/dist/ui/chunk-E76ECIOX.js +81 -0
  62. package/dist/ui/chunk-FBSBL476.js +1 -0
  63. package/dist/ui/chunk-FFHV5S6A.js +1 -0
  64. package/dist/ui/{chunk-X2WHBGTP.js → chunk-FJLNXXE3.js} +1 -1
  65. package/dist/ui/chunk-FSVNOZ6F.js +1 -0
  66. package/dist/ui/{chunk-BZIRGB4W.js → chunk-GDXNSFLE.js} +1 -1
  67. package/dist/ui/{chunk-C5NH23G4.js → chunk-GQ5IRK43.js} +1 -1
  68. package/dist/ui/{chunk-DEGMKEHP.js → chunk-GU24U5RM.js} +1 -1
  69. package/dist/ui/{chunk-HRGYNHZ3.js → chunk-HARRKJFZ.js} +1 -1
  70. package/dist/ui/{chunk-PHBMVORG.js → chunk-HO3W4RVG.js} +1 -1
  71. package/dist/ui/{chunk-62UWGWON.js → chunk-J5E457OI.js} +1 -1
  72. package/dist/ui/{chunk-W3HIZQ4Z.js → chunk-JS6TK4OP.js} +1 -1
  73. package/dist/ui/{chunk-54DVDYU6.js → chunk-JTIQBW33.js} +1 -1
  74. package/dist/ui/{chunk-ORXEMIQC.js → chunk-KRNQ6L35.js} +1 -1
  75. package/dist/ui/chunk-LROR6N3B.js +7 -0
  76. package/dist/ui/{chunk-NZHF733K.js.LEGAL.txt → chunk-LROR6N3B.js.LEGAL.txt} +6 -1
  77. package/dist/ui/{chunk-E2RCCK2T.js → chunk-M3T56ZRP.js} +1 -1
  78. package/dist/ui/chunk-MXGHX55S.js +141 -0
  79. package/dist/ui/{chunk-KFAZBEPV.js → chunk-MZTOPPWQ.js} +1 -1
  80. package/dist/ui/{chunk-JHBAMPGB.js → chunk-N3JSLTMV.js} +1 -1
  81. package/dist/ui/{chunk-L4RHGQUG.js → chunk-NSOTG64N.js} +1 -1
  82. package/dist/ui/{chunk-HLMBCVRX.js → chunk-O5P3CPJ4.js} +1 -1
  83. package/dist/ui/chunk-OWQL5DVE.js +1 -0
  84. package/dist/ui/{chunk-P3NETZZP.js → chunk-OXVYTSIZ.js} +1 -1
  85. package/dist/ui/chunk-P2Z66DHV.js +1 -0
  86. package/dist/ui/chunk-QEE7XS6O.js +1 -0
  87. package/dist/ui/chunk-QHJOTXYB.js +1 -0
  88. package/dist/ui/{chunk-3IYZCUPI.js → chunk-R6B3W5AJ.js} +1 -1
  89. package/dist/ui/{chunk-QGBR3J2Y.js → chunk-RAXWL656.js} +1 -1
  90. package/dist/ui/chunk-SRX7EWL4.js +1 -0
  91. package/dist/ui/chunk-TDUBSLEC.js +1 -0
  92. package/dist/ui/chunk-TFB3VGWP.js +1 -0
  93. package/dist/ui/{chunk-767BAQ53.js → chunk-U7PWJV6F.js} +1 -1
  94. package/dist/ui/{chunk-PWKJDYE2.js → chunk-UUVAD4U4.js} +1 -1
  95. package/dist/ui/chunk-V4CTOC6E.js +1 -0
  96. package/dist/ui/{chunk-EGEB6N4J.js → chunk-VD6G5NV4.js} +11 -11
  97. package/dist/ui/chunk-W5DOO6ID.js +1 -0
  98. package/dist/ui/{chunk-HHMG665Z.js → chunk-WFQU7V3W.js} +1 -1
  99. package/dist/ui/{chunk-SQRKKWRG.js → chunk-WKF7CSWS.js} +1 -1
  100. package/dist/ui/{chunk-4W73RW5I.js → chunk-WXT7LTQM.js} +1 -1
  101. package/dist/ui/{chunk-VMT7JFAM.js → chunk-XT5FNJCX.js} +1 -1
  102. package/dist/ui/chunk-YLSRRNSE.js +1 -0
  103. package/dist/ui/chunk-ZN2Y5OUF.js +3 -0
  104. package/dist/ui/gcs-ECSDFCIU.js +1 -0
  105. package/dist/ui/ui.css +1 -1
  106. package/dist/ui/ui.js +1 -1
  107. package/package.json +14 -10
  108. package/dist/ui/AIPage-F3NNYM5E.js +0 -1
  109. package/dist/ui/AssetsPage-DZQHAENZ.js +0 -1
  110. package/dist/ui/CollectionPage-WVVG62NR.js +0 -1
  111. package/dist/ui/ComparePage-CRDHP45W.js +0 -1
  112. package/dist/ui/DataPage-WMLBCPGF.js +0 -1
  113. package/dist/ui/DataSourcePage-POZAQFPU.js +0 -1
  114. package/dist/ui/DocTranslationsPage-UR5D2RF2.js +0 -1
  115. package/dist/ui/DocumentPage-SQ7ROBMC.js +0 -1
  116. package/dist/ui/EditDataSourcePage-PUA2AJ4C.js +0 -1
  117. package/dist/ui/EditReleasePage-CENP46EO.js +0 -1
  118. package/dist/ui/LogsPage-FZRN6MBJ.js +0 -1
  119. package/dist/ui/NewDataSourcePage-FTILYFJY.js +0 -1
  120. package/dist/ui/NewReleasePage-MHJC66KK.js +0 -1
  121. package/dist/ui/NotFoundPage-EP2OE4JV.js +0 -1
  122. package/dist/ui/ProjectPage-6J7QCG75.js +0 -1
  123. package/dist/ui/ReleasePage-IZ3DNGT4.js +0 -1
  124. package/dist/ui/ReleasesPage-RWFOJ5VG.js +0 -1
  125. package/dist/ui/SettingsPage-M4SIDBTI.js +0 -1
  126. package/dist/ui/SidebarToolsPage-GAX3XJ7W.js +0 -1
  127. package/dist/ui/TaskPage-UCATTNZ5.js +0 -1
  128. package/dist/ui/TasksPage-4AQLQ4IT.js +0 -1
  129. package/dist/ui/TranslationsArbPage-JGQGATCS.js +0 -2
  130. package/dist/ui/TranslationsEditPage-7AGZGHKS.js +0 -1
  131. package/dist/ui/chunk-7MTDTPYB.js +0 -1
  132. package/dist/ui/chunk-7UIUAHC4.js +0 -1
  133. package/dist/ui/chunk-AEWL2RWR.js +0 -141
  134. package/dist/ui/chunk-AFWBSIPL.js +0 -1
  135. package/dist/ui/chunk-AL3TN2KI.js +0 -1
  136. package/dist/ui/chunk-DUJYIOLE.js +0 -5
  137. package/dist/ui/chunk-I6ICVKEC.js +0 -1
  138. package/dist/ui/chunk-JKCZGT6B.js +0 -1
  139. package/dist/ui/chunk-JZFTZ4X4.js +0 -87
  140. package/dist/ui/chunk-KKEWCXVV.js +0 -1
  141. package/dist/ui/chunk-NZHF733K.js +0 -7
  142. package/dist/ui/chunk-ONTGW2VA.js +0 -1
  143. package/dist/ui/chunk-P4U2LUTF.js +0 -1
  144. package/dist/ui/chunk-PJA7YP4A.js +0 -1
  145. package/dist/ui/chunk-RSVO46S3.js +0 -1
  146. package/dist/ui/chunk-TJBVMFNQ.js +0 -1
  147. package/dist/ui/chunk-XOQ3KDSR.js +0 -3
  148. package/dist/ui/chunk-YFA6U2CV.js +0 -1
  149. package/dist/ui/gcs-L33FIRZU.js +0 -1
  150. /package/dist/ui/{ImageEditorDialog-4H665KK2.js.LEGAL.txt → ImageEditorDialog-GGS4VFEA.js.LEGAL.txt} +0 -0
  151. /package/dist/ui/{chunk-SKEP5WYH.js.LEGAL.txt → chunk-7SK47HHZ.js.LEGAL.txt} +0 -0
  152. /package/dist/ui/{chunk-JZFTZ4X4.js.LEGAL.txt → chunk-E76ECIOX.js.LEGAL.txt} +0 -0
  153. /package/dist/ui/{chunk-AEWL2RWR.js.LEGAL.txt → chunk-MXGHX55S.js.LEGAL.txt} +0 -0
  154. /package/dist/ui/{chunk-EGEB6N4J.js.LEGAL.txt → chunk-VD6G5NV4.js.LEGAL.txt} +0 -0
  155. /package/dist/ui/{prerender-Q4YSDCPB.js → prerender-M47IWV5Q.js} +0 -0
@@ -1 +1 @@
1
- import{a as s,g as F}from"./chunk-HKINZLMW.js";import{c as $}from"./chunk-JDW4UORS.js";import"./chunk-PVAE643M.js";function k(e,t){if(e==null)return[];if(typeof e!="object"||Array.isArray(e))return[{path:"",message:"Expected object for fields data",expected:"object",received:E(e)}];let i=[];for(let r of t.fields){if(!r.id||!(r.id in e))continue;let o=e[r.id];i.push(...g(o,r,r.id))}return i}function g(e,t,i){if(e===void 0)return[];switch(t.type){case"string":case"select":return typeof e!="string"?[c(i,"string",e)]:[];case"number":return typeof e!="number"?[c(i,"number",e)]:isNaN(e)?[c(i,"number",e)]:[];case"boolean":return typeof e!="boolean"?[c(i,"boolean",e)]:[];case"date":case"datetime":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[],o=e.seconds,n=e.nanoseconds;return o===void 0?r.push({path:`${i}.seconds`,message:"Required",expected:"number",received:"undefined"}):typeof o!="number"&&r.push(c(`${i}.seconds`,"number",o)),n===void 0?r.push({path:`${i}.nanoseconds`,message:"Required",expected:"number",received:"undefined"}):typeof n!="number"&&r.push(c(`${i}.nanoseconds`,"number",n)),r}case"multiselect":return Array.isArray(e)?e.flatMap((r,o)=>typeof r!="string"?[c(`${i}.${o}`,"string",r)]:[]):[c(i,"array",e)];case"image":case"file":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[];return e.src===void 0?r.push({path:`${i}.src`,message:"Required",expected:"string",received:"undefined"}):typeof e.src!="string"&&r.push(c(`${i}.src`,"string",e.src)),e.alt!==void 0&&typeof e.alt!="string"&&r.push(c(`${i}.alt`,"string",e.alt)),r}case"object":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=t,o=[];for(let n of r.fields)!n.id||!(n.id in e)||o.push(...g(e[n.id],n,`${i}.${n.id}`));return o}case"array":{if(!Array.isArray(e))return[c(i,"array",e)];let o=t.of;return e.flatMap((n,a)=>g(n,o,`${i}.${a}`))}case"oneof":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=t,o=e._type,n=new Map,a=[];for(let l of r.types){if(typeof l=="string"){a.push(l);continue}n.set(l.name,l),a.push(l.name)}if(!a.includes(o)){let l=a.map(u=>`'${u}'`).join(" | ");return[{path:`${i}._type`,message:`Invalid discriminator value. Expected ${l}`,expected:"valid discriminator value",received:o}]}let d=n.get(o);if(!d)return[];let f=[];for(let l of d.fields)!l.id||!(l.id in e)||f.push(...g(e[l.id],l,`${i}.${l.id}`));return f}case"richtext":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[];return e.blocks===void 0?r.push({path:`${i}.blocks`,message:"Required",expected:"array",received:"undefined"}):Array.isArray(e.blocks)?e.blocks.forEach((o,n)=>{if(typeof o!="object"||o===null){r.push(c(`${i}.blocks.${n}`,"object",o));return}o.type===void 0?r.push({path:`${i}.blocks.${n}.type`,message:"Required",expected:"string",received:"undefined"}):typeof o.type!="string"&&r.push(c(`${i}.blocks.${n}.type`,"string",o.type))}):r.push(c(`${i}.blocks`,"array",e.blocks)),r}case"reference":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[],o=["id","collection","slug"];for(let n of o)e[n]===void 0?r.push({path:`${i}.${n}`,message:"Required",expected:"string",received:"undefined"}):typeof e[n]!="string"&&r.push(c(`${i}.${n}`,"string",e[n]));return r}case"references":return Array.isArray(e)?e.flatMap((r,o)=>{if(typeof r!="object"||r===null||Array.isArray(r))return[c(`${i}.${o}`,"object",r)];let n=[],a=["id","collection","slug"];for(let d of a)r[d]===void 0?n.push({path:`${i}.${o}.${d}`,message:"Required",expected:"string",received:"undefined"}):typeof r[d]!="string"&&n.push(c(`${i}.${o}.${d}`,"string",r[d]));return n}):[c(i,"array",e)];default:return console.warn(`Unknown field type: ${t.type}`),[]}}function E(e){return e===null?"null":Array.isArray(e)?"array":typeof e=="number"&&Number.isNaN(e)?"nan":typeof e}function c(e,t,i){let r=E(i);return{path:e,message:`Expected ${t}, received ${r}`,expected:t,received:r}}var Y=["collections_list","docs_list","doc_get","doc_getVersion","doc_set","doc_create","doc_updateField","doc_edit","doc_duplicate","doc_listVersions","doc_translateField","schema_get"],T=["collections_list","docs_list","doc_get","doc_getVersion","doc_listVersions","schema_get"];function Z(e){let t=M(e),i={};for(let r of T)t[r]&&(i[r]=t[r]);return i}function M(e){return{collections_list:{description:"List all CMS collections defined in the project. Returns each collection id along with optional name/description metadata.",inputSchema:s.object({}),execute:async()=>{let t=await e.loadAllCollections();return{collections:Object.entries(t).map(([i,r])=>({id:i,name:r.name,description:r.description}))}}},docs_list:{description:"List documents inside a CMS collection. Returns up to `limit` docs (default 25, max 100). Use this to explore content before reading individual docs.",inputSchema:s.object({collectionId:s.string().describe('Collection id, e.g. "Pages" or "BlogPosts".'),mode:s.enum(["draft","published"]).default("draft").describe("Whether to read draft or published versions."),limit:s.number().int().min(1).max(100).default(25)}),execute:async({collectionId:t,mode:i="draft",limit:r=25})=>{let o=v(r,1,100,25);return{docs:(await e.cmsClient.listDocs(t,{mode:i,limit:o})).docs.map(a=>({id:a.id,slug:a.slug,sys:A(a.sys)}))}}},doc_get:{description:"Read a single CMS document. Returns the doc fields plus system metadata. Use this when you need the full content of a doc.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),mode:s.enum(["draft","published"]).default("draft")}),execute:async({docId:t,mode:i="draft"})=>{let{collection:r,slug:o}=S(t),n=await e.cmsClient.getRawDoc(r,o,{mode:i});return n?{found:!0,doc:{id:n.id,collection:n.collection,slug:n.slug,sys:A(n.sys),fields:N(n.fields)}}:{found:!1}}},doc_getVersion:{description:'Read a specific version of a CMS document. Use versionId "draft" or "published" for the current draft/published state, or a numeric timestamp for a historical version (from `doc_listVersions`).',inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),versionId:s.string().describe('Version identifier: "draft", "published", or a numeric timestamp.')}),execute:async({docId:t,versionId:i})=>{let{collection:r,slug:o}=S(t),n;i==="draft"?n=`Projects/${e.cmsClient.projectId}/Collections/${r}/Drafts/${o}`:i==="published"?n=`Projects/${e.cmsClient.projectId}/Collections/${r}/Published/${o}`:n=`Projects/${e.cmsClient.projectId}/Collections/${r}/Drafts/${o}/Versions/${i}`;let a=await e.cmsClient.db.doc(n).get();if(!a.exists)return{found:!1};let d=a.data();return{found:!0,doc:{id:d.id,collection:d.collection,slug:d.slug,sys:A(d.sys),fields:N(d.fields)}}}},doc_set:{description:"Replace the entire draft fields payload of a CMS document. Pass the full JSON object that should become the new draft contents \u2014 any fields omitted will be removed. The payload is validated against the collection schema and the call is rejected on validation errors. Prefer `doc_updateField` for targeted edits. Only writes the draft version; users must publish separately. Format: pass plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the payload into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),fields:s.record(s.string(),s.any()).describe("New fields object. Replaces the existing draft fields entirely.")})},doc_create:{description:"Create a new draft CMS document with the given slug. Fails if the doc already exists. Pass optional initial fields (validated against the collection schema). Format: pass plain JSON for `fields`. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the payload into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "BlogPosts/my-new-post").'),fields:s.record(s.string(),s.any()).optional().describe("Optional initial fields for the new doc.")})},doc_updateField:{description:'Update a single field on a draft CMS document by JSON path. Paths are relative to the doc fields object; do not prefix them with "fields.". Use dotted paths (e.g. "hero.title") and zero-based array indices. For example, update the first module title with path "content.modules.0.title". To insert or remove array items, prefer `doc_edit` (it supports insert/remove operations); alternatively set the whole array path here (e.g. "content.modules") to the updated array. The value is validated against the field schema and the call is rejected if the shape is wrong (e.g. passing a string to a richtext field). Only updates the draft version; users must publish separately. Format: pass `value` as plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the value into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape and `blocks` MUST be a plain JSON array of `{type, data}` objects (never wrapped in `_array`).',inputSchema:s.object({docId:s.string(),path:s.string().describe('Dotted JSON path within the fields object, e.g. "content.modules.0.title".'),value:s.any().describe("JSON value to set at the path.")})},doc_edit:{description:'Apply multiple edits to a draft CMS document in a single call. Use this when a change spans more than one field or needs to add or remove array items (e.g. append a new module AND update a title). Pass an ordered `operations` list; each operation has an `op`:\n- "set": set the value at `path` (e.g. "hero.title" or "content.modules.0.title"). Provide `value`.\n- "insert_item": insert `value` into the array at `path` (e.g. "content.modules"). Optionally pass a zero-based `index` to insert before; omit `index` to append.\n- "remove_item": remove the array item at zero-based `index` from the array at `path`.\nOperations apply in order against the current draft. Array indices in each operation refer to the array state AFTER earlier operations have been applied. The whole result is validated against the collection schema and the call is rejected as a group on any error \u2014 nothing is written unless every operation succeeds. Paths are relative to the doc fields object; do not prefix them with "fields.". Use dotted paths and zero-based array indices. Only writes the draft version; users must publish separately. Format: pass `value` as plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals values into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.',inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),operations:s.array(s.object({op:s.enum(["set","insert_item","remove_item"]).describe('Operation: "set" a field value, "insert_item" into an array, or "remove_item" from an array.'),path:s.string().describe('Dotted path within the fields object. For "set" it targets the field to write (e.g. "hero.title"); for "insert_item"/"remove_item" it targets the array (e.g. "content.modules").'),value:s.any().optional().describe('JSON value. Required for "set" (the new field value) and "insert_item" (the new array item). Ignored for "remove_item".'),index:s.number().int().min(0).optional().describe('Zero-based array index. For "insert_item" it is the position to insert before (omit to append); for "remove_item" it is the item to delete (required).')})).min(1).describe("Ordered list of edit operations to apply to the draft.")})},doc_duplicate:{description:"Duplicate an existing CMS document to a new slug. Copies all draft fields to the target doc id. Fails if the target already exists.",inputSchema:s.object({fromDocId:s.string().describe('Source doc id to copy from (e.g. "Pages/home").'),toDocId:s.string().describe('Target doc id for the copy (e.g. "Pages/home-copy").')})},doc_listVersions:{description:"List version history for a CMS document. Returns versions ordered by most recent first. Use the versionId from the results with `doc_getVersion` to read a specific version.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),limit:s.number().int().min(1).max(50).default(10)}),execute:async({docId:t,limit:i=10})=>{let{collection:r,slug:o}=S(t),n=v(i,1,50,10),a=`Projects/${e.cmsClient.projectId}/Collections/${r}/Drafts/${o}/Versions`;return{versions:(await e.cmsClient.db.collection(a).orderBy("sys.modifiedAt","desc").limit(n).get()).docs.map(f=>{let l=f.data();return{versionId:f.id,sys:A(l.sys),tags:l.tags||[],publishMessage:l.publishMessage}})}}},doc_translateField:{description:"Translate a text value into one or more target locales using AI. Returns the translated strings keyed by locale. Use this to help with localization workflows.",inputSchema:s.object({sourceText:s.string().min(1).describe("The source text to translate."),targetLocales:s.array(s.string()).min(1).describe('Array of locale codes to translate into (e.g. ["es", "fr", "de"]).'),description:s.string().optional().describe("Optional context about the text to improve translation quality.")})},schema_get:{description:"Get the field schema for a CMS collection. Returns the full field definitions including types, labels, and validation rules. Use this to understand what fields a collection supports before creating or editing docs.",inputSchema:s.object({collectionId:s.string().describe('Collection id, e.g. "Pages" or "BlogPosts".')}),execute:async({collectionId:t})=>{let i=await e.loadCollection(t);return i?{found:!0,collectionId:t,fields:_(i.fields||[])}:{found:!1,collectionId:t}}}}}function S(e){let t=e.indexOf("/");if(t<=0||t===e.length-1)throw new Error(`invalid docId: "${e}" (expected "Collection/slug")`);return{collection:e.slice(0,t),slug:$(e.slice(t+1))}}function v(e,t,i,r){let o=Number.isFinite(e)?Math.trunc(e):r;return Math.min(Math.max(o,t),i)}function A(e){return F(e??{})}function N(e){return F(e??{})}function _(e){return e.map(t=>{let i={id:t.id,type:t.type};return t.label&&(i.label=t.label),t.description&&(i.description=t.description),t.required&&(i.required=!0),t.translate&&(i.translate=!0),t.options&&(i.options=t.options),t.type==="object"&&t.fields&&(i.fields=_(t.fields)),t.type==="array"&&t.of&&(i.of=_([t.of])[0]),t.type==="oneof"&&t.types&&(i.types=t.types.map(r=>typeof r=="string"?r:{id:r.id,fields:_(r.fields||[])})),i})}function H(e,t,i){let r=V(e,t);if(r.error)return[r.error];let o=r.field;return o?g(i,o,t):[]}function V(e,t){let i=R(t);if(i)return{field:null,error:i};let r=t.trim().split(".");if(r.length===0)return{field:null};let o=e.fields||[],n=null;for(let a=0;a<r.length;a++){let d=r[a],f=r.slice(0,a+1).join("."),l=/^\d+$/.test(d),u=/^(0|[1-9]\d*)$/.test(d);if(l&&!u)return{field:null,error:h(f,"Array indices must be zero-based numeric path segments without leading zeros.","array index",d)};if(u){if(!n||n.type!=="array")return{field:null,error:h(f,"Array index path segments can only be used after an array field.","array field",n?.type||"root")};let x=n.of;n=x,o=x.type==="object"?x.fields:[];continue}if(n?.type==="array")return{field:null,error:h(f,"Array fields must be followed by a zero-based numeric index before nested fields.","array index",d)};let m=o.find(p=>p.id===d);if(!m&&n?.type==="oneof"){let p=n,x=Array.isArray(p.types)?p.types:[];for(let C of x){if(typeof C=="string")continue;let O=(C.fields||[]).find(P=>P.id===d);if(O){m=O;break}}}if(!m)return{field:null};n=m,m.type==="object"?o=m.fields:m.type==="array"?o=[]:o=[]}return{field:n}}function R(e){let t=e.trim();if(!t)return h(e,"Path is required and must be relative to the doc fields object.","non-empty field path",e);let i=t.split(".");return i.some(r=>r.length===0)?h(e,"Path must use dotted field segments without empty segments.","dotted field path",e):i[0]==="fields"?h(e,'Path must be relative to the fields object; remove the leading "fields." prefix.',"field path without fields prefix",e):i.some(r=>/[[\]]/.test(r))?h(e,'Use dotted zero-based array indices, e.g. "content.modules.0.title".',"dotted array index path",e):null}function h(e,t,i,r){return{path:e,message:t,expected:i,received:r}}var w=/^(0|[1-9]\d*)$/;function K(e,t){let i=JSON.parse(JSON.stringify(e??{}));for(let r=0;r<t.length;r++){let o=D(i,t[r],r);if(o)return{ok:!1,error:o}}return{ok:!0,fields:i}}function D(e,t,i){if(t.op!=="set"&&t.op!=="insert_item"&&t.op!=="remove_item")return y(i,t,typeof t.path=="string"?t.path:String(t.path),`Unknown operation "${t.op}".`,"set | insert_item | remove_item",t.op);if(typeof t.path!="string")return y(i,t,String(t.path),"Operation `path` must be a string.","string",b(t.path));let r=R(t.path);if(r)return{opIndex:i,op:t.op,...r};let o=t.path.trim().split("."),n=o[o.length-1],a=t.path.trim(),d=w.test(n),f=q(e,o,t.op!=="remove_item");if(!f.ok)return{opIndex:i,op:t.op,...f.error};let l=f.container;if(t.op==="set"){if(t.value===void 0)return y(i,t,a,'A "set" operation requires a `value`.',"value","undefined");if(Array.isArray(l)){if(!d)return y(i,t,a,"Use a zero-based array index to set an array item.","array index",n);let m=Number(n);return m>l.length?y(i,t,a,"Array index is out of range; set an existing index or append at the array length.",`0..${l.length}`,m):(l[m]=t.value,null)}return l&&typeof l=="object"?d?y(i,t,a,"Array index used on a non-array field.","object key",n):(l[n]=t.value,null):y(i,t,a,"Cannot set a value here; the parent is not an object or array.","object or array",b(l))}let u=J(l,n,d);if(t.op==="insert_item"){if(t.value===void 0)return y(i,t,a,'An "insert_item" operation requires a `value`.',"value","undefined");if(u==null){u=[];let p=U(l,n,d,u,i,t);if(p)return p}if(!Array.isArray(u))return y(i,t,a,'The target of an "insert_item" must be an array field.',"array",b(u));let m=t.index===void 0?u.length:t.index;return m<0||m>u.length?y(i,t,a,"Insert index is out of range.",`0..${u.length}`,m):(u.splice(m,0,t.value),null)}return Array.isArray(u)?t.index===void 0?y(i,t,a,'A "remove_item" operation requires an `index`.',"index","undefined"):t.index<0||t.index>=u.length?y(i,t,a,"Remove index is out of range.",`0..${Math.max(u.length-1,0)}`,t.index):(u.splice(t.index,1),null):y(i,t,a,'The target of a "remove_item" must be an array field.',"array",b(u))}function q(e,t,i){let r=e;for(let o=0;o<t.length-1;o++){let n=t[o],a=t.slice(0,o+1).join("."),d=w.test(n);if(Array.isArray(r)){if(!d)return j(a,"Expected a zero-based array index after an array field.","array index",n);let f=Number(n);if(f>=r.length)return j(a,"Array index is out of range for the current draft.",`0..${Math.max(r.length-1,0)}`,f);r=r[f];continue}if(r===null||typeof r!="object")return j(a,"Path walks through a value that is not an object or array.","object or array",b(r));if(d)return j(a,"Array index used on a non-array field.","object key",n);if(r[n]===void 0||r[n]===null){if(!i)return j(a,"Path segment does not exist in the current draft.","existing field",n);r[n]=w.test(t[o+1])?[]:{}}r=r[n]}return{ok:!0,container:r}}function J(e,t,i){if(Array.isArray(e))return i?e[Number(t)]:void 0;if(e&&typeof e=="object")return e[t]}function U(e,t,i,r,o,n){return Array.isArray(e)?i?(e[Number(t)]=r,null):y(o,n,n.path.trim(),"Use a zero-based array index for an array field.","array index",t):e&&typeof e=="object"?i?y(o,n,n.path.trim(),"Array index used on a non-array field.","object key",t):(e[t]=r,null):y(o,n,n.path.trim(),"Cannot write here; the parent is not an object or array.","object or array",b(e))}function j(e,t,i,r){return{ok:!1,error:{path:e,message:t,expected:i,received:r}}}function y(e,t,i,r,o,n){return{opIndex:e,op:t.op,path:i,message:r,expected:o,received:n}}function b(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}export{Y as CMS_TOOL_NAMES,T as READ_ONLY_CMS_TOOL_NAMES,K as applyDocEdits,M as createCmsTools,Z as createReadOnlyCmsTools,k as validateFields,H as validateValueAtPath};
1
+ import{a as s,g as F}from"./chunk-344GZOGG.js";import{c as $}from"./chunk-JDW4UORS.js";import"./chunk-PVAE643M.js";function k(e,t){if(e==null)return[];if(typeof e!="object"||Array.isArray(e))return[{path:"",message:"Expected object for fields data",expected:"object",received:E(e)}];let i=[];for(let r of t.fields){if(!r.id||!(r.id in e))continue;let o=e[r.id];i.push(...g(o,r,r.id))}return i}function g(e,t,i){if(e===void 0)return[];switch(t.type){case"string":case"select":return typeof e!="string"?[c(i,"string",e)]:[];case"number":return typeof e!="number"?[c(i,"number",e)]:isNaN(e)?[c(i,"number",e)]:[];case"boolean":return typeof e!="boolean"?[c(i,"boolean",e)]:[];case"date":case"datetime":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[],o=e.seconds,n=e.nanoseconds;return o===void 0?r.push({path:`${i}.seconds`,message:"Required",expected:"number",received:"undefined"}):typeof o!="number"&&r.push(c(`${i}.seconds`,"number",o)),n===void 0?r.push({path:`${i}.nanoseconds`,message:"Required",expected:"number",received:"undefined"}):typeof n!="number"&&r.push(c(`${i}.nanoseconds`,"number",n)),r}case"multiselect":return Array.isArray(e)?e.flatMap((r,o)=>typeof r!="string"?[c(`${i}.${o}`,"string",r)]:[]):[c(i,"array",e)];case"image":case"file":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[];return e.src===void 0?r.push({path:`${i}.src`,message:"Required",expected:"string",received:"undefined"}):typeof e.src!="string"&&r.push(c(`${i}.src`,"string",e.src)),e.alt!==void 0&&typeof e.alt!="string"&&r.push(c(`${i}.alt`,"string",e.alt)),r}case"object":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=t,o=[];for(let n of r.fields)!n.id||!(n.id in e)||o.push(...g(e[n.id],n,`${i}.${n.id}`));return o}case"array":{if(!Array.isArray(e))return[c(i,"array",e)];let o=t.of;return e.flatMap((n,a)=>g(n,o,`${i}.${a}`))}case"oneof":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=t,o=e._type,n=new Map,a=[];for(let l of r.types){if(typeof l=="string"){a.push(l);continue}n.set(l.name,l),a.push(l.name)}if(!a.includes(o)){let l=a.map(u=>`'${u}'`).join(" | ");return[{path:`${i}._type`,message:`Invalid discriminator value. Expected ${l}`,expected:"valid discriminator value",received:o}]}let d=n.get(o);if(!d)return[];let f=[];for(let l of d.fields)!l.id||!(l.id in e)||f.push(...g(e[l.id],l,`${i}.${l.id}`));return f}case"richtext":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[];return e.blocks===void 0?r.push({path:`${i}.blocks`,message:"Required",expected:"array",received:"undefined"}):Array.isArray(e.blocks)?e.blocks.forEach((o,n)=>{if(typeof o!="object"||o===null){r.push(c(`${i}.blocks.${n}`,"object",o));return}o.type===void 0?r.push({path:`${i}.blocks.${n}.type`,message:"Required",expected:"string",received:"undefined"}):typeof o.type!="string"&&r.push(c(`${i}.blocks.${n}.type`,"string",o.type))}):r.push(c(`${i}.blocks`,"array",e.blocks)),r}case"reference":{if(typeof e!="object"||Array.isArray(e))return[c(i,"object",e)];let r=[],o=["id","collection","slug"];for(let n of o)e[n]===void 0?r.push({path:`${i}.${n}`,message:"Required",expected:"string",received:"undefined"}):typeof e[n]!="string"&&r.push(c(`${i}.${n}`,"string",e[n]));return r}case"references":return Array.isArray(e)?e.flatMap((r,o)=>{if(typeof r!="object"||r===null||Array.isArray(r))return[c(`${i}.${o}`,"object",r)];let n=[],a=["id","collection","slug"];for(let d of a)r[d]===void 0?n.push({path:`${i}.${o}.${d}`,message:"Required",expected:"string",received:"undefined"}):typeof r[d]!="string"&&n.push(c(`${i}.${o}.${d}`,"string",r[d]));return n}):[c(i,"array",e)];default:return console.warn(`Unknown field type: ${t.type}`),[]}}function E(e){return e===null?"null":Array.isArray(e)?"array":typeof e=="number"&&Number.isNaN(e)?"nan":typeof e}function c(e,t,i){let r=E(i);return{path:e,message:`Expected ${t}, received ${r}`,expected:t,received:r}}var Y=["collections_list","docs_list","doc_get","doc_getVersion","doc_set","doc_create","doc_updateField","doc_edit","doc_duplicate","doc_listVersions","doc_translateField","schema_get"],T=["collections_list","docs_list","doc_get","doc_getVersion","doc_listVersions","schema_get"];function Z(e){let t=M(e),i={};for(let r of T)t[r]&&(i[r]=t[r]);return i}function M(e){return{collections_list:{description:"List all CMS collections defined in the project. Returns each collection id along with optional name/description metadata.",inputSchema:s.object({}),execute:async()=>{let t=await e.loadAllCollections();return{collections:Object.entries(t).map(([i,r])=>({id:i,name:r.name,description:r.description}))}}},docs_list:{description:"List documents inside a CMS collection. Returns up to `limit` docs (default 25, max 100). Use this to explore content before reading individual docs.",inputSchema:s.object({collectionId:s.string().describe('Collection id, e.g. "Pages" or "BlogPosts".'),mode:s.enum(["draft","published"]).default("draft").describe("Whether to read draft or published versions."),limit:s.number().int().min(1).max(100).default(25)}),execute:async({collectionId:t,mode:i="draft",limit:r=25})=>{let o=v(r,1,100,25);return{docs:(await e.cmsClient.listDocs(t,{mode:i,limit:o})).docs.map(a=>({id:a.id,slug:a.slug,sys:A(a.sys)}))}}},doc_get:{description:"Read a single CMS document. Returns the doc fields plus system metadata. Use this when you need the full content of a doc.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),mode:s.enum(["draft","published"]).default("draft")}),execute:async({docId:t,mode:i="draft"})=>{let{collection:r,slug:o}=S(t),n=await e.cmsClient.getRawDoc(r,o,{mode:i});return n?{found:!0,doc:{id:n.id,collection:n.collection,slug:n.slug,sys:A(n.sys),fields:N(n.fields)}}:{found:!1}}},doc_getVersion:{description:'Read a specific version of a CMS document. Use versionId "draft" or "published" for the current draft/published state, or a numeric timestamp for a historical version (from `doc_listVersions`).',inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),versionId:s.string().describe('Version identifier: "draft", "published", or a numeric timestamp.')}),execute:async({docId:t,versionId:i})=>{let{collection:r,slug:o}=S(t),n;i==="draft"?n=`Projects/${e.cmsClient.projectId}/Collections/${r}/Drafts/${o}`:i==="published"?n=`Projects/${e.cmsClient.projectId}/Collections/${r}/Published/${o}`:n=`Projects/${e.cmsClient.projectId}/Collections/${r}/Drafts/${o}/Versions/${i}`;let a=await e.cmsClient.db.doc(n).get();if(!a.exists)return{found:!1};let d=a.data();return{found:!0,doc:{id:d.id,collection:d.collection,slug:d.slug,sys:A(d.sys),fields:N(d.fields)}}}},doc_set:{description:"Replace the entire draft fields payload of a CMS document. Pass the full JSON object that should become the new draft contents \u2014 any fields omitted will be removed. The payload is validated against the collection schema and the call is rejected on validation errors. Prefer `doc_updateField` for targeted edits. Only writes the draft version; users must publish separately. Format: pass plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the payload into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),fields:s.record(s.string(),s.any()).describe("New fields object. Replaces the existing draft fields entirely.")})},doc_create:{description:"Create a new draft CMS document with the given slug. Fails if the doc already exists. Pass optional initial fields (validated against the collection schema). Format: pass plain JSON for `fields`. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the payload into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "BlogPosts/my-new-post").'),fields:s.record(s.string(),s.any()).optional().describe("Optional initial fields for the new doc.")})},doc_updateField:{description:'Update a single field on a draft CMS document by JSON path. Paths are relative to the doc fields object; do not prefix them with "fields.". Use dotted paths (e.g. "hero.title") and zero-based array indices. For example, update the first module title with path "content.modules.0.title". To insert or remove array items, prefer `doc_edit` (it supports insert/remove operations); alternatively set the whole array path here (e.g. "content.modules") to the updated array. The value is validated against the field schema and the call is rejected if the shape is wrong (e.g. passing a string to a richtext field). Only updates the draft version; users must publish separately. Format: pass `value` as plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals the value into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape and `blocks` MUST be a plain JSON array of `{type, data}` objects (never wrapped in `_array`).',inputSchema:s.object({docId:s.string(),path:s.string().describe('Dotted JSON path within the fields object, e.g. "content.modules.0.title".'),value:s.any().describe("JSON value to set at the path.")})},doc_edit:{description:'Apply multiple edits to a draft CMS document in a single call. Use this when a change spans more than one field or needs to add or remove array items (e.g. append a new module AND update a title). Pass an ordered `operations` list; each operation has an `op`:\n- "set": set the value at `path` (e.g. "hero.title" or "content.modules.0.title"). Provide `value`.\n- "insert_item": insert `value` into the array at `path` (e.g. "content.modules"). Optionally pass a zero-based `index` to insert before; omit `index` to append.\n- "remove_item": remove the array item at zero-based `index` from the array at `path`.\nOperations apply in order against the current draft. Array indices in each operation refer to the array state AFTER earlier operations have been applied. The whole result is validated against the collection schema and the call is rejected as a group on any error \u2014 nothing is written unless every operation succeeds. Paths are relative to the doc fields object; do not prefix them with "fields.". Use dotted paths and zero-based array indices. Only writes the draft version; users must publish separately. Format: pass `value` as plain JSON. Arrays must be plain JSON arrays \u2014 do NOT use the `_array` object notation. The tool marshals values into Firestore storage shape on its own. Rich text fields use the `{version, time, blocks}` shape with `blocks` as a plain JSON array of `{type, data}` objects.',inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),operations:s.array(s.object({op:s.enum(["set","insert_item","remove_item"]).describe('Operation: "set" a field value, "insert_item" into an array, or "remove_item" from an array.'),path:s.string().describe('Dotted path within the fields object. For "set" it targets the field to write (e.g. "hero.title"); for "insert_item"/"remove_item" it targets the array (e.g. "content.modules").'),value:s.any().optional().describe('JSON value. Required for "set" (the new field value) and "insert_item" (the new array item). Ignored for "remove_item".'),index:s.number().int().min(0).optional().describe('Zero-based array index. For "insert_item" it is the position to insert before (omit to append); for "remove_item" it is the item to delete (required).')})).min(1).describe("Ordered list of edit operations to apply to the draft.")})},doc_duplicate:{description:"Duplicate an existing CMS document to a new slug. Copies all draft fields to the target doc id. Fails if the target already exists.",inputSchema:s.object({fromDocId:s.string().describe('Source doc id to copy from (e.g. "Pages/home").'),toDocId:s.string().describe('Target doc id for the copy (e.g. "Pages/home-copy").')})},doc_listVersions:{description:"List version history for a CMS document. Returns versions ordered by most recent first. Use the versionId from the results with `doc_getVersion` to read a specific version.",inputSchema:s.object({docId:s.string().describe('Full doc id in the form "Collection/slug" (e.g. "Pages/home").'),limit:s.number().int().min(1).max(50).default(10)}),execute:async({docId:t,limit:i=10})=>{let{collection:r,slug:o}=S(t),n=v(i,1,50,10),a=`Projects/${e.cmsClient.projectId}/Collections/${r}/Drafts/${o}/Versions`;return{versions:(await e.cmsClient.db.collection(a).orderBy("sys.modifiedAt","desc").limit(n).get()).docs.map(f=>{let l=f.data();return{versionId:f.id,sys:A(l.sys),tags:l.tags||[],publishMessage:l.publishMessage}})}}},doc_translateField:{description:"Translate a text value into one or more target locales using AI. Returns the translated strings keyed by locale. Use this to help with localization workflows.",inputSchema:s.object({sourceText:s.string().min(1).describe("The source text to translate."),targetLocales:s.array(s.string()).min(1).describe('Array of locale codes to translate into (e.g. ["es", "fr", "de"]).'),description:s.string().optional().describe("Optional context about the text to improve translation quality.")})},schema_get:{description:"Get the field schema for a CMS collection. Returns the full field definitions including types, labels, and validation rules. Use this to understand what fields a collection supports before creating or editing docs.",inputSchema:s.object({collectionId:s.string().describe('Collection id, e.g. "Pages" or "BlogPosts".')}),execute:async({collectionId:t})=>{let i=await e.loadCollection(t);return i?{found:!0,collectionId:t,fields:_(i.fields||[])}:{found:!1,collectionId:t}}}}}function S(e){let t=e.indexOf("/");if(t<=0||t===e.length-1)throw new Error(`invalid docId: "${e}" (expected "Collection/slug")`);return{collection:e.slice(0,t),slug:$(e.slice(t+1))}}function v(e,t,i,r){let o=Number.isFinite(e)?Math.trunc(e):r;return Math.min(Math.max(o,t),i)}function A(e){return F(e??{})}function N(e){return F(e??{})}function _(e){return e.map(t=>{let i={id:t.id,type:t.type};return t.label&&(i.label=t.label),t.description&&(i.description=t.description),t.required&&(i.required=!0),t.translate&&(i.translate=!0),t.options&&(i.options=t.options),t.type==="object"&&t.fields&&(i.fields=_(t.fields)),t.type==="array"&&t.of&&(i.of=_([t.of])[0]),t.type==="oneof"&&t.types&&(i.types=t.types.map(r=>typeof r=="string"?r:{id:r.id,fields:_(r.fields||[])})),i})}function H(e,t,i){let r=V(e,t);if(r.error)return[r.error];let o=r.field;return o?g(i,o,t):[]}function V(e,t){let i=R(t);if(i)return{field:null,error:i};let r=t.trim().split(".");if(r.length===0)return{field:null};let o=e.fields||[],n=null;for(let a=0;a<r.length;a++){let d=r[a],f=r.slice(0,a+1).join("."),l=/^\d+$/.test(d),u=/^(0|[1-9]\d*)$/.test(d);if(l&&!u)return{field:null,error:h(f,"Array indices must be zero-based numeric path segments without leading zeros.","array index",d)};if(u){if(!n||n.type!=="array")return{field:null,error:h(f,"Array index path segments can only be used after an array field.","array field",n?.type||"root")};let x=n.of;n=x,o=x.type==="object"?x.fields:[];continue}if(n?.type==="array")return{field:null,error:h(f,"Array fields must be followed by a zero-based numeric index before nested fields.","array index",d)};let m=o.find(p=>p.id===d);if(!m&&n?.type==="oneof"){let p=n,x=Array.isArray(p.types)?p.types:[];for(let C of x){if(typeof C=="string")continue;let O=(C.fields||[]).find(P=>P.id===d);if(O){m=O;break}}}if(!m)return{field:null};n=m,m.type==="object"?o=m.fields:m.type==="array"?o=[]:o=[]}return{field:n}}function R(e){let t=e.trim();if(!t)return h(e,"Path is required and must be relative to the doc fields object.","non-empty field path",e);let i=t.split(".");return i.some(r=>r.length===0)?h(e,"Path must use dotted field segments without empty segments.","dotted field path",e):i[0]==="fields"?h(e,'Path must be relative to the fields object; remove the leading "fields." prefix.',"field path without fields prefix",e):i.some(r=>/[[\]]/.test(r))?h(e,'Use dotted zero-based array indices, e.g. "content.modules.0.title".',"dotted array index path",e):null}function h(e,t,i,r){return{path:e,message:t,expected:i,received:r}}var w=/^(0|[1-9]\d*)$/;function K(e,t){let i=JSON.parse(JSON.stringify(e??{}));for(let r=0;r<t.length;r++){let o=D(i,t[r],r);if(o)return{ok:!1,error:o}}return{ok:!0,fields:i}}function D(e,t,i){if(t.op!=="set"&&t.op!=="insert_item"&&t.op!=="remove_item")return y(i,t,typeof t.path=="string"?t.path:String(t.path),`Unknown operation "${t.op}".`,"set | insert_item | remove_item",t.op);if(typeof t.path!="string")return y(i,t,String(t.path),"Operation `path` must be a string.","string",b(t.path));let r=R(t.path);if(r)return{opIndex:i,op:t.op,...r};let o=t.path.trim().split("."),n=o[o.length-1],a=t.path.trim(),d=w.test(n),f=q(e,o,t.op!=="remove_item");if(!f.ok)return{opIndex:i,op:t.op,...f.error};let l=f.container;if(t.op==="set"){if(t.value===void 0)return y(i,t,a,'A "set" operation requires a `value`.',"value","undefined");if(Array.isArray(l)){if(!d)return y(i,t,a,"Use a zero-based array index to set an array item.","array index",n);let m=Number(n);return m>l.length?y(i,t,a,"Array index is out of range; set an existing index or append at the array length.",`0..${l.length}`,m):(l[m]=t.value,null)}return l&&typeof l=="object"?d?y(i,t,a,"Array index used on a non-array field.","object key",n):(l[n]=t.value,null):y(i,t,a,"Cannot set a value here; the parent is not an object or array.","object or array",b(l))}let u=J(l,n,d);if(t.op==="insert_item"){if(t.value===void 0)return y(i,t,a,'An "insert_item" operation requires a `value`.',"value","undefined");if(u==null){u=[];let p=U(l,n,d,u,i,t);if(p)return p}if(!Array.isArray(u))return y(i,t,a,'The target of an "insert_item" must be an array field.',"array",b(u));let m=t.index===void 0?u.length:t.index;return m<0||m>u.length?y(i,t,a,"Insert index is out of range.",`0..${u.length}`,m):(u.splice(m,0,t.value),null)}return Array.isArray(u)?t.index===void 0?y(i,t,a,'A "remove_item" operation requires an `index`.',"index","undefined"):t.index<0||t.index>=u.length?y(i,t,a,"Remove index is out of range.",`0..${Math.max(u.length-1,0)}`,t.index):(u.splice(t.index,1),null):y(i,t,a,'The target of a "remove_item" must be an array field.',"array",b(u))}function q(e,t,i){let r=e;for(let o=0;o<t.length-1;o++){let n=t[o],a=t.slice(0,o+1).join("."),d=w.test(n);if(Array.isArray(r)){if(!d)return j(a,"Expected a zero-based array index after an array field.","array index",n);let f=Number(n);if(f>=r.length)return j(a,"Array index is out of range for the current draft.",`0..${Math.max(r.length-1,0)}`,f);r=r[f];continue}if(r===null||typeof r!="object")return j(a,"Path walks through a value that is not an object or array.","object or array",b(r));if(d)return j(a,"Array index used on a non-array field.","object key",n);if(r[n]===void 0||r[n]===null){if(!i)return j(a,"Path segment does not exist in the current draft.","existing field",n);r[n]=w.test(t[o+1])?[]:{}}r=r[n]}return{ok:!0,container:r}}function J(e,t,i){if(Array.isArray(e))return i?e[Number(t)]:void 0;if(e&&typeof e=="object")return e[t]}function U(e,t,i,r,o,n){return Array.isArray(e)?i?(e[Number(t)]=r,null):y(o,n,n.path.trim(),"Use a zero-based array index for an array field.","array index",t):e&&typeof e=="object"?i?y(o,n,n.path.trim(),"Array index used on a non-array field.","object key",t):(e[t]=r,null):y(o,n,n.path.trim(),"Cannot write here; the parent is not an object or array.","object or array",b(e))}function j(e,t,i,r){return{ok:!1,error:{path:e,message:t,expected:i,received:r}}}function y(e,t,i,r,o,n){return{opIndex:e,op:t.op,path:i,message:r,expected:o,received:n}}function b(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}export{Y as CMS_TOOL_NAMES,T as READ_ONLY_CMS_TOOL_NAMES,K as applyDocEdits,M as createCmsTools,Z as createReadOnlyCmsTools,k as validateFields,H as validateValueAtPath};
@@ -1,8 +1,8 @@
1
- import{a as _t,b as ht,c as ut,d as tt}from"./chunk-PHBMVORG.js";import{a as lt,b as mt,d as Z}from"./chunk-JZFTZ4X4.js";import{b as dt,d as ct}from"./chunk-HKINZLMW.js";import{f as pt}from"./chunk-SKEP5WYH.js";import{f as K}from"./chunk-5MV6XVGA.js";import{d as at,f as M}from"./chunk-AL3TN2KI.js";import{$a as X,Bc as rt,Ga as O,Ha as t,Pc as st,Uc as B,V,W as E,_a as q,a as p,ab as Y,c as k,ca as J,e as N,ea as S,ec as G,g as ot,h as T,j as At,jc as Q,kc as it,mb as nt,ra as $,vc as j}from"./chunk-NZHF733K.js";import{d as et}from"./chunk-KUCVLANF.js";At();function ft(o){let{size:e=14}=o,a=e*3.57,i=e*2;return t("div",{className:"BouncingLoader",style:{"--dot-size":`${e}px`,width:`${a}px`,height:`${i}px`}})}var W=[{id:"read",label:"Read only",description:"Inspect CMS content without planning or applying writes."},{id:"approve",label:"Ask before writing",description:"Read freely, then pause for approval before draft edits."},{id:"auto",label:"Auto-apply draft edits",description:"Apply draft-only writes without approval in this chat."}],It="root-cms.ai.executionMode",vt="root-cms.ai.selectedModel";function bt(o){return W.some(e=>e.id===o)}function Rt(){if(typeof window>"u")return"approve";try{let o=window.localStorage.getItem(It);if(bt(o))return o}catch(o){console.error("failed to read AI execution mode preference",o)}return"approve"}function yt(o){if(typeof window>"u")return null;try{let e=window.localStorage.getItem(vt);if(e&&o.some(a=>a.id===e))return e}catch(e){console.error("failed to read AI model preference",e)}return null}function wt(o){if(!(typeof window>"u"))try{window.localStorage.setItem(vt,o)}catch(e){console.error("failed to save AI model preference",e)}}function kt(o){if(!(typeof window>"u"))try{window.localStorage.setItem(It,o)}catch(e){console.error("failed to save AI execution mode preference",e)}}var U="";function Ie(o){let[e,a]=p(null),[i,m]=p("");k(()=>{let r=!0;return fetch("/cms/api/ai.config",{credentials:"include"}).then(async l=>{let g=await l.json();r&&a(g)}).catch(l=>{r&&m(String(l))}),()=>{r=!1}},[]);let h=!!e?.enabled&&(e.models?.length||0)>0;return t("div",{className:M("RootAIChat",`RootAIChat--${o.variant}`),children:!e&&!i?t("div",{className:"RootAIChat__loading",children:t(V,{size:"md",color:"gray"})}):h?t(Mt,{variant:o.variant,config:e,initialChatId:o.variant==="panel"?void 0:o.initialChatId,docContext:o.docContext,onClose:o.onClose}):t(Nt,{error:i,onClose:o.onClose})})}function Nt(o){return t("div",{className:"RootAIChat__notEnabled",children:[o.onClose&&t(E,{className:"RootAIChat__notEnabled__close",onClick:o.onClose,title:"Close",children:t(B,{size:16})}),t("div",{className:"RootAIChat__notEnabled__icon",children:t(j,{size:36})}),t("div",{className:"RootAIChat__notEnabled__title",children:"Root AI is not configured for this project."}),t("div",{className:"RootAIChat__notEnabled__body",children:["Add an ",t("code",{children:"ai.models"})," entry to ",t("code",{children:"cmsPlugin()"})," in"," ",t("code",{children:"root.config.ts"}),"."]}),o.error&&t("pre",{className:"RootAIChat__notEnabled__error",children:o.error})]})}function Mt(o){let e=o.variant==="panel",{route:a}=at(),i=o.config.models||[],m=()=>yt(i)||o.config.defaultModel||i[0]?.id||"",[h,r]=p(m),[l,g]=p(Rt),[u,I]=p(o.initialChatId||U),[P,y]=p(o.initialChatId||U),[D,s]=p([]),[f,x]=p([]),[v,w]=p(0),z=async()=>{if(!e)try{let R=await(await fetch("/cms/api/ai.chats.list",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({})})).json();R.success&&x(R.chats||[])}catch(d){console.error("failed to load chat list",d)}};k(()=>{z(),!e&&o.initialChatId&&n(o.initialChatId)},[]),k(()=>{kt(l)},[l]);let n=async d=>{try{let b=await(await fetch("/cms/api/ai.chats.get",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({id:d})})).json();if(!b.success)return;I(d),y(d),s(b.chat.messages||[]),b.chat.modelId&&i.find(F=>F.id===b.chat.modelId)&&r(b.chat.modelId),w(L=>L+1)}catch(R){console.error("failed to load chat",R)}},_=()=>{r(m()),I(U),y(U),s([]),w(d=>d+1),e||a("/cms/ai")},c=async d=>{if(d!==P)try{let b=await(await fetch("/cms/api/ai.chats.get",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({id:d})})).json();if(!b.success)return;I(d),y(d),s(b.chat.messages||[]),b.chat.modelId&&i.find(F=>F.id===b.chat.modelId)&&r(b.chat.modelId),w(L=>L+1),e||a(`/cms/ai/chat/${d}`)}catch(R){console.error("failed to load chat",R)}},C=async d=>{try{await fetch("/cms/api/ai.chats.delete",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({id:d})}),P===d&&_(),z()}catch(R){console.error("failed to delete chat",R)}},A=i.find(d=>d.id===h)||i[0],H=d=>{r(d),wt(d)};return t("div",{className:"RootAIChat__layout",children:[!e&&t(Tt,{chats:f,activeChatId:P,onSelect:c,onNew:_,onDelete:C}),t("div",{className:"RootAIChat__main",children:[e&&t(Pt,{onNewChat:_,onClose:o.onClose}),t(zt,{initialChatId:u,model:A,initialMessages:D,executionMode:l,models:i,selectedModel:A,docContext:o.docContext,onSelectModel:H,onSelectExecutionMode:g,onChatPersisted:d=>{y(d),z(),e||window.history.replaceState(null,"",`/cms/ai/chat/${d}`)}},v)]})]})}function Pt(o){return t("div",{className:"RootAIChat__panelHeader",children:[t("div",{className:"RootAIChat__panelHeader__title",children:[t(j,{size:14}),t("span",{children:"Root AI"})]}),t("div",{className:"RootAIChat__panelHeader__actions",children:[t(O,{label:"New chat",children:t(E,{size:"xs",onClick:o.onNewChat,children:t(G,{size:14})})}),o.onClose&&t(O,{label:"Close (\u2318 + i)",children:t(E,{size:"xs",onClick:o.onClose,children:t(B,{size:14})})})]})]})}function Tt(o){return t("aside",{className:"RootAIChat__sidebar",children:[t("button",{type:"button",className:"RootAIChat__sidebar__newButton",onClick:o.onNew,children:[t(G,{size:18}),t("span",{children:"New chat"})]}),t("div",{className:"RootAIChat__sidebar__list",children:[o.chats.length===0&&t("div",{className:"RootAIChat__sidebar__empty",children:"No chats yet."}),o.chats.map(e=>t("div",{className:M("RootAIChat__sidebar__item",e.id===o.activeChatId&&"RootAIChat__sidebar__item--active"),onClick:()=>o.onSelect(e.id),children:[t("div",{className:"RootAIChat__sidebar__item__title",title:e.title||"Untitled chat",children:e.title||"Untitled chat"}),t("button",{type:"button",className:"RootAIChat__sidebar__item__delete",title:"Delete chat",onClick:a=>{a.stopPropagation(),window.confirm("Delete this chat?")&&o.onDelete(e.id)},children:t(st,{size:14})})]},e.id))]})]})}function Et(o){let e=W.find(a=>a.id===o.executionMode)||W[0];return t("div",{className:"RootAIChat__options",children:[t($,{control:t(S,{type:"button",className:"RootAIChat__modePicker",variant:"subtle",color:"dark",size:"xs",compact:!0,leftIcon:t(it,{size:16}),children:e.label}),children:W.map(a=>t($.Item,{onClick:()=>o.onSelectExecutionMode(a.id),children:t("div",{className:"RootAIChat__modePicker__option",children:[t("div",{className:"RootAIChat__modePicker__option__label",children:a.label}),t("div",{className:"RootAIChat__modePicker__option__description",children:a.description})]})},a.id))}),t($,{control:t(S,{type:"button",className:"RootAIChat__modelPicker",variant:"subtle",color:"dark",size:"xs",compact:!0,leftIcon:t(j,{size:16}),children:o.selectedModel?.label||"Select model"}),children:o.models.map(a=>t($.Item,{onClick:()=>o.onSelectModel(a.id),children:t("div",{className:"RootAIChat__modelPicker__option",children:[t("div",{className:"RootAIChat__modelPicker__option__label",children:a.label}),a.description&&t("div",{className:"RootAIChat__modelPicker__option__description",children:a.description})]})},a.id))})]})}function zt(o){let[e]=p(()=>o.initialChatId||Gt()),a=N(o.model?.id);a.current=o.model?.id;let i=N(o.executionMode);i.current=o.executionMode;let m=N(o.docContext);m.current=o.docContext;let[h,r]=p({}),l=N({});k(()=>()=>{for(let n of Object.values(l.current))n("reject");l.current={}},[]);let g=T((n,_,c,C)=>new Promise(A=>{l.current[n]=A,r(H=>({...H,[n]:{toolCallId:n,toolName:_,input:c,preview:C,status:"pending"}}))}),[]),u=T(n=>{r(_=>{let c=_[n];return c?{..._,[n]:{...c,status:"executing"}}:_}),l.current[n]?.("approve"),delete l.current[n]},[]),I=T(n=>{r(_=>{let c={..._};return delete c[n],c}),l.current[n]?.("reject"),delete l.current[n]},[]),P=T(async n=>{if(!ht(n.toolName))return await tt(n.toolName,n.input);let _=i.current;if(_==="read")return{success:!1,error:"WRITE_BLOCKED_BY_MODE",message:"The current execution mode is read only. Do not call write tools."};let c;try{c=await ut(n.toolName,n.input)}catch(C){return{success:!1,error:"PREVIEW_FAILED",message:C?.message||String(C)}}if(c.error)return{success:!1,error:c.error,message:c.summary,errors:c.errors,hint:c.hint};if(_==="approve"&&await g(n.toolCallId,n.toolName,n.input,c)==="reject")return{success:!1,error:"USER_REJECTED",message:"The user rejected this draft change. Do not retry unless they ask for a revised version."};try{return await tt(n.toolName,n.input)}finally{r(C=>{if(!C[n.toolCallId])return C;let A={...C};return delete A[n.toolCallId],A})}},[g]),y=ot(()=>new dt({api:"/cms/api/ai.chat",credentials:"include",prepareSendMessagesRequest:({messages:n})=>({body:{message:n.at(-1),chatId:e,modelId:a.current,executionMode:i.current,docId:m.current?.docId}})}),[e]),{messages:D,sendMessage:s,status:f,error:x,stop:v,addToolOutput:w}=_t({id:e,messages:o.initialMessages,transport:y,sendAutomaticallyWhen:ct,onToolCall:async({toolCall:n})=>{let _=await P(n);w({tool:n.toolName,toolCallId:n.toolCallId,output:_})},onFinish:()=>{o.onChatPersisted(e)}}),z=f==="streaming"||f==="submitted";return t(et,{children:[t(St,{messages:D,isStreaming:z,emptyMessage:o.model?void 0:"Select a model to start.",toolApprovals:{approvals:h,onApprove:u,onReject:I}}),x&&t("div",{className:"RootAIChat__error",children:[t("strong",{children:"Error:"})," ",x.message]}),t(Vt,{disabled:!o.model,canAttach:o.model?.capabilities.attachments??!1,isStreaming:z,onStop:v,controls:t(Et,{models:o.models,selectedModel:o.selectedModel,onSelectModel:o.onSelectModel,executionMode:o.executionMode,onSelectExecutionMode:o.onSelectExecutionMode}),onSend:(n,_)=>{if(!n&&_.length===0)return;let c=Jt(_),C=[n,c.text].filter(Boolean).join(`
1
+ import{a as pt,b as ht,c as ut,d as tt}from"./chunk-HO3W4RVG.js";import{a as dt}from"./chunk-3T4ZWQR4.js";import{a as mt,c as Z}from"./chunk-E76ECIOX.js";import{b as ct,d as _t}from"./chunk-344GZOGG.js";import{f as K}from"./chunk-5MV6XVGA.js";import{d as at,f as M}from"./chunk-YLSRRNSE.js";import{$a as Y,Dc as st,Fa as O,Ga as t,Rc as lt,V,W as E,Yc as B,Za as q,_a as X,a as p,ba as J,c as k,da as S,e as N,g as ot,gc as G,h as T,j as At,lb as it,lc as Q,mc as rt,qa as $,xc as j}from"./chunk-LROR6N3B.js";import{d as et}from"./chunk-KUCVLANF.js";import{h as nt}from"./chunk-7SK47HHZ.js";At();function ft(o){let{size:e=14}=o,a=e*3.57,i=e*2;return t("div",{className:"BouncingLoader",style:{"--dot-size":`${e}px`,width:`${a}px`,height:`${i}px`}})}var W=[{id:"read",label:"Read only",description:"Inspect CMS content without planning or applying writes."},{id:"approve",label:"Ask before writing",description:"Read freely, then pause for approval before draft edits."},{id:"auto",label:"Auto-apply draft edits",description:"Apply draft-only writes without approval in this chat."}],It="root-cms.ai.executionMode",vt="root-cms.ai.selectedModel";function bt(o){return W.some(e=>e.id===o)}function Rt(){if(typeof window>"u")return"approve";try{let o=window.localStorage.getItem(It);if(bt(o))return o}catch(o){console.error("failed to read AI execution mode preference",o)}return"approve"}function yt(o){if(typeof window>"u")return null;try{let e=window.localStorage.getItem(vt);if(e&&o.some(a=>a.id===e))return e}catch(e){console.error("failed to read AI model preference",e)}return null}function wt(o){if(!(typeof window>"u"))try{window.localStorage.setItem(vt,o)}catch(e){console.error("failed to save AI model preference",e)}}function kt(o){if(!(typeof window>"u"))try{window.localStorage.setItem(It,o)}catch(e){console.error("failed to save AI execution mode preference",e)}}var U="";function Ie(o){let[e,a]=p(null),[i,m]=p("");k(()=>{let r=!0;return fetch("/cms/api/ai.config",{credentials:"include"}).then(async l=>{let g=await l.json();r&&a(g)}).catch(l=>{r&&m(String(l))}),()=>{r=!1}},[]);let h=!!e?.enabled&&(e.models?.length||0)>0;return t("div",{className:M("RootAIChat",`RootAIChat--${o.variant}`),children:!e&&!i?t("div",{className:"RootAIChat__loading",children:t(V,{size:"md",color:"gray"})}):h?t(Mt,{variant:o.variant,config:e,initialChatId:o.variant==="panel"?void 0:o.initialChatId,docContext:o.docContext,onClose:o.onClose}):t(Nt,{error:i,onClose:o.onClose})})}function Nt(o){return t("div",{className:"RootAIChat__notEnabled",children:[o.onClose&&t(E,{className:"RootAIChat__notEnabled__close",onClick:o.onClose,title:"Close",children:t(B,{size:16})}),t("div",{className:"RootAIChat__notEnabled__icon",children:t(j,{size:36})}),t("div",{className:"RootAIChat__notEnabled__title",children:"Root AI is not configured for this project."}),t("div",{className:"RootAIChat__notEnabled__body",children:["Add an ",t("code",{children:"ai.models"})," entry to ",t("code",{children:"cmsPlugin()"})," in"," ",t("code",{children:"root.config.ts"}),"."]}),o.error&&t("pre",{className:"RootAIChat__notEnabled__error",children:o.error})]})}function Mt(o){let e=o.variant==="panel",{route:a}=at(),i=o.config.models||[],m=()=>yt(i)||o.config.defaultModel||i[0]?.id||"",[h,r]=p(m),[l,g]=p(Rt),[u,I]=p(o.initialChatId||U),[P,y]=p(o.initialChatId||U),[D,s]=p([]),[f,x]=p([]),[v,w]=p(0),z=async()=>{if(!e)try{let R=await(await fetch("/cms/api/ai.chats.list",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({})})).json();R.success&&x(R.chats||[])}catch(d){console.error("failed to load chat list",d)}};k(()=>{z(),!e&&o.initialChatId&&n(o.initialChatId)},[]),k(()=>{kt(l)},[l]);let n=async d=>{try{let b=await(await fetch("/cms/api/ai.chats.get",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({id:d})})).json();if(!b.success)return;I(d),y(d),s(b.chat.messages||[]),b.chat.modelId&&i.find(F=>F.id===b.chat.modelId)&&r(b.chat.modelId),w(L=>L+1)}catch(R){console.error("failed to load chat",R)}},_=()=>{r(m()),I(U),y(U),s([]),w(d=>d+1),e||a("/cms/ai")},c=async d=>{if(d!==P)try{let b=await(await fetch("/cms/api/ai.chats.get",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({id:d})})).json();if(!b.success)return;I(d),y(d),s(b.chat.messages||[]),b.chat.modelId&&i.find(F=>F.id===b.chat.modelId)&&r(b.chat.modelId),w(L=>L+1),e||a(`/cms/ai/chat/${d}`)}catch(R){console.error("failed to load chat",R)}},C=async d=>{try{await fetch("/cms/api/ai.chats.delete",{method:"POST",credentials:"include",headers:{"content-type":"application/json"},body:JSON.stringify({id:d})}),P===d&&_(),z()}catch(R){console.error("failed to delete chat",R)}},A=i.find(d=>d.id===h)||i[0],H=d=>{r(d),wt(d)};return t("div",{className:"RootAIChat__layout",children:[!e&&t(Tt,{chats:f,activeChatId:P,onSelect:c,onNew:_,onDelete:C}),t("div",{className:"RootAIChat__main",children:[e&&t(Pt,{onNewChat:_,onClose:o.onClose}),t(zt,{initialChatId:u,model:A,initialMessages:D,executionMode:l,models:i,selectedModel:A,docContext:o.docContext,onSelectModel:H,onSelectExecutionMode:g,onChatPersisted:d=>{y(d),z(),e||window.history.replaceState(null,"",`/cms/ai/chat/${d}`)}},v)]})]})}function Pt(o){return t("div",{className:"RootAIChat__panelHeader",children:[t("div",{className:"RootAIChat__panelHeader__title",children:[t(j,{size:14}),t("span",{children:"Root AI"})]}),t("div",{className:"RootAIChat__panelHeader__actions",children:[t(O,{label:"New chat",children:t(E,{size:"xs",onClick:o.onNewChat,children:t(G,{size:14})})}),o.onClose&&t(O,{label:"Close (\u2318 + i)",children:t(E,{size:"xs",onClick:o.onClose,children:t(B,{size:14})})})]})]})}function Tt(o){return t("aside",{className:"RootAIChat__sidebar",children:[t("button",{type:"button",className:"RootAIChat__sidebar__newButton",onClick:o.onNew,children:[t(G,{size:18}),t("span",{children:"New chat"})]}),t("div",{className:"RootAIChat__sidebar__list",children:[o.chats.length===0&&t("div",{className:"RootAIChat__sidebar__empty",children:"No chats yet."}),o.chats.map(e=>t("div",{className:M("RootAIChat__sidebar__item",e.id===o.activeChatId&&"RootAIChat__sidebar__item--active"),onClick:()=>o.onSelect(e.id),children:[t("div",{className:"RootAIChat__sidebar__item__title",title:e.title||"Untitled chat",children:e.title||"Untitled chat"}),t("button",{type:"button",className:"RootAIChat__sidebar__item__delete",title:"Delete chat",onClick:a=>{a.stopPropagation(),window.confirm("Delete this chat?")&&o.onDelete(e.id)},children:t(lt,{size:14})})]},e.id))]})]})}function Et(o){let e=W.find(a=>a.id===o.executionMode)||W[0];return t("div",{className:"RootAIChat__options",children:[t($,{control:t(S,{type:"button",className:"RootAIChat__modePicker",variant:"subtle",color:"dark",size:"xs",compact:!0,leftIcon:t(rt,{size:16}),children:e.label}),children:W.map(a=>t($.Item,{onClick:()=>o.onSelectExecutionMode(a.id),children:t("div",{className:"RootAIChat__modePicker__option",children:[t("div",{className:"RootAIChat__modePicker__option__label",children:a.label}),t("div",{className:"RootAIChat__modePicker__option__description",children:a.description})]})},a.id))}),t($,{control:t(S,{type:"button",className:"RootAIChat__modelPicker",variant:"subtle",color:"dark",size:"xs",compact:!0,leftIcon:t(j,{size:16}),children:o.selectedModel?.label||"Select model"}),children:o.models.map(a=>t($.Item,{onClick:()=>o.onSelectModel(a.id),children:t("div",{className:"RootAIChat__modelPicker__option",children:[t("div",{className:"RootAIChat__modelPicker__option__label",children:a.label}),a.description&&t("div",{className:"RootAIChat__modelPicker__option__description",children:a.description})]})},a.id))})]})}function zt(o){let[e]=p(()=>o.initialChatId||Gt()),a=N(o.model?.id);a.current=o.model?.id;let i=N(o.executionMode);i.current=o.executionMode;let m=N(o.docContext);m.current=o.docContext;let[h,r]=p({}),l=N({});k(()=>()=>{for(let n of Object.values(l.current))n("reject");l.current={}},[]);let g=T((n,_,c,C)=>new Promise(A=>{l.current[n]=A,r(H=>({...H,[n]:{toolCallId:n,toolName:_,input:c,preview:C,status:"pending"}}))}),[]),u=T(n=>{r(_=>{let c=_[n];return c?{..._,[n]:{...c,status:"executing"}}:_}),l.current[n]?.("approve"),delete l.current[n]},[]),I=T(n=>{r(_=>{let c={..._};return delete c[n],c}),l.current[n]?.("reject"),delete l.current[n]},[]),P=T(async n=>{if(!ht(n.toolName))return await tt(n.toolName,n.input);let _=i.current;if(_==="read")return{success:!1,error:"WRITE_BLOCKED_BY_MODE",message:"The current execution mode is read only. Do not call write tools."};let c;try{c=await ut(n.toolName,n.input)}catch(C){return{success:!1,error:"PREVIEW_FAILED",message:C?.message||String(C)}}if(c.error)return{success:!1,error:c.error,message:c.summary,errors:c.errors,hint:c.hint};if(_==="approve"&&await g(n.toolCallId,n.toolName,n.input,c)==="reject")return{success:!1,error:"USER_REJECTED",message:"The user rejected this draft change. Do not retry unless they ask for a revised version."};try{return await tt(n.toolName,n.input)}finally{r(C=>{if(!C[n.toolCallId])return C;let A={...C};return delete A[n.toolCallId],A})}},[g]),y=ot(()=>new ct({api:"/cms/api/ai.chat",credentials:"include",prepareSendMessagesRequest:({messages:n})=>({body:{message:n.at(-1),chatId:e,modelId:a.current,executionMode:i.current,docId:m.current?.docId}})}),[e]),{messages:D,sendMessage:s,status:f,error:x,stop:v,addToolOutput:w}=pt({id:e,messages:o.initialMessages,transport:y,sendAutomaticallyWhen:_t,onToolCall:async({toolCall:n})=>{let _=await P(n);w({tool:n.toolName,toolCallId:n.toolCallId,output:_})},onFinish:()=>{o.onChatPersisted(e)}}),z=f==="streaming"||f==="submitted";return t(et,{children:[t(St,{messages:D,isStreaming:z,emptyMessage:o.model?void 0:"Select a model to start.",toolApprovals:{approvals:h,onApprove:u,onReject:I}}),x&&t("div",{className:"RootAIChat__error",children:[t("strong",{children:"Error:"})," ",x.message]}),t(Vt,{disabled:!o.model,canAttach:o.model?.capabilities.attachments??!1,isStreaming:z,onStop:v,controls:t(Et,{models:o.models,selectedModel:o.selectedModel,onSelectModel:o.onSelectModel,executionMode:o.executionMode,onSelectExecutionMode:o.onSelectExecutionMode}),onSend:(n,_)=>{if(!n&&_.length===0)return;let c=Jt(_),C=[n,c.text].filter(Boolean).join(`
2
2
 
3
3
  `);s({text:C,files:c.files.map(A=>({type:"file",mediaType:A.mediaType,url:A.url,filename:A.filename}))})}})]})}function St(o){let e=N(null);return k(()=>{let a=e.current;a&&(a.scrollTop=a.scrollHeight)},[o.messages]),o.messages.length===0?t("div",{className:"RootAIChat__transcript RootAIChat__transcript--empty",ref:e,children:t("div",{className:"RootAIChat__welcome",children:[t("div",{className:"RootAIChat__welcome__icon",children:t(j,{size:36})}),t("div",{className:"RootAIChat__welcome__title",children:"Root AI"}),t("div",{className:"RootAIChat__welcome__body",children:o.emptyMessage||"What are we going to get done today?"})]})}):t("div",{className:"RootAIChat__transcript",ref:e,children:t("div",{className:"RootAIChat__transcript__inner",children:[o.messages.map(a=>t(jt,{message:a,toolApprovals:o.toolApprovals},a.id)),o.isStreaming&&t("div",{className:"RootAIChat__streamingIndicator",children:t(ft,{size:6})})]})})}function jt(o){let e=o.message,a=e.role==="user",i=a?"You":"Root AI",m=a?window.firebase.user?.photoURL:null,[h,r]=p(!1),l=T(()=>(e.parts||[]).filter(u=>u.type==="text"&&u.text).map(u=>u.text).join(`
4
4
 
5
- `),[e.parts]),g=T(async()=>{let u=l();if(!u)return;let I=mt.parse(u);try{await navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([I],{type:"text/html"}),"text/plain":new Blob([u],{type:"text/plain"})})]),r(!0),setTimeout(()=>r(!1),2e3)}catch{await navigator.clipboard.writeText(u),r(!0),setTimeout(()=>r(!1),2e3)}},[l]);return t("div",{className:M("RootAIChat__message",`RootAIChat__message--${e.role}`),children:[t("div",{className:"RootAIChat__message__avatar",children:m?t("img",{src:m,alt:i}):t(j,{size:20})}),t("div",{className:"RootAIChat__message__body",children:[t("div",{className:"RootAIChat__message__username",children:i}),t("div",{className:"RootAIChat__message__parts",children:(e.parts||[]).map((u,I)=>t(Dt,{part:u,toolApprovals:o.toolApprovals},I))}),t("button",{type:"button",className:M("RootAIChat__message__copy",h&&"RootAIChat__message__copy--copied"),title:h?"Copied!":"Copy message",onClick:g,children:h?t(q,{size:14}):t(nt,{size:14})})]})]})}function Dt(o){let e=o.part;return e.type==="text"?e.text?t("div",{className:"RootAIChat__textPart",children:t(Z,{code:e.text})}):null:e.type==="reasoning"?t(Lt,{text:e.text}):e.type==="file"?t($t,{part:e}):e.type==="source-url"?t("a",{className:"RootAIChat__sourcePart",href:e.url,target:"_blank",rel:"noopener noreferrer",children:e.title||e.url}):typeof e.type=="string"&&e.type.startsWith("tool-")?t(gt,{part:e,toolApprovals:o.toolApprovals}):e.type==="dynamic-tool"?t(gt,{part:e,toolApprovals:o.toolApprovals}):e.type==="step-start"?null:t("div",{className:"RootAIChat__unknownPart",children:t("pre",{children:JSON.stringify(e,null,2)})})}function Lt(o){let[e,a]=p(!1);return o.text?t("div",{className:M("RootAIChat__reasoning",e&&"RootAIChat__reasoning--open"),children:[t("button",{type:"button",className:"RootAIChat__reasoning__toggle",onClick:()=>a(!e),children:[t(X,{size:14,style:{transform:e?"rotate(0deg)":"rotate(-90deg)"}}),t("span",{children:"Thinking"})]}),e&&t("div",{className:"RootAIChat__reasoning__body",children:t(Z,{code:o.text})})]}):null}function $t(o){let e=o.part;return e.mediaType?.startsWith("image/")?t("div",{className:"RootAIChat__filePart",children:t("img",{src:e.url,alt:e.filename||"attachment"})}):t("a",{className:"RootAIChat__filePart RootAIChat__filePart--link",href:e.url,target:"_blank",rel:"noopener noreferrer",children:[t(Q,{size:14}),t("span",{children:e.filename||e.url})]})}function gt(o){let e=o.part,a=typeof e.type=="string"&&e.type.startsWith("tool-")?e.type.slice(5):e.toolName||"tool",i=e.state||"",m=Bt(e),h=o.toolApprovals,r=m?h?.approvals[m]:void 0,[l,g]=p(!!r);return k(()=>{r&&g(!0)},[r]),t("div",{className:"RootAIChat__tool",children:[t("button",{type:"button",className:"RootAIChat__tool__header",onClick:()=>g(!l),children:[t(X,{className:M("RootAIChat__tool__header__icon",l&&"RootAIChat__tool__header__icon--open"),size:14}),t(J,{color:"dark",variant:"filled",size:"xs",children:a}),t("span",{className:"RootAIChat__tool__title",children:Ot(a,e.input)}),t("span",{className:"RootAIChat__tool__state",children:r?Ht(r.status):Ft(i)})]}),l&&t("div",{className:"RootAIChat__tool__body",children:[r&&h&&t(Ut,{approval:r,onApprove:()=>h.onApprove(r.toolCallId),onReject:()=>h.onReject(r.toolCallId)}),e.output?.receipt&&t(Wt,{output:e.output}),e.input&&t("details",{children:[t("summary",{children:[t(Y,{size:14,className:"RootAIChat__tool__json__icon"}),t("span",{children:"Input"})]}),t("pre",{children:JSON.stringify(e.input,null,2)})]}),e.output&&t("details",{children:[t("summary",{children:[t(Y,{size:14,className:"RootAIChat__tool__json__icon"}),t("span",{children:"Output"})]}),t("pre",{children:JSON.stringify(e.output,null,2)})]}),e.errorText&&t("div",{className:"RootAIChat__tool__error",children:e.errorText})]})]})}function Bt(o){return o.toolCallId||o.id||""}function Ot(o,e){switch(o){case"collections_list":return"List collections";case"docs_list":return`List ${e?.collectionId||"documents"}`;case"docs_search":return`Search docs${e?.query?` for "${e.query}"`:""}`;case"doc_get":return`Read ${e?.docId||"document"}`;case"doc_getVersion":return`Read ${e?.docId||"document"} version`;case"doc_set":return`Replace ${e?.docId||"draft fields"}`;case"doc_create":return`Create ${e?.docId||"draft document"}`;case"doc_updateField":return`Update ${e?.path||"field"}`;case"doc_edit":return`Edit ${e?.docId||"document"}`;case"doc_duplicate":return`Duplicate ${e?.fromDocId||"document"}`;case"doc_listVersions":return`List versions for ${e?.docId||"document"}`;case"doc_translateField":return"Translate field text";case"schema_get":return`Read ${e?.collectionId||"collection"} schema`;default:return o}}function Ut(o){let e=o.approval.preview,a=e.before!==void 0&&e.after!==void 0;return t("div",{className:"RootAIChat__approval",children:[t("div",{className:"RootAIChat__approval__header",children:[t("div",{children:[t("div",{className:"RootAIChat__approval__title",children:e.title}),t("div",{className:"RootAIChat__approval__summary",children:e.summary})]}),t(J,{className:"RootAIChat__approval__status",variant:"light",color:"gray",children:o.approval.status==="executing"?"Applying":"Review"})]}),e.details.length>0&&t("div",{className:"RootAIChat__approval__details",children:e.details.map(i=>t("div",{children:[t("span",{children:i.label}),t("strong",{children:i.value})]},`${i.label}:${i.value}`))}),a&&t(lt,{className:"RootAIChat__approval__diff",oldCode:K(e.before),newCode:K(e.after)}),t("div",{className:"RootAIChat__approval__actions",children:[t(S,{variant:"default",color:"dark",size:"xs",type:"button",className:"RootAIChat__approval__button",disabled:o.approval.status==="executing",onClick:o.onReject,children:"Reject"}),t(S,{variant:"filled",color:"green",size:"xs",type:"button",className:"RootAIChat__approval__button RootAIChat__approval__button--primary",disabled:o.approval.status==="executing",onClick:o.onApprove,children:"Approve draft edit"})]})]})}function Wt(o){let e=o.output.receipt;return t("div",{className:"RootAIChat__receipt",children:[t("div",{className:"RootAIChat__receipt__title",children:[t(q,{size:14}),t("span",{children:e.title})]}),t("div",{className:"RootAIChat__receipt__summary",children:e.summary}),e.details?.length>0&&t("div",{className:"RootAIChat__receipt__details",children:e.details.map(a=>t("div",{children:[t("span",{children:a.label}),t("strong",{children:a.value})]},`${a.label}:${a.value}`))}),e.adminUrl&&t(S,{component:"a",className:"RootAIChat__receipt__link",variant:"default",size:"xs",compact:!0,href:e.adminUrl,children:"Open document"})]})}function Ht(o){return o==="executing"?"applying\u2026":"waiting for approval"}function Ft(o){switch(o){case"input-streaming":return"preparing\u2026";case"input-available":return"running\u2026";case"output-available":return"done";case"output-error":return"error";default:return o}}function Vt(o){let[e,a]=p(""),[i,m]=p([]),[h,r]=p(!1),l=N(null),g=N(null);k(()=>{window.requestAnimationFrame(()=>{let s=g.current;s&&(s.style.height="auto",s.style.height=`${Math.min(s.scrollHeight,240)}px`)})},[e,i]);let I=()=>{o.disabled||o.isStreaming||!e&&i.length===0||(o.onSend(e,i),a(""),m([]),l.current&&(l.current.value=""))},P=s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),I())},y=async s=>{r(!0);try{let f=s.type||Yt(s.name),x=await qt(s,f),v=await pt(s,{disableGci:!0});m(w=>[...w,{url:v.src,filename:v.filename||s.name,mediaType:f,textContent:x?.text,textTruncated:x?.truncated,width:v.width,height:v.height}])}catch(f){console.error("upload failed",f)}finally{r(!1),l.current&&(l.current.value="")}},D=s=>{let f=s.target;Array.from(f.files||[]).forEach(y)};return t("div",{className:"RootAIChat__composer",children:[i.length>0&&t("div",{className:"RootAIChat__composer__attachments",children:i.map((s,f)=>t("div",{className:"RootAIChat__composer__attachment",children:[s.mediaType.startsWith("image/")?t("img",{src:s.url,alt:s.filename}):t("span",{className:"RootAIChat__composer__attachment__name",children:s.filename}),t("button",{type:"button",className:"RootAIChat__composer__attachment__remove",onClick:()=>m(x=>x.filter((v,w)=>w!==f)),children:t(B,{size:12})})]},f))}),t("div",{className:"RootAIChat__composer__row",children:[t(O,{label:o.canAttach?"Attach file":"Model doesn't support attachments",className:"RootAIChat__composer__attachTooltip",children:t(E,{component:"label",radius:"xl",className:M("RootAIChat__composer__attach",!o.canAttach&&"RootAIChat__composer__attach--disabled"),disabled:!o.canAttach,children:[h?t(V,{size:"xs"}):t(Q,{size:18}),t("input",{ref:l,type:"file",style:{display:"none"},onChange:D})]})}),t("textarea",{ref:g,className:"RootAIChat__composer__textarea",placeholder:o.disabled?"Select a model\u2026":"Ask anything\u2026",value:e,rows:1,autofocus:!0,disabled:o.disabled,onKeyDown:P,onChange:s=>a(s.target.value),onPaste:s=>{let f=s.clipboardData?.items||[];for(let x of f)if(x.kind==="file"){let v=x.getAsFile();v&&o.canAttach&&y(v)}}}),o.isStreaming?t(E,{className:"RootAIChat__composer__button RootAIChat__composer__stopButton",radius:"xl",color:"dark",variant:"filled",onClick:o.onStop,title:"Stop",children:t(B,{size:18})}):t(E,{className:"RootAIChat__composer__button RootAIChat__composer__submitButton",radius:"xl",color:"dark",variant:"filled",disabled:o.disabled||h||!e&&i.length===0,onClick:I,title:"Send",children:t(rt,{size:18})})]}),o.controls]})}var xt=1e5;function Jt(o){let e=o.filter(Ct),a=o.filter(i=>!Ct(i)).map(Kt);return{files:e,text:a.length?`Attached files:
5
+ `),[e.parts]),g=T(async()=>{let u=l();if(!u)return;let I=mt.parse(u);try{await navigator.clipboard.write([new ClipboardItem({"text/html":new Blob([I],{type:"text/html"}),"text/plain":new Blob([u],{type:"text/plain"})})]),r(!0),setTimeout(()=>r(!1),2e3)}catch{await navigator.clipboard.writeText(u),r(!0),setTimeout(()=>r(!1),2e3)}},[l]);return t("div",{className:M("RootAIChat__message",`RootAIChat__message--${e.role}`),children:[t("div",{className:"RootAIChat__message__avatar",children:m?t("img",{src:m,alt:i}):t(j,{size:20})}),t("div",{className:"RootAIChat__message__body",children:[t("div",{className:"RootAIChat__message__username",children:i}),t("div",{className:"RootAIChat__message__parts",children:(e.parts||[]).map((u,I)=>t(Dt,{part:u,toolApprovals:o.toolApprovals},I))}),t("button",{type:"button",className:M("RootAIChat__message__copy",h&&"RootAIChat__message__copy--copied"),title:h?"Copied!":"Copy message",onClick:g,children:h?t(q,{size:14}):t(it,{size:14})})]})]})}function Dt(o){let e=o.part;return e.type==="text"?e.text?t("div",{className:"RootAIChat__textPart",children:t(Z,{code:e.text})}):null:e.type==="reasoning"?t(Lt,{text:e.text}):e.type==="file"?t($t,{part:e}):e.type==="source-url"?t("a",{className:"RootAIChat__sourcePart",href:e.url,target:"_blank",rel:"noopener noreferrer",children:e.title||e.url}):typeof e.type=="string"&&e.type.startsWith("tool-")?t(gt,{part:e,toolApprovals:o.toolApprovals}):e.type==="dynamic-tool"?t(gt,{part:e,toolApprovals:o.toolApprovals}):e.type==="step-start"?null:t("div",{className:"RootAIChat__unknownPart",children:t("pre",{children:JSON.stringify(e,null,2)})})}function Lt(o){let[e,a]=p(!1);return o.text?t("div",{className:M("RootAIChat__reasoning",e&&"RootAIChat__reasoning--open"),children:[t("button",{type:"button",className:"RootAIChat__reasoning__toggle",onClick:()=>a(!e),children:[t(X,{size:14,style:{transform:e?"rotate(0deg)":"rotate(-90deg)"}}),t("span",{children:"Thinking"})]}),e&&t("div",{className:"RootAIChat__reasoning__body",children:t(Z,{code:o.text})})]}):null}function $t(o){let e=o.part;return e.mediaType?.startsWith("image/")?t("div",{className:"RootAIChat__filePart",children:t("img",{src:e.url,alt:e.filename||"attachment"})}):t("a",{className:"RootAIChat__filePart RootAIChat__filePart--link",href:e.url,target:"_blank",rel:"noopener noreferrer",children:[t(Q,{size:14}),t("span",{children:e.filename||e.url})]})}function gt(o){let e=o.part,a=typeof e.type=="string"&&e.type.startsWith("tool-")?e.type.slice(5):e.toolName||"tool",i=e.state||"",m=Bt(e),h=o.toolApprovals,r=m?h?.approvals[m]:void 0,[l,g]=p(!!r);return k(()=>{r&&g(!0)},[r]),t("div",{className:"RootAIChat__tool",children:[t("button",{type:"button",className:"RootAIChat__tool__header",onClick:()=>g(!l),children:[t(X,{className:M("RootAIChat__tool__header__icon",l&&"RootAIChat__tool__header__icon--open"),size:14}),t(J,{color:"dark",variant:"filled",size:"xs",children:a}),t("span",{className:"RootAIChat__tool__title",children:Ot(a,e.input)}),t("span",{className:"RootAIChat__tool__state",children:r?Ht(r.status):Ft(i)})]}),l&&t("div",{className:"RootAIChat__tool__body",children:[r&&h&&t(Ut,{approval:r,onApprove:()=>h.onApprove(r.toolCallId),onReject:()=>h.onReject(r.toolCallId)}),e.output?.receipt&&t(Wt,{output:e.output}),e.input&&t("details",{children:[t("summary",{children:[t(Y,{size:14,className:"RootAIChat__tool__json__icon"}),t("span",{children:"Input"})]}),t("pre",{children:JSON.stringify(e.input,null,2)})]}),e.output&&t("details",{children:[t("summary",{children:[t(Y,{size:14,className:"RootAIChat__tool__json__icon"}),t("span",{children:"Output"})]}),t("pre",{children:JSON.stringify(e.output,null,2)})]}),e.errorText&&t("div",{className:"RootAIChat__tool__error",children:e.errorText})]})]})}function Bt(o){return o.toolCallId||o.id||""}function Ot(o,e){switch(o){case"collections_list":return"List collections";case"docs_list":return`List ${e?.collectionId||"documents"}`;case"docs_search":return`Search docs${e?.query?` for "${e.query}"`:""}`;case"doc_get":return`Read ${e?.docId||"document"}`;case"doc_getVersion":return`Read ${e?.docId||"document"} version`;case"doc_set":return`Replace ${e?.docId||"draft fields"}`;case"doc_create":return`Create ${e?.docId||"draft document"}`;case"doc_updateField":return`Update ${e?.path||"field"}`;case"doc_edit":return`Edit ${e?.docId||"document"}`;case"doc_duplicate":return`Duplicate ${e?.fromDocId||"document"}`;case"doc_listVersions":return`List versions for ${e?.docId||"document"}`;case"doc_translateField":return"Translate field text";case"schema_get":return`Read ${e?.collectionId||"collection"} schema`;default:return o}}function Ut(o){let e=o.approval.preview,a=e.before!==void 0&&e.after!==void 0;return t("div",{className:"RootAIChat__approval",children:[t("div",{className:"RootAIChat__approval__header",children:[t("div",{children:[t("div",{className:"RootAIChat__approval__title",children:e.title}),t("div",{className:"RootAIChat__approval__summary",children:e.summary})]}),t(J,{className:"RootAIChat__approval__status",variant:"light",color:"gray",children:o.approval.status==="executing"?"Applying":"Review"})]}),e.details.length>0&&t("div",{className:"RootAIChat__approval__details",children:e.details.map(i=>t("div",{children:[t("span",{children:i.label}),t("strong",{children:i.value})]},`${i.label}:${i.value}`))}),a&&t(dt,{className:"RootAIChat__approval__diff",oldCode:K(e.before),newCode:K(e.after)}),t("div",{className:"RootAIChat__approval__actions",children:[t(S,{variant:"default",color:"dark",size:"xs",type:"button",className:"RootAIChat__approval__button",disabled:o.approval.status==="executing",onClick:o.onReject,children:"Reject"}),t(S,{variant:"filled",color:"green",size:"xs",type:"button",className:"RootAIChat__approval__button RootAIChat__approval__button--primary",disabled:o.approval.status==="executing",onClick:o.onApprove,children:"Approve draft edit"})]})]})}function Wt(o){let e=o.output.receipt;return t("div",{className:"RootAIChat__receipt",children:[t("div",{className:"RootAIChat__receipt__title",children:[t(q,{size:14}),t("span",{children:e.title})]}),t("div",{className:"RootAIChat__receipt__summary",children:e.summary}),e.details?.length>0&&t("div",{className:"RootAIChat__receipt__details",children:e.details.map(a=>t("div",{children:[t("span",{children:a.label}),t("strong",{children:a.value})]},`${a.label}:${a.value}`))}),e.adminUrl&&t(S,{component:"a",className:"RootAIChat__receipt__link",variant:"default",size:"xs",compact:!0,href:e.adminUrl,children:"Open document"})]})}function Ht(o){return o==="executing"?"applying\u2026":"waiting for approval"}function Ft(o){switch(o){case"input-streaming":return"preparing\u2026";case"input-available":return"running\u2026";case"output-available":return"done";case"output-error":return"error";default:return o}}function Vt(o){let[e,a]=p(""),[i,m]=p([]),[h,r]=p(!1),l=N(null),g=N(null);k(()=>{window.requestAnimationFrame(()=>{let s=g.current;s&&(s.style.height="auto",s.style.height=`${Math.min(s.scrollHeight,240)}px`)})},[e,i]);let I=()=>{o.disabled||o.isStreaming||!e&&i.length===0||(o.onSend(e,i),a(""),m([]),l.current&&(l.current.value=""))},P=s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),I())},y=async s=>{r(!0);try{let f=s.type||Yt(s.name),x=await qt(s,f),v=await nt(s,{disableGci:!0});m(w=>[...w,{url:v.src,filename:v.filename||s.name,mediaType:f,textContent:x?.text,textTruncated:x?.truncated,width:v.width,height:v.height}])}catch(f){console.error("upload failed",f)}finally{r(!1),l.current&&(l.current.value="")}},D=s=>{let f=s.target;Array.from(f.files||[]).forEach(y)};return t("div",{className:"RootAIChat__composer",children:[i.length>0&&t("div",{className:"RootAIChat__composer__attachments",children:i.map((s,f)=>t("div",{className:"RootAIChat__composer__attachment",children:[s.mediaType.startsWith("image/")?t("img",{src:s.url,alt:s.filename}):t("span",{className:"RootAIChat__composer__attachment__name",children:s.filename}),t("button",{type:"button",className:"RootAIChat__composer__attachment__remove",onClick:()=>m(x=>x.filter((v,w)=>w!==f)),children:t(B,{size:12})})]},f))}),t("div",{className:"RootAIChat__composer__row",children:[t(O,{label:o.canAttach?"Attach file":"Model doesn't support attachments",className:"RootAIChat__composer__attachTooltip",children:t(E,{component:"label",radius:"xl",className:M("RootAIChat__composer__attach",!o.canAttach&&"RootAIChat__composer__attach--disabled"),disabled:!o.canAttach,children:[h?t(V,{size:"xs"}):t(Q,{size:18}),t("input",{ref:l,type:"file",style:{display:"none"},onChange:D})]})}),t("textarea",{ref:g,className:"RootAIChat__composer__textarea",placeholder:o.disabled?"Select a model\u2026":"Ask anything\u2026",value:e,rows:1,autofocus:!0,disabled:o.disabled,onKeyDown:P,onChange:s=>a(s.target.value),onPaste:s=>{let f=s.clipboardData?.items||[];for(let x of f)if(x.kind==="file"){let v=x.getAsFile();v&&o.canAttach&&y(v)}}}),o.isStreaming?t(E,{className:"RootAIChat__composer__button RootAIChat__composer__stopButton",radius:"xl",color:"dark",variant:"filled",onClick:o.onStop,title:"Stop",children:t(B,{size:18})}):t(E,{className:"RootAIChat__composer__button RootAIChat__composer__submitButton",radius:"xl",color:"dark",variant:"filled",disabled:o.disabled||h||!e&&i.length===0,onClick:I,title:"Send",children:t(st,{size:18})})]}),o.controls]})}var xt=1e5;function Jt(o){let e=o.filter(Ct),a=o.filter(i=>!Ct(i)).map(Kt);return{files:e,text:a.length?`Attached files:
6
6
 
7
7
  ${a.join(`
8
8