@reviseio/engine 3.0.0 → 3.1.0

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 (43) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/assets/{historyMaterializeWorker-Kl0syEbc.js → historyMaterializeWorker-BMHTnStL.js} +131 -130
  3. package/chunks/{AgentHtmlConverter-BnK7NaYA.js → AgentHtmlConverter-B5qstcmM.js} +129 -128
  4. package/chunks/{AgentPageRenderer-DLwq6nAa.js → AgentPageRenderer-JMhCw-hi.js} +4 -4
  5. package/chunks/BlockDiff-C8eiZ-sf.js +45 -0
  6. package/chunks/{CanvasRenderer-Bqsj1S0p.js → CanvasRenderer-C2vAzLWM.js} +12 -12
  7. package/chunks/DocumentCompare-DX4RWeSV.js +10 -0
  8. package/chunks/{DocumentLayoutEngine-7iOYvyVb.js → DocumentLayoutEngine-BhcWXkeu.js} +45 -45
  9. package/chunks/{DocumentMutator-DIrZBuLr.js → DocumentMutator-FEFU1YM0.js} +6 -6
  10. package/chunks/DocumentOutline-BOZoTohH.js +4 -0
  11. package/chunks/{DocumentScrubber-Cz8Q05hF.js → DocumentScrubber-C4N3Qagm.js} +1 -1
  12. package/chunks/{DocumentSession-lXSXqua5.js → DocumentSession-gZHWP7By.js} +1 -1
  13. package/chunks/{DocxConverter-BfDw7777.js → DocxConverter-BOyLn5eZ.js} +709 -703
  14. package/chunks/{DocxGraft-D0uCnGCo.js → DocxGraft-BbE-AaM5.js} +2 -2
  15. package/chunks/{HtmlConverter-7Xj_g9Jr.js → HtmlConverter-BlzwsPEn.js} +3 -3
  16. package/chunks/MarkdownConverter-BHVskVXI.js +59 -0
  17. package/chunks/{OdtConverter-GwRDMnwS.js → OdtConverter-BdmBFOD1.js} +1 -1
  18. package/chunks/{OfficeImportShared-nlMtIUni.js → OfficeImportShared-B2XJgnDO.js} +4 -4
  19. package/chunks/{PdfConverter-yOlWiVIj.js → PdfConverter-DZMCHDAo.js} +6 -6
  20. package/chunks/{RtfConverter--wLd0qrw.js → RtfConverter-RqE-xZcW.js} +66 -66
  21. package/chunks/{TableBorders-C5pNsuxP.js → TableBorders-ARyTi49V.js} +1 -1
  22. package/chunks/TextDecoding-IPbuUqcC.js +2 -0
  23. package/chunks/TextFileDecoder-BZBBejlR.js +10 -0
  24. package/chunks/{TxtConverter-BoRVCDZw.js → TxtConverter-EPQtb6A6.js} +1 -1
  25. package/chunks/{Typography-DAGM5kfI.js → Typography-XR6scRNV.js} +9 -9
  26. package/chunks/XmlConverter-9sFRFaza.js +55 -0
  27. package/chunks/{capture-Dtinb4bY.js → capture-DhGn0CWA.js} +1 -1
  28. package/chunks/{carrier-RNy67HN4.js → carrier-D58g-gw4.js} +1 -1
  29. package/chunks/{chromeImageLayout-bgHYmqTp.js → chromeImageLayout-DeYYS8YP.js} +1 -1
  30. package/chunks/{engine-TnK8N-gT.js → engine-C5fxuZJo.js} +140 -140
  31. package/chunks/{footnoteFlatten-BcKaWzVs.js → footnoteFlatten-coCVFd3c.js} +1 -1
  32. package/chunks/{graftExport-DxAALMHp.js → graftExport-FBGE2qvt.js} +1 -1
  33. package/chunks/{index-CTti7wRd.js → index-Cezk1s_y.js} +4 -4
  34. package/chunks/{serverDocumentSession-BmYdjC6e.js → serverDocumentSession-LMu3kocH.js} +559 -560
  35. package/chunks/{signatures-CU2LMLBp.js → signatures-DsJnnIqV.js} +1 -1
  36. package/chunks/textExtraction-Bqaqt1Kg.js +2 -0
  37. package/engine.js +2 -2
  38. package/package.json +2 -2
  39. package/chunks/BlockDiff-BdlcKY-t.js +0 -42
  40. package/chunks/DocumentCompare-BqyiP87r.js +0 -6
  41. package/chunks/MarkdownConverter-cnW_oePY.js +0 -57
  42. package/chunks/TextFileDecoder--rsVs3NR.js +0 -9
  43. package/chunks/XmlConverter-CO8Z28dX.js +0 -55
@@ -1,166 +1,167 @@
1
- import{DocumentSession as Ko}from"./DocumentSession-lXSXqua5.js";import{n as fn,A as ae,a as Vo,c as bn}from"./AgentHtmlConverter-BnK7NaYA.js";import{c as ke,a as _n,b as qt,e as Le,d as ht,g as Dt,h as Xo,
2
- i as Qo,j as Zo,k as yn,l as Pt,m as Xe,n as Yo,o as er,p as tr,q as wn,s as nr,t as or,u as kn,v as rr,w as ir}from"./DocumentMutator-DIrZBuLr.js";import{b as Ce}from"./TableGrid-DbroRucl.js";import{
3
- D as Rt,i as sr,A as ar}from"./AgentPageRenderViews-BTLjPZJQ.js";import{f as re,h as Ae,i as vn,j as lr}from"./CanvasRenderer-Bqsj1S0p.js";import*as Qe from"yjs";import{d as cr,y as In,r as xn,c as Sn,
4
- e as dr,t as ur,i as mr,j as hr}from"./engine-TnK8N-gT.js";import{b as Nt}from"./base64-Di1bxoXD.js";import{createStandardLayout as pr}from"./DocumentLayout-CsU5MR-3.js";import{c as gr,h as fr}from"./DocumentLayoutEngine-7iOYvyVb.js";
5
- import{c as br}from"./index-CTti7wRd.js";import"./ParagraphDiffAnalysis-DrmStvmz.js";import{c as _r}from"./UnicodeUtils-CXtusU4g.js";import{R as yr}from"./suggestionAuthorship-B-IuLQlE.js";class wr extends Error{constructor(t){
6
- super(t.message),this.failure=t,this.name="ReviseToolError",this.callId=t.callId,this.tool=t.tool,this.code=t.code}}const kr={count:()=>{},gauge:()=>{},distribution:()=>{}},Mt=/(<img\b[^>]*?\bsrc\s*=\s*)(["'])([\s\S]*?)\2/gi,
7
- $n=/(!\[[^\]]*\]\(\s*)(<[^>]+>|[^)\s]+)((?:\s+(?:"[^"]*"|'[^']*'|\([^)]*\)))?\s*\))/g;function pt(e){const t=e.trim();return t.startsWith("<")&&t.endsWith(">")?t.slice(1,-1).trim():t}function vr(e){const t=new Set(
8
- ["images.revise.io"]);for(const n of e.flatMap(o=>(o??"").split(",")))if(n.trim())try{t.add(new URL(n.includes("://")?n.trim():"https://"+n.trim()).host)}catch{}return t}function Ir(e,t,n){try{const o=new URL(
9
- pt(e),n);return!["http:","https:"].includes(o.protocol)||t.has(o.host)?!1:!n||o.origin!==new URL(n).origin}catch{return!1}}function xr(e,t,n,o=!1){for(const r of e.matchAll(Mt)){const i=pt(r[3]);n(i)&&
10
- t.add(i)}if(o)for(const r of e.matchAll($n)){const i=pt(r[2]);n(i)&&t.add(i)}}function Sr(e){try{const t=new URL(e);if(t.hostname!=="upload.wikimedia.org")return e;const n=t.pathname.split("/");return n.
11
- length<8||n[1]!=="wikipedia"||n[2]!=="commons"||n[3]!=="thumb"?e:(t.pathname=["","wikipedia","commons",...n.slice(4,-1)].join("/"),t.toString())}catch{return e}}function $r(e){return e.replace(/&/g,"&\
12
- amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Cr(e,t){return e.replace(/<img\b[^>]*>/gi,n=>{const o=Array.from(n.matchAll(Mt))[0];if(!o)return n;const r=o[3].trim(),
13
- i=t.get(r);if(!i)return n;let a=n.replace(Mt,(c,d,u)=>`${d}${u}${i.url}${u}`);const l=[];return/\bdata-source-url\s*=/i.test(a)||l.push(`data-source-url="${$r(r)}"`),i.naturalWidth&&i.naturalHeight&&!/\bdata-revise-natural-(?:width|height)\s*=/i.
14
- test(a)&&l.push(`data-revise-natural-width="${i.naturalWidth}"`,`data-revise-natural-height="${i.naturalHeight}"`),l.length>0&&(a=a.replace(/\s*\/?>$/,c=>` ${l.join(" ")}${c}`)),a})}function Cn(e,t,n=!1){
15
- const o=n?e.replace($n,(r,i,a,l)=>{const c=t.get(pt(a));return c?i+"<"+c.url+">"+l:r}):e;return Cr(o,t)}const Ar="https://app-api.revise-sdk.invalid";function An(e){return Ir(e,vr([""]),typeof window<
16
- "u"?window.location.href:void 0)}function Tn(e){return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}async function Tr(e){try{const t=await fetch(`${Ar}/uploads/images/rehost`,{method:"POST",headers:{
17
- "Content-Type":"application/json"},body:JSON.stringify({url:Sr(e)}),signal:AbortSignal.timeout(3e4)});if(!t.ok){let i=`Image copy request failed (HTTP ${t.status}).`;try{const a=await t.json();typeof a.
18
- error=="string"&&a.error.trim().length>0&&(i=a.error.trim())}catch{}return{ok:!1,failure:{url:e,status:t.status,message:i}}}const n=await t.json();if(typeof n.fileUrl!="string"||!n.fileUrl)return{ok:!1,
19
- failure:{url:e,status:t.status,message:"Image copy response did not include a file URL."}};const o=Tn(n.width),r=Tn(n.height);return{ok:!0,image:{url:n.fileUrl,...o&&r?{naturalWidth:o,naturalHeight:r}:
20
- {}}}}catch{return{ok:!1,failure:{url:e,message:"Image copy request could not reach Revise storage."}}}}function qn(e){if(e?.name!=="set_header_footer")return null;const t=e.arguments?.image;if(!t||typeof t!=
21
- "object")return null;const n=t.url;return typeof n=="string"&&n.trim().length>0?t:null}const Dn=new Set(["insert_block","replace_block"]);function qr(e){const t=new Set;for(const n of e??[]){const o=qn(
22
- n);if(o&&An(o.url)&&t.add(o.url),!n?.name||!Dn.has(n.name))continue;const r=n.arguments?.content;for(const i of Array.isArray(r)?r:[r])typeof i=="string"&&xr(i,t,An)}return t}async function Pn(e,t=Tr){
23
- const n={attempted:0,rehosted:0,failedUrls:[],failures:[]};if(!Array.isArray(e)||e.length===0)return n;const o=qr(e);if(o.size===0)return n;const r=new Map,i=[];await Promise.all([...o].map(async l=>{
24
- const c=await t(l);c.ok?r.set(l,c.image):i.push(c.failure)}));const a=[...o].filter(l=>!r.has(l));if(r.size===0)return{attempted:o.size,rehosted:0,failedUrls:a,failures:i};for(const l of e){const c=qn(
25
- l),d=c&&r.get(c.url);if(c&&d&&(c.url=d.url,d.naturalWidth&&d.naturalHeight&&(c.naturalWidth=d.naturalWidth,c.naturalHeight=d.naturalHeight)),!l?.name||!Dn.has(l.name))continue;const u=l.arguments;u&&(typeof u.
26
- content=="string"?u.content=Cn(u.content,r):Array.isArray(u.content)&&(u.content=u.content.map(f=>typeof f=="string"?Cn(f,r):f)))}return{attempted:o.size,rehosted:r.size,failedUrls:a,failures:i}}const Dr=20*
27
- 1024*1024,Pr=2e4,Rr=5,Nr=1e8;function Mr(e){const t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=(o,r)=>String.fromCharCode(...e.subarray(o,o+r));if(e.length>=24&&n(1,3)==="PNG")return{mime:"ima\
28
- ge/png",width:t.getUint32(16),height:t.getUint32(20)};if(e.length>=10&&n(0,3)==="GIF")return{mime:"image/gif",width:t.getUint16(6,!0),height:t.getUint16(8,!0)};if(e.length>=30&&n(0,4)==="RIFF"&&n(8,4)===
29
- "WEBP"){const o=n(12,4);if(o==="VP8X"){const r=i=>e[i]|e[i+1]<<8|e[i+2]<<16;return{mime:"image/webp",width:r(24)+1,height:r(27)+1}}if(o==="VP8 ")return{mime:"image/webp",width:t.getUint16(26,!0)&16383,
30
- height:t.getUint16(28,!0)&16383};if(o==="VP8L"&&e[20]===47){const r=t.getUint32(21,!0);return{mime:"image/webp",width:(r&16383)+1,height:(r>>14&16383)+1}}return null}if(e.length>=4&&e[0]===255&&e[1]===
31
- 216){let o=2;for(;o+9<e.length&&e[o]===255;){const r=e[o+1],i=t.getUint16(o+2);if(r>=192&&r<=207&&r!==196&&r!==200&&r!==204)return{mime:"image/jpeg",height:t.getUint16(o+5),width:t.getUint16(o+7)};o+=
32
- 2+i}return{mime:"image/jpeg"}}return null}function Br(e){let t=e.toLowerCase().replace(/^\[|\]$/g,"").replace(/%.*$/,"");if(!t.includes(":"))return null;const n=/(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(t);if(n){
33
- const[u,f,b,y]=n.slice(1).map(Number);t=`${t.slice(0,n.index)}${(u<<8|f).toString(16)}:${(b<<8|y).toString(16)}`}const[o,r]=t.split("::"),i=u=>u?u.split(":").map(f=>Number.parseInt(f,16)):[],a=i(o),l=t.
34
- includes("::")?i(r):[],c=8-a.length-l.length;if(c<0||!t.includes("::")&&c!==0)return null;const d=[...a,...Array(c).fill(0),...l];return d.every(u=>Number.isInteger(u)&&u>=0&&u<=65535)?d:null}function Rn(e,t){
35
- return e===0||e===10||e===127||e===100&&t>=64&&t<=127||e===169&&t===254||e===172&&t>=16&&t<=31||e===192&&t===168||e===198&&(t===18||t===19)||e>=224}function Nn(e){const t=/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.
36
- exec(e);if(t)return Rn(Number(t[1]),Number(t[2]));const n=Br(e);if(!n)return!0;const o=i=>Rn(i>>8,i&255),r=(i,a)=>n.slice(i,a).every(l=>l===0);return r(0,5)&&n[5]===65535?o(n[6]):r(0,6)?!0:n[0]===100&&
37
- n[1]===65435&&r(2,6)?o(n[6]):n[0]===8194?o(n[1]):(n[0]&65024)===64512||(n[0]&65472)===65152||(n[0]&65280)===65280}class Te extends Error{constructor(t,n){super(t),this.status=n}}async function Or(e,t,n){
38
- if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Te(`Only http(s) image URLs can be fetched, not ${e.protocol}`);const[{isIP:o},r,i]=await Promise.all([import("node:net"),import("node:dns"),e.
39
- protocol==="https:"?import("node:https"):import("node:http")]),a=e.hostname.replace(/^\[|\]$/g,""),l=()=>new Te(`${a} is a private or local address; images are fetched only from public hosts.`);if(o(a)&&
40
- !t.allowPrivateNetwork&&Nn(a))throw l();const c=(d,u,f)=>{r.lookup(d,{...u,all:!0},(b,y)=>{if(b)return f(b,"");const N=y;return!t.allowPrivateNetwork&&(N.length===0||N.some(L=>Nn(L.address)))?f(l(),""):
41
- u.all?f(null,N):f(null,N[0].address,N[0].family)})};return new Promise((d,u)=>{const f=i.request(e,{lookup:c,signal:n,headers:{"user-agent":"revise"}},d);f.on("error",u),f.end()})}async function jr(e,t,n){
42
- const o=AbortSignal.timeout(Pr),r=()=>new Te(`The image is larger than ${Math.round(n/1048576)} MB.`),i=[];let a=0;const l=u=>{if(a+=u.length,a>n)throw r();i.push(u)};if(t.fetch){const u=await t.fetch(
43
- e,{signal:o});if(!u.ok)throw new Te(`The image URL answered HTTP ${u.status}.`,u.status);if(Number(u.headers.get("content-length")??0)>n)throw await u.body?.cancel(),r();if(u.body){const f=u.body.getReader();
44
- try{for(;;){const{done:b,value:y}=await f.read();if(b)break;l(y)}}catch(b){throw await f.cancel().catch(()=>{}),b}}else l(new Uint8Array(await u.arrayBuffer()))}else{let u=new URL(e);for(let f=0;;f+=1){
45
- const b=await Or(u,t,o),y=b.statusCode??0,N=b.headers.location;if(y>=300&&y<400&&N){if(b.resume(),f>=Rr)throw new Te("Too many redirects.");u=new URL(N,u);continue}if(y<200||y>=300)throw b.resume(),new Te(
46
- `The image URL answered HTTP ${y}.`,y);if(Number(b.headers["content-length"]??0)>n)throw b.destroy(),r();try{for await(const L of b)l(L)}catch(L){throw b.destroy(),L}break}}const c=new Uint8Array(a);let d=0;
47
- for(const u of i)c.set(u,d),d+=u.length;return c}function gt(e,t,n){const o={url:e,message:t};return n!==void 0&&(o.status=n),{ok:!1,failure:o}}function Er(e={}){const t=e.maxBytes??Dr;return async function(n){
48
- let o;try{o=await jr(n,e,t)}catch(i){return gt(n,i instanceof Te?i.message:`Could not download the image: ${i.message}`,i instanceof Te?i.status:void 0)}const r=Mr(o);return r?!r.width||!r.height?gt(n,
49
- "The image's pixel size could not be read."):r.width*r.height>Nr?gt(n,"The image's pixel dimensions are implausibly large."):{ok:!0,image:{url:`data:${r.mime};base64,${Buffer.from(o).toString("base64")}`,
50
- ...r.width?{naturalWidth:r.width}:{},...r.height?{naturalHeight:r.height}:{}}}:gt(n,"The URL did not return a PNG, JPEG, GIF, or WebP image (an HTML page or SVG, perhaps). Use a direct link to a raste\
51
- r image.")}}const Bt=new Set(["move_blocks","edit_table_cells","import_attachment_into_document","insert_block","insert_footnote","replace_block","set_block_attribute","style_blocks","clear_formatting",
52
- "append_to_paragraph","break_paragraph","join_paragraphs","replace","replace_all","replace_many","rollback_agent_suggestions","leave_comment","remove_blocks","remove_block","set_title","set_notes","se\
53
- t_page_layout","set_header_footer","insert_table_row","remove_table_rows","remove_table_row","insert_table_column","remove_table_column"]),Lr=new Set(["pending","in_progress","completed","blocked","ca\
54
- ncelled"]);function Mn(e){return Array.isArray(e.work)&&e.work.length>0}const Bn="create_plan/update_plan have no work field; the calls listed in work were NOT executed. Emit them as ordinary tool cal\
55
- ls.";function On(e){if(!Array.isArray(e)||e.some(t=>typeof t!="string"||!t.trim()))throw new Error("steps must be an array of non-empty strings.");return e.map(t=>t.trim())}function jn(e,t,n){if(t==="\
56
- create_plan"){if(typeof n.objective!="string"||!n.objective.trim())throw new Error("objective is required.");const l=On(n.steps);if(!l.length)throw new Error("A plan requires at least one step.");if(e.
57
- plan&&n.supersedes_plan_id!==e.plan.id)throw new Error(`To start a new task, explicitly set supersedes_plan_id to ${e.plan.id}. Use update_plan for steering the existing task.`);if(!e.plan&&n.supersedes_plan_id!=
58
- null)throw new Error("There is no plan to supersede.");const c=`plan_${e.nextPlanNumber}`;return{nextPlanNumber:e.nextPlanNumber+1,plan:{id:c,objective:n.objective.trim(),items:l.map((d,u)=>({id:`${c}\
59
- _item_${u+1}`,step:d,status:"pending"}))}}}const o=e.plan;if(!o||n.plan_id!==o.id)throw new Error(`Use the current plan_id: ${o?.id??"no plan; call create_plan first"}.`);const r=n.add_steps===void 0?
60
- []:On(n.add_steps),i=n.updates===void 0?[]:n.updates;if(!Array.isArray(i))throw new Error("updates must be an array.");const a=new Set;for(const l of i){if(!l||typeof l!="object"||!o.items.some(c=>c.id===
61
- l.item_id)||!Lr.has(l.status)||Object.keys(l).some(c=>!["item_id","status"].includes(c))||a.has(l.item_id))throw new Error("Each update requires a unique existing item_id and valid status. Step text i\
62
- s immutable; add a new item and cancel the old item to change a requirement.");a.add(l.item_id)}if(!i.length&&!r.length)throw new Error(Mn(n)?`Provide updates or add_steps. ${Bn}`:"Provide updates or \
63
- add_steps.");return{nextPlanNumber:e.nextPlanNumber,plan:{...o,items:[...o.items.map(l=>({...l,status:i.find(c=>c.item_id===l.id)?.status??l.status})),...r.map((l,c)=>({id:`${o.id}_item_${o.items.length+
64
- c+1}`,step:l,status:"pending"}))]}}}const En=50,Ur=32*1024;function Fr(e,t){const n=[];if(Ue(e.cell,c=>n.push(c.id)),n.length)return{id:e.cell.id,column:e.col,kind:"rich",truncated:!0,block_ids:e.cell.
65
- children.map(c=>c.id),text:`Contains nested tables. Read them with read_table: ${n.slice(0,20).join(", ")}. Read other nested blocks separately. This preview does not authorize replacement.`};const o=Ft(
66
- e.cell),r=et(e.cell);let i={id:e.cell.id,column:e.col,kind:r?"empty":o?"text":"rich",row_span:e.rowSpan,col_span:e.colSpan,block_ids:ue(e.cell)};const a=(o?.children.find(c=>c.text)??o?.children[0])?.
67
- marks,l=a?ft(a):void 0;return i.formatting={cell:ft(e.cell),...o?{paragraph:ft(o),text_marks:l&&Object.keys(l).length?l:void 0}:{}},o||r?i.text=zt(e.cell):i.html=t?.(e.cell)??"Rich content; read neste\
68
- d blocks before editing.",JSON.stringify(i).length>2e4&&(i={id:e.cell.id,column:e.col,kind:i.kind,truncated:!0,text:"Content omitted: use cell_text with this cell_id, or read a nested block with read_\
69
- specific_blocks and edit that block ID. This preview does not authorize replacement."}),i}const zr=/^(oxml|docx)/;function ft(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!["type","id",
70
- "children"].includes(t)&&!zr.test(t)))}const Jr=new Set(["bold","italic","underline","strikethrough","doubleStrikethrough","smallCaps","allCaps","hidden","letterSpacing","lang","code","superscript","s\
71
- ubscript","fontSize","color","backgroundColor","fontFamily"]),Wr=e=>JSON.stringify(Object.fromEntries(Object.entries(e).sort(([t],[n])=>t.localeCompare(n))));function ue(e){if(!e||typeof e!="object")return[];
72
- const t=e;return[...t.id?[t.id]:[],...Ot(e).flatMap(ue)]}function Ot(e){const t=e;return[t.children,t.notes,t.chrome].flatMap(n=>Array.isArray(n)?n:[])}const Ze=24e3,Hr=2e3;function Gr(e,t,n,o,r){const i=n.
73
- map(u=>e.children[u].id),a=i.reduce((u,f)=>f.length>u.length?f:u,""),l=u=>({table_id:e.id,...u,column_start:t.cols,column_count:t.cols,continuation_revision:r}),c=l(o===null?{row_ids:i}:{row_start:t.rows,
74
- row_count:o}),d=u=>JSON.stringify(u).length-1;return Math.max(d({next_row:t.rows,next_read:c}),d({next_row:t.rows,next_column:t.cols,next_read:l({row_ids:[a]}),following_read:c,remaining_row_ids:i}))}
75
- function jt(e){return ke([e.columnWidths,e.children.map(t=>[t.id,t.children.map(n=>[n.id,n.rowSpan,n.colSpan])])])}function Et(e,t,n){const o=Ne(e,String(t.table_id??"")),r={table_id:String(t.table_id??
76
- ""),row_count:0,column_count:0,revision:"",columns:[],unplaced_cell_ids:[],rows:[],complete_cell_ids:[]};if(!o)return{...r,error:"Unknown table_id."};const i=Ce(o);r.row_count=i.rows,r.column_count=i.
77
- cols,r.revision=jt(o),r.columns=Array.from({length:i.cols},(D,A)=>({column:A,empty:0,filled:0,covered:0}));for(let D=0;D<i.rows;D++)for(let A=0;A<i.cols;A++){const M=i.occupancy[D][A];M&&(M.row!==D||M.
78
- col!==A?r.columns[A].covered++:et(M.cell)?r.columns[A].empty++:r.columns[A].filled++)}const a=o.children.flatMap(D=>D.children.filter(A=>!i.byId.has(A.id)).map(A=>A.id));r.unplaced_cell_count=a.length;
79
- let l=2;for(const D of a){if(r.unplaced_cell_ids.length>=100)break;const A=JSON.stringify(D).length+(r.unplaced_cell_ids.length?1:0);l+A>Hr||(r.unplaced_cell_ids.push(D),l+=A)}const c=Number.isInteger(
80
- t.column_start)&&Number(t.column_start)>=0?Number(t.column_start):0;r.columns=r.columns.slice(c,c+100),c+100<i.cols&&(r.next_summary={table_id:o.id,mode:"summary",column_start:c+100});const d=t.mode??
81
- "rows";if(d==="summary")return r;if(d==="cell_text"){const D=i.byId.get(String(t.cell_id??""));if(!D)return{...r,error:"Unknown cell_id."};const A=ke(D.cell);if(t.continuation_revision!=null&&t.continuation_revision!==
82
- A)return{...r,error:"Cell changed since the previous window; restart at text_offset=0."};const M=t.text_offset??0,I=Zr(D.cell);if("error"in I)return{...r,error:I.error};const C=I.text,q=(h,$)=>I.segments.
83
- filter((we,pe)=>{const lt=I.segments[pe+1]?.start??C.length+1;return we.start<$&&lt>h}).map(we=>({id:we.id,text_offset:we.start}));if(!Number.isInteger(M)||Number(M)<0||Number(M)>C.length)return{...r,
84
- error:"Invalid text_offset."};if(Number(M)>0&&/[\uDC00-\uDFFF]/u.test(C.charAt(Number(M))))return{...r,error:"text_offset splits a Unicode character."};const J=Ze-JSON.stringify({...r,revision:A,cell_id:D.
85
- cell.id,text:"",text_offset:Number(M),next_text_offset:C.length,blocks:q(Number(M),Math.min(C.length,Number(M)+8e3))}).length,z=Math.min(C.length,Number(M)+8e3);let j=Number(M),oe=0;for(;j<z;){const h=/[\uD800-\uDBFF]/.
86
- test(C.charAt(j))&&/[\uDC00-\uDFFF]/.test(C.charAt(j+1))?2:1;if(j+h>z)break;const $=JSON.stringify(C.slice(j,j+h)).length-2;if(oe+$>J)break;oe+=$,j+=h}return j===Number(M)&&j<C.length?{...r,error:"Thi\
87
- s cell's text cannot fit beside the table summary within 24,000 characters."}:{...r,revision:A,cell_id:D.cell.id,text:C.slice(Number(M),j),text_offset:Number(M),...j<C.length?{next_text_offset:j}:{},blocks:q(
88
- Number(M),Math.max(j,Number(M)+1))}}if(d!=="rows")return{...r,error:"mode must be summary, rows, or cell_text."};if(t.continuation_revision!=null&&t.continuation_revision!==r.revision)return{...r,error:"\
89
- Table geometry changed since the previous window; reread the summary and resume using stable row_ids."};const u=t.row_start??0,f=t.row_count??25,b=t.column_start??0,y=t.column_count??i.cols;if(![u,f,b,
90
- y].every(D=>Number.isInteger(D))||Number(u)<0||Number(f)<1||Number(f)>50||Number(b)<0||Number(y)<1)return{...r,error:"Invalid row or column window (maximum 50 rows)."};let N;if(t.row_ids!=null){if(!Array.
91
- isArray(t.row_ids)||!t.row_ids.length||t.row_ids.length>50||new Set(t.row_ids).size!==t.row_ids.length)return{...r,error:"row_ids requires 1-50 unique row IDs."};if(N=t.row_ids.map(D=>o.children.findIndex(
92
- A=>A.id===D)),N.some(D=>D<0))return{...r,error:"Unknown row_id; nothing read."}}else N=Array.from({length:Math.max(0,Math.min(Number(f),i.rows-Number(u)))},(D,A)=>Number(u)+A);if(Number(b)>=i.cols)return{
93
- ...r,error:`column_start is beyond the table's ${i.cols} columns.`};let L=JSON.stringify(r).length;const O=Gr(o,i,N,t.row_ids==null?Number(f):null,r.revision);for(const D of N){const A={row_id:o.children[D].
94
- id,row_index:D,cells:[]},M=JSON.stringify({...A,cells:[]}).length+(r.rows.length?1:0);for(let I=Number(b);I<Math.min(i.cols,Number(b)+Number(y));I++){const C=i.occupancy[D][I];let q;C?C.row!==D||C.col!==
95
- I?q={id:"",column:I,kind:"covered",anchor_id:C.cell.id}:q=Fr(C,n):q={id:"",column:I,kind:"unplaced"};const J=!!C&&C.row===D&&C.col===I&&!q.truncated&&!!(Ft(C.cell)||et(C.cell)||n),z=(oe,h)=>(A.cells.length?
96
- 1:M)+JSON.stringify(oe).length+(h?JSON.stringify(oe.id).length+(r.complete_cell_ids.length?1:0):0);let j=z(q,J);if(L+j+O>Ze&&!r.rows.length&&!A.cells.length){if(q={id:q.id,column:I,kind:q.kind,truncated:!0,
97
- text:"Content omitted: this cell does not fit in a row window. Page its text with mode=cell_text and this cell_id, or read a nested block with read_specific_blocks and edit that block ID. This preview\
98
- does not authorize replacement."},j=z(q,!1),L+j+O>Ze)return{...r,error:"This table window cannot fit even one cell preview within 24,000 characters. Read fewer columns with column_start and column_co\
99
- unt, request fewer row_ids, or page one cell with mode=cell_text."};A.cells.push(q),L+=j;continue}if(L+j+O>Ze){if(r.rows.length){const h=new Set(A.cells.map($=>$.id));return r.complete_cell_ids=r.complete_cell_ids.
100
- filter($=>!h.has($)),r.next_row=D,r.next_read={table_id:o.id,...t.row_ids==null?{row_start:D,row_count:Number(f)}:{row_ids:N.slice(N.indexOf(D)).map($=>o.children[$].id)},column_start:Number(b),column_count:Number(
101
- y),continuation_revision:r.revision},r}A.cells.length&&r.rows.push(A),r.next_row=D,r.next_column=I,r.next_read={table_id:o.id,row_ids:[o.children[D].id],column_start:I,column_count:Math.min(i.cols,Number(
102
- b)+Number(y))-I,continuation_revision:r.revision};const oe=N.slice(N.indexOf(D)+1).map(h=>o.children[h].id);return t.row_ids==null&&D+1<i.rows?r.following_read={table_id:o.id,row_start:D+1,row_count:Number(
103
- f),column_start:Number(b),column_count:Number(y),continuation_revision:r.revision}:oe.length&&(r.following_read={table_id:o.id,row_ids:oe,column_start:Number(b),column_count:Number(y),continuation_revision:r.
104
- revision}),r.remaining_row_ids=oe,r}A.cells.push(q),L+=j,J&&r.complete_cell_ids.push(C.cell.id)}r.rows.push(A)}const T=N.at(-1);return t.row_ids==null&&T!==void 0&&T+1<i.rows&&(r.next_row=T+1,r.next_read=
105
- {table_id:o.id,row_start:T+1,row_count:Number(f),column_start:Number(b),column_count:Number(y),continuation_revision:r.revision}),r}function Ye(e,t,n){if(!t?.scopedTableIds?.length)return n;const o=new Set(
106
- n);for(const r of t.scopedTableIds){const i=Ne(e,r);if(!i)continue;for(const d of ue(i))o.delete(d);const a=d=>{const u=d,f=u.id===r||Ot(d).map(a).some(Boolean);return f&&u.id&&o.delete(u.id),f};a(e);
107
- const l=Ce(i);let c=!0;for(const d of l.cells){const u=t.cells[bt(r,i.children[d.row].id,d.col)];if(!u||!Vr(i,l,d,u)){c=!1;continue}for(const f of u.blockIds)o.add(f)}if(c&&l.cells.length===i.children.
108
- reduce((d,u)=>d+u.children.length,0)){o.add(i.id);for(const d of i.children)o.add(d.id)}}for(const[r,i]of Object.entries(t.blocks??{})){const a=re(e,r),l=Ne(e,i.tableId);if(a?.id===r&&l&&ue(l).includes(
109
- r)&&ke(a)===i.content)for(const c of i.blockIds)o.add(c)}return o}function Ln(e,t,n,o){const r=re(e,o);!r||r.id!==o||(t.blocks??(t.blocks={}),t.blocks[o]={tableId:n,content:ke(r),blockIds:ue(r)})}function Kr(e,t,n,o){
110
- const r=Ne(e,String(o.tableId??""));if(!r)return!1;const i=jt(r),a=t.geometries?.[r.id]===i;if(n==="insert_table_row"||n==="insert_table_column")return a;let l,c=!1;if(n==="remove_table_row"){const b=_n(
111
- r,o);if("error"in b)return!1;l=b.rowIndices,c=b.byId}if(!c&&!a)return!1;const d=o.columnIndex;if(!l&&(!Number.isInteger(d)||Number(d)<0))return!1;const u=Ce(r).cells.filter(b=>l?l.some(y=>b.row<=y&&b.
112
- row+b.rowSpan>y):b.col<=Number(d)&&b.col+b.colSpan>Number(d)),f=Ye(e,t,new Set);return u.length>0&&u.every(b=>f.has(b.cell.id)&&(c||!l||t.cells[bt(r.id,r.children[b.row].id,b.col)]?.revision===i))}function Un(){
113
- return{cells:{}}}function Ne(e,t){const n=re(e,t);return n?.type==="table"&&n.id===t?n:null}function Ue(e,t){if(!e||typeof e!="object")return;const n=e;n.type==="table"&&t(n);for(const o of Ot(e))Ue(o,
114
- t)}const bt=(e,t,n)=>JSON.stringify([e,t,n]),Lt=(e,t)=>ke([t,e.columnWidths]),Ut=(e,t)=>JSON.stringify(e.children.slice(t.row,t.row+t.rowSpan).map(n=>n.id));function Vr(e,t,n,o){return o.cellId===n.cell.
115
- id&&o.rowId===e.children[n.row].id&&o.column===n.col&&o.content===ke(n.cell)&&o.coveredRows===Ut(e,n)&&o.geometry===Lt(e,t.cols)&&o.rowSpan===n.rowSpan&&o.colSpan===n.colSpan}function _t(e,t,n,o){const r=Ne(
116
- e,n);if(!r)return;const i=Ce(r),a=o?new Set(o):null,l=Lt(r,i.cols),c=jt(r);for(const d of i.cells){if(a&&!a.has(d.cell.id))continue;const u=r.children[d.row].id;t.cells[bt(n,u,d.col)]={tableId:n,rowId:u,
117
- column:d.col,cellId:d.cell.id,rowSpan:d.rowSpan,colSpan:d.colSpan,geometry:l,coveredRows:Ut(r,d),content:ke(d.cell),blockIds:ue(d.cell),revision:c}}}function Ft(e){if(e.children.length!==1)return null;
118
- const t=e.children[0];if(t.type!=="paragraph"||!t.children.every(o=>o.type==="text"))return null;let n;for(const o of t.children){const r=ft(o.marks??{});if(Object.keys(r).some(a=>!Jr.has(a)))return null;
119
- if(!o.text)continue;const i=Wr(r);if(n!==void 0&&i!==n)return null;n=i}return t}const Xr=Ze,Qr=e=>`[[${e}]] `;function Zr(e){const t=[];for(const d of e.children)Ue(d,u=>t.push(u.id));if(t.length)return{
120
- error:`Cell contains nested tables (${t.slice(0,20).join(", ")}). Read them with read_table(table_id=...) and read the cell's other blocks with read_specific_blocks; cell_text does not flatten nested \
121
- tables.`};const n=[],o=[],r=(d,u)=>{n.push(d),o.push(u??"")},i=d=>d.map(u=>u.type==="text"?u.text??"":"").join(""),a=d=>{if(d.type==="paragraph"){r(i(d.children),d.id);return}if(d.type==="list"){const f=[];
122
- for(const b of d.children){const y=Math.max(0,b.indentLevel??0);f.length=y+1;const N=y===0?d.startNumber??1:1;f[y]=f[y]===void 0?N:f[y]+1;const L=d.variant==="ordered"?`${f[y]}. `:d.variant==="todo"?b.
123
- checked?"[x] ":"[ ] ":"• ";r(`${" ".repeat(y)}${L}${i(b.children)}`,b.id??d.id)}return}const u=d;if(typeof u.content=="string"){r(u.content,u.id);return}if(Array.isArray(u.children)&&u.children.length){
124
- for(const f of u.children)a(f);return}r(`[${u.type}${u.id?` ${u.id}`:""}]`,u.id)};for(const d of e.children)a(d);const l=[];let c=0;return{text:n.map((d,u)=>{const f=o[u],b=!!f&&l.at(-1)?.id!==f;b&&l.
125
- push({id:f,start:c});const y=b?`${Qr(f)}${d}`:d;return c+=y.length+1,y}).join(`
1
+ import{DocumentSession as Ko}from"./DocumentSession-gZHWP7By.js";import{n as fn,A as ae,a as Vo,c as bn}from"./AgentHtmlConverter-B5qstcmM.js";import{c as ke,a as _n,b as qt,d as ht,e as Dt,g as Xo,h as Qo,
2
+ i as Zo,j as yn,k as Pt,l as Ve,m as Yo,n as er,o as tr,p as wn,q as nr,s as or,t as kn,u as rr,v as ir}from"./DocumentMutator-FEFU1YM0.js";import{b as Ce}from"./TableGrid-DbroRucl.js";import{D as Nt,
3
+ i as sr,A as ar}from"./AgentPageRenderViews-BTLjPZJQ.js";import{f as re,h as Ae,i as vn,j as lr}from"./CanvasRenderer-C2vAzLWM.js";import{e as Xe}from"./textExtraction-Bqaqt1Kg.js";import*as Qe from"yjs";
4
+ import{d as cr,y as In,r as xn,c as Sn,e as dr,t as ur,i as mr,j as hr}from"./engine-C5fxuZJo.js";import{b as Rt}from"./base64-Di1bxoXD.js";import{documentHeadingSections as pr}from"./DocumentOutline-BOZoTohH.js";
5
+ import{createStandardLayout as gr}from"./DocumentLayout-CsU5MR-3.js";import{c as fr,h as br}from"./DocumentLayoutEngine-BhcWXkeu.js";import{c as _r}from"./index-Cezk1s_y.js";import"./ParagraphDiffAnalysis-DrmStvmz.js";
6
+ import{c as yr}from"./UnicodeUtils-CXtusU4g.js";import{R as wr}from"./suggestionAuthorship-B-IuLQlE.js";class kr extends Error{constructor(t){super(t.message),this.failure=t,this.name="ReviseToolError",
7
+ this.callId=t.callId,this.tool=t.tool,this.code=t.code}}const vr={count:()=>{},gauge:()=>{},distribution:()=>{}},Mt=/(<img\b[^>]*?\bsrc\s*=\s*)(["'])([\s\S]*?)\2/gi,$n=/(!\[[^\]]*\]\(\s*)(<[^>]+>|[^)\s]+)((?:\s+(?:"[^"]*"|'[^']*'|\([^)]*\)))?\s*\))/g;
8
+ function pt(e){const t=e.trim();return t.startsWith("<")&&t.endsWith(">")?t.slice(1,-1).trim():t}function Ir(e){const t=new Set(["images.revise.io"]);for(const n of e.flatMap(o=>(o??"").split(",")))if(n.
9
+ trim())try{t.add(new URL(n.includes("://")?n.trim():"https://"+n.trim()).host)}catch{}return t}function xr(e,t,n){try{const o=new URL(pt(e),n);return!["http:","https:"].includes(o.protocol)||t.has(o.host)?
10
+ !1:!n||o.origin!==new URL(n).origin}catch{return!1}}function Sr(e,t,n,o=!1){for(const r of e.matchAll(Mt)){const i=pt(r[3]);n(i)&&t.add(i)}if(o)for(const r of e.matchAll($n)){const i=pt(r[2]);n(i)&&t.
11
+ add(i)}}function $r(e){try{const t=new URL(e);if(t.hostname!=="upload.wikimedia.org")return e;const n=t.pathname.split("/");return n.length<8||n[1]!=="wikipedia"||n[2]!=="commons"||n[3]!=="thumb"?e:(t.
12
+ pathname=["","wikipedia","commons",...n.slice(4,-1)].join("/"),t.toString())}catch{return e}}function Cr(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt\
13
+ ;")}function Ar(e,t){return e.replace(/<img\b[^>]*>/gi,n=>{const o=Array.from(n.matchAll(Mt))[0];if(!o)return n;const r=o[3].trim(),i=t.get(r);if(!i)return n;let a=n.replace(Mt,(c,d,u)=>`${d}${u}${i.url}${u}`);
14
+ const l=[];return/\bdata-source-url\s*=/i.test(a)||l.push(`data-source-url="${Cr(r)}"`),i.naturalWidth&&i.naturalHeight&&!/\bdata-revise-natural-(?:width|height)\s*=/i.test(a)&&l.push(`data-revise-nat\
15
+ ural-width="${i.naturalWidth}"`,`data-revise-natural-height="${i.naturalHeight}"`),l.length>0&&(a=a.replace(/\s*\/?>$/,c=>` ${l.join(" ")}${c}`)),a})}function Cn(e,t,n=!1){const o=n?e.replace($n,(r,i,a,l)=>{
16
+ const c=t.get(pt(a));return c?i+"<"+c.url+">"+l:r}):e;return Ar(o,t)}const Tr="https://app-api.revise-sdk.invalid";function An(e){return xr(e,Ir([""]),typeof window<"u"?window.location.href:void 0)}function Tn(e){
17
+ return typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0}async function qr(e){try{const t=await fetch(`${Tr}/uploads/images/rehost`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.
18
+ stringify({url:$r(e)}),signal:AbortSignal.timeout(3e4)});if(!t.ok){let i=`Image copy request failed (HTTP ${t.status}).`;try{const a=await t.json();typeof a.error=="string"&&a.error.trim().length>0&&(i=
19
+ a.error.trim())}catch{}return{ok:!1,failure:{url:e,status:t.status,message:i}}}const n=await t.json();if(typeof n.fileUrl!="string"||!n.fileUrl)return{ok:!1,failure:{url:e,status:t.status,message:"Ima\
20
+ ge copy response did not include a file URL."}};const o=Tn(n.width),r=Tn(n.height);return{ok:!0,image:{url:n.fileUrl,...o&&r?{naturalWidth:o,naturalHeight:r}:{}}}}catch{return{ok:!1,failure:{url:e,message:"\
21
+ Image copy request could not reach Revise storage."}}}}function qn(e){if(e?.name!=="set_header_footer")return null;const t=e.arguments?.image;if(!t||typeof t!="object")return null;const n=t.url;return typeof n==
22
+ "string"&&n.trim().length>0?t:null}const Dn=new Set(["insert_block","replace_block"]);function Dr(e){const t=new Set;for(const n of e??[]){const o=qn(n);if(o&&An(o.url)&&t.add(o.url),!n?.name||!Dn.has(
23
+ n.name))continue;const r=n.arguments?.content;for(const i of Array.isArray(r)?r:[r])typeof i=="string"&&Sr(i,t,An)}return t}async function Pn(e,t=qr){const n={attempted:0,rehosted:0,failedUrls:[],failures:[]};
24
+ if(!Array.isArray(e)||e.length===0)return n;const o=Dr(e);if(o.size===0)return n;const r=new Map,i=[];await Promise.all([...o].map(async l=>{const c=await t(l);c.ok?r.set(l,c.image):i.push(c.failure)}));
25
+ const a=[...o].filter(l=>!r.has(l));if(r.size===0)return{attempted:o.size,rehosted:0,failedUrls:a,failures:i};for(const l of e){const c=qn(l),d=c&&r.get(c.url);if(c&&d&&(c.url=d.url,d.naturalWidth&&d.
26
+ naturalHeight&&(c.naturalWidth=d.naturalWidth,c.naturalHeight=d.naturalHeight)),!l?.name||!Dn.has(l.name))continue;const u=l.arguments;u&&(typeof u.content=="string"?u.content=Cn(u.content,r):Array.isArray(
27
+ u.content)&&(u.content=u.content.map(f=>typeof f=="string"?Cn(f,r):f)))}return{attempted:o.size,rehosted:r.size,failedUrls:a,failures:i}}const Pr=20*1024*1024,Nr=2e4,Rr=5,Mr=1e8;function Br(e){const t=new DataView(
28
+ e.buffer,e.byteOffset,e.byteLength),n=(o,r)=>String.fromCharCode(...e.subarray(o,o+r));if(e.length>=24&&n(1,3)==="PNG")return{mime:"image/png",width:t.getUint32(16),height:t.getUint32(20)};if(e.length>=
29
+ 10&&n(0,3)==="GIF")return{mime:"image/gif",width:t.getUint16(6,!0),height:t.getUint16(8,!0)};if(e.length>=30&&n(0,4)==="RIFF"&&n(8,4)==="WEBP"){const o=n(12,4);if(o==="VP8X"){const r=i=>e[i]|e[i+1]<<8|
30
+ e[i+2]<<16;return{mime:"image/webp",width:r(24)+1,height:r(27)+1}}if(o==="VP8 ")return{mime:"image/webp",width:t.getUint16(26,!0)&16383,height:t.getUint16(28,!0)&16383};if(o==="VP8L"&&e[20]===47){const r=t.
31
+ getUint32(21,!0);return{mime:"image/webp",width:(r&16383)+1,height:(r>>14&16383)+1}}return null}if(e.length>=4&&e[0]===255&&e[1]===216){let o=2;for(;o+9<e.length&&e[o]===255;){const r=e[o+1],i=t.getUint16(
32
+ o+2);if(r>=192&&r<=207&&r!==196&&r!==200&&r!==204)return{mime:"image/jpeg",height:t.getUint16(o+5),width:t.getUint16(o+7)};o+=2+i}return{mime:"image/jpeg"}}return null}function Or(e){let t=e.toLowerCase().
33
+ replace(/^\[|\]$/g,"").replace(/%.*$/,"");if(!t.includes(":"))return null;const n=/(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(t);if(n){const[u,f,b,y]=n.slice(1).map(Number);t=`${t.slice(0,n.index)}${(u<<8|f).toString(
34
+ 16)}:${(b<<8|y).toString(16)}`}const[o,r]=t.split("::"),i=u=>u?u.split(":").map(f=>Number.parseInt(f,16)):[],a=i(o),l=t.includes("::")?i(r):[],c=8-a.length-l.length;if(c<0||!t.includes("::")&&c!==0)return null;
35
+ const d=[...a,...Array(c).fill(0),...l];return d.every(u=>Number.isInteger(u)&&u>=0&&u<=65535)?d:null}function Nn(e,t){return e===0||e===10||e===127||e===100&&t>=64&&t<=127||e===169&&t===254||e===172&&
36
+ t>=16&&t<=31||e===192&&t===168||e===198&&(t===18||t===19)||e>=224}function Rn(e){const t=/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(e);if(t)return Nn(Number(t[1]),Number(t[2]));const n=Or(e);if(!n)return!0;const o=i=>Nn(
37
+ i>>8,i&255),r=(i,a)=>n.slice(i,a).every(l=>l===0);return r(0,5)&&n[5]===65535?o(n[6]):r(0,6)?!0:n[0]===100&&n[1]===65435&&r(2,6)?o(n[6]):n[0]===8194?o(n[1]):(n[0]&65024)===64512||(n[0]&65472)===65152||
38
+ (n[0]&65280)===65280}class Te extends Error{constructor(t,n){super(t),this.status=n}}async function jr(e,t,n){if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Te(`Only http(s) image URLs can b\
39
+ e fetched, not ${e.protocol}`);const[{isIP:o},r,i]=await Promise.all([import("node:net"),import("node:dns"),e.protocol==="https:"?import("node:https"):import("node:http")]),a=e.hostname.replace(/^\[|\]$/g,
40
+ ""),l=()=>new Te(`${a} is a private or local address; images are fetched only from public hosts.`);if(o(a)&&!t.allowPrivateNetwork&&Rn(a))throw l();const c=(d,u,f)=>{r.lookup(d,{...u,all:!0},(b,y)=>{if(b)
41
+ return f(b,"");const R=y;return!t.allowPrivateNetwork&&(R.length===0||R.some(L=>Rn(L.address)))?f(l(),""):u.all?f(null,R):f(null,R[0].address,R[0].family)})};return new Promise((d,u)=>{const f=i.request(
42
+ e,{lookup:c,signal:n,headers:{"user-agent":"revise"}},d);f.on("error",u),f.end()})}async function Er(e,t,n){const o=AbortSignal.timeout(Nr),r=()=>new Te(`The image is larger than ${Math.round(n/1048576)}\
43
+ MB.`),i=[];let a=0;const l=u=>{if(a+=u.length,a>n)throw r();i.push(u)};if(t.fetch){const u=await t.fetch(e,{signal:o});if(!u.ok)throw new Te(`The image URL answered HTTP ${u.status}.`,u.status);if(Number(
44
+ u.headers.get("content-length")??0)>n)throw await u.body?.cancel(),r();if(u.body){const f=u.body.getReader();try{for(;;){const{done:b,value:y}=await f.read();if(b)break;l(y)}}catch(b){throw await f.cancel().
45
+ catch(()=>{}),b}}else l(new Uint8Array(await u.arrayBuffer()))}else{let u=new URL(e);for(let f=0;;f+=1){const b=await jr(u,t,o),y=b.statusCode??0,R=b.headers.location;if(y>=300&&y<400&&R){if(b.resume(),
46
+ f>=Rr)throw new Te("Too many redirects.");u=new URL(R,u);continue}if(y<200||y>=300)throw b.resume(),new Te(`The image URL answered HTTP ${y}.`,y);if(Number(b.headers["content-length"]??0)>n)throw b.destroy(),
47
+ r();try{for await(const L of b)l(L)}catch(L){throw b.destroy(),L}break}}const c=new Uint8Array(a);let d=0;for(const u of i)c.set(u,d),d+=u.length;return c}function gt(e,t,n){const o={url:e,message:t};
48
+ return n!==void 0&&(o.status=n),{ok:!1,failure:o}}function Lr(e={}){const t=e.maxBytes??Pr;return async function(n){let o;try{o=await Er(n,e,t)}catch(i){return gt(n,i instanceof Te?i.message:`Could no\
49
+ t download the image: ${i.message}`,i instanceof Te?i.status:void 0)}const r=Br(o);return r?!r.width||!r.height?gt(n,"The image's pixel size could not be read."):r.width*r.height>Mr?gt(n,"The image's \
50
+ pixel dimensions are implausibly large."):{ok:!0,image:{url:`data:${r.mime};base64,${Buffer.from(o).toString("base64")}`,...r.width?{naturalWidth:r.width}:{},...r.height?{naturalHeight:r.height}:{}}}:
51
+ gt(n,"The URL did not return a PNG, JPEG, GIF, or WebP image (an HTML page or SVG, perhaps). Use a direct link to a raster image.")}}const Bt=new Set(["move_blocks","edit_table_cells","import_attachme\
52
+ nt_into_document","insert_block","insert_footnote","replace_block","set_block_attribute","style_blocks","clear_formatting","append_to_paragraph","break_paragraph","join_paragraphs","replace","replace_\
53
+ all","replace_many","rollback_agent_suggestions","leave_comment","remove_blocks","remove_block","set_title","set_notes","set_page_layout","set_header_footer","insert_table_row","remove_table_rows","re\
54
+ move_table_row","insert_table_column","remove_table_column"]),Ur=new Set(["pending","in_progress","completed","blocked","cancelled"]);function Mn(e){return Array.isArray(e.work)&&e.work.length>0}const Bn="\
55
+ create_plan/update_plan have no work field; the calls listed in work were NOT executed. Emit them as ordinary tool calls.";function On(e){if(!Array.isArray(e)||e.some(t=>typeof t!="string"||!t.trim()))
56
+ throw new Error("steps must be an array of non-empty strings.");return e.map(t=>t.trim())}function jn(e,t,n){if(t==="create_plan"){if(typeof n.objective!="string"||!n.objective.trim())throw new Error(
57
+ "objective is required.");const l=On(n.steps);if(!l.length)throw new Error("A plan requires at least one step.");if(e.plan&&n.supersedes_plan_id!==e.plan.id)throw new Error(`To start a new task, expli\
58
+ citly set supersedes_plan_id to ${e.plan.id}. Use update_plan for steering the existing task.`);if(!e.plan&&n.supersedes_plan_id!=null)throw new Error("There is no plan to supersede.");const c=`plan_${e.
59
+ nextPlanNumber}`;return{nextPlanNumber:e.nextPlanNumber+1,plan:{id:c,objective:n.objective.trim(),items:l.map((d,u)=>({id:`${c}_item_${u+1}`,step:d,status:"pending"}))}}}const o=e.plan;if(!o||n.plan_id!==
60
+ o.id)throw new Error(`Use the current plan_id: ${o?.id??"no plan; call create_plan first"}.`);const r=n.add_steps===void 0?[]:On(n.add_steps),i=n.updates===void 0?[]:n.updates;if(!Array.isArray(i))throw new Error(
61
+ "updates must be an array.");const a=new Set;for(const l of i){if(!l||typeof l!="object"||!o.items.some(c=>c.id===l.item_id)||!Ur.has(l.status)||Object.keys(l).some(c=>!["item_id","status"].includes(c))||
62
+ a.has(l.item_id))throw new Error("Each update requires a unique existing item_id and valid status. Step text is immutable; add a new item and cancel the old item to change a requirement.");a.add(l.item_id)}
63
+ if(!i.length&&!r.length)throw new Error(Mn(n)?`Provide updates or add_steps. ${Bn}`:"Provide updates or add_steps.");return{nextPlanNumber:e.nextPlanNumber,plan:{...o,items:[...o.items.map(l=>({...l,status:i.
64
+ find(c=>c.item_id===l.id)?.status??l.status})),...r.map((l,c)=>({id:`${o.id}_item_${o.items.length+c+1}`,step:l,status:"pending"}))]}}}const En=50,Fr=32*1024;function zr(e,t){const n=[];if(Le(e.cell,c=>n.
65
+ push(c.id)),n.length)return{id:e.cell.id,column:e.col,kind:"rich",truncated:!0,block_ids:e.cell.children.map(c=>c.id),text:`Contains nested tables. Read them with read_table: ${n.slice(0,20).join(", ")}\
66
+ . Read other nested blocks separately. This preview does not authorize replacement.`};const o=Ft(e.cell),r=et(e.cell);let i={id:e.cell.id,column:e.col,kind:r?"empty":o?"text":"rich",row_span:e.rowSpan,
67
+ col_span:e.colSpan,block_ids:ue(e.cell)};const a=(o?.children.find(c=>c.text)??o?.children[0])?.marks,l=a?ft(a):void 0;return i.formatting={cell:ft(e.cell),...o?{paragraph:ft(o),text_marks:l&&Object.keys(
68
+ l).length?l:void 0}:{}},o||r?i.text=zt(e.cell):i.html=t?.(e.cell)??"Rich content; read nested blocks before editing.",JSON.stringify(i).length>2e4&&(i={id:e.cell.id,column:e.col,kind:i.kind,truncated:!0,
69
+ text:"Content omitted: use cell_text with this cell_id, or read a nested block with read_specific_blocks and edit that block ID. This preview does not authorize replacement."}),i}const Jr=/^(oxml|docx)/;
70
+ function ft(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!["type","id","children"].includes(t)&&!Jr.test(t)))}const Wr=new Set(["bold","italic","underline","strikethrough","doubleStrik\
71
+ ethrough","smallCaps","allCaps","hidden","letterSpacing","lang","code","superscript","subscript","fontSize","color","backgroundColor","fontFamily"]),Hr=e=>JSON.stringify(Object.fromEntries(Object.entries(
72
+ e).sort(([t],[n])=>t.localeCompare(n))));function ue(e){if(!e||typeof e!="object")return[];const t=e;return[...t.id?[t.id]:[],...Ot(e).flatMap(ue)]}function Ot(e){const t=e;return[t.children,t.notes,t.
73
+ chrome].flatMap(n=>Array.isArray(n)?n:[])}const Ze=24e3,Gr=2e3;function Kr(e,t,n,o,r){const i=n.map(u=>e.children[u].id),a=i.reduce((u,f)=>f.length>u.length?f:u,""),l=u=>({table_id:e.id,...u,column_start:t.
74
+ cols,column_count:t.cols,continuation_revision:r}),c=l(o===null?{row_ids:i}:{row_start:t.rows,row_count:o}),d=u=>JSON.stringify(u).length-1;return Math.max(d({next_row:t.rows,next_read:c}),d({next_row:t.
75
+ rows,next_column:t.cols,next_read:l({row_ids:[a]}),following_read:c,remaining_row_ids:i}))}function jt(e){return ke([e.columnWidths,e.children.map(t=>[t.id,t.children.map(n=>[n.id,n.rowSpan,n.colSpan])])])}
76
+ function Et(e,t,n){const o=Re(e,String(t.table_id??"")),r={table_id:String(t.table_id??""),row_count:0,column_count:0,revision:"",columns:[],unplaced_cell_ids:[],rows:[],complete_cell_ids:[]};if(!o)return{
77
+ ...r,error:"Unknown table_id."};const i=Ce(o);r.row_count=i.rows,r.column_count=i.cols,r.revision=jt(o),r.columns=Array.from({length:i.cols},(D,A)=>({column:A,empty:0,filled:0,covered:0}));for(let D=0;D<
78
+ i.rows;D++)for(let A=0;A<i.cols;A++){const M=i.occupancy[D][A];M&&(M.row!==D||M.col!==A?r.columns[A].covered++:et(M.cell)?r.columns[A].empty++:r.columns[A].filled++)}const a=o.children.flatMap(D=>D.children.
79
+ filter(A=>!i.byId.has(A.id)).map(A=>A.id));r.unplaced_cell_count=a.length;let l=2;for(const D of a){if(r.unplaced_cell_ids.length>=100)break;const A=JSON.stringify(D).length+(r.unplaced_cell_ids.length?
80
+ 1:0);l+A>Gr||(r.unplaced_cell_ids.push(D),l+=A)}const c=Number.isInteger(t.column_start)&&Number(t.column_start)>=0?Number(t.column_start):0;r.columns=r.columns.slice(c,c+100),c+100<i.cols&&(r.next_summary=
81
+ {table_id:o.id,mode:"summary",column_start:c+100});const d=t.mode??"rows";if(d==="summary")return r;if(d==="cell_text"){const D=i.byId.get(String(t.cell_id??""));if(!D)return{...r,error:"Unknown cell_\
82
+ id."};const A=ke(D.cell);if(t.continuation_revision!=null&&t.continuation_revision!==A)return{...r,error:"Cell changed since the previous window; restart at text_offset=0."};const M=t.text_offset??0,I=Yr(
83
+ D.cell);if("error"in I)return{...r,error:I.error};const C=I.text,q=(h,$)=>I.segments.filter((we,pe)=>{const lt=I.segments[pe+1]?.start??C.length+1;return we.start<$&&lt>h}).map(we=>({id:we.id,text_offset:we.
84
+ start}));if(!Number.isInteger(M)||Number(M)<0||Number(M)>C.length)return{...r,error:"Invalid text_offset."};if(Number(M)>0&&/[\uDC00-\uDFFF]/u.test(C.charAt(Number(M))))return{...r,error:"text_offset \
85
+ splits a Unicode character."};const J=Ze-JSON.stringify({...r,revision:A,cell_id:D.cell.id,text:"",text_offset:Number(M),next_text_offset:C.length,blocks:q(Number(M),Math.min(C.length,Number(M)+8e3))}).
86
+ length,z=Math.min(C.length,Number(M)+8e3);let j=Number(M),oe=0;for(;j<z;){const h=/[\uD800-\uDBFF]/.test(C.charAt(j))&&/[\uDC00-\uDFFF]/.test(C.charAt(j+1))?2:1;if(j+h>z)break;const $=JSON.stringify(C.
87
+ slice(j,j+h)).length-2;if(oe+$>J)break;oe+=$,j+=h}return j===Number(M)&&j<C.length?{...r,error:"This cell's text cannot fit beside the table summary within 24,000 characters."}:{...r,revision:A,cell_id:D.
88
+ cell.id,text:C.slice(Number(M),j),text_offset:Number(M),...j<C.length?{next_text_offset:j}:{},blocks:q(Number(M),Math.max(j,Number(M)+1))}}if(d!=="rows")return{...r,error:"mode must be summary, rows, \
89
+ or cell_text."};if(t.continuation_revision!=null&&t.continuation_revision!==r.revision)return{...r,error:"Table geometry changed since the previous window; reread the summary and resume using stable r\
90
+ ow_ids."};const u=t.row_start??0,f=t.row_count??25,b=t.column_start??0,y=t.column_count??i.cols;if(![u,f,b,y].every(D=>Number.isInteger(D))||Number(u)<0||Number(f)<1||Number(f)>50||Number(b)<0||Number(
91
+ y)<1)return{...r,error:"Invalid row or column window (maximum 50 rows)."};let R;if(t.row_ids!=null){if(!Array.isArray(t.row_ids)||!t.row_ids.length||t.row_ids.length>50||new Set(t.row_ids).size!==t.row_ids.
92
+ length)return{...r,error:"row_ids requires 1-50 unique row IDs."};if(R=t.row_ids.map(D=>o.children.findIndex(A=>A.id===D)),R.some(D=>D<0))return{...r,error:"Unknown row_id; nothing read."}}else R=Array.
93
+ from({length:Math.max(0,Math.min(Number(f),i.rows-Number(u)))},(D,A)=>Number(u)+A);if(Number(b)>=i.cols)return{...r,error:`column_start is beyond the table's ${i.cols} columns.`};let L=JSON.stringify(
94
+ r).length;const O=Kr(o,i,R,t.row_ids==null?Number(f):null,r.revision);for(const D of R){const A={row_id:o.children[D].id,row_index:D,cells:[]},M=JSON.stringify({...A,cells:[]}).length+(r.rows.length?1:
95
+ 0);for(let I=Number(b);I<Math.min(i.cols,Number(b)+Number(y));I++){const C=i.occupancy[D][I];let q;C?C.row!==D||C.col!==I?q={id:"",column:I,kind:"covered",anchor_id:C.cell.id}:q=zr(C,n):q={id:"",column:I,
96
+ kind:"unplaced"};const J=!!C&&C.row===D&&C.col===I&&!q.truncated&&!!(Ft(C.cell)||et(C.cell)||n),z=(oe,h)=>(A.cells.length?1:M)+JSON.stringify(oe).length+(h?JSON.stringify(oe.id).length+(r.complete_cell_ids.
97
+ length?1:0):0);let j=z(q,J);if(L+j+O>Ze&&!r.rows.length&&!A.cells.length){if(q={id:q.id,column:I,kind:q.kind,truncated:!0,text:"Content omitted: this cell does not fit in a row window. Page its text w\
98
+ ith mode=cell_text and this cell_id, or read a nested block with read_specific_blocks and edit that block ID. This preview does not authorize replacement."},j=z(q,!1),L+j+O>Ze)return{...r,error:"This \
99
+ table window cannot fit even one cell preview within 24,000 characters. Read fewer columns with column_start and column_count, request fewer row_ids, or page one cell with mode=cell_text."};A.cells.push(
100
+ q),L+=j;continue}if(L+j+O>Ze){if(r.rows.length){const h=new Set(A.cells.map($=>$.id));return r.complete_cell_ids=r.complete_cell_ids.filter($=>!h.has($)),r.next_row=D,r.next_read={table_id:o.id,...t.row_ids==
101
+ null?{row_start:D,row_count:Number(f)}:{row_ids:R.slice(R.indexOf(D)).map($=>o.children[$].id)},column_start:Number(b),column_count:Number(y),continuation_revision:r.revision},r}A.cells.length&&r.rows.
102
+ push(A),r.next_row=D,r.next_column=I,r.next_read={table_id:o.id,row_ids:[o.children[D].id],column_start:I,column_count:Math.min(i.cols,Number(b)+Number(y))-I,continuation_revision:r.revision};const oe=R.
103
+ slice(R.indexOf(D)+1).map(h=>o.children[h].id);return t.row_ids==null&&D+1<i.rows?r.following_read={table_id:o.id,row_start:D+1,row_count:Number(f),column_start:Number(b),column_count:Number(y),continuation_revision:r.
104
+ revision}:oe.length&&(r.following_read={table_id:o.id,row_ids:oe,column_start:Number(b),column_count:Number(y),continuation_revision:r.revision}),r.remaining_row_ids=oe,r}A.cells.push(q),L+=j,J&&r.complete_cell_ids.
105
+ push(C.cell.id)}r.rows.push(A)}const T=R.at(-1);return t.row_ids==null&&T!==void 0&&T+1<i.rows&&(r.next_row=T+1,r.next_read={table_id:o.id,row_start:T+1,row_count:Number(f),column_start:Number(b),column_count:Number(
106
+ y),continuation_revision:r.revision}),r}function Ye(e,t,n){if(!t?.scopedTableIds?.length)return n;const o=new Set(n);for(const r of t.scopedTableIds){const i=Re(e,r);if(!i)continue;for(const d of ue(i))
107
+ o.delete(d);const a=d=>{const u=d,f=u.id===r||Ot(d).map(a).some(Boolean);return f&&u.id&&o.delete(u.id),f};a(e);const l=Ce(i);let c=!0;for(const d of l.cells){const u=t.cells[bt(r,i.children[d.row].id,
108
+ d.col)];if(!u||!Xr(i,l,d,u)){c=!1;continue}for(const f of u.blockIds)o.add(f)}if(c&&l.cells.length===i.children.reduce((d,u)=>d+u.children.length,0)){o.add(i.id);for(const d of i.children)o.add(d.id)}}
109
+ for(const[r,i]of Object.entries(t.blocks??{})){const a=re(e,r),l=Re(e,i.tableId);if(a?.id===r&&l&&ue(l).includes(r)&&ke(a)===i.content)for(const c of i.blockIds)o.add(c)}return o}function Ln(e,t,n,o){
110
+ const r=re(e,o);!r||r.id!==o||(t.blocks??(t.blocks={}),t.blocks[o]={tableId:n,content:ke(r),blockIds:ue(r)})}function Vr(e,t,n,o){const r=Re(e,String(o.tableId??""));if(!r)return!1;const i=jt(r),a=t.geometries?.[r.
111
+ id]===i;if(n==="insert_table_row"||n==="insert_table_column")return a;let l,c=!1;if(n==="remove_table_row"){const b=_n(r,o);if("error"in b)return!1;l=b.rowIndices,c=b.byId}if(!c&&!a)return!1;const d=o.
112
+ columnIndex;if(!l&&(!Number.isInteger(d)||Number(d)<0))return!1;const u=Ce(r).cells.filter(b=>l?l.some(y=>b.row<=y&&b.row+b.rowSpan>y):b.col<=Number(d)&&b.col+b.colSpan>Number(d)),f=Ye(e,t,new Set);return u.
113
+ length>0&&u.every(b=>f.has(b.cell.id)&&(c||!l||t.cells[bt(r.id,r.children[b.row].id,b.col)]?.revision===i))}function Un(){return{cells:{}}}function Re(e,t){const n=re(e,t);return n?.type==="table"&&n.
114
+ id===t?n:null}function Le(e,t){if(!e||typeof e!="object")return;const n=e;n.type==="table"&&t(n);for(const o of Ot(e))Le(o,t)}const bt=(e,t,n)=>JSON.stringify([e,t,n]),Lt=(e,t)=>ke([t,e.columnWidths]),
115
+ Ut=(e,t)=>JSON.stringify(e.children.slice(t.row,t.row+t.rowSpan).map(n=>n.id));function Xr(e,t,n,o){return o.cellId===n.cell.id&&o.rowId===e.children[n.row].id&&o.column===n.col&&o.content===ke(n.cell)&&
116
+ o.coveredRows===Ut(e,n)&&o.geometry===Lt(e,t.cols)&&o.rowSpan===n.rowSpan&&o.colSpan===n.colSpan}function _t(e,t,n,o){const r=Re(e,n);if(!r)return;const i=Ce(r),a=o?new Set(o):null,l=Lt(r,i.cols),c=jt(
117
+ r);for(const d of i.cells){if(a&&!a.has(d.cell.id))continue;const u=r.children[d.row].id;t.cells[bt(n,u,d.col)]={tableId:n,rowId:u,column:d.col,cellId:d.cell.id,rowSpan:d.rowSpan,colSpan:d.colSpan,geometry:l,
118
+ coveredRows:Ut(r,d),content:ke(d.cell),blockIds:ue(d.cell),revision:c}}}function Ft(e){if(e.children.length!==1)return null;const t=e.children[0];if(t.type!=="paragraph"||!t.children.every(o=>o.type===
119
+ "text"))return null;let n;for(const o of t.children){const r=ft(o.marks??{});if(Object.keys(r).some(a=>!Wr.has(a)))return null;if(!o.text)continue;const i=Hr(r);if(n!==void 0&&i!==n)return null;n=i}return t}
120
+ const Qr=Ze,Zr=e=>`[[${e}]] `;function Yr(e){const t=[];for(const d of e.children)Le(d,u=>t.push(u.id));if(t.length)return{error:`Cell contains nested tables (${t.slice(0,20).join(", ")}). Read them w\
121
+ ith read_table(table_id=...) and read the cell's other blocks with read_specific_blocks; cell_text does not flatten nested tables.`};const n=[],o=[],r=(d,u)=>{n.push(d),o.push(u??"")},i=d=>d.map(u=>u.
122
+ type==="text"?u.text??"":"").join(""),a=d=>{if(d.type==="paragraph"){r(i(d.children),d.id);return}if(d.type==="list"){const f=[];for(const b of d.children){const y=Math.max(0,b.indentLevel??0);f.length=
123
+ y+1;const R=y===0?d.startNumber??1:1;f[y]=f[y]===void 0?R:f[y]+1;const L=d.variant==="ordered"?`${f[y]}. `:d.variant==="todo"?b.checked?"[x] ":"[ ] ":"• ";r(`${" ".repeat(y)}${L}${i(b.children)}`,b.
124
+ id??d.id)}return}const u=d;if(typeof u.content=="string"){r(u.content,u.id);return}if(Array.isArray(u.children)&&u.children.length){for(const f of u.children)a(f);return}r(`[${u.type}${u.id?` ${u.id}`:
125
+ ""}]`,u.id)};for(const d of e.children)a(d);const l=[];let c=0;return{text:n.map((d,u)=>{const f=o[u],b=!!f&&l.at(-1)?.id!==f;b&&l.push({id:f,start:c});const y=b?`${Zr(f)}${d}`:d;return c+=y.length+1,
126
+ y}).join(`
126
127
  `),segments:l}}function zt(e){return e.children.map(t=>t.type==="paragraph"?t.children.map(n=>n.type==="text"?n.text:"").join(""):"").join(`
127
128
  `)}function et(e){return e.children.every(t=>t.type==="paragraph"&&t.children.every(n=>n.type==="text"&&!n.text.replace(/[\s\u200b\u200c\u200d\ufeff]/gu,"")))}const Fn=e=>`<span>${e.replaceAll("&","&a\
128
129
  mp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll(`
129
130
  `,"<br>").replaceAll(" ","&#9;")}</span>`;function zn(e,t,n,o={}){const r={actions:[],targets:[],errors:[],skipped:[],unchanged:[]},i=n,a=b=>(r.errors.push({row_id:"",column:-1,reason:b}),r);if(!i||typeof i.
130
131
  table_id!="string")return a("table_id is required.");if(i.mode!=="fill_if_empty"&&i.mode!=="replace")return a("mode must be fill_if_empty or replace.");if(!Array.isArray(i.cells)||!i.cells.length||i.cells.
131
- length>En)return a(`Provide 1-${En} cells.`);if(new TextEncoder().encode(JSON.stringify(i)).length>Ur)return a("Cell-edit arguments exceed 32KiB; split the batch.");const l=Ne(e,i.table_id);if(!l)return a(
132
- "Unknown table_id; read the current table first.");const c=Ce(l),d=Lt(l,c.cols),u=new Set,f=new Map;for(const b of ue(e))f.set(b,(f.get(b)??0)+1);for(const b of i.cells){const y=b,N=typeof y?.row_id==
133
- "string"?y.row_id:"",L=typeof y?.column=="number"?y.column:-1,O=q=>({row_id:N,column:L,reason:q});if(!N||!Number.isInteger(L)||L<0||typeof y?.text!="string"){r.errors.push(O("Each item requires row_id\
134
- , a zero-based integer column, and exact text."));continue}const T=bt(l.id,N,L);if(u.has(T)){r.errors.push(O("Duplicate target in batch."));continue}u.add(T);const D=l.children.findIndex(q=>q.id===N),
135
- A=c.occupancy[D]?.[L];if(!A||A.row!==D||A.col!==L){r.errors.push(O("Unknown row/column or covered merge position; target the anchor cell."));continue}const M=t.cells[T];if(!M&&zt(A.cell).length>Xr){r.
132
+ length>En)return a(`Provide 1-${En} cells.`);if(new TextEncoder().encode(JSON.stringify(i)).length>Fr)return a("Cell-edit arguments exceed 32KiB; split the batch.");const l=Re(e,i.table_id);if(!l)return a(
133
+ "Unknown table_id; read the current table first.");const c=Ce(l),d=Lt(l,c.cols),u=new Set,f=new Map;for(const b of ue(e))f.set(b,(f.get(b)??0)+1);for(const b of i.cells){const y=b,R=typeof y?.row_id==
134
+ "string"?y.row_id:"",L=typeof y?.column=="number"?y.column:-1,O=q=>({row_id:R,column:L,reason:q});if(!R||!Number.isInteger(L)||L<0||typeof y?.text!="string"){r.errors.push(O("Each item requires row_id\
135
+ , a zero-based integer column, and exact text."));continue}const T=bt(l.id,R,L);if(u.has(T)){r.errors.push(O("Duplicate target in batch."));continue}u.add(T);const D=l.children.findIndex(q=>q.id===R),
136
+ A=c.occupancy[D]?.[L];if(!A||A.row!==D||A.col!==L){r.errors.push(O("Unknown row/column or covered merge position; target the anchor cell."));continue}const M=t.cells[T];if(!M&&zt(A.cell).length>Qr){r.
136
137
  errors.push(O(`Cell ${A.cell.id} is too large for any table read to deliver, so edit_table_cells cannot target it. To change a passage inside it, find the nested block with read_table mode=cell_text, \
137
138
  read that block with read_specific_blocks, then edit the block ID with replace.`));continue}if(!M){r.errors.push(O("Cell was not delivered in this request. Read it before editing."));continue}if(ue(A.
138
- cell).some(q=>f.get(q)!==1)||f.get(N)!==1){r.errors.push(O("Duplicate document identity makes this target ambiguous; repair the malformed table before editing."));continue}if(M.cellId!==A.cell.id||M.rowSpan!==
139
+ cell).some(q=>f.get(q)!==1)||f.get(R)!==1){r.errors.push(O("Duplicate document identity makes this target ambiguous; repair the malformed table before editing."));continue}if(M.cellId!==A.cell.id||M.rowSpan!==
139
140
  A.rowSpan||M.colSpan!==A.colSpan||M.coveredRows!==Ut(l,A)||M.geometry!==d){r.errors.push(O("Table geometry or anchor identity changed since delivery; reread."));continue}if(o.responseTurn!==void 0&&t.
140
141
  responseClaims?.turn===o.responseTurn&&t.responseClaims.cellIds.includes(A.cell.id)){r.errors.push(O("Another call in this response already edited this cell; inspect the result before editing again."));
141
142
  continue}if(o.hasForeignSuggestion?.(A.cell)){(i.mode==="fill_if_empty"?r.skipped:r.errors).push(O("Cell has a conflicting pending suggestion from another author; preserved."));continue}if(i.mode==="f\
142
143
  ill_if_empty"&&!et(A.cell)){r.skipped.push(O("Cell is non-empty; preserved."));continue}if(M.content!==ke(A.cell)){r.errors.push(O("Cell changed after delivery; reread before replacing."));continue}const I=Ft(
143
144
  A.cell);if(!I){r.errors.push(O("Cell contains rich or multi-block content. Use its nested block IDs with the existing rich editing tools."));continue}const C=zt(A.cell);if(C===y.text){r.unchanged.push(
144
- O("Already equal."));continue}r.actions.push({name:"replace",arguments:{id:I.id,find:C?Fn(C):"",replace:Fn(y.text)}}),r.targets.push({row_id:N,column:L,cellId:A.cell.id,paragraphId:I.id})}return r.errors.
145
- length&&(r.actions=[],r.targets=[]),r}function Yr(e){const t=[/"([^"\n]{2,300})"/g,/“([^”\n]{2,300})”/g,/‘([^’\n]{2,300})’/g,/(?<![\p{L}\p{N}])'([^'\n]{2,300})'(?![\p{L}\p{N}])/gu],n=new Set;
146
- for(const o of t)for(const r of e.matchAll(o)){const i=r[1].trim();i&&n.add(i)}return[...n]}function ei(e,t,n){const o=qt(e,t);if(o.length!==1)return null;const[r]=o,i=fn(t).text.trim();if(i.length<3)
147
- return null;const a=Le(e),l=Yr(n).filter(d=>{const u=fn(d).text.trim();return u.length>i.length&&(u.startsWith(i)||u.endsWith(i))}),c=new Set;for(const d of l){const u=qt(e,d);if(u.length!==1)continue;
148
- const[f]=u;f.start<=r.start&&f.end>=r.end&&c.add(a.slice(f.start,f.end))}return c.size===1?[...c][0]:null}const ti="outside_user_selection",ni=new Set(["replace","replace_all","replace_block","remove_\
145
+ O("Already equal."));continue}r.actions.push({name:"replace",arguments:{id:I.id,find:C?Fn(C):"",replace:Fn(y.text)}}),r.targets.push({row_id:R,column:L,cellId:A.cell.id,paragraphId:I.id})}return r.errors.
146
+ length&&(r.actions=[],r.targets=[]),r}function ei(e){const t=[/"([^"\n]{2,300})"/g,/“([^”\n]{2,300})”/g,/‘([^’\n]{2,300})’/g,/(?<![\p{L}\p{N}])'([^'\n]{2,300})'(?![\p{L}\p{N}])/gu],n=new Set;
147
+ for(const o of t)for(const r of e.matchAll(o)){const i=r[1].trim();i&&n.add(i)}return[...n]}function ti(e,t,n){const o=qt(e,t);if(o.length!==1)return null;const[r]=o,i=fn(t).text.trim();if(i.length<3)
148
+ return null;const a=Xe(e),l=ei(n).filter(d=>{const u=fn(d).text.trim();return u.length>i.length&&(u.startsWith(i)||u.endsWith(i))}),c=new Set;for(const d of l){const u=qt(e,d);if(u.length!==1)continue;
149
+ const[f]=u;f.start<=r.start&&f.end>=r.end&&c.add(a.slice(f.start,f.end))}return c.size===1?[...c][0]:null}const ni="outside_user_selection",oi=new Set(["replace","replace_all","replace_block","remove_\
149
150
  block","style_blocks","clear_formatting","edit_table_cells"]);function Jn(e){const t=[],n=(o,r)=>{const i=o,a=typeof i.id=="string"?i.id:null;if(a&&t.push({id:a,ancestors:r}),Array.isArray(i.children))
150
- for(const l of i.children)n(l,a?[...r,a]:r)};for(const o of e.children)n(o,[]);return t}function oi(e,t){const n=Jn(e),o=new Map(n.map((a,l)=>[a.id,l])),r=new Set,i=new Set;for(const a of t){const l=o.
151
+ for(const l of i.children)n(l,a?[...r,a]:r)};for(const o of e.children)n(o,[]);return t}function ri(e,t){const n=Jn(e),o=new Map(n.map((a,l)=>[a.id,l])),r=new Set,i=new Set;for(const a of t){const l=o.
151
152
  get(a.startBlock),c=o.get(a.endBlock);if(l===void 0||c===void 0)return null;const[d,u]=l<=c?[l,c]:[c,l];for(let b=d;b<=u;b++)r.add(n[b].id);const f=n[u].id;for(let b=u+1;b<n.length&&n[b].ancestors.includes(
152
- f);b++)r.add(n[b].id);for(const b of[n[d].id,f])for(const y of n[o.get(b)].ancestors)i.add(y)}return{selected:r,containers:i}}function ri(e,t){let n=null;const o=r=>{if(n)return;const i=r;if(i.type===
153
- "table"&&i.id===t){n=r;return}i.children?.forEach(o)};return e.children.forEach(o),n}function ii(e,t,n){if(!ni.has(t)||!n)return[];const o=new Set,r=i=>{typeof i=="string"&&i.trim()&&o.add(i.trim())};
154
- if(t==="edit_table_cells"){const i=typeof n.table_id=="string"?ri(e,n.table_id):null;if(!i||!Array.isArray(n.cells))return[];const a=Ce(i);for(const l of n.cells){const c=l,d=i.children.findIndex(f=>f.
153
+ f);b++)r.add(n[b].id);for(const b of[n[d].id,f])for(const y of n[o.get(b)].ancestors)i.add(y)}return{selected:r,containers:i}}function ii(e,t){let n=null;const o=r=>{if(n)return;const i=r;if(i.type===
154
+ "table"&&i.id===t){n=r;return}i.children?.forEach(o)};return e.children.forEach(o),n}function si(e,t,n){if(!oi.has(t)||!n)return[];const o=new Set,r=i=>{typeof i=="string"&&i.trim()&&o.add(i.trim())};
155
+ if(t==="edit_table_cells"){const i=typeof n.table_id=="string"?ii(e,n.table_id):null;if(!i||!Array.isArray(n.cells))return[];const a=Ce(i);for(const l of n.cells){const c=l,d=i.children.findIndex(f=>f.
155
156
  id===c?.row_id),u=typeof c?.column=="number"?c.column:-1;r(a.occupancy[d]?.[u]?.cell.id)}return[...o]}r(n.id);for(const i of["id","ids","block_ids"])Array.isArray(n[i])&&n[i].forEach(r);if(Array.isArray(
156
157
  n.replacements))for(const i of n.replacements)r(i?.id);if(Array.isArray(n.selectors)){for(const i of n.selectors)if(typeof i=="string"){const a=/^#([A-Za-z0-9_-]+)$/.exec(i.trim());a&&r(a[1])}}return[
157
- ...o]}function si(e,t,n){if(!n.length||!t.length)return[];const o=oi(e,t);if(!o)return[];const r=Jn(e),i=new Map(r.map(c=>[c.id,c])),a=new Map,l=c=>{const d=c;typeof d.id=="string"&&a.set(d.id,c),d.children?.
158
+ ...o]}function ai(e,t,n){if(!n.length||!t.length)return[];const o=ri(e,t);if(!o)return[];const r=Jn(e),i=new Map(r.map(c=>[c.id,c])),a=new Map,l=c=>{const d=c;typeof d.id=="string"&&a.set(d.id,c),d.children?.
158
159
  forEach(l)};return e.children.forEach(l),n.filter(c=>{if(!i.get(c)||o.selected.has(c)||o.containers.has(c)||r.some(u=>u.ancestors.includes(c)&&o.selected.has(u.id)))return!1;const d=a.get(c);return(d?.
159
- structuralSuggestionKind??d?.diffState)!=="insert"})}function ai(e){const t=e.map(n=>n.selectedText.replace(/\s+/g," ").trim()).join(" … ");return t.length>160?`${t.slice(0,157)}...`:t}const li="emp\
160
+ structuralSuggestionKind??d?.diffState)!=="insert"})}function li(e){const t=e.map(n=>n.selectedText.replace(/\s+/g," ").trim()).join(" … ");return t.length>160?`${t.slice(0,157)}...`:t}const ci="emp\
160
161
  ty_mutation_arguments",yt="To change colors, borders, shading, fonts, alignment or other formatting, use style_blocks",Wn="to delete blocks, use remove_blocks",Jt="to add a table column use insert_tab\
161
- le_column, and to add rows insert_table_row",Hn="to swap or reorder blocks or images, use move_blocks";function ci(e){return typeof e=="string"?e.trim().length===0:e==null}function Wt(e){return e==null?
162
- !0:typeof e=="string"?e.trim().length===0:Array.isArray(e)?e.length===0||e.every(ci):!1}function Gn(e){return typeof e=="string"&&e.trim().length>0}function ve(e,t,n){return`${e} was called with an em\
163
- pty ${t}, so nothing was changed. ${n}`}function di(e,t){const n=t&&typeof t=="object"?t:{};switch(e){case"replace_block":return Wt(n.content)?ve("replace_block","content array",`It never removes or r\
162
+ le_column, and to add rows insert_table_row",Hn="to swap or reorder blocks or images, use move_blocks";function di(e){return typeof e=="string"?e.trim().length===0:e==null}function Wt(e){return e==null?
163
+ !0:typeof e=="string"?e.trim().length===0:Array.isArray(e)?e.length===0||e.every(di):!1}function Gn(e){return typeof e=="string"&&e.trim().length>0}function ve(e,t,n){return`${e} was called with an em\
164
+ pty ${t}, so nothing was changed. ${n}`}function ui(e,t){const n=t&&typeof t=="object"?t:{};switch(e){case"replace_block":return Wt(n.content)?ve("replace_block","content array",`It never removes or r\
164
165
  estyles a block. ${yt}; ${Wn}; ${Jt}; ${Hn}. Otherwise call replace_block again with the complete replacement HTML.`):null;case"insert_block":return Wt(n.content)?ve("insert_block","content array",`Pa\
165
166
  ss the HTML of each block to insert. ${yt}; ${Jt}.`):null;case"replace":case"replace_many":{const o=n.replacements;return Array.isArray(o)&&o.length===0?ve(e,"replacements array",`Each replacement nee\
166
167
  ds find and replace text. ${yt}; ${Hn}; ${Wn}.`):null}case"edit_table_cells":return Array.isArray(n.cells)&&n.cells.length===0?ve("edit_table_cells","cells array",`List each cell to write as {row_id, \
@@ -170,330 +171,328 @@ _table_row":case"remove_table_rows":{const o=n.rowIds,r=n.rowIndices,i=o==null||
170
171
  wIds list","List the row IDs (<tr id> / row_id) of the rows to remove. To clear cell text instead, use edit_table_cells."):null}case"move_blocks":return Array.isArray(n.block_ids)&&n.block_ids.length===
171
172
  0?ve("move_blocks","block_ids array","List the source block IDs in current document order, plus reference_id and position."):null;case"style_blocks":return Array.isArray(n.attrs)&&n.attrs.length===0?ve(
172
173
  "style_blocks","attrs array",'List each formatting change as {name, value}, e.g. {name: "color", value: "#c00000"}.'):Array.isArray(n.selectors)&&n.selectors.length===0?ve("style_blocks","selectors li\
173
- st","Name what to style, e.g. #blockId, #tableId td p, or p."):null;default:return null}}const Kn=50,Vn=200,Xn=5e3,ui=5e3,mi=8,hi=200,Qn=32*1024;function Zn(){return{version:1,nextTaskNumber:1,task:null}}
174
- const pi=new TextEncoder;function tt(e){return pi.encode(e).length}function Yn(e,t,n="…"){if(tt(e)<=t)return e;const o=Math.max(0,t-tt(n));let r=0,i="";for(const a of e){const l=tt(a);if(r+l>o)break;
175
- r+=l,i+=a}return i+n}function gi(e,t){const n=e.replace(/[\u0000-\u001f\u007f]+/gu," ").replace(/\s+/gu," ").trim();return Yn(n,t)}const wt=e=>typeof e=="number"&&Number.isInteger(e)&&e>=0,fi=e=>wt(e)&&
176
- e>0,kt=e=>typeof e=="string";function bi(e,t,n){const o=tt(t),r=o>Qn;return{requestId:e,text:r?Yn(t,Qn,""):t,originalBytes:o,truncated:r,...typeof n=="number"&&Number.isFinite(n)?{timestamp:n}:{}}}function _i(e){
174
+ st","Name what to style, e.g. #blockId, #tableId td p, or p."):null;default:return null}}const Kn=50,Vn=200,Xn=5e3,mi=5e3,hi=8,pi=200,Qn=32*1024;function Zn(){return{version:1,nextTaskNumber:1,task:null}}
175
+ const gi=new TextEncoder;function tt(e){return gi.encode(e).length}function Yn(e,t,n="…"){if(tt(e)<=t)return e;const o=Math.max(0,t-tt(n));let r=0,i="";for(const a of e){const l=tt(a);if(r+l>o)break;
176
+ r+=l,i+=a}return i+n}function fi(e,t){const n=e.replace(/[\u0000-\u001f\u007f]+/gu," ").replace(/\s+/gu," ").trim();return Yn(n,t)}const wt=e=>typeof e=="number"&&Number.isInteger(e)&&e>=0,bi=e=>wt(e)&&
177
+ e>0,kt=e=>typeof e=="string";function _i(e,t,n){const o=tt(t),r=o>Qn;return{requestId:e,text:r?Yn(t,Qn,""):t,originalBytes:o,truncated:r,...typeof n=="number"&&Number.isFinite(n)?{timestamp:n}:{}}}function yi(e){
177
178
  for(let t=e.length-1;t>=0;t--){const n=e[t];if(n.role!=="user")continue;const o=It(n);if(o.trim())return`${n.requestId??"?"}|${n.timestamp??""}|${ke(o)}`}}function eo(e,t,n){const o=e??{};if(!(t in o)&&
178
- Object.keys(o).length>=mi)return o;const r=new Set(o[t]??[]);for(const l of n)r.delete(l),r.add(l);const i=Object.entries(o).filter(([l])=>l!==t).reduce((l,[,c])=>l+c.length,0),a=Math.max(0,ui-i);return{
179
- ...o,[t]:a?[...r].slice(-a):[]}}const yi=["task_kind","scope_row_start","scope_row_count","scope_columns","source_attachment_id"];function vt(e){return e==null?!1:typeof e=="string"?e.trim().length>0:
180
- Array.isArray(e)?e.length>0:!0}function It(e){return typeof e.content=="string"?e.content:""}function wi(e,t){const n=e.find(o=>o.role==="user"&&o.requestId===t&&It(o).trim());if(n)return n;for(let o=e.
181
- length-1;o>=0;o--){const r=e[o];if(r.role==="user"&&It(r).trim())return r}}function ki(e,t,n,o,r,i,a){const l={cells:0,rows:[],columns:[]};if(!e||e.requestId!==i||e.userMarker!==void 0&&e.userMarker!==
182
- a)return l;const c=(e.guardedCellIds??e.cellIds)?.[t.id]??[],d=new Set,u=new Set;let f=0;for(const b of c){const y=n.byId.get(b);if(!y||et(y.cell))continue;let N=!1;for(let L=y.row;L<y.row+y.rowSpan&&
183
- !N;L++)if(o.has(t.children[L]?.id??""))for(let O=y.col;O<y.col+y.colSpan;O++)r.has(O)&&(N=!0);N||(f++,d.add(y.row),u.add(y.col))}return{cells:f,rows:[...d].sort((b,y)=>b-y),columns:[...u].sort((b,y)=>b-
184
- y)}}function vi(e,t,n,o){const r=yi.some(f=>vt(n[f])),i=n.deliberate_blanks,a=vt(i);if(!r&&!a)return{state:e,declared:!1};const l=kt(n.table_id)?n.table_id:"",c=Ne(t,l);if(!c)return{error:"Unknown tab\
179
+ Object.keys(o).length>=hi)return o;const r=new Set(o[t]??[]);for(const l of n)r.delete(l),r.add(l);const i=Object.entries(o).filter(([l])=>l!==t).reduce((l,[,c])=>l+c.length,0),a=Math.max(0,mi-i);return{
180
+ ...o,[t]:a?[...r].slice(-a):[]}}const wi=["task_kind","scope_row_start","scope_row_count","scope_columns","source_attachment_id"];function vt(e){return e==null?!1:typeof e=="string"?e.trim().length>0:
181
+ Array.isArray(e)?e.length>0:!0}function It(e){return typeof e.content=="string"?e.content:""}function ki(e,t){const n=e.find(o=>o.role==="user"&&o.requestId===t&&It(o).trim());if(n)return n;for(let o=e.
182
+ length-1;o>=0;o--){const r=e[o];if(r.role==="user"&&It(r).trim())return r}}function vi(e,t,n,o,r,i,a){const l={cells:0,rows:[],columns:[]};if(!e||e.requestId!==i||e.userMarker!==void 0&&e.userMarker!==
183
+ a)return l;const c=(e.guardedCellIds??e.cellIds)?.[t.id]??[],d=new Set,u=new Set;let f=0;for(const b of c){const y=n.byId.get(b);if(!y||et(y.cell))continue;let R=!1;for(let L=y.row;L<y.row+y.rowSpan&&
184
+ !R;L++)if(o.has(t.children[L]?.id??""))for(let O=y.col;O<y.col+y.colSpan;O++)r.has(O)&&(R=!0);R||(f++,d.add(y.row),u.add(y.col))}return{cells:f,rows:[...d].sort((b,y)=>b-y),columns:[...u].sort((b,y)=>b-
185
+ y)}}function Ii(e,t,n,o){const r=wi.some(f=>vt(n[f])),i=n.deliberate_blanks,a=vt(i);if(!r&&!a)return{state:e,declared:!1};const l=kt(n.table_id)?n.table_id:"",c=Re(t,l);if(!c)return{error:"Unknown tab\
185
186
  le_id; no task scope was recorded."};const d=Ce(c);let u;if(r){const f=n.task_kind;if(f!=="fill"&&f!=="transform")return{error:"Declaring a table task requires task_kind (fill or transform) together w\
186
- ith scope_row_start, scope_row_count and scope_columns; no scope was recorded."};const b=n.scope_row_start,y=n.scope_row_count,N=n.scope_columns;if(!wt(b)||!fi(y)||!Array.isArray(N)||!N.length)return{
187
+ ith scope_row_start, scope_row_count and scope_columns; no scope was recorded."};const b=n.scope_row_start,y=n.scope_row_count,R=n.scope_columns;if(!wt(b)||!bi(y)||!Array.isArray(R)||!R.length)return{
187
188
  error:"A table task scope requires integer scope_row_start, scope_row_count >= 1 and a non-empty scope_columns array; no scope was recorded."};if(b+y>d.rows)return{error:`Task scope rows ${b}-${b+y-1}\
188
- exceed the table's ${d.rows} rows; no scope was recorded.`};if(y>Xn)return{error:`A table task scope may cover at most ${Xn} rows; declare the scope in parts.`};if(!N.every(wt)||new Set(N).size!==N.length||
189
- N.some(j=>j>=d.cols))return{error:`scope_columns must be unique 0-based columns below ${d.cols}; no scope was recorded.`};let L;if(vt(n.source_attachment_id)){if(!kt(n.source_attachment_id)||!n.source_attachment_id.
189
+ exceed the table's ${d.rows} rows; no scope was recorded.`};if(y>Xn)return{error:`A table task scope may cover at most ${Xn} rows; declare the scope in parts.`};if(!R.every(wt)||new Set(R).size!==R.length||
190
+ R.some(j=>j>=d.cols))return{error:`scope_columns must be unique 0-based columns below ${d.cols}; no scope was recorded.`};let L;if(vt(n.source_attachment_id)){if(!kt(n.source_attachment_id)||!n.source_attachment_id.
190
191
  trim()||tt(n.source_attachment_id)>200)return{error:"source_attachment_id must be a non-empty attachment ID; no scope was recorded."};if(o.attachmentExists&&!o.attachmentExists(n.source_attachment_id))
191
192
  return{error:`Attachment '${n.source_attachment_id}' is not available in this conversation; no scope was recorded.`};L=n.source_attachment_id}const O=c.children.slice(b,b+y).map(j=>j.id),T=e.task,D=T&&
192
- T.tableId===c.id&&T.kind===f,A=wi(o.chatHistory,o.requestId),M=D?T.originRequest:bi(typeof A?.requestId=="number"?A.requestId:o.requestId,A?It(A):"",A?.timestamp),I=new Set(O),C=new Set(N),q=_i(o.chatHistory);
193
- let J=q;if(D){const j=new Set(c.children.map(pe=>pe.id)),oe=T.rowIds.filter(pe=>j.has(pe)&&!I.has(pe)),h=T.columns.filter(pe=>!C.has(pe)),$=oe.length>0||h.length>0,we=!$&&O.length===T.rowIds.length&&N.
193
+ T.tableId===c.id&&T.kind===f,A=ki(o.chatHistory,o.requestId),M=D?T.originRequest:_i(typeof A?.requestId=="number"?A.requestId:o.requestId,A?It(A):"",A?.timestamp),I=new Set(O),C=new Set(R),q=yi(o.chatHistory);
194
+ let J=q;if(D){const j=new Set(c.children.map(pe=>pe.id)),oe=T.rowIds.filter(pe=>j.has(pe)&&!I.has(pe)),h=T.columns.filter(pe=>!C.has(pe)),$=oe.length>0||h.length>0,we=!$&&O.length===T.rowIds.length&&R.
194
195
  length===T.columns.length;if($&&T.scopeUserMarker!==void 0&&T.scopeUserMarker===q)return{error:`This declaration would drop ${[oe.length?`${oe.length} rows`:"",h.length?`columns ${h.join(",")}`:""].filter(
195
196
  Boolean).join(" and ")} from the declared task scope without a newer user instruction. The task scope must cover the user's whole request: repeat the full scope (or omit the scope fields) and use row_\
196
- start/row_count or row_ids for a smaller read window. The declared scope is unchanged.`};we&&(J=T.scopeUserMarker??q)}else{const j=ki(e.localEdits,c,d,I,C,o.requestId,q);if(j.cells)return{error:`This \
197
- first task declaration omits ${j.cells} cell${j.cells===1?"":"s"} this request already edited in this table (row_index ${xi(j.rows,12)}; columns ${j.columns.join(",")}). The task scope must cover the \
197
+ start/row_count or row_ids for a smaller read window. The declared scope is unchanged.`};we&&(J=T.scopeUserMarker??q)}else{const j=vi(e.localEdits,c,d,I,C,o.requestId,q);if(j.cells)return{error:`This \
198
+ first task declaration omits ${j.cells} cell${j.cells===1?"":"s"} this request already edited in this table (row_index ${Si(j.rows,12)}; columns ${j.columns.join(",")}). The task scope must cover the \
198
199
  user's whole request, including work already done: declare the full scope and use row_start/row_count or row_ids for a smaller read window. No scope was recorded.`}}const z=L??(D?T.sourceAttachmentId:
199
- void 0);u={id:D?T.id:`table_task_${e.nextTaskNumber}`,tableId:c.id,kind:f,rowIds:O,declaredRowStart:b,columns:[...N].sort((j,oe)=>j-oe),...z?{sourceAttachmentId:z}:{},deliberateBlanks:D?T.deliberateBlanks.
200
+ void 0);u={id:D?T.id:`table_task_${e.nextTaskNumber}`,tableId:c.id,kind:f,rowIds:O,declaredRowStart:b,columns:[...R].sort((j,oe)=>j-oe),...z?{sourceAttachmentId:z}:{},deliberateBlanks:D?T.deliberateBlanks.
200
201
  filter(j=>I.has(j.rowId)&&C.has(j.column)):[],touchedCellIds:D?T.touchedCellIds:[],originRequest:M,...D&&T.latestSteering?{latestSteering:T.latestSteering}:{},declaredRequestId:o.requestId,lastActivityRequestId:o.
201
202
  requestId,...J?{scopeUserMarker:J}:{}}}else{const f=e.task;if(!f||f.tableId!==c.id)return{error:"deliberate_blanks require a declared task for this table; include task_kind and scope_* first."};u={...f,
202
203
  deliberateBlanks:[...f.deliberateBlanks],lastActivityRequestId:o.requestId}}if(a){if(!Array.isArray(i)||i.length>Kn)return{error:`deliberate_blanks must be an array of at most ${Kn} cells; no scope wa\
203
- s recorded.`};const f=new Set(u.rowIds),b=new Set(u.columns),y=new Set,N=[];for(const O of i){const T=O,D=`${String(T?.row_id)}:${String(T?.column)}`;if(!T||!kt(T.row_id)||!wt(T.column)||!kt(T.reason)||
204
+ s recorded.`};const f=new Set(u.rowIds),b=new Set(u.columns),y=new Set,R=[];for(const O of i){const T=O,D=`${String(T?.row_id)}:${String(T?.column)}`;if(!T||!kt(T.row_id)||!wt(T.column)||!kt(T.reason)||
204
205
  !T.reason.trim())return{error:`Each deliberate blank needs row_id, column and a non-empty reason (${D}); no scope was recorded.`};if(!f.has(T.row_id)||!b.has(T.column))return{error:`Deliberate blank ${D}\
205
206
  is outside the declared task scope; no scope was recorded.`};const A=c.children.findIndex(I=>I.id===T.row_id),M=d.occupancy[A]?.[T.column];if(!M||M.row!==A||M.col!==T.column)return{error:`Deliberate \
206
- blank ${D} is a covered merge position or unplaced cell; name the anchor cell.`};if(y.has(D))return{error:`Duplicate deliberate blank ${D}; no scope was recorded.`};y.add(D),N.push({rowId:T.row_id,column:T.
207
- column,reason:gi(T.reason,hi)})}const L=new Map(u.deliberateBlanks.map(O=>[`${O.rowId}:${O.column}`,O]));for(const O of N)L.set(`${O.rowId}:${O.column}`,O);if(L.size>Vn)return{error:`A task may record\
207
+ blank ${D} is a covered merge position or unplaced cell; name the anchor cell.`};if(y.has(D))return{error:`Duplicate deliberate blank ${D}; no scope was recorded.`};y.add(D),R.push({rowId:T.row_id,column:T.
208
+ column,reason:fi(T.reason,pi)})}const L=new Map(u.deliberateBlanks.map(O=>[`${O.rowId}:${O.column}`,O]));for(const O of R)L.set(`${O.rowId}:${O.column}`,O);if(L.size>Vn)return{error:`A task may record\
208
209
  at most ${Vn} deliberate blanks; no scope was recorded.`};u.deliberateBlanks=[...L.values()]}return{state:{version:1,nextTaskNumber:u.id!==e.task?.id?e.nextTaskNumber+1:e.nextTaskNumber,task:u,...e.localEdits?
209
- {localEdits:e.localEdits}:{}},declared:!0}}function Ii(e,t){if(!t.cellIds.length)return e;const n=e.localEdits?.requestId===t.requestId?e.localEdits:{requestId:t.requestId,tables:{}},o={...n,tables:{...n.
210
+ {localEdits:e.localEdits}:{}},declared:!0}}function xi(e,t){if(!t.cellIds.length)return e;const n=e.localEdits?.requestId===t.requestId?e.localEdits:{requestId:t.requestId,tables:{}},o={...n,tables:{...n.
210
211
  tables,[t.tableId]:(n.tables[t.tableId]??0)+t.cellIds.length},cellIds:eo(n.cellIds,t.tableId,t.cellIds),...n.guardedCellIds?{guardedCellIds:eo(n.guardedCellIds,t.tableId,t.cellIds)}:{}},r=e.task;if(!r||
211
212
  r.tableId!==t.tableId)return{...e,localEdits:o};const i=[...new Set([...r.touchedCellIds,...t.cellIds])].slice(-5e3);return{...e,localEdits:o,task:{...r,touchedCellIds:i,lastActivityRequestId:t.requestId}}}
212
- function xi(e,t){if(!e.length)return"none";const n=[];let o=e[0],r=e[0];for(const i of e.slice(1)){if(i===r+1){r=i;continue}n.push(o===r?`${o}`:`${o}-${r}`),o=r=i}return n.push(o===r?`${o}`:`${o}-${r}`),
213
- n.length<=t?n.join(","):`${n.slice(0,t).join(",")} +${n.length-t} more ranges`}const to=50,Si="out_of_context_edit";function $i(e){const{toolCall:t,docBefore:n,isTargetAllowed:o}=e;if(t.name!=="remove\
213
+ function Si(e,t){if(!e.length)return"none";const n=[];let o=e[0],r=e[0];for(const i of e.slice(1)){if(i===r+1){r=i;continue}n.push(o===r?`${o}`:`${o}-${r}`),o=r=i}return n.push(o===r?`${o}`:`${o}-${r}`),
214
+ n.length<=t?n.join(","):`${n.slice(0,t).join(",")} +${n.length-t} more ranges`}const to=50,$i="out_of_context_edit";function Ci(e){const{toolCall:t,docBefore:n,isTargetAllowed:o}=e;if(t.name!=="remove\
214
215
  _block")return null;const r=t.arguments;if(!r||typeof r!="object")return null;const i=r.through_end;if(i==null||i===!1)return null;if(i!==!0)return{toolCall:t,targetBlockIds:[],error:"remove_blocks th\
215
216
  rough_end must be true when provided."};const a=r.id,l=r.count,c=r.ids,d=r.search_result_id;if(typeof a!="string"||a.trim().length===0)return{toolCall:t,targetBlockIds:[],error:"remove_blocks through_\
216
217
  end requires a non-empty top-level id."};if(l!=null||c!=null||d!=null)return{toolCall:t,targetBlockIds:[],error:"remove_blocks through_end is mutually exclusive with count, ids, and search_result_id."};
217
218
  const u=a.trim(),f=Ae(n,u);if(f<0||n.children[f]?.id!==u)return{toolCall:t,targetBlockIds:[],error:`remove_blocks through_end target '${u}' must be a current top-level block.`};if(!o(u))return{toolCall:t,
218
- targetBlockIds:[],error:`remove_blocks through_end start '${u}' is outside the request-level document context. Read or search for that boundary block first, then retry.`,errorCode:Si};const b=n.children.
219
- slice(f).map(y=>y.id).filter(y=>typeof y=="string"&&y.length>0);return{toolCall:{...t,arguments:{id:u,count:b.length}},targetBlockIds:b}}function Ci(e,t,n){if(e.name!=="remove_block")return{actions:[e]};
219
+ targetBlockIds:[],error:`remove_blocks through_end start '${u}' is outside the request-level document context. Read or search for that boundary block first, then retry.`,errorCode:$i};const b=n.children.
220
+ slice(f).map(y=>y.id).filter(y=>typeof y=="string"&&y.length>0);return{toolCall:{...t,arguments:{id:u,count:b.length}},targetBlockIds:b}}function Ai(e,t,n){if(e.name!=="remove_block")return{actions:[e]};
220
221
  const o=e.arguments;if(!o||typeof o!="object")return{actions:[],error:"remove_blocks requires object arguments"};const r=o.ids;if(r==null)return{actions:[e]};if(typeof o.id=="string")return{actions:[],
221
222
  error:"remove_blocks accepts either id + count or ids, not both."};if(!Array.isArray(r)||r.length===0)return{actions:[],error:"remove_blocks ids must be a non-empty array"};if(r.length>to)return{actions:[],
222
223
  error:`remove_blocks supports at most ${to} exact IDs per call`};const i=[],a=new Set;for(const c of r){if(typeof c!="string"||c.trim().length===0)return{actions:[],error:"remove_blocks ids must all b\
223
224
  e non-empty strings"};const d=c.trim();if(!a.has(d)){if(!re(t,d))return{actions:[],error:`remove_blocks target '${d}' was not found`};if(!n(d))return{actions:[],error:`remove_blocks target '${d}' is o\
224
225
  utside the request-level document context. Read or search for that block first, then retry the exact ID batch.`};a.add(d),i.push(d)}}const l=i.filter(c=>ht(t,c)).length;return l>0&&l<i.length?{actions:[],
225
226
  error:"Remove footnotes/endnotes separately from main-document blocks. Pass only note IDs in this batch so each note and its references are removed together."}:{actions:i.map((c,d)=>({id:`${e.id||"rem\
226
- ove_block"}-${d+1}`,name:"remove_block",arguments:{id:c,count:1}}))}}const Ai=new Set(["replace_block","remove_block"]);function Ti(e,t){const n=vn(e,t);if(!n)return null;if(n===e){for(const o of[e.children,
227
- e.chrome??[],e.notes??[]])if(o.some(r=>r.id===t))return o;return null}return"children"in n?n.children:null}function qi(e){const{toolCall:t,docBefore:n}=e;if(!Ai.has(t.name))return null;const o=t.arguments;
228
- if(!o||typeof o!="object"||o.end_id==null)return null;const r=t.name==="remove_block"?"remove_blocks":t.name,i=N=>({toolCall:t,error:N}),{id:a,end_id:l}=o;if(typeof l!="string"||!l.trim())return i(`${r}\
229
- end_id must be a block ID.`);if(typeof a!="string"||!a.trim())return i(`${r} end_id requires id, the first block of the range.`);for(const N of["ids","search_result_id","through_end"])if(o[N]!=null&&
230
- o[N]!==!1)return i(`${r} end_id names a range from id; it cannot be combined with ${N}.`);const c=Ti(n,a),d=c?.findIndex(N=>N.id===a)??-1;if(!c||d===-1)return i(`${r} id '${a}' was not found in the do\
231
- cument.`);const u=c.findIndex(N=>N.id===l);if(u===-1)return i(re(n,l)?`${r} end_id '${l}' is not in the same container as id '${a}'. A range covers consecutive sibling blocks: use end_id from the same\
227
+ ove_block"}-${d+1}`,name:"remove_block",arguments:{id:c,count:1}}))}}const Ti=new Set(["replace_block","remove_block"]);function qi(e,t){const n=vn(e,t);if(!n)return null;if(n===e){for(const o of[e.children,
228
+ e.chrome??[],e.notes??[]])if(o.some(r=>r.id===t))return o;return null}return"children"in n?n.children:null}function Di(e){const{toolCall:t,docBefore:n}=e;if(!Ti.has(t.name))return null;const o=t.arguments;
229
+ if(!o||typeof o!="object"||o.end_id==null)return null;const r=t.name==="remove_block"?"remove_blocks":t.name,i=R=>({toolCall:t,error:R}),{id:a,end_id:l}=o;if(typeof l!="string"||!l.trim())return i(`${r}\
230
+ end_id must be a block ID.`);if(typeof a!="string"||!a.trim())return i(`${r} end_id requires id, the first block of the range.`);for(const R of["ids","search_result_id","through_end"])if(o[R]!=null&&
231
+ o[R]!==!1)return i(`${r} end_id names a range from id; it cannot be combined with ${R}.`);const c=qi(n,a),d=c?.findIndex(R=>R.id===a)??-1;if(!c||d===-1)return i(`${r} id '${a}' was not found in the do\
232
+ cument.`);const u=c.findIndex(R=>R.id===l);if(u===-1)return i(re(n,l)?`${r} end_id '${l}' is not in the same container as id '${a}'. A range covers consecutive sibling blocks: use end_id from the same\
232
233
  level (for content inside a table cell or list, target blocks in that cell or list).`:`${r} end_id '${l}' was not found in the document.`);if(u<d)return i(`${r} end_id '${l}' comes before id '${a}'. \
233
234
  Use the first block of the range as id and the last as end_id.`);const f=u-d+1;if(o.count!=null&&o.count!==f)return i(`${r} got count ${String(o.count)} but id '${a}' through end_id '${l}' is ${f} blo\
234
235
  cks. Pass only id and end_id.`);const{end_id:b,...y}=o;return{toolCall:{...t,arguments:{...y,count:f}}}}function no(e){const t=new URLSearchParams;e.query!==void 0&&t.set("q",e.query),t.set("includeCo\
235
236
  ntent","false");for(const n of["page","limit","currentFolderId","parentFolderId","sortBy","order"]){const o=e[n];o!=null&&o!==""&&t.set(n,String(o))}return e.includeFolders&&t.set("includeFolders","1"),
236
237
  t}function oo(e,t=10){const n=e,o=Array.isArray(n?.items)?n.items:[],r=i=>typeof i=="number"&&Number.isFinite(i)&&i>=0;return{items:o,totalCount:r(n?.pagination?.totalCount)?n.pagination.totalCount:o.
237
238
  length,totalPages:r(n?.pagination?.totalPages)?n.pagination.totalPages:Math.max(1,Math.ceil(o.length/Math.max(1,t))),hasMore:n?.pagination?.hasMore===!0}}function ro(e){return typeof e=="object"&&e!==
238
- null&&e.type==="doc"&&Array.isArray(e.children)}function Di(e,t=[]){const n=new Qe.Doc;Qe.applyUpdate(n,Nt(e));for(const o of t)o&&Qe.applyUpdate(n,Nt(o));return In(n)}function Pi({content:e,yjsState:t,
239
- yjsUpdates:n,source:o}){const r=Array.isArray(n)?n.filter(i=>i.length>0):[];if(typeof t=="string"&&t.length>0||r.length>0)try{if(typeof t=="string"&&t.length>0)return Di(t,r);const i=ro(e)?cr(e):new Qe.
240
- Doc;if(r.length>0){for(const a of r)Qe.applyUpdate(i,Nt(a));return In(i)}}catch(i){console.error(`[resolveDocRootFromSerializedState] Failed to decode yjs updates${o?` for ${o}`:""}`,i)}return ro(e)?e:
241
- null}const Ri="revise_conversations",Ni=2,io="conversations",nt="attachments";let qe=null;function so(){return typeof indexedDB<"u"}function ao(e){return qe||(qe=new Promise((t,n)=>{if(!so()){n(new Error(
242
- "IndexedDB not available"));return}const o=indexedDB.open(Ri,e??Ni);o.onerror=()=>{qe=null,n(o.error)},o.onblocked=()=>{console.warn("[LocalConversationStorage] Database upgrade blocked - close other \
239
+ null&&e.type==="doc"&&Array.isArray(e.children)}function Pi(e,t=[]){const n=new Qe.Doc;Qe.applyUpdate(n,Rt(e));for(const o of t)o&&Qe.applyUpdate(n,Rt(o));return In(n)}function Ni({content:e,yjsState:t,
240
+ yjsUpdates:n,source:o}){const r=Array.isArray(n)?n.filter(i=>i.length>0):[];if(typeof t=="string"&&t.length>0||r.length>0)try{if(typeof t=="string"&&t.length>0)return Pi(t,r);const i=ro(e)?cr(e):new Qe.
241
+ Doc;if(r.length>0){for(const a of r)Qe.applyUpdate(i,Rt(a));return In(i)}}catch(i){console.error(`[resolveDocRootFromSerializedState] Failed to decode yjs updates${o?` for ${o}`:""}`,i)}return ro(e)?e:
242
+ null}const Ri="revise_conversations",Mi=2,io="conversations",nt="attachments";let qe=null;function so(){return typeof indexedDB<"u"}function ao(e){return qe||(qe=new Promise((t,n)=>{if(!so()){n(new Error(
243
+ "IndexedDB not available"));return}const o=indexedDB.open(Ri,e??Mi);o.onerror=()=>{qe=null,n(o.error)},o.onblocked=()=>{console.warn("[LocalConversationStorage] Database upgrade blocked - close other \
243
244
  tabs")},o.onsuccess=()=>{const r=o.result;if(!r.objectStoreNames.contains(nt)){if(e!==void 0){r.close(),qe=null,n(new Error("Attachments store still missing after version bump"));return}console.warn("\
244
245
  [LocalConversationStorage] Attachments store missing, bumping version to create it");const i=r.version+1;r.close(),qe=null,ao(i).then(t).catch(n);return}r.onclose=()=>{qe=null},r.onerror=()=>{qe=null},
245
246
  t(r)},o.onupgradeneeded=r=>{const i=r.target.result;if(!i.objectStoreNames.contains(io)){const a=i.createObjectStore(io,{keyPath:"id"});a.createIndex("documentId","documentId",{unique:!1}),a.createIndex(
246
- "updatedAt","updatedAt",{unique:!1})}i.objectStoreNames.contains(nt)||i.createObjectStore(nt,{keyPath:"id"}).createIndex("conversationId","conversationId",{unique:!1})}}),qe)}async function Mi(e){if(!so())
247
+ "updatedAt","updatedAt",{unique:!1})}i.objectStoreNames.contains(nt)||i.createObjectStore(nt,{keyPath:"id"}).createIndex("conversationId","conversationId",{unique:!1})}}),qe)}async function Bi(e){if(!so())
247
248
  return null;try{const t=await ao();return new Promise((n,o)=>{const r=t.transaction(nt,"readonly").objectStore(nt).get(e);r.onsuccess=()=>{n(r.result??null)},r.onerror=()=>o(r.error)})}catch(t){return console.
248
- warn("[LocalConversationStorage] Failed to get attachment:",t),null}}function Bi(e,t){const n=e.children.flatMap((o,r)=>o.type==="paragraph"&&o.heading?[{index:r,level:o.heading,blockId:o.id,title:Le(
249
- o).replace(/\s+/g," ").trim()}]:[]);return n.filter(o=>o.level<=t?.maxDepth).map(o=>({...o,endIndex:(n.find(r=>r.index>o.index&&(t?.flat||r.level<=o.level))?.index??e.children.length)-1}))}const Oi=new Set(
250
- [8203,8204,8205,8288,65279]);function ji(){return{wordCount:0,paragraphCount:0,characterCount:0,hasVisibleText:!1,inWord:!1}}function lo(e,t){for(let n=0;n<e.length;n+=1){const o=e.codePointAt(n);if(o===
251
- void 0||(o>65535&&(n+=1),Oi.has(o)))continue;const r=String.fromCodePoint(o);if(t.characterCount+=r.length,/\s/.test(r)){t.inWord=!1;continue}t.hasVisibleText=!0,t.inWord||(t.wordCount+=1,t.inWord=!0)}}
252
- function co(e,t){if(!e||typeof e!="object")return;const n=e;if(n.type==="text"&&typeof n.text=="string"){lo(n.text,t);return}if(n.type==="paragraph"&&(t.paragraphCount+=1),(n.type==="code"||n.type==="\
253
- math")&&typeof n.content=="string"){lo(n.content,t),t.inWord=!1;return}if(n.type==="placeholder"||n.type==="image"||n.type==="page-break"||n.type==="section-break"){t.inWord=!1;return}if(Array.isArray(
254
- n.children))for(const o of n.children)co(o,t),o&&typeof o=="object"&&"type"in o&&o.type!=="text"&&(t.inWord=!1)}function Ei(e){const t=ji();for(const o of e)co(o,t),t.inWord=!1;const n={parts:[],paragraphCount:0,
255
- containsSentinel:!1};for(const o of e)uo(o,n),n.parts.push(" ");return t.wordCount=_r(n.parts.join("")),t}const ot="\0";function uo(e,t){if(!e||typeof e!="object")return;const n=e;if(n.type==="text"&&
256
- typeof n.text=="string"){n.text.includes(ot)&&(t.containsSentinel=!0),t.parts.push(n.text);return}if(n.type==="paragraph"&&(t.paragraphCount+=1),(n.type==="code"||n.type==="math")&&typeof n.content=="\
257
- string"){n.content.includes(ot)&&(t.containsSentinel=!0),t.parts.push(n.content,ot);return}if(n.type==="placeholder"||n.type==="image"||n.type==="page-break"||n.type==="section-break"){t.parts.push(ot);
258
- return}if(Array.isArray(n.children))for(const o of n.children)uo(o,t),o&&typeof o=="object"&&"type"in o&&o.type!=="text"&&t.parts.push(ot)}function mo(e){return Ei(e)}function ho(e){const t=xn(e.pageLayout),
259
- n=dr(t);return{layout:pr({pageWidth:n.pageWidth,pageHeight:n.pageHeight,pageMargin:t.marginLeftPx,pageMarginTop:t.marginTopPx,pageMarginRight:t.marginRightPx,pageMarginBottom:t.marginBottomPx,pageMarginLeft:t.
260
- marginLeftPx,availableWidth:Math.max(1,n.pageWidth-t.marginLeftPx-t.marginRightPx),textStartY:t.marginTopPx,indentStepPx:t.indentStepPx,blockSpacingPx:t.blockSpacingPx,hyphenationEnabled:t.hyphenationEnabled,
261
- lineNumbering:t.lineNumbering,columnCount:t.columnCount,columnGapPx:ur(t.columnGapTwips),pageless:e.pageless===!0}),resolved:t}}function po(e){if(typeof document>"u")return null;const t=document.createElement(
262
- "canvas").getContext("2d");if(!t)return null;const n=br(t),{layout:o}=ho(e);return gr(e,n,o)}function go(e,t){const n=new Map;if(!t||e.pageless===!0)return new Map;const o=(a,l)=>{if(!a||typeof l!="nu\
263
- mber"||!Number.isFinite(l))return;const c=Math.max(1,Math.floor(l)),d=n.get(a);if(!d){n.set(a,{min:c,max:c});return}d.min=Math.min(d.min,c),d.max=Math.max(d.max,c)};for(const a of t.fragments)o(a.blockId,
264
- a.pageNumber);for(const a of t.blocks)o(a.blockId,a.pageNumber);const r=xn(e.pageLayout),i=new Map;for(const[a,l]of n)i.set(a,{pageStart:Sn(r,l.min-1),pageEnd:Sn(r,l.max-1)});return i}function Li(e,t){
265
- let n,o;for(const r of e){const i=t.get(r);i&&(n=n===void 0?i.pageStart:Math.min(n,i.pageStart),o=o===void 0?i.pageEnd:Math.max(o,i.pageEnd))}return n!==void 0&&o!==void 0?{pageStart:n,pageEnd:o}:void 0}
266
- function fo(e,t,n,o){const r=Math.max(0,Math.min(t,e.children.length-1)),i=Math.max(0,Math.min(n,e.children.length-1));if(r>i||e.children.length===0)return null;const a=e.children.slice(r,i+1),l=e.children[r],
267
- c=e.children[i];if(!l?.id||!c?.id)return null;const d=mo(a),u=a.map(b=>b.id).filter(Boolean),f=Li(u,o);return{startIndex:r,endIndex:i,startBlockId:l.id,endBlockId:c.id,inclusive:!0,blockCount:a.length,
268
- wordCount:d.wordCount,paragraphCount:d.paragraphCount,characterCount:d.characterCount,...f?{pageStart:f.pageStart,pageEnd:f.pageEnd}:{}}}function Ui(e,t,n){const o=[],r=n?new Set(n):null;for(const i of Bi(
269
- e,{maxDepth:3})){const a=i.index,l=i.endIndex,c=i.level;if(r&&!r.has(c))continue;const d=fo(e,a,l,t);d&&o.push({startIndex:d.startIndex,endIndex:d.endIndex,startBlockId:d.startBlockId,endBlockId:d.endBlockId,
270
- headingLevel:c,title:i.title,wordCount:d.wordCount,paragraphCount:d.paragraphCount,characterCount:d.characterCount,...d.pageStart!==void 0?{pageStart:d.pageStart,pageEnd:d.pageEnd}:{}})}return o}function bo(e,t){
271
- const n=t&&"layout"in t?t.layout??null:e.pageless===!0?null:po(e),o=mo(e.children),r=e.pageless===!0?null:n,i=t?.includeSections===!0?go(e,n):new Map;return{inclusive:!0,totalBlocks:e.children.length,
272
- wordCount:o.wordCount,paragraphCount:o.paragraphCount,characterCount:o.characterCount,...r?{pageCount:r.pageCount}:{},...t?.includeFractionalPageCount===!0&&r?{fractionalPageCount:Fi(e,r)}:{},...t?.includeSections===
273
- !0?{sections:Ui(e,i,t.headingLevels).map(a=>({...a,inclusive:!0,blockCount:a.endIndex-a.startIndex+1}))}:{}}}function Fi(e,t){const{layout:n}=ho(e);return fr(n,t)}function _o(e){return typeof e!="stri\
274
- ng"?"":e.trim().replace(/^#+/,"")}function zi(e,t,n){const o=po(e),r=go(e,o),i=new Map;for(let c=0;c<e.children.length;c+=1){const d=e.children[c]?.id;d&&i.set(d,c)}const a=[],l=[];for(const c of t){const d=_o(
275
- c.startBlockId),u=_o(c.endBlockId??d),f=i.get(d),b=i.get(u);if(!d){l.push({error:"start_block_id is required."});continue}if(f===void 0){l.push({startBlockId:d,endBlockId:u,error:`start_block_id "${d}\
276
- " was not found.`});continue}if(b===void 0){l.push({startBlockId:d,endBlockId:u,error:`end_block_id "${u}" was not found.`});continue}if(b<f){l.push({startBlockId:d,endBlockId:u,error:`end_block_id "${u}\
277
- " comes before start_block_id "${d}". Ranges must be forward and inclusive.`});continue}const y=fo(e,f,b,r);if(!y){l.push({startBlockId:d,endBlockId:u,error:`Could not measure inclusive range "${d}"-"${u}\
278
- ".`});continue}a.push(y)}return{inclusive:!0,totalBlocks:e.children.length,ranges:a,errors:l}}const Ji="The agent had trouble completing this request. Please try again.",yo="Document session unavailab\
279
- le after waiting for document load",Wi="document_session_unavailable";class Hi extends Error{constructor(t){super("Open the source document linked in the conversation to continue these edits."),this.sourceDocumentId=
280
- t,this.name="ForeignDocumentTargetError"}}const Gi="InvalidAssistantResponseError",Ki="Couldn't reach the server. Please check your connection and try again.",Vi=["aborted without reason","bodystreamb\
281
- uffer was aborted","client.timeout","connection reset by peer","context canceled","context cancellation","context cancelled","context deadline exceeded","econnreset","etimedout","failed to fetch","fai\
282
- led to execute 'fetch'","fetch is aborted","gateway timeout","http error! status:","illegal access","illegal invocation","load failed","network request failed","socket hang up","upstream request timeo\
283
- ut","while reading body"],Xi=["function call is missing a thought_signature","does not support the effort parameter","response with id=","gemini api error: 400","xai api error: 404","anthropic api err\
284
- or: 400"],Qi=["server_error","service_unavailable","server_is_overloaded","503 service unavailable","error in input stream"],Zi=["context_length_exceeded","input token count exceeds","exceeds the cont\
285
- ext window","maximum number of tokens","maximum context length","prompt is too long","too many input tokens"],Yi=['attachment "',"attachment not found","unable to download the file","failed to fetch a\
286
- ttachment","expected a valid url","invalid 'input","image_url"],es=['block id "',"document changed while","reference block","not found in document","not found in the document","insert_block"];function ts(e){
287
- const t=e.toLowerCase();return t.includes("network")||Vi.some(n=>t.includes(n))}function ns(e){if(e?.name==="AbortError"||e instanceof DOMException&&e.code===20)return{isAbort:!0,isRateLimited:!1,isNetworkError:!1,
288
- kind:"abort",rawMessage:"",message:"",shouldRetryWithStableModel:!1,shouldTrackConversationError:!1};const t=e instanceof Error?e.message:typeof e?.toString=="function"?e.toString():String(e??""),n=t.
289
- toLowerCase(),o=t==="RATE_LIMITED"||e?.message==="RATE_LIMITED",r=e instanceof TypeError||ts(t),i=e instanceof Error&&e.name===Gi,a=d=>d.some(u=>n.includes(u)),l=e instanceof Hi?"document_target":o?"r\
290
- ate_limited":i?"invalid_assistant_response":t.trim().length===0?"unknown_empty":a(Zi)?"context_limit":a(Yi)?"attachment":n.includes(yo.toLowerCase())?"document_loading":a(es)?"document_state":a(Xi)?"p\
291
- rovider_protocol":a(Qi)?"provider_transient":r?"connection":"unknown";let c;return o?c="Rate limit reached":i?c="The agent sent an invalid response. Please try again.":l==="connection"?c=Ki:l==="provi\
292
- der_protocol"||l==="provider_transient"?c="The model service had trouble completing this request. Please try again.":l==="context_limit"?c="This request is too large for the model. Try a smaller reque\
293
- st or attach fewer files.":l==="attachment"?c="The agent could not read one of the attached files.":l==="document_loading"?c="The document is still loading. Please wait a moment and try again.":l==="d\
294
- ocument_target"?c=t:l==="document_state"?c="Document state changed during the request.":l==="unknown_empty"?c="The agent stopped unexpectedly. Your prompt is saved.":c=Ji,{isAbort:!1,isRateLimited:o,isNetworkError:r,
295
- kind:l,rawMessage:t,message:c,shouldRetryWithStableModel:l==="provider_protocol"||l==="provider_transient",shouldTrackConversationError:l!=="rate_limited"&&l!=="connection"&&l!=="document_loading"}}const wo=[
296
- {name:"get_selection",description:"Read the host user's current semantic editor selection. Returns selected text, caret/range positions, portable target segments, active formatting, comment IDs, and p\
297
- ending suggestion IDs. Returns no viewport geometry. Use this when the host has not already supplied selection context.",inputSchema:{additionalProperties:!1,properties:{},type:"object"}},{name:"read_\
298
- blocks_from_index",description:"Read consecutive blocks from a 0-based start index. Omit document_id for the current document, or pass a known document_id to read another document. If the user names o\
299
- r links a specific document and you know its ID, use this directly instead of search_documents. Client chooses count by budget. Use at most one read/search tool per turn.",inputSchema:{additionalProperties:!1,
300
- properties:{context_notes:{description:"Plain-text notes to carry forward from current context before this read/search. Use 'N/A' if none.",type:"string"},document_id:{description:"Optional document I\
301
- D. Omit for the current document. Other documents are read-only sources: their block IDs cannot be used in mutation tools. To edit another document, ask the user to open it and continue there.",type:"\
302
- string"},index:{description:"0-based start block index.",minimum:0,type:"integer"}},required:["index","context_notes"],type:"object"}},{name:"search_document",description:"Search text within one docum\
303
- ent. Call this when you need to locate specific wording, a term, a name, or every occurrence of something and you do not already know which blocks contain it — searching is how you find the target bef\
304
- ore editing it, and is cheaper and more reliable than reading through the document. Current-document results include a request-scoped search_result_id for the full unpaginated match set; pass it to re\
305
- place, replace_block, style_blocks, or remove_blocks to target every match without paging through IDs. Omit document_id for the current document, or pass a known document_id to search within another d\
306
- ocument. If you instead need to read a document start-to-finish and already know its ID, prefer read_blocks_from_index with document_id. Displayed matches are paginated. Use at most one read/search to\
307
- ol per turn.",inputSchema:{additionalProperties:!1,properties:{context_notes:{description:"Plain-text notes to carry forward from current context before this read/search. Use 'N/A' if none.",type:"str\
308
- ing"},document_id:{description:"Optional document ID. Omit for the current document. Other documents are read-only sources: their block IDs cannot be used in mutation tools. To edit another document, \
309
- ask the user to open it and continue there.",type:"string"},page:{description:"0-based result page.",type:"integer"},queries:{description:"Search terms, max 20. Plain strings are case-insensitive; pre\
310
- fix regex patterns with 'regex:'.",items:{type:"string"},type:"array"}},required:["queries","page","context_notes"],type:"object"}},{name:"find_highlights",description:'Find highlighted text blocks, o\
311
- ptionally by color. Call this whenever the request refers to highlighted text — "the highlighted parts", "what I marked", "the yellow bits" — before acting on it; highlights are not visible in loaded \
312
- document content, so this is the only way to learn which blocks the user means. Matching blocks load next turn. Results are paginated at 25 blocks/page. Use at most one read/search tool per turn.',inputSchema:{
313
- additionalProperties:!1,properties:{color:{description:"Optional color filter.",enum:["yellow","orange","green","blue","purple","pink","gray"],type:"string"},context_notes:{description:"Plain-text not\
314
- es to carry forward from current context before this read/search. Use 'N/A' if none.",type:"string"},page:{description:"0-based result page.",type:"integer"}},required:["page","context_notes"],type:"o\
315
- bject"}},{name:"read_specific_blocks",description:"Read specific blocks by ID. Omit document_id for the current document, or pass a known document_id to read another document. If you already know both\
316
- the document ID and block IDs, use this directly instead of search_documents. Use at most one read/search tool per turn.",inputSchema:{additionalProperties:!1,properties:{block_ids:{description:"Bloc\
317
- k IDs to read, max 50.",items:{type:"string"},type:"array"},context_notes:{description:"Plain-text notes to carry forward from current context before this read/search. Use 'N/A' if none.",type:"string"},
318
- document_id:{description:"Optional document ID. Omit for the current document. Other documents are read-only sources: their block IDs cannot be used in mutation tools. To edit another document, ask th\
319
- e user to open it and continue there.",type:"string"}},required:["block_ids","context_notes"],type:"object"}},{name:"read_table",description:"Read a bounded part of a table in the current document by \
320
- table_id. Native agents receive row contents in the next document snapshot; other callers receive rows in this result. Results include coverage metadata and continuations. When a serialized window is \
321
- partial, consume next_read and then following_read to avoid skipping columns or later rows. mode=summary returns dimensions, merged anchors/spans, per-column fill counts and missing ranges only: it de\
322
- livers no cell contents and grants no edit rights. mode=rows (default) delivers rows by row_start/row_count or explicit row_ids, optionally limited to a column range; only delivered cells can be edite\
323
- d. mode=cell_text pages one oversized cell by cell_id/text_offset and continuation_revision; cell_text includes list markers and explicit non-text placeholders, opens each nested block's text with an \
324
- inline [[block_id]] marker (metadata, not document text; never include it in find text), and routes nested tables to their own read_table calls. Its windows are always read-only and never authorize wh\
325
- ole-cell replacement; read a complete nested block with read_specific_blocks to edit that block. For cells not already fully delivered in a table seed or cell snapshot, read the needed rows, then batc\
326
- h edits with edit_table_cells. Do not re-read cells whose current contents are already delivered. Optionally declare the overall task scope (task_kind, scope_*, source_attachment_id) and deliberate_bl\
327
- anks so progress can be tracked across turns; scope is never inferred from a partial edit. Use at most one read/search tool per turn.",inputSchema:{additionalProperties:!1,properties:{cell_id:{description:"\
328
- Cell ID for mode=cell_text.",type:"string"},column_count:{description:"Optional number of logical columns starting at column_start.",minimum:1,type:"integer"},column_start:{description:"Optional 0-bas\
329
- ed first logical column. Omit to read all columns. A partial column read authorizes edits only to the delivered cells, not the whole row.",minimum:0,type:"integer"},context_notes:{description:"Plain-t\
330
- ext notes to carry forward from current context before this read/search. Use 'N/A' if none.",type:"string"},continuation_revision:{description:"Revision from the previous result continuation. Rejects \
331
- continuation when cell text or table geometry changed, so stale and fresh windows are never combined.",type:"string"},deliberate_blanks:{description:"Optional in-scope cells intentionally left empty, \
332
- each with a reason, so they are not reported as remaining work.",items:{additionalProperties:!1,properties:{column:{description:"0-based logical column.",minimum:0,type:"integer"},reason:{description:"\
333
- Why the cell stays empty.",type:"string"},row_id:{description:"Stable row ID.",type:"string"}},required:["row_id","column","reason"],type:"object"},maxItems:50,type:"array"},mode:{description:"summary\
334
- : metadata and counts only. rows (default when omitted): deliver row contents. cell_text: bounded text window of one oversized cell.",enum:["summary","rows","cell_text"],type:"string"},row_count:{description:"\
335
- Rows to deliver for mode=rows. Defaults to 25; maximum 50.",maximum:50,minimum:1,type:"integer"},row_ids:{description:"Explicit stable row IDs (<tr id>) to deliver instead of row_start/row_count.",items:{
336
- type:"string"},maxItems:50,type:"array"},row_start:{description:"0-based first row for mode=rows, counting header rows. Ignored when row_ids is supplied.",minimum:0,type:"integer"},scope_columns:{description:"\
337
- Optional declared task scope: 0-based logical columns the task writes.",items:{minimum:0,type:"integer"},type:"array"},scope_row_count:{description:"Optional declared task scope: number of rows covere\
338
- d by the user's whole request.",minimum:1,type:"integer"},scope_row_start:{description:"Optional declared task scope: first 0-based row covered by the user's whole request.",minimum:0,type:"integer"},
339
- source_attachment_id:{description:"Optional attachment ID the task copies or derives values from.",type:"string"},table_id:{description:"Table block ID in the current document.",type:"string"},task_kind:{
340
- description:"Optional task declaration. fill: populate empty cells. transform: rewrite existing cells (translate, shorten, etc.).",enum:["fill","transform"],type:"string"},text_offset:{description:"Ch\
341
- aracter offset for mode=cell_text. Use the offset from the previous result's continuation.",minimum:0,type:"integer"}},required:["table_id","context_notes"],type:"object"}},{name:"measure_document",description:"\
342
- Measure the current document without loading body text. Use this for total word count, paragraph count, block count, rendered page count, and paginated per-heading section measurements. Primary totals\
343
- treat pending suggestions as accepted; when pending suggestions change counts, the result also reports the original review projection so you can reconcile the number visible in the user's editor view\
344
- . Set include_sections=true for per-chapter/per-section counts and inclusive block ranges.",inputSchema:{additionalProperties:!1,properties:{heading_levels:{description:"Optional heading levels to inc\
345
- lude when include_sections is true. Defaults to h1, h2, and h3.",items:{enum:[1,2,3],type:"integer"},type:"array"},include_sections:{description:"Whether to include heading section measurements. Defau\
346
- lt false. Use true for per-chapter or per-section counts.",type:"boolean"},section_limit:{description:"Maximum heading sections to return when include_sections is true. Default and maximum 100.",maximum:100,
347
- minimum:1,type:"integer"},section_offset:{description:"Zero-based section offset when include_sections is true. Default 0. Use nextSectionOffset from the previous result to continue.",minimum:0,type:"\
348
- integer"}},type:"object"}},{name:"measure_blocks",description:"Measure inclusive block ranges in the current document without loading document text. Use this for word counts, paragraph counts, block c\
349
- ounts, and rendered page ranges. Block IDs may be passed with or without a leading #.",inputSchema:{additionalProperties:!1,properties:{mode:{description:"Range mode. Only inclusive is supported.",enum:[
350
- "inclusive"],type:"string"},ranges:{description:"Inclusive block ranges to measure. Omit end_block_id to measure only start_block_id.",items:{additionalProperties:!1,properties:{end_block_id:{description:"\
351
- Last block ID in the inclusive range. Omit to measure only the start block.",type:"string"},start_block_id:{description:"First block ID in the inclusive range.",type:"string"}},required:["start_block_\
352
- id"],type:"object"},type:"array"}},required:["ranges"],type:"object"}},{name:"view_image",description:'View a document image by block ID when its <img> src is hidden. Viewing is only for seeing pixels\
353
- ; you do not need the hidden source to copy, move, or swap an image—write <img src="IMAGE_ID"> with its exact document id in insert_block or replace_block HTML.',inputSchema:{additionalProperties:!1,
354
- properties:{block_id:{description:"Image block ID.",type:"string"}},required:["block_id"],type:"object"}},{name:"insert_block",description:'Insert native block(s) before/after a reference block using \
355
- HTML. To add items inside an existing list, reference a list-item ID and pass separate <li>...</li> entries in the desired order; this preserves the existing list numbering and style. Referencing the \
356
- list container inserts a separate sibling block, not items within that list. A reference may be nested inside a table cell; inserting <img> (bare or wrapped by a paragraph/presentational span) next to\
357
- that reference creates a native image block in the same cell. For a web-sourced image, use a verified direct raster URL returned by search for src; never guess or infer an image filename. Add data-so\
358
- urce-url="..." to the <img> using the source webpage URL returned by web search, or the original image URL when no webpage URL is available; Revise preserves this provenance across later requests whil\
359
- e rehosting the rendered image. For a live table of contents that automatically tracks document headings, insert <toc levels="3"></toc> (levels may be 1-6; omitting the attribute defaults to 3). Never\
360
- build a table of contents from ordinary paragraphs, tabs, lists, or manually copied headings. For an Arabic/RTL live TOC, keep the toc block and set dir="rtl" and style="text-align:right" on it; dire\
361
- ction:rtl and text-align:right also work through style_blocks. RTL places page numbers at the left edge. Do not replace a live TOC with a static table to adjust formatting. Put alignment directly in i\
362
- nserted HTML when needed. To cite inside new content, embed native notes inline: <sup data-footnote="Note body.">1</sup> creates a footnote in this same call (data-note-kind="endnote" for endnotes).',
363
- inputSchema:{additionalProperties:!1,properties:{content:{description:'HTML block elements to insert, e.g. <p>, <h1>, <li> (within an existing list), <ul> (a new list), <img>, <toc levels="3"></toc> (\
364
- live table of contents), <page-break />, <hr /> (horizontal rule), <pre>. An image may be wrapped in a paragraph/span for alignment and display dimensions. For a web-sourced image, use a verified dire\
365
- ct raster URL returned by search for src. Never guess or infer an image filename. Put its source webpage URL in data-source-url on the <img> (fall back to the original image URL). An image whose src i\
366
- s hidden is still usable: to copy or move it, write <img src="IMAGE_ID"> with its exact document id (dimensions and alt may be restated); the source is resolved automatically, so never ask the user fo\
367
- r it.',items:{type:"string"},minItems:1,type:"array"},position:{description:"Insert before or after reference block.",enum:["before","after"],type:"string"},referenceId:{description:"Current reference\
368
- block ID. For a blank document, pass an empty string with position=after; the editor resolves the blank insertion location. Never ask the user to type placeholder text. For a document with content, u\
369
- se an existing block ID.",type:"string"}},required:["content","position","referenceId"],type:"object"}},{name:"insert_footnote",description:"Insert a footnote: a numbered superscript reference placed \
370
- right after the anchor text in a paragraph, plus the footnote body (rendered at the bottom of the page). Footnote bodies appear in the document as [^n] references with their own blocks — edit them wit\
371
- h replace/replace_block and remove them with remove_blocks on the footnote block (removing a body also removes its reference).",inputSchema:{additionalProperties:!1,properties:{find:{description:"Anch\
372
- or text inside the block; the reference is inserted right after it. Empty string appends at the end of the block.",type:"string"},id:{description:"Paragraph block ID that receives the reference.",type:"\
373
- string"},kind:{description:"Note stream: footnote (per-page bottom area, numbered 1,2,3 — default) or endnote (grouped on its own page at the document end, numbered i,ii,iii).",enum:["footnote","end\
374
- note"],type:"string"},text:{description:"Footnote body text.",type:"string"}},required:["id","find","text"],type:"object"}},{name:"remove_blocks",description:"Remove native footnotes/endnotes by targe\
375
- ting the note ID or its body block ID with id alone; this removes the entire note and all its inline references while preserving the surrounding paragraph. To remove multiple notes, use ids containing\
376
- only note/body IDs (do not mix with main-document block IDs or use an end_id range). For notes found by search, use their explicit IDs rather than search_result_id. Remove one or more blocks by a dir\
377
- ect target (id alone for one block, or id + end_id for a consecutive range, both inclusive), an explicit tail range (id + through_end=true), an exact nonconsecutive ID batch (ids), or every block in a\
378
- full search_document result (search_result_id). through_end removes the starting top-level block and every block after it through the current end of the document; use it only when that entire tail mu\
379
- st be removed. The starting id must have appeared in current request context, but through_end does not require reading every interior block. Other direct targets must have appeared in current request \
380
- context. Prefer search_result_id for large or sparse match sets; search discovers candidates but never deletes them implicitly.",inputSchema:{additionalProperties:!1,properties:{end_id:{description:"L\
381
- ast block ID of a consecutive range to remove, inclusive, at the same level as id (same document level, table cell, or list). Omit to remove only id. Every block from id through end_id must have appea\
382
- red in current request context.",type:"string"},id:{description:"First block ID to remove.",type:"string"},ids:{description:"Exact nonconsecutive block IDs to remove. Each ID must have appeared in doc\
383
- ument context during this request. Do not infer IDs from a query.",items:{type:"string"},maxItems:50,minItems:1,type:"array"},search_result_id:{description:"Request-scoped ID returned by search_docume\
384
- nt for the current document. Applies this operation to every block in the full unpaginated result set. Use instead of id or ids. Rerun search_document if the reference is unavailable or stale.",type:"\
385
- string"},through_end:{description:"Set true with id to remove that top-level block and the entire document tail after it. Mutually exclusive with end_id, ids, and search_result_id. Omit unless the who\
386
- le tail is intentionally in scope.",type:"boolean"}},type:"object"}},{name:"append_to_paragraph",description:"Append HTML content to a paragraph.",inputSchema:{additionalProperties:!1,properties:{content:{
387
- description:"HTML content to append.",type:"string"},id:{description:"Paragraph ID.",type:"string"}},required:["id","content"],type:"object"}},{name:"break_paragraph",description:"Split a paragraph at\
388
- the first occurrence of substring; second paragraph starts there.",inputSchema:{additionalProperties:!1,properties:{id:{description:"Paragraph ID.",type:"string"},substring:{description:"Substring wh\
389
- ere split begins.",type:"string"}},required:["id","substring"],type:"object"}},{name:"join_paragraphs",description:"Join two adjacent paragraphs without rewriting their text. The second paragraph is a\
390
- ppended to the first, preserving inline formatting from both paragraphs, then removed. Use this to repair an accidental paragraph break or hard return.",inputSchema:{additionalProperties:!1,properties:{
391
- firstId:{description:"ID of the first paragraph. This paragraph and its block formatting are preserved.",type:"string"},secondId:{description:"ID of the immediately following sibling paragraph. Its in\
392
- line-formatted text is appended, then this block is removed.",type:"string"},separator:{description:"Text placed between the paragraphs. Defaults to one space between non-empty paragraphs. A non-empty\
393
- separator replaces existing boundary whitespace so it is not duplicated. Pass an empty string to add nothing and preserve existing boundary whitespace.",type:"string"}},required:["firstId","secondId"],
394
- type:"object"}},{name:"replace_block",description:'Replace entire consecutive block(s) with HTML block(s), or apply the same one-block replacement independently to every block in a full search_documen\
395
- t result via search_result_id. Use this only when the whole block must be replaced, its block type must change, or multiple consecutive blocks must become a different block structure. Prefer replace f\
396
- or ordinary wording, sentence, paragraph-text, typo, punctuation, or formatting-preserving edits—even when most or all visible text in one paragraph changes—because replace preserves block identity an\
397
- d untouched formatting. Preserve the existing block type unless the user asks to change it: use <pre language="..."> for code, <latex> for display math, and <latex-inline> for inline math. Put alignme\
398
- nt in replacement HTML. For a web-sourced replacement image, use a verified direct raster URL returned by search for src; never guess or infer an image filename. Put its source webpage URL in data-sou\
399
- rce-url on the <img> (fall back to the original image URL).',inputSchema:{additionalProperties:!1,properties:{content:{description:'Replacement HTML block elements, e.g. <p>, <h1>, <ul>, <pre language\
400
- ="typescript">code</pre>, <img>, or <latex>E = mc^2</latex>. Match the original block type unless a type change was requested. For a web-sourced image, use a verified direct raster URL returned by sea\
401
- rch for src. Never guess or infer an image filename. Put its source webpage URL in data-source-url on the <img> (fall back to the original image URL). An image whose src is hidden is still usable: to \
402
- copy or move it, write <img src="IMAGE_ID"> with its exact document id (dimensions and alt may be restated); the source is resolved automatically, so never ask the user for it.',items:{type:"string"},
403
- minItems:1,type:"array"},end_id:{description:"Last block ID of a consecutive range to replace, inclusive, at the same level as id (same document level, table cell, or list). Omit to replace only id. E\
404
- very block from id through end_id must have appeared in current request context.",type:"string"},id:{description:"First block ID to replace.",type:"string"},search_result_id:{description:"Request-scop\
405
- ed ID returned by search_document for the current document. Applies this operation to every block in the full unpaginated result set. Use instead of id or ids. Rerun search_document if the reference i\
406
- s unavailable or stale.",type:"string"}},required:["content"],type:"object"}},{name:"style_blocks",description:'Style existing content with forgiving CSS-lite selectors and values. Use one bulk style_\
407
- blocks call instead of per-block replace calls when matching content shares a selector or search result. Pass search_result_id to scope selectors to every block in the full unpaginated search_document\
408
- result; * then means each matched block. Block selectors include *, #blockId, p, h1-h6, li, lists, tables, and descendants. Inline selectors such as span, b/strong, i/em, u, s/strike/del, code, sup, \
409
- sub, mark, and a target text ranges; they may be scoped, for example p span, p b, or #blockId strong. Text color accepts CSS named colors, hex colors, and CSS color functions and stores an absolute he\
410
- x color. For text highlighting, use backgroundColor with one of the seven canonical values yellow, orange, green, blue, purple, pink, or gray; other names and CSS colors normalize to this palette by h\
411
- ue (a pale lavender such as #E4DFEC becomes purple) and may be the same color. A backgroundColor on a table-cell selector sets the cell fill; on text blocks or inline selectors it highlights text, whi\
412
- ch is also how to express paragraph shading. Setting a value back to the original reverts your pending formatting suggestion. Table-cell selectors apply text styles, alignment, and spacing to their de\
413
- scendant paragraphs. Examples: highlight all h3 headings orange with selectors="h3" and attrs=[{"name":"backgroundColor","value":"orange"}]; remove all bold with selectors="b" and attrs=[{"name":"font\
414
- Weight","value":"normal"}]; set the entire document to Century Schoolbook 14pt double-spaced with selectors="*" and fontFamily/fontSize/lineSpacing attrs; bold headings with selectors=["h1","h2","h3"]\
415
- and fontWeight="bold".',inputSchema:{additionalProperties:!1,properties:{attrs:{description:"Use CSS/Revise names. Text colors accept CSS names, hex, or functions. Highlights: yellow, orange, green, \
416
- blue, purple, pink, or gray. Supports text typography, block alignment, hanging indents, list presentation, image sizing with CSS lengths, and table/cell sizing with percentage widths. CSS maps to dur\
417
- able document equivalents; feedback lists approximations and unsupported values. Null resets.",items:{additionalProperties:!1,properties:{name:{description:"Attribute/style name, e.g. fontSize, font-s\
418
- ize, fontFamily, text-align.",type:"string"},value:{description:"Value to set, or null to remove/reset.",oneOf:[{type:"string"},{type:"number"},{type:"boolean"},{type:"null"}]}},required:["name","valu\
419
- e"],type:"object"},minItems:1,type:"array"},search_result_id:{description:"Request-scoped ID returned by search_document for the current document. Applies this operation to every block in the full unp\
420
- aginated result set. Use instead of id or ids. Rerun search_document if the reference is unavailable or stale.",type:"string"},selectors:{description:'CSS-lite selectors over the document HTML: * (als\
421
- o all, document, or :root), #blockId, p, h1-h6, li, ul, ol, pre, latex, img, table, tr, td/th, div, p[data-style-id="StyleName"], and inline formatting tags span, b/strong, i/em, u, s/strike/del, code\
422
- , sup, sub, mark, a. Simple descendants, general siblings, descendant wildcards, :first-child, and :nth-child(n) are accepted, e.g. table tr:first-child td, table td:nth-child(2) p, #blockId td p, #bl\
423
- ockId *, #blockId ~ p, p span, p b, or #blockId strong. Inline selectors affect matching text ranges; span means all text in its scope. Arrays and comma grouping are allowed.',oneOf:[{type:"string"},{
424
- items:{type:"string"},minItems:1,type:"array"}]}},required:["selectors","attrs"],type:"object"}},{name:"clear_formatting",description:"Clear removable inline emphasis from paragraph/list-item target(s\
425
- ): bold, italic, underline, code, LaTeX, superscript/subscript, background highlight, and links. Preserve font family, font size, text color, and paragraph attributes.",inputSchema:{additionalProperties:!1,
426
- properties:{id:{description:"Target paragraph/list-item/list ID or IDs.",oneOf:[{type:"string"},{items:{type:"string"},minItems:1,type:"array"}]}},required:["id"],type:"object"}},{name:"set_title",description:"\
427
- Change the document title",inputSchema:{additionalProperties:!1,properties:{title:{description:"The new document title",maxLength:300,type:"string"}},required:["title"],type:"object"}},{name:"set_page\
428
- _layout",description:"Patch page or section layout: preset, size, margins, 1-3 columns, page numbers, spacing, pageless mode. ONLY the fields you pass change; everything else keeps its current or inhe\
429
- rited value (a section keeps inheriting document-level settings for fields you don't pass). Pass sectionIndex to change one section; omit it to apply the passed fields to the document defaults and eve\
430
- ry section. Length fields must be strings with explicit px/in/cm units. Preset 'apa7' applies standard APA layout.",inputSchema:{additionalProperties:!1,properties:{blockSpacing:{description:'Vertical\
431
- spacing between adjacent blocks, shown in the UI in inches or centimeters. Typical values are "0.08in" to "0.25in" (about "0.2cm" to "0.64cm"); do not use whole-inch values like "2in" or "4in" for no\
432
- rmal paragraph spacing. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},clearPageBorders:{
433
- description:"Set true to remove all page borders from the target section(s), including preserved Word art borders.",type:"boolean"},columnCount:{description:"Number of newspaper-style columns in the t\
434
- arget section.",enum:[1,2,3],type:"integer"},columnGap:{description:'Gap between columns. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values \
435
- shown in the UI. Do not send bare numbers.',type:"string"},indentStep:{description:'Paragraph indent step. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for pa\
436
- ge layout values shown in the UI. Do not send bare numbers.',type:"string"},margin:{description:'Uniform page margin applied to all sides. Include an explicit unit: in, cm, or px (examples: "1in", "3c\
437
- m", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginBottom:{description:'Bottom page margin. Include an explicit unit: in, cm, or px (exam\
438
- ples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginLeft:{description:'Left page margin. Include an explicit unit: in, cm,\
439
- or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginRight:{description:'Right page margin. Include an explicit\
440
- unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginTop:{description:'Top page margin. Include a\
441
- n explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},noteMode:{description:"Bulk-convert exis\
442
- ting native notes to this stream: footnotes (per-page areas, 1,2,3) or endnotes (own page at document end, i,ii,iii). Does not convert manually typed superscript numbers or note paragraphs; create nat\
443
- ive notes with their complete bodies and references first. Individual notes choose a stream at insert time.",enum:["footnotes","endnotes"],type:"string"},orientation:{description:"Page orientation.",enum:[
444
- "portrait","landscape"],type:"string"},pageBorders:{additionalProperties:!1,description:"Native page border for the target section(s), rendered in the editor and PDF and preserved in DOCX. Replaces th\
445
- e whole border configuration; omitted sides have no border. To remove borders use clearPageBorders=true. Measurements are points (1/72 inch).",properties:{bottom:{additionalProperties:!1,properties:{color:{
446
- pattern:"^#[0-9a-fA-F]{6}$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"string"},widthPt:{maximum:12,minimum:.25,type:"number"}},
447
- required:["style","color","widthPt","spacePt"],type:"object"},display:{enum:["allPages","firstPage","notFirstPage"],type:"string"},left:{additionalProperties:!1,properties:{color:{pattern:"^#[0-9a-fA-\
448
- F]{6}$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"string"},widthPt:{maximum:12,minimum:.25,type:"number"}},required:["style","\
449
- color","widthPt","spacePt"],type:"object"},offsetFrom:{enum:["page","text"],type:"string"},right:{additionalProperties:!1,properties:{color:{pattern:"^#[0-9a-fA-F]{6}$",type:"string"},spacePt:{maximum:31,
450
- minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"string"},widthPt:{maximum:12,minimum:.25,type:"number"}},required:["style","color","widthPt","spacePt"],type:"object"},
451
- top:{additionalProperties:!1,properties:{color:{pattern:"^#[0-9a-fA-F]{6}$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"string"},
452
- widthPt:{maximum:12,minimum:.25,type:"number"}},required:["style","color","widthPt","spacePt"],type:"object"},zOrder:{enum:["front","back"],type:"string"}},required:["offsetFrom","display","zOrder"],type:"\
453
- object"},pageHeight:{description:'Explicit page height. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare \
454
- numbers.',type:"string"},pageNumberFormat:{description:"Page number style: decimal (1, 2, 3), lowerRoman (i, ii, iii), or upperRoman (I, II, III). Applies to page-number fields, the table of contents,\
455
- and exports. Use sectionIndex for front matter.",enum:["decimal","lowerRoman","upperRoman"],type:"string"},pageNumberPosition:{description:"Page number position.",enum:["top-left","top-right","bottom\
456
- -left","bottom-right"],type:"string"},pageNumberRestart:{description:"Section numbering mode (use with sectionIndex, including the final section): true restarts at pageNumberStart (default 1); false c\
457
- ontinues from the previous section. Typical thesis: Roman front matter, then the final body section restarts at 1.",type:"boolean"},pageNumberStart:{description:"First page number. With sectionIndex i\
458
- t restarts numbering at that section (e.g. body starts again at 1 after Roman front matter).",minimum:1,type:"integer"},pageSize:{description:"Named page-size preset.",enum:["letter","tabloid","legal",
459
- "statement","executive","folio","a3","a4","a5","b4","b5"],type:"string"},pageWidth:{description:'Explicit page width. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer i\
460
- n/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},pageless:{description:"Enable pageless mode.",type:"boolean"},preset:{description:"Preset applied before override\
461
- s.",enum:["apa7"],type:"string"},sectionIndex:{description:"One-based section number to patch (invalid indexes fail the call). Omit to apply the passed fields to the document defaults and every sectio\
462
- n.",minimum:1,type:"integer"},showPageNumbers:{description:"Show or hide page numbers. Page numbers are header/footer content: this manages an automatic page-number field slot (combine with pageNumber\
463
- Position). Hand-authored header/footer content is never overwritten.",type:"boolean"}},required:[],type:"object"}},{name:"set_header_footer",description:`Edit page header/footer content. Each side has\
464
- three zones (left, center, right); provide only the zones to change - untouched zones keep their content and formatting. Use the literal token {PAGE} for a live page number and {PAGES} for the total \
465
- page count, anywhere in any zone (e.g. right: "Page {PAGE} of {PAGES}"). An empty string clears a zone; clear=true removes the header or footer from every page (all slots and every section's override,\
466
- unless slot or sectionIndex narrows it). Without sectionIndex, zone edits change the document-wide header/footer; a section with its own override keeps it (the result says so). The result lists the h\
467
- eaders/footers that exist afterwards, and a call that changes nothing fails with that list. For a plain bottom-right page number, set_page_layout with showPageNumbers also works.`,inputSchema:{properties:{
468
- center:{description:"Center zone text ({PAGE}/{PAGES} tokens allowed). Omit to keep unchanged; empty string clears.",type:"string"},clear:{description:"Remove this side's header/footer: from every pag\
469
- e and section unless slot or sectionIndex narrows it.",type:"boolean"},image:{additionalProperties:!1,description:"Put an image (e.g. a logo) in this header/footer on every page, replacing any image a\
470
- lready in that band. Pass image_id to reuse an image already in the document, or url for a direct image URL. It is drawn in the page margin band, scaled down to fit (never into the body text), next to\
471
- any zone text. Do not insert copies of the image into the body to fake a header. Applies to every section; do not combine with sectionIndex or clear.",properties:{alt:{description:"Short description \
472
- of the image.",type:"string"},height:{description:"Optional display height in px.",type:"number"},image_id:{description:"ID of an existing image block to reuse.",type:"string"},url:{description:"Direc\
473
- t http(s) URL of a raster image (PNG/JPEG/GIF/WebP).",type:"string"},width:{description:"Optional display width in px (height follows the aspect ratio). Omit to use the image's own size.",type:"number"},
474
- zone:{description:"Horizontal position in the band. Default left.",enum:["left","center","right"],type:"string"}},type:"object"},left:{description:"Left zone text ({PAGE}/{PAGES} tokens allowed). Omit\
475
- to keep unchanged; empty string clears.",type:"string"},right:{description:"Right zone text ({PAGE}/{PAGES} tokens allowed). Omit to keep unchanged; empty string clears.",type:"string"},sectionIndex:{
476
- description:"One-based section whose own header/footer override to edit or clear. Omit for the document-wide header/footer (and, with clear, every section's override too).",minimum:1,type:"integer"},side:{
477
- description:"Which band to edit.",enum:["header","footer"],type:"string"},slot:{description:"Which pages this applies to (Word slot model). Zone edits default to 'default' (all pages); clear without s\
478
- lot removes every slot.",enum:["default","first","even"],type:"string"}},required:["side"],type:"object"}},{name:"replace",description:"Preferred/default tool for editing text inside an existing block\
479
- , including wording, sentences, typos, punctuation, formatting-preserving rewrites, and even replacing all visible text in one paragraph when its block type/structure should stay the same. It preserve\
480
- s block identity and untouched formatting; use replace_block only for whole-block structural or block-type changes. Supports one or more in-place edits inside one block, uniquely identifiable edits ac\
481
- ross loaded blocks when id is omitted, or the same edits independently in every block from a full search_document result via search_result_id. An empty find safely fills a direct-id target only when t\
482
- hat target is truly empty. Each operation may include its own comment, which is attached to every suggestion produced by that operation. For each edit, occurrence defaults to unique: its find HTML/tex\
483
- t must be specific enough to match exactly one location in each target block or the entire call fails without changing the document. Use occurrence=all only when every exact occurrence should change. \
484
- Omit no-op replacements where find and replace are identical.",inputSchema:{additionalProperties:!1,properties:{id:{description:"Target block ID. May be omitted only when every non-empty find uniquely\
485
- identifies one loaded block, or when search_result_id is used.",type:"string"},replacements:{description:"Ordered replacement operations. Use one item for one edit and multiple items to batch edits i\
486
- n the same block.",items:{additionalProperties:!1,properties:{comment:{description:"Optional comment explaining this operation. It is attached separately to every resulting suggestion from this operat\
487
- ion, including every match when occurrence=all. Prefer this over a separate leave_comment when the feedback explains the suggested edit.",type:"string"},find:{description:"Exact text to find; HTML all\
488
- owed for formatted targets. With occurrence=unique or when occurrence is omitted, include enough surrounding context to match exactly one location.",type:"string"},occurrence:{description:"unique (def\
489
- ault when omitted) requires exactly one match; all replaces every exact match.",enum:["unique","all"],type:"string"},replace:{description:"Replacement text; HTML allowed for formatting changes. Must d\
490
- iffer from find unless the replacement HTML creates a real formatting change.",type:"string"}},required:["find","replace"],type:"object"},maxItems:50,minItems:1,type:"array"},search_result_id:{description:"\
491
- Request-scoped ID returned by search_document for the current document. Applies this operation to every block in the full unpaginated result set. Use instead of id or ids. Rerun search_document if the\
492
- reference is unavailable or stale.",type:"string"}},required:["replacements"],type:"object"}},{name:"leave_comment",description:"Leave granular review feedback on the current document without changin\
493
- g its text. Prefer this for substantive passage-specific critique, feedback, annotations, issues, or improvements instead of putting that feedback in a long chat response. Two modes. To START a thread\
494
- : target one block with id and exactly one anchor form — unique exact text for a short range, start/end boundary text for a longer range without reproducing it, or the whole block for structural/empty\
495
- content. To REPLY to a thread that already exists: pass reply_to_comment_id (a <comment-thread> id from loaded document content) and comment, with no id and no anchor. Existing threads are visible as\
496
- <comment-thread> elements in loaded document content; when text already carries one, reply to it rather than starting a second thread that repeats the same point.",inputSchema:{additionalProperties:!1,
249
+ warn("[LocalConversationStorage] Failed to get attachment:",t),null}}const Oi=new Set([8203,8204,8205,8288,65279]);function ji(){return{wordCount:0,paragraphCount:0,characterCount:0,hasVisibleText:!1,
250
+ inWord:!1}}function lo(e,t){for(let n=0;n<e.length;n+=1){const o=e.codePointAt(n);if(o===void 0||(o>65535&&(n+=1),Oi.has(o)))continue;const r=String.fromCodePoint(o);if(t.characterCount+=r.length,/\s/.
251
+ test(r)){t.inWord=!1;continue}t.hasVisibleText=!0,t.inWord||(t.wordCount+=1,t.inWord=!0)}}function co(e,t){if(!e||typeof e!="object")return;const n=e;if(n.type==="text"&&typeof n.text=="string"){lo(n.
252
+ text,t);return}if(n.type==="paragraph"&&(t.paragraphCount+=1),(n.type==="code"||n.type==="math")&&typeof n.content=="string"){lo(n.content,t),t.inWord=!1;return}if(n.type==="placeholder"||n.type==="im\
253
+ age"||n.type==="page-break"||n.type==="section-break"){t.inWord=!1;return}if(Array.isArray(n.children))for(const o of n.children)co(o,t),o&&typeof o=="object"&&"type"in o&&o.type!=="text"&&(t.inWord=!1)}
254
+ function Ei(e){const t=ji();for(const o of e)co(o,t),t.inWord=!1;const n={parts:[],paragraphCount:0,containsSentinel:!1};for(const o of e)uo(o,n),n.parts.push(" ");return t.wordCount=yr(n.parts.join("")),
255
+ t}const ot="\0";function uo(e,t){if(!e||typeof e!="object")return;const n=e;if(n.type==="text"&&typeof n.text=="string"){n.text.includes(ot)&&(t.containsSentinel=!0),t.parts.push(n.text);return}if(n.type===
256
+ "paragraph"&&(t.paragraphCount+=1),(n.type==="code"||n.type==="math")&&typeof n.content=="string"){n.content.includes(ot)&&(t.containsSentinel=!0),t.parts.push(n.content,ot);return}if(n.type==="placeh\
257
+ older"||n.type==="image"||n.type==="page-break"||n.type==="section-break"){t.parts.push(ot);return}if(Array.isArray(n.children))for(const o of n.children)uo(o,t),o&&typeof o=="object"&&"type"in o&&o.type!==
258
+ "text"&&t.parts.push(ot)}function mo(e){return Ei(e)}function ho(e){const t=xn(e.pageLayout),n=dr(t);return{layout:gr({pageWidth:n.pageWidth,pageHeight:n.pageHeight,pageMargin:t.marginLeftPx,pageMarginTop:t.
259
+ marginTopPx,pageMarginRight:t.marginRightPx,pageMarginBottom:t.marginBottomPx,pageMarginLeft:t.marginLeftPx,availableWidth:Math.max(1,n.pageWidth-t.marginLeftPx-t.marginRightPx),textStartY:t.marginTopPx,
260
+ indentStepPx:t.indentStepPx,blockSpacingPx:t.blockSpacingPx,hyphenationEnabled:t.hyphenationEnabled,lineNumbering:t.lineNumbering,columnCount:t.columnCount,columnGapPx:ur(t.columnGapTwips),pageless:e.
261
+ pageless===!0}),resolved:t}}function po(e){if(typeof document>"u")return null;const t=document.createElement("canvas").getContext("2d");if(!t)return null;const n=_r(t),{layout:o}=ho(e);return fr(e,n,o)}
262
+ function go(e,t){const n=new Map;if(!t||e.pageless===!0)return new Map;const o=(a,l)=>{if(!a||typeof l!="number"||!Number.isFinite(l))return;const c=Math.max(1,Math.floor(l)),d=n.get(a);if(!d){n.set(a,
263
+ {min:c,max:c});return}d.min=Math.min(d.min,c),d.max=Math.max(d.max,c)};for(const a of t.fragments)o(a.blockId,a.pageNumber);for(const a of t.blocks)o(a.blockId,a.pageNumber);const r=xn(e.pageLayout),i=new Map;
264
+ for(const[a,l]of n)i.set(a,{pageStart:Sn(r,l.min-1),pageEnd:Sn(r,l.max-1)});return i}function Li(e,t){let n,o;for(const r of e){const i=t.get(r);i&&(n=n===void 0?i.pageStart:Math.min(n,i.pageStart),o=
265
+ o===void 0?i.pageEnd:Math.max(o,i.pageEnd))}return n!==void 0&&o!==void 0?{pageStart:n,pageEnd:o}:void 0}function fo(e,t,n,o){const r=Math.max(0,Math.min(t,e.children.length-1)),i=Math.max(0,Math.min(
266
+ n,e.children.length-1));if(r>i||e.children.length===0)return null;const a=e.children.slice(r,i+1),l=e.children[r],c=e.children[i];if(!l?.id||!c?.id)return null;const d=mo(a),u=a.map(b=>b.id).filter(Boolean),
267
+ f=Li(u,o);return{startIndex:r,endIndex:i,startBlockId:l.id,endBlockId:c.id,inclusive:!0,blockCount:a.length,wordCount:d.wordCount,paragraphCount:d.paragraphCount,characterCount:d.characterCount,...f?{
268
+ pageStart:f.pageStart,pageEnd:f.pageEnd}:{}}}function Ui(e,t,n){const o=[],r=n?new Set(n):null;for(const i of pr(e,{maxDepth:3})){const a=i.index,l=i.endIndex,c=i.level;if(r&&!r.has(c))continue;const d=fo(
269
+ e,a,l,t);d&&o.push({startIndex:d.startIndex,endIndex:d.endIndex,startBlockId:d.startBlockId,endBlockId:d.endBlockId,headingLevel:c,title:i.title,wordCount:d.wordCount,paragraphCount:d.paragraphCount,characterCount:d.
270
+ characterCount,...d.pageStart!==void 0?{pageStart:d.pageStart,pageEnd:d.pageEnd}:{}})}return o}function bo(e,t){const n=t&&"layout"in t?t.layout??null:e.pageless===!0?null:po(e),o=mo(e.children),r=e.pageless===
271
+ !0?null:n,i=t?.includeSections===!0?go(e,n):new Map;return{inclusive:!0,totalBlocks:e.children.length,wordCount:o.wordCount,paragraphCount:o.paragraphCount,characterCount:o.characterCount,...r?{pageCount:r.
272
+ pageCount}:{},...t?.includeFractionalPageCount===!0&&r?{fractionalPageCount:Fi(e,r)}:{},...t?.includeSections===!0?{sections:Ui(e,i,t.headingLevels).map(a=>({...a,inclusive:!0,blockCount:a.endIndex-a.
273
+ startIndex+1}))}:{}}}function Fi(e,t){const{layout:n}=ho(e);return br(n,t)}function _o(e){return typeof e!="string"?"":e.trim().replace(/^#+/,"")}function zi(e,t,n){const o=po(e),r=go(e,o),i=new Map;for(let c=0;c<
274
+ e.children.length;c+=1){const d=e.children[c]?.id;d&&i.set(d,c)}const a=[],l=[];for(const c of t){const d=_o(c.startBlockId),u=_o(c.endBlockId??d),f=i.get(d),b=i.get(u);if(!d){l.push({error:"start_blo\
275
+ ck_id is required."});continue}if(f===void 0){l.push({startBlockId:d,endBlockId:u,error:`start_block_id "${d}" was not found.`});continue}if(b===void 0){l.push({startBlockId:d,endBlockId:u,error:`end_\
276
+ block_id "${u}" was not found.`});continue}if(b<f){l.push({startBlockId:d,endBlockId:u,error:`end_block_id "${u}" comes before start_block_id "${d}". Ranges must be forward and inclusive.`});continue}
277
+ const y=fo(e,f,b,r);if(!y){l.push({startBlockId:d,endBlockId:u,error:`Could not measure inclusive range "${d}"-"${u}".`});continue}a.push(y)}return{inclusive:!0,totalBlocks:e.children.length,ranges:a,
278
+ errors:l}}const Ji="The agent had trouble completing this request. Please try again.",yo="Document session unavailable after waiting for document load",Wi="document_session_unavailable";class Hi extends Error{constructor(t){
279
+ super("Open the source document linked in the conversation to continue these edits."),this.sourceDocumentId=t,this.name="ForeignDocumentTargetError"}}const Gi="InvalidAssistantResponseError",Ki="Could\
280
+ n't reach the server. Please check your connection and try again.",Vi=["aborted without reason","bodystreambuffer was aborted","client.timeout","connection reset by peer","context canceled","context c\
281
+ ancellation","context cancelled","context deadline exceeded","econnreset","etimedout","failed to fetch","failed to execute 'fetch'","fetch is aborted","gateway timeout","http error! status:","illegal \
282
+ access","illegal invocation","load failed","network request failed","socket hang up","upstream request timeout","while reading body"],Xi=["function call is missing a thought_signature","does not suppo\
283
+ rt the effort parameter","response with id=","gemini api error: 400","xai api error: 404","anthropic api error: 400"],Qi=["server_error","service_unavailable","server_is_overloaded","503 service unava\
284
+ ilable","error in input stream"],Zi=["context_length_exceeded","input token count exceeds","exceeds the context window","maximum number of tokens","maximum context length","prompt is too long","too ma\
285
+ ny input tokens"],Yi=['attachment "',"attachment not found","unable to download the file","failed to fetch attachment","expected a valid url","invalid 'input","image_url"],es=['block id "',"document c\
286
+ hanged while","reference block","not found in document","not found in the document","insert_block"];function ts(e){const t=e.toLowerCase();return t.includes("network")||Vi.some(n=>t.includes(n))}function ns(e){
287
+ if(e?.name==="AbortError"||e instanceof DOMException&&e.code===20)return{isAbort:!0,isRateLimited:!1,isNetworkError:!1,kind:"abort",rawMessage:"",message:"",shouldRetryWithStableModel:!1,shouldTrackConversationError:!1};
288
+ const t=e instanceof Error?e.message:typeof e?.toString=="function"?e.toString():String(e??""),n=t.toLowerCase(),o=t==="RATE_LIMITED"||e?.message==="RATE_LIMITED",r=e instanceof TypeError||ts(t),i=e instanceof
289
+ Error&&e.name===Gi,a=d=>d.some(u=>n.includes(u)),l=e instanceof Hi?"document_target":o?"rate_limited":i?"invalid_assistant_response":t.trim().length===0?"unknown_empty":a(Zi)?"context_limit":a(Yi)?"at\
290
+ tachment":n.includes(yo.toLowerCase())?"document_loading":a(es)?"document_state":a(Xi)?"provider_protocol":a(Qi)?"provider_transient":r?"connection":"unknown";let c;return o?c="Rate limit reached":i?c=
291
+ "The agent sent an invalid response. Please try again.":l==="connection"?c=Ki:l==="provider_protocol"||l==="provider_transient"?c="The model service had trouble completing this request. Please try aga\
292
+ in.":l==="context_limit"?c="This request is too large for the model. Try a smaller request or attach fewer files.":l==="attachment"?c="The agent could not read one of the attached files.":l==="documen\
293
+ t_loading"?c="The document is still loading. Please wait a moment and try again.":l==="document_target"?c=t:l==="document_state"?c="Document state changed during the request.":l==="unknown_empty"?c="T\
294
+ he agent stopped unexpectedly. Your prompt is saved.":c=Ji,{isAbort:!1,isRateLimited:o,isNetworkError:r,kind:l,rawMessage:t,message:c,shouldRetryWithStableModel:l==="provider_protocol"||l==="provider_\
295
+ transient",shouldTrackConversationError:l!=="rate_limited"&&l!=="connection"&&l!=="document_loading"}}const wo=[{name:"get_selection",description:"Read the host user's current semantic editor selectio\
296
+ n. Returns selected text, caret/range positions, portable target segments, active formatting, comment IDs, and pending suggestion IDs. Returns no viewport geometry. Use this when the host has not alre\
297
+ ady supplied selection context.",inputSchema:{additionalProperties:!1,properties:{},type:"object"}},{name:"read_blocks_from_index",description:"Read consecutive blocks from a 0-based start index. Omit\
298
+ document_id for the current document, or pass a known document_id to read another document. If the user names or links a specific document and you know its ID, use this directly instead of search_doc\
299
+ uments. Client chooses count by budget. Use at most one read/search tool per turn.",inputSchema:{additionalProperties:!1,properties:{context_notes:{description:"Plain-text notes to carry forward from \
300
+ current context before this read/search. Use 'N/A' if none.",type:"string"},document_id:{description:"Optional document ID. Omit for the current document. Other documents are read-only sources: their \
301
+ block IDs cannot be used in mutation tools. To edit another document, ask the user to open it and continue there.",type:"string"},index:{description:"0-based start block index.",minimum:0,type:"intege\
302
+ r"}},required:["index","context_notes"],type:"object"}},{name:"search_document",description:"Search text within one document. Call this when you need to locate specific wording, a term, a name, or eve\
303
+ ry occurrence of something and you do not already know which blocks contain it — searching is how you find the target before editing it, and is cheaper and more reliable than reading through the docum\
304
+ ent. Current-document results include a request-scoped search_result_id for the full unpaginated match set; pass it to replace, replace_block, style_blocks, or remove_blocks to target every match with\
305
+ out paging through IDs. Omit document_id for the current document, or pass a known document_id to search within another document. If you instead need to read a document start-to-finish and already kno\
306
+ w its ID, prefer read_blocks_from_index with document_id. Displayed matches are paginated. Use at most one read/search tool per turn.",inputSchema:{additionalProperties:!1,properties:{context_notes:{description:"\
307
+ Plain-text notes to carry forward from current context before this read/search. Use 'N/A' if none.",type:"string"},document_id:{description:"Optional document ID. Omit for the current document. Other \
308
+ documents are read-only sources: their block IDs cannot be used in mutation tools. To edit another document, ask the user to open it and continue there.",type:"string"},page:{description:"0-based resu\
309
+ lt page.",type:"integer"},queries:{description:"Search terms, max 20. Plain strings are case-insensitive; prefix regex patterns with 'regex:'.",items:{type:"string"},type:"array"}},required:["queries",
310
+ "page","context_notes"],type:"object"}},{name:"find_highlights",description:'Find highlighted text blocks, optionally by color. Call this whenever the request refers to highlighted text — "the highlig\
311
+ hted parts", "what I marked", "the yellow bits" — before acting on it; highlights are not visible in loaded document content, so this is the only way to learn which blocks the user means. Matching blo\
312
+ cks load next turn. Results are paginated at 25 blocks/page. Use at most one read/search tool per turn.',inputSchema:{additionalProperties:!1,properties:{color:{description:"Optional color filter.",enum:[
313
+ "yellow","orange","green","blue","purple","pink","gray"],type:"string"},context_notes:{description:"Plain-text notes to carry forward from current context before this read/search. Use 'N/A' if none.",
314
+ type:"string"},page:{description:"0-based result page.",type:"integer"}},required:["page","context_notes"],type:"object"}},{name:"read_specific_blocks",description:"Read specific blocks by ID. Omit do\
315
+ cument_id for the current document, or pass a known document_id to read another document. If you already know both the document ID and block IDs, use this directly instead of search_documents. Use at \
316
+ most one read/search tool per turn.",inputSchema:{additionalProperties:!1,properties:{block_ids:{description:"Block IDs to read, max 50.",items:{type:"string"},type:"array"},context_notes:{description:"\
317
+ Plain-text notes to carry forward from current context before this read/search. Use 'N/A' if none.",type:"string"},document_id:{description:"Optional document ID. Omit for the current document. Other \
318
+ documents are read-only sources: their block IDs cannot be used in mutation tools. To edit another document, ask the user to open it and continue there.",type:"string"}},required:["block_ids","context\
319
+ _notes"],type:"object"}},{name:"read_table",description:"Read a bounded part of a table in the current document by table_id. Native agents receive row contents in the next document snapshot; other cal\
320
+ lers receive rows in this result. Results include coverage metadata and continuations. When a serialized window is partial, consume next_read and then following_read to avoid skipping columns or later\
321
+ rows. mode=summary returns dimensions, merged anchors/spans, per-column fill counts and missing ranges only: it delivers no cell contents and grants no edit rights. mode=rows (default) delivers rows \
322
+ by row_start/row_count or explicit row_ids, optionally limited to a column range; only delivered cells can be edited. mode=cell_text pages one oversized cell by cell_id/text_offset and continuation_re\
323
+ vision; cell_text includes list markers and explicit non-text placeholders, opens each nested block's text with an inline [[block_id]] marker (metadata, not document text; never include it in find tex\
324
+ t), and routes nested tables to their own read_table calls. Its windows are always read-only and never authorize whole-cell replacement; read a complete nested block with read_specific_blocks to edit \
325
+ that block. For cells not already fully delivered in a table seed or cell snapshot, read the needed rows, then batch edits with edit_table_cells. Do not re-read cells whose current contents are alread\
326
+ y delivered. Optionally declare the overall task scope (task_kind, scope_*, source_attachment_id) and deliberate_blanks so progress can be tracked across turns; scope is never inferred from a partial \
327
+ edit. Use at most one read/search tool per turn.",inputSchema:{additionalProperties:!1,properties:{cell_id:{description:"Cell ID for mode=cell_text.",type:"string"},column_count:{description:"Optional\
328
+ number of logical columns starting at column_start.",minimum:1,type:"integer"},column_start:{description:"Optional 0-based first logical column. Omit to read all columns. A partial column read author\
329
+ izes edits only to the delivered cells, not the whole row.",minimum:0,type:"integer"},context_notes:{description:"Plain-text notes to carry forward from current context before this read/search. Use 'N\
330
+ /A' if none.",type:"string"},continuation_revision:{description:"Revision from the previous result continuation. Rejects continuation when cell text or table geometry changed, so stale and fresh windo\
331
+ ws are never combined.",type:"string"},deliberate_blanks:{description:"Optional in-scope cells intentionally left empty, each with a reason, so they are not reported as remaining work.",items:{additionalProperties:!1,
332
+ properties:{column:{description:"0-based logical column.",minimum:0,type:"integer"},reason:{description:"Why the cell stays empty.",type:"string"},row_id:{description:"Stable row ID.",type:"string"}},
333
+ required:["row_id","column","reason"],type:"object"},maxItems:50,type:"array"},mode:{description:"summary: metadata and counts only. rows (default when omitted): deliver row contents. cell_text: bound\
334
+ ed text window of one oversized cell.",enum:["summary","rows","cell_text"],type:"string"},row_count:{description:"Rows to deliver for mode=rows. Defaults to 25; maximum 50.",maximum:50,minimum:1,type:"\
335
+ integer"},row_ids:{description:"Explicit stable row IDs (<tr id>) to deliver instead of row_start/row_count.",items:{type:"string"},maxItems:50,type:"array"},row_start:{description:"0-based first row \
336
+ for mode=rows, counting header rows. Ignored when row_ids is supplied.",minimum:0,type:"integer"},scope_columns:{description:"Optional declared task scope: 0-based logical columns the task writes.",items:{
337
+ minimum:0,type:"integer"},type:"array"},scope_row_count:{description:"Optional declared task scope: number of rows covered by the user's whole request.",minimum:1,type:"integer"},scope_row_start:{description:"\
338
+ Optional declared task scope: first 0-based row covered by the user's whole request.",minimum:0,type:"integer"},source_attachment_id:{description:"Optional attachment ID the task copies or derives val\
339
+ ues from.",type:"string"},table_id:{description:"Table block ID in the current document.",type:"string"},task_kind:{description:"Optional task declaration. fill: populate empty cells. transform: rewri\
340
+ te existing cells (translate, shorten, etc.).",enum:["fill","transform"],type:"string"},text_offset:{description:"Character offset for mode=cell_text. Use the offset from the previous result's continu\
341
+ ation.",minimum:0,type:"integer"}},required:["table_id","context_notes"],type:"object"}},{name:"measure_document",description:"Measure the current document without loading body text. Use this for tota\
342
+ l word count, paragraph count, block count, rendered page count, and paginated per-heading section measurements. Primary totals treat pending suggestions as accepted; when pending suggestions change c\
343
+ ounts, the result also reports the original review projection so you can reconcile the number visible in the user's editor view. Set include_sections=true for per-chapter/per-section counts and inclus\
344
+ ive block ranges.",inputSchema:{additionalProperties:!1,properties:{heading_levels:{description:"Optional heading levels to include when include_sections is true. Defaults to h1, h2, and h3.",items:{enum:[
345
+ 1,2,3],type:"integer"},type:"array"},include_sections:{description:"Whether to include heading section measurements. Default false. Use true for per-chapter or per-section counts.",type:"boolean"},section_limit:{
346
+ description:"Maximum heading sections to return when include_sections is true. Default and maximum 100.",maximum:100,minimum:1,type:"integer"},section_offset:{description:"Zero-based section offset wh\
347
+ en include_sections is true. Default 0. Use nextSectionOffset from the previous result to continue.",minimum:0,type:"integer"}},type:"object"}},{name:"measure_blocks",description:"Measure inclusive bl\
348
+ ock ranges in the current document without loading document text. Use this for word counts, paragraph counts, block counts, and rendered page ranges. Block IDs may be passed with or without a leading \
349
+ #.",inputSchema:{additionalProperties:!1,properties:{mode:{description:"Range mode. Only inclusive is supported.",enum:["inclusive"],type:"string"},ranges:{description:"Inclusive block ranges to measu\
350
+ re. Omit end_block_id to measure only start_block_id.",items:{additionalProperties:!1,properties:{end_block_id:{description:"Last block ID in the inclusive range. Omit to measure only the start block.",
351
+ type:"string"},start_block_id:{description:"First block ID in the inclusive range.",type:"string"}},required:["start_block_id"],type:"object"},type:"array"}},required:["ranges"],type:"object"}},{name:"\
352
+ view_image",description:'View a document image by block ID when its <img> src is hidden. Viewing is only for seeing pixels; you do not need the hidden source to copy, move, or swap an image—write <img\
353
+ src="IMAGE_ID"> with its exact document id in insert_block or replace_block HTML.',inputSchema:{additionalProperties:!1,properties:{block_id:{description:"Image block ID.",type:"string"}},required:["\
354
+ block_id"],type:"object"}},{name:"insert_block",description:'Insert native block(s) before/after a reference block using HTML. To add items inside an existing list, reference a list-item ID and pass s\
355
+ eparate <li>...</li> entries in the desired order; this preserves the existing list numbering and style. Referencing the list container inserts a separate sibling block, not items within that list. A \
356
+ reference may be nested inside a table cell; inserting <img> (bare or wrapped by a paragraph/presentational span) next to that reference creates a native image block in the same cell. For a web-source\
357
+ d image, use a verified direct raster URL returned by search for src; never guess or infer an image filename. Add data-source-url="..." to the <img> using the source webpage URL returned by web search\
358
+ , or the original image URL when no webpage URL is available; Revise preserves this provenance across later requests while rehosting the rendered image. For a live table of contents that automatically\
359
+ tracks document headings, insert <toc levels="3"></toc> (levels may be 1-6; omitting the attribute defaults to 3). Never build a table of contents from ordinary paragraphs, tabs, lists, or manually c\
360
+ opied headings. For an Arabic/RTL live TOC, keep the toc block and set dir="rtl" and style="text-align:right" on it; direction:rtl and text-align:right also work through style_blocks. RTL places page \
361
+ numbers at the left edge. Do not replace a live TOC with a static table to adjust formatting. Put alignment directly in inserted HTML when needed. To cite inside new content, embed native notes inline\
362
+ : <sup data-footnote="Note body.">1</sup> creates a footnote in this same call (data-note-kind="endnote" for endnotes).',inputSchema:{additionalProperties:!1,properties:{content:{description:'HTML blo\
363
+ ck elements to insert, e.g. <p>, <h1>, <li> (within an existing list), <ul> (a new list), <img>, <toc levels="3"></toc> (live table of contents), <page-break />, <hr /> (horizontal rule), <pre>. An im\
364
+ age may be wrapped in a paragraph/span for alignment and display dimensions. For a web-sourced image, use a verified direct raster URL returned by search for src. Never guess or infer an image filenam\
365
+ e. Put its source webpage URL in data-source-url on the <img> (fall back to the original image URL). An image whose src is hidden is still usable: to copy or move it, write <img src="IMAGE_ID"> with i\
366
+ ts exact document id (dimensions and alt may be restated); the source is resolved automatically, so never ask the user for it.',items:{type:"string"},minItems:1,type:"array"},position:{description:"In\
367
+ sert before or after reference block.",enum:["before","after"],type:"string"},referenceId:{description:"Current reference block ID. For a blank document, pass an empty string with position=after; the \
368
+ editor resolves the blank insertion location. Never ask the user to type placeholder text. For a document with content, use an existing block ID.",type:"string"}},required:["content","position","refer\
369
+ enceId"],type:"object"}},{name:"insert_footnote",description:"Insert a footnote: a numbered superscript reference placed right after the anchor text in a paragraph, plus the footnote body (rendered at\
370
+ the bottom of the page). Footnote bodies appear in the document as [^n] references with their own blocks — edit them with replace/replace_block and remove them with remove_blocks on the footnote bloc\
371
+ k (removing a body also removes its reference).",inputSchema:{additionalProperties:!1,properties:{find:{description:"Anchor text inside the block; the reference is inserted right after it. Empty strin\
372
+ g appends at the end of the block.",type:"string"},id:{description:"Paragraph block ID that receives the reference.",type:"string"},kind:{description:"Note stream: footnote (per-page bottom area, numb\
373
+ ered 1,2,3 — default) or endnote (grouped on its own page at the document end, numbered i,ii,iii).",enum:["footnote","endnote"],type:"string"},text:{description:"Footnote body text.",type:"string"}},
374
+ required:["id","find","text"],type:"object"}},{name:"remove_blocks",description:"Remove native footnotes/endnotes by targeting the note ID or its body block ID with id alone; this removes the entire n\
375
+ ote and all its inline references while preserving the surrounding paragraph. To remove multiple notes, use ids containing only note/body IDs (do not mix with main-document block IDs or use an end_id \
376
+ range). For notes found by search, use their explicit IDs rather than search_result_id. Remove one or more blocks by a direct target (id alone for one block, or id + end_id for a consecutive range, bo\
377
+ th inclusive), an explicit tail range (id + through_end=true), an exact nonconsecutive ID batch (ids), or every block in a full search_document result (search_result_id). through_end removes the start\
378
+ ing top-level block and every block after it through the current end of the document; use it only when that entire tail must be removed. The starting id must have appeared in current request context, \
379
+ but through_end does not require reading every interior block. Other direct targets must have appeared in current request context. Prefer search_result_id for large or sparse match sets; search discov\
380
+ ers candidates but never deletes them implicitly.",inputSchema:{additionalProperties:!1,properties:{end_id:{description:"Last block ID of a consecutive range to remove, inclusive, at the same level as\
381
+ id (same document level, table cell, or list). Omit to remove only id. Every block from id through end_id must have appeared in current request context.",type:"string"},id:{description:"First block I\
382
+ D to remove.",type:"string"},ids:{description:"Exact nonconsecutive block IDs to remove. Each ID must have appeared in document context during this request. Do not infer IDs from a query.",items:{type:"\
383
+ string"},maxItems:50,minItems:1,type:"array"},search_result_id:{description:"Request-scoped ID returned by search_document for the current document. Applies this operation to every block in the full u\
384
+ npaginated result set. Use instead of id or ids. Rerun search_document if the reference is unavailable or stale.",type:"string"},through_end:{description:"Set true with id to remove that top-level blo\
385
+ ck and the entire document tail after it. Mutually exclusive with end_id, ids, and search_result_id. Omit unless the whole tail is intentionally in scope.",type:"boolean"}},type:"object"}},{name:"appe\
386
+ nd_to_paragraph",description:"Append HTML content to a paragraph.",inputSchema:{additionalProperties:!1,properties:{content:{description:"HTML content to append.",type:"string"},id:{description:"Parag\
387
+ raph ID.",type:"string"}},required:["id","content"],type:"object"}},{name:"break_paragraph",description:"Split a paragraph at the first occurrence of substring; second paragraph starts there.",inputSchema:{
388
+ additionalProperties:!1,properties:{id:{description:"Paragraph ID.",type:"string"},substring:{description:"Substring where split begins.",type:"string"}},required:["id","substring"],type:"object"}},{name:"\
389
+ join_paragraphs",description:"Join two adjacent paragraphs without rewriting their text. The second paragraph is appended to the first, preserving inline formatting from both paragraphs, then removed.\
390
+ Use this to repair an accidental paragraph break or hard return.",inputSchema:{additionalProperties:!1,properties:{firstId:{description:"ID of the first paragraph. This paragraph and its block format\
391
+ ting are preserved.",type:"string"},secondId:{description:"ID of the immediately following sibling paragraph. Its inline-formatted text is appended, then this block is removed.",type:"string"},separator:{
392
+ description:"Text placed between the paragraphs. Defaults to one space between non-empty paragraphs. A non-empty separator replaces existing boundary whitespace so it is not duplicated. Pass an empty \
393
+ string to add nothing and preserve existing boundary whitespace.",type:"string"}},required:["firstId","secondId"],type:"object"}},{name:"replace_block",description:'Replace entire consecutive block(s)\
394
+ with HTML block(s), or apply the same one-block replacement independently to every block in a full search_document result via search_result_id. Use this only when the whole block must be replaced, it\
395
+ s block type must change, or multiple consecutive blocks must become a different block structure. Prefer replace for ordinary wording, sentence, paragraph-text, typo, punctuation, or formatting-preser\
396
+ ving edits—even when most or all visible text in one paragraph changes—because replace preserves block identity and untouched formatting. Preserve the existing block type unless the user asks to chang\
397
+ e it: use <pre language="..."> for code, <latex> for display math, and <latex-inline> for inline math. Put alignment in replacement HTML. For a web-sourced replacement image, use a verified direct ras\
398
+ ter URL returned by search for src; never guess or infer an image filename. Put its source webpage URL in data-source-url on the <img> (fall back to the original image URL).',inputSchema:{additionalProperties:!1,
399
+ properties:{content:{description:'Replacement HTML block elements, e.g. <p>, <h1>, <ul>, <pre language="typescript">code</pre>, <img>, or <latex>E = mc^2</latex>. Match the original block type unless \
400
+ a type change was requested. For a web-sourced image, use a verified direct raster URL returned by search for src. Never guess or infer an image filename. Put its source webpage URL in data-source-url\
401
+ on the <img> (fall back to the original image URL). An image whose src is hidden is still usable: to copy or move it, write <img src="IMAGE_ID"> with its exact document id (dimensions and alt may be \
402
+ restated); the source is resolved automatically, so never ask the user for it.',items:{type:"string"},minItems:1,type:"array"},end_id:{description:"Last block ID of a consecutive range to replace, inc\
403
+ lusive, at the same level as id (same document level, table cell, or list). Omit to replace only id. Every block from id through end_id must have appeared in current request context.",type:"string"},id:{
404
+ description:"First block ID to replace.",type:"string"},search_result_id:{description:"Request-scoped ID returned by search_document for the current document. Applies this operation to every block in \
405
+ the full unpaginated result set. Use instead of id or ids. Rerun search_document if the reference is unavailable or stale.",type:"string"}},required:["content"],type:"object"}},{name:"style_blocks",description:'\
406
+ Style existing content with forgiving CSS-lite selectors and values. Use one bulk style_blocks call instead of per-block replace calls when matching content shares a selector or search result. Pass se\
407
+ arch_result_id to scope selectors to every block in the full unpaginated search_document result; * then means each matched block. Block selectors include *, #blockId, p, h1-h6, li, lists, tables, and \
408
+ descendants. Inline selectors such as span, b/strong, i/em, u, s/strike/del, code, sup, sub, mark, and a target text ranges; they may be scoped, for example p span, p b, or #blockId strong. Text color\
409
+ accepts CSS named colors, hex colors, and CSS color functions and stores an absolute hex color. For text highlighting, use backgroundColor with one of the seven canonical values yellow, orange, green\
410
+ , blue, purple, pink, or gray; other names and CSS colors normalize to this palette by hue (a pale lavender such as #E4DFEC becomes purple) and may be the same color. A backgroundColor on a table-cell\
411
+ selector sets the cell fill; on text blocks or inline selectors it highlights text, which is also how to express paragraph shading. Setting a value back to the original reverts your pending formattin\
412
+ g suggestion. Table-cell selectors apply text styles, alignment, and spacing to their descendant paragraphs. Examples: highlight all h3 headings orange with selectors="h3" and attrs=[{"name":"backgrou\
413
+ ndColor","value":"orange"}]; remove all bold with selectors="b" and attrs=[{"name":"fontWeight","value":"normal"}]; set the entire document to Century Schoolbook 14pt double-spaced with selectors="*" \
414
+ and fontFamily/fontSize/lineSpacing attrs; bold headings with selectors=["h1","h2","h3"] and fontWeight="bold".',inputSchema:{additionalProperties:!1,properties:{attrs:{description:"Use CSS/Revise nam\
415
+ es. Text colors accept CSS names, hex, or functions. Highlights: yellow, orange, green, blue, purple, pink, or gray. Supports text typography, block alignment, hanging indents, list presentation, imag\
416
+ e sizing with CSS lengths, and table/cell sizing with percentage widths. CSS maps to durable document equivalents; feedback lists approximations and unsupported values. Null resets.",items:{additionalProperties:!1,
417
+ properties:{name:{description:"Attribute/style name, e.g. fontSize, font-size, fontFamily, text-align.",type:"string"},value:{description:"Value to set, or null to remove/reset.",oneOf:[{type:"string"},
418
+ {type:"number"},{type:"boolean"},{type:"null"}]}},required:["name","value"],type:"object"},minItems:1,type:"array"},search_result_id:{description:"Request-scoped ID returned by search_document for the\
419
+ current document. Applies this operation to every block in the full unpaginated result set. Use instead of id or ids. Rerun search_document if the reference is unavailable or stale.",type:"string"},selectors:{
420
+ description:'CSS-lite selectors over the document HTML: * (also all, document, or :root), #blockId, p, h1-h6, li, ul, ol, pre, latex, img, table, tr, td/th, div, p[data-style-id="StyleName"], and inli\
421
+ ne formatting tags span, b/strong, i/em, u, s/strike/del, code, sup, sub, mark, a. Simple descendants, general siblings, descendant wildcards, :first-child, and :nth-child(n) are accepted, e.g. table \
422
+ tr:first-child td, table td:nth-child(2) p, #blockId td p, #blockId *, #blockId ~ p, p span, p b, or #blockId strong. Inline selectors affect matching text ranges; span means all text in its scope. Ar\
423
+ rays and comma grouping are allowed.',oneOf:[{type:"string"},{items:{type:"string"},minItems:1,type:"array"}]}},required:["selectors","attrs"],type:"object"}},{name:"clear_formatting",description:"Cle\
424
+ ar removable inline emphasis from paragraph/list-item target(s): bold, italic, underline, code, LaTeX, superscript/subscript, background highlight, and links. Preserve font family, font size, text col\
425
+ or, and paragraph attributes.",inputSchema:{additionalProperties:!1,properties:{id:{description:"Target paragraph/list-item/list ID or IDs.",oneOf:[{type:"string"},{items:{type:"string"},minItems:1,type:"\
426
+ array"}]}},required:["id"],type:"object"}},{name:"set_title",description:"Change the document title",inputSchema:{additionalProperties:!1,properties:{title:{description:"The new document title",maxLength:300,
427
+ type:"string"}},required:["title"],type:"object"}},{name:"set_page_layout",description:"Patch page or section layout: preset, size, margins, 1-3 columns, page numbers, spacing, pageless mode. ONLY the\
428
+ fields you pass change; everything else keeps its current or inherited value (a section keeps inheriting document-level settings for fields you don't pass). Pass sectionIndex to change one section; o\
429
+ mit it to apply the passed fields to the document defaults and every section. Length fields must be strings with explicit px/in/cm units. Preset 'apa7' applies standard APA layout.",inputSchema:{additionalProperties:!1,
430
+ properties:{blockSpacing:{description:'Vertical spacing between adjacent blocks, shown in the UI in inches or centimeters. Typical values are "0.08in" to "0.25in" (about "0.2cm" to "0.64cm"); do not u\
431
+ se whole-inch values like "2in" or "4in" for normal paragraph spacing. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do\
432
+ not send bare numbers.',type:"string"},clearPageBorders:{description:"Set true to remove all page borders from the target section(s), including preserved Word art borders.",type:"boolean"},columnCount:{
433
+ description:"Number of newspaper-style columns in the target section.",enum:[1,2,3],type:"integer"},columnGap:{description:'Gap between columns. Include an explicit unit: in, cm, or px (examples: "1in\
434
+ ", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},indentStep:{description:'Paragraph indent step. Include an explicit unit: in, cm, or p\
435
+ x (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},margin:{description:'Uniform page margin applied to all sides. Includ\
436
+ e an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginBottom:{description:'Bottom pag\
437
+ e margin. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginLeft:{description:'\
438
+ Left page margin. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},marginRight:{
439
+ description:'Right page margin. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},
440
+ marginTop:{description:'Top page margin. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"\
441
+ string"},noteMode:{description:"Bulk-convert existing native notes to this stream: footnotes (per-page areas, 1,2,3) or endnotes (own page at document end, i,ii,iii). Does not convert manually typed s\
442
+ uperscript numbers or note paragraphs; create native notes with their complete bodies and references first. Individual notes choose a stream at insert time.",enum:["footnotes","endnotes"],type:"string"},
443
+ orientation:{description:"Page orientation.",enum:["portrait","landscape"],type:"string"},pageBorders:{additionalProperties:!1,description:"Native page border for the target section(s), rendered in th\
444
+ e editor and PDF and preserved in DOCX. Replaces the whole border configuration; omitted sides have no border. To remove borders use clearPageBorders=true. Measurements are points (1/72 inch).",properties:{
445
+ bottom:{additionalProperties:!1,properties:{color:{pattern:"^#[0-9a-fA-F]{6}$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"strin\
446
+ g"},widthPt:{maximum:12,minimum:.25,type:"number"}},required:["style","color","widthPt","spacePt"],type:"object"},display:{enum:["allPages","firstPage","notFirstPage"],type:"string"},left:{additionalProperties:!1,
447
+ properties:{color:{pattern:"^#[0-9a-fA-F]{6}$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"string"},widthPt:{maximum:12,minimum:.25,
448
+ type:"number"}},required:["style","color","widthPt","spacePt"],type:"object"},offsetFrom:{enum:["page","text"],type:"string"},right:{additionalProperties:!1,properties:{color:{pattern:"^#[0-9a-fA-F]{6\
449
+ }$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","double","dotted","dashed"],type:"string"},widthPt:{maximum:12,minimum:.25,type:"number"}},required:["style","colo\
450
+ r","widthPt","spacePt"],type:"object"},top:{additionalProperties:!1,properties:{color:{pattern:"^#[0-9a-fA-F]{6}$",type:"string"},spacePt:{maximum:31,minimum:0,type:"number"},style:{enum:["single","do\
451
+ uble","dotted","dashed"],type:"string"},widthPt:{maximum:12,minimum:.25,type:"number"}},required:["style","color","widthPt","spacePt"],type:"object"},zOrder:{enum:["front","back"],type:"string"}},required:[
452
+ "offsetFrom","display","zOrder"],type:"object"},pageHeight:{description:'Explicit page height. Include an explicit unit: in, cm, or px (examples: "1in", "3cm", "72px"). Prefer in/cm for page layout va\
453
+ lues shown in the UI. Do not send bare numbers.',type:"string"},pageNumberFormat:{description:"Page number style: decimal (1, 2, 3), lowerRoman (i, ii, iii), or upperRoman (I, II, III). Applies to pag\
454
+ e-number fields, the table of contents, and exports. Use sectionIndex for front matter.",enum:["decimal","lowerRoman","upperRoman"],type:"string"},pageNumberPosition:{description:"Page number position\
455
+ .",enum:["top-left","top-right","bottom-left","bottom-right"],type:"string"},pageNumberRestart:{description:"Section numbering mode (use with sectionIndex, including the final section): true restarts \
456
+ at pageNumberStart (default 1); false continues from the previous section. Typical thesis: Roman front matter, then the final body section restarts at 1.",type:"boolean"},pageNumberStart:{description:"\
457
+ First page number. With sectionIndex it restarts numbering at that section (e.g. body starts again at 1 after Roman front matter).",minimum:1,type:"integer"},pageSize:{description:"Named page-size pre\
458
+ set.",enum:["letter","tabloid","legal","statement","executive","folio","a3","a4","a5","b4","b5"],type:"string"},pageWidth:{description:'Explicit page width. Include an explicit unit: in, cm, or px (ex\
459
+ amples: "1in", "3cm", "72px"). Prefer in/cm for page layout values shown in the UI. Do not send bare numbers.',type:"string"},pageless:{description:"Enable pageless mode.",type:"boolean"},preset:{description:"\
460
+ Preset applied before overrides.",enum:["apa7"],type:"string"},sectionIndex:{description:"One-based section number to patch (invalid indexes fail the call). Omit to apply the passed fields to the docu\
461
+ ment defaults and every section.",minimum:1,type:"integer"},showPageNumbers:{description:"Show or hide page numbers. Page numbers are header/footer content: this manages an automatic page-number field\
462
+ slot (combine with pageNumberPosition). Hand-authored header/footer content is never overwritten.",type:"boolean"}},required:[],type:"object"}},{name:"set_header_footer",description:`Edit page header\
463
+ /footer content. Each side has three zones (left, center, right); provide only the zones to change - untouched zones keep their content and formatting. Use the literal token {PAGE} for a live page num\
464
+ ber and {PAGES} for the total page count, anywhere in any zone (e.g. right: "Page {PAGE} of {PAGES}"). An empty string clears a zone; clear=true removes the header or footer from every page (all slots\
465
+ and every section's override, unless slot or sectionIndex narrows it). Without sectionIndex, zone edits change the document-wide header/footer; a section with its own override keeps it (the result sa\
466
+ ys so). The result lists the headers/footers that exist afterwards, and a call that changes nothing fails with that list. For a plain bottom-right page number, set_page_layout with showPageNumbers als\
467
+ o works.`,inputSchema:{properties:{center:{description:"Center zone text ({PAGE}/{PAGES} tokens allowed). Omit to keep unchanged; empty string clears.",type:"string"},clear:{description:"Remove this s\
468
+ ide's header/footer: from every page and section unless slot or sectionIndex narrows it.",type:"boolean"},image:{additionalProperties:!1,description:"Put an image (e.g. a logo) in this header/footer o\
469
+ n every page, replacing any image already in that band. Pass image_id to reuse an image already in the document, or url for a direct image URL. It is drawn in the page margin band, scaled down to fit \
470
+ (never into the body text), next to any zone text. Do not insert copies of the image into the body to fake a header. Applies to every section; do not combine with sectionIndex or clear.",properties:{alt:{
471
+ description:"Short description of the image.",type:"string"},height:{description:"Optional display height in px.",type:"number"},image_id:{description:"ID of an existing image block to reuse.",type:"s\
472
+ tring"},url:{description:"Direct http(s) URL of a raster image (PNG/JPEG/GIF/WebP).",type:"string"},width:{description:"Optional display width in px (height follows the aspect ratio). Omit to use the \
473
+ image's own size.",type:"number"},zone:{description:"Horizontal position in the band. Default left.",enum:["left","center","right"],type:"string"}},type:"object"},left:{description:"Left zone text ({P\
474
+ AGE}/{PAGES} tokens allowed). Omit to keep unchanged; empty string clears.",type:"string"},right:{description:"Right zone text ({PAGE}/{PAGES} tokens allowed). Omit to keep unchanged; empty string cle\
475
+ ars.",type:"string"},sectionIndex:{description:"One-based section whose own header/footer override to edit or clear. Omit for the document-wide header/footer (and, with clear, every section's override\
476
+ too).",minimum:1,type:"integer"},side:{description:"Which band to edit.",enum:["header","footer"],type:"string"},slot:{description:"Which pages this applies to (Word slot model). Zone edits default t\
477
+ o 'default' (all pages); clear without slot removes every slot.",enum:["default","first","even"],type:"string"}},required:["side"],type:"object"}},{name:"replace",description:"Preferred/default tool f\
478
+ or editing text inside an existing block, including wording, sentences, typos, punctuation, formatting-preserving rewrites, and even replacing all visible text in one paragraph when its block type/str\
479
+ ucture should stay the same. It preserves block identity and untouched formatting; use replace_block only for whole-block structural or block-type changes. Supports one or more in-place edits inside o\
480
+ ne block, uniquely identifiable edits across loaded blocks when id is omitted, or the same edits independently in every block from a full search_document result via search_result_id. An empty find saf\
481
+ ely fills a direct-id target only when that target is truly empty. Each operation may include its own comment, which is attached to every suggestion produced by that operation. For each edit, occurren\
482
+ ce defaults to unique: its find HTML/text must be specific enough to match exactly one location in each target block or the entire call fails without changing the document. Use occurrence=all only whe\
483
+ n every exact occurrence should change. Omit no-op replacements where find and replace are identical.",inputSchema:{additionalProperties:!1,properties:{id:{description:"Target block ID. May be omitted\
484
+ only when every non-empty find uniquely identifies one loaded block, or when search_result_id is used.",type:"string"},replacements:{description:"Ordered replacement operations. Use one item for one \
485
+ edit and multiple items to batch edits in the same block.",items:{additionalProperties:!1,properties:{comment:{description:"Optional comment explaining this operation. It is attached separately to eve\
486
+ ry resulting suggestion from this operation, including every match when occurrence=all. Prefer this over a separate leave_comment when the feedback explains the suggested edit.",type:"string"},find:{description:"\
487
+ Exact text to find; HTML allowed for formatted targets. With occurrence=unique or when occurrence is omitted, include enough surrounding context to match exactly one location.",type:"string"},occurrence:{
488
+ description:"unique (default when omitted) requires exactly one match; all replaces every exact match.",enum:["unique","all"],type:"string"},replace:{description:"Replacement text; HTML allowed for fo\
489
+ rmatting changes. Must differ from find unless the replacement HTML creates a real formatting change.",type:"string"}},required:["find","replace"],type:"object"},maxItems:50,minItems:1,type:"array"},search_result_id:{
490
+ description:"Request-scoped ID returned by search_document for the current document. Applies this operation to every block in the full unpaginated result set. Use instead of id or ids. Rerun search_do\
491
+ cument if the reference is unavailable or stale.",type:"string"}},required:["replacements"],type:"object"}},{name:"leave_comment",description:"Leave granular review feedback on the current document wi\
492
+ thout changing its text. Prefer this for substantive passage-specific critique, feedback, annotations, issues, or improvements instead of putting that feedback in a long chat response. Two modes. To S\
493
+ TART a thread: target one block with id and exactly one anchor form — unique exact text for a short range, start/end boundary text for a longer range without reproducing it, or the whole block for str\
494
+ uctural/empty content. To REPLY to a thread that already exists: pass reply_to_comment_id (a <comment-thread> id from loaded document content) and comment, with no id and no anchor. Existing threads a\
495
+ re visible as <comment-thread> elements in loaded document content; when text already carries one, reply to it rather than starting a second thread that repeats the same point.",inputSchema:{additionalProperties:!1,
497
496
  properties:{acknowledge_existing_thread_ids:{description:"Only for a NEW thread that deliberately overlaps existing unresolved threads: list their ids to confirm you read them and are raising a genuin\
498
497
  ely different point. Without this, a new thread overlapping an existing one is rejected. Do not use it to restate a point an existing thread already makes — reply to that thread instead.",items:{type:"\
499
498
  string"},type:"array"},anchor:{description:"Exactly one single-block anchor. Required for a new thread; omit when replying.",oneOf:[{additionalProperties:!1,properties:{text:{description:"Exact text o\
@@ -537,11 +536,11 @@ string"},text:{description:"Exact literal cell text. Not HTML.",type:"string"}},
537
536
  skips and reports cells that are no longer empty; replace overwrites the delivered cell text.",enum:["fill_if_empty","replace"],type:"string"},table_id:{description:"Table block ID in the current doc\
538
537
  ument.",type:"string"}},required:["table_id","mode","cells"],type:"object"}}],os=new Map(wo.map(e=>[e.name,e.inputSchema]));function Ht(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function ko(e,t){
539
538
  return Object.prototype.hasOwnProperty.call(e,t)}function rs(e,t){switch(t){case"null":return e===null;case"object":return Ht(e);case"array":return Array.isArray(e);case"string":return typeof e=="stri\
540
- ng";case"number":return typeof e=="number"&&Number.isFinite(e);case"integer":return typeof e=="number"&&Number.isInteger(e);case"boolean":return typeof e=="boolean";default:return!0}}function Fe(e,t){
541
- return!(e.const!==void 0&&!Object.is(e.const,t)||e.enum&&!e.enum.some(n=>Object.is(n,t))||e.type&&!(Array.isArray(e.type)?e.type:[e.type]).some(n=>rs(t,n))||e.allOf?.some(n=>!Fe(n,t))||e.anyOf&&!e.anyOf.
542
- some(n=>Fe(n,t))||e.oneOf&&e.oneOf.filter(n=>Fe(n,t)).length!==1||e.not&&Fe(e.not,t)||Ht(t)&&e.required&&!e.required.every(n=>ko(t,n)))}function rt(e,t){let n=e;if(Array.isArray(n)&&t.items)n=n.map(o=>rt(
543
- o,t.items));else if(Ht(n)&&t.properties){const o=new Set(t.required??[]),r={...n};for(const[i,a]of Object.entries(t.properties))if(ko(r,i)){if(r[i]===null&&!o.has(i)&&!Fe(a,null)){delete r[i];continue}
544
- r[i]=rt(r[i],a)}n=r}for(const o of t.allOf??[])n=rt(n,o);for(const o of[t.anyOf,t.oneOf]){const r=o?.filter(i=>Fe(i,n));r?.length===1&&(n=rt(n,r[0]))}return n}function is(e,t){const n=os.get(e);return n?
539
+ ng";case"number":return typeof e=="number"&&Number.isFinite(e);case"integer":return typeof e=="number"&&Number.isInteger(e);case"boolean":return typeof e=="boolean";default:return!0}}function Ue(e,t){
540
+ return!(e.const!==void 0&&!Object.is(e.const,t)||e.enum&&!e.enum.some(n=>Object.is(n,t))||e.type&&!(Array.isArray(e.type)?e.type:[e.type]).some(n=>rs(t,n))||e.allOf?.some(n=>!Ue(n,t))||e.anyOf&&!e.anyOf.
541
+ some(n=>Ue(n,t))||e.oneOf&&e.oneOf.filter(n=>Ue(n,t)).length!==1||e.not&&Ue(e.not,t)||Ht(t)&&e.required&&!e.required.every(n=>ko(t,n)))}function rt(e,t){let n=e;if(Array.isArray(n)&&t.items)n=n.map(o=>rt(
542
+ o,t.items));else if(Ht(n)&&t.properties){const o=new Set(t.required??[]),r={...n};for(const[i,a]of Object.entries(t.properties))if(ko(r,i)){if(r[i]===null&&!o.has(i)&&!Ue(a,null)){delete r[i];continue}
543
+ r[i]=rt(r[i],a)}n=r}for(const o of t.allOf??[])n=rt(n,o);for(const o of[t.anyOf,t.oneOf]){const r=o?.filter(i=>Ue(i,n));r?.length===1&&(n=rt(n,r[0]))}return n}function is(e,t){const n=os.get(e);return n?
545
544
  rt(t,n):t}const ss="This request is non-interactive. Continue the supported work using the supplied context and reasonable assumptions. Explain material gaps in the final response or permitted comment\
546
545
  s; do not invent facts or ask for clarification or approval.",as=new Set(["read_table","create_plan","update_plan","read_blocks","read_blocks_from_index","read_specific_blocks","search_document","find\
547
546
  _highlights","measure_document","measure_blocks","list_documents","search_documents","get_attachment","view_image","render_document_pages","set_status","request_user_input","end_agent_run","finish_res\
@@ -551,28 +550,28 @@ ble_row":t}function cs(e){return Array.from(new Set(e.map(vo).filter(Boolean)))}
551
550
  e.allowedTools).includes(n)?{code:"agent_tool_not_allowed",message:"This tool is outside the host's execution allowlist. Continue using permitted tools or finish with the best supported response."}:Bt.
552
551
  has(n)?e.documentAccess==="edit"||e.documentAccess==="comment"&&n==="leave_comment"?null:{code:"agent_document_access_denied",message:"This request does not permit this document mutation. Continue wit\
553
552
  hin the granted document access and explain any work that could not be completed."}:as.has(n)?null:{code:"agent_tool_not_allowed",message:"This tool has no execution-policy classification and cannot r\
554
- un. Continue using permitted tools."}}const Io="no_new_read_context",ze={scanDocumentFontFamily:!1};function Je(e){return e.getAgentAuthorName?.()?.trim()||yr}const xo=2,us=48,ms=.4,Me=10,hs=100,ps=100,
555
- We=48e3,Be="out_of_context_edit",De="document_state_changed",So="table_batch_rejected",gs="duplicate_comment_anchor",fs="one_read_search_per_turn",Gt="terminal_tool_requires_turn_two_continuation",$o="\
553
+ un. Continue using permitted tools."}}const Io="no_new_read_context",Fe={scanDocumentFontFamily:!1};function ze(e){return e.getAgentAuthorName?.()?.trim()||wr}const xo=2,us=48,ms=.4,Me=10,hs=100,ps=100,
554
+ Je=48e3,Be="out_of_context_edit",De="document_state_changed",So="table_batch_rejected",gs="duplicate_comment_anchor",fs="one_read_search_per_turn",Gt="terminal_tool_requires_turn_two_continuation",$o="\
556
555
  terminal_response_status_only",bs="end_agent_run",_s="finish_response",ys="ready_for_verification",ws=new Set(["read_blocks","read_blocks_from_index","read_specific_blocks","search_document","search_d\
557
556
  ocuments","find_highlights","render_document_pages"]);function ks(e){return e===bs||e===_s}function Co(e){return e.replace(/<status\b[^>]*>[\s\S]*?<\/status>/gi,"").trim().length===0}const Kt="https:/\
558
557
  /app-api.revise-sdk.invalid";function vs(e){if(e&&typeof e=="object"&&!Array.isArray(e))return e;if(typeof e!="string")return null;const t=e.trim();if(!t)return null;if(!t.startsWith("{")||!t.endsWith(
559
- "}"))return{text:t};try{const n=JSON.parse(t);return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}function Is(e){const t=Xe(e.doc,e.requestedBlockId);if(!t||!Array.isArray(t.children))
560
- return null;const n=[],o=r=>{if(!(!r||typeof r!="object")&&(r.id!==e.requestedBlockId&&typeof r.id=="string"&&ir(r)&&n.push({blockId:r.id,text:Le(r),html:bn(e.anchorText)?kn(r):void 0}),Array.isArray(
558
+ "}"))return{text:t};try{const n=JSON.parse(t);return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}function Is(e){const t=Ve(e.doc,e.requestedBlockId);if(!t||!Array.isArray(t.children))
559
+ return null;const n=[],o=r=>{if(!(!r||typeof r!="object")&&(r.id!==e.requestedBlockId&&typeof r.id=="string"&&ir(r)&&n.push({blockId:r.id,text:Xe(r),html:bn(e.anchorText)?kn(r):void 0}),Array.isArray(
561
560
  r.children)))for(const i of r.children)o(i)};return o(t),wn(n,e.anchorText)}function xs(e){return!e.loadedBlockIds||e.loadedBlockIds.size===0?null:wn(nr(e.doc).filter(t=>t.blockId!==e.requestedBlockId&&
562
- or(t,e.loadedBlockIds)).map(t=>({...t,html:bn(e.anchorText)?kn(Xe(e.doc,t.blockId)):void 0})),e.anchorText)}function Ss(e,t,n,o,r,i,a){if(a.hasBlockId||a.hasAnchor)return v(e,"A reply inherits its thr\
561
+ or(t,e.loadedBlockIds)).map(t=>({...t,html:bn(e.anchorText)?kn(Ve(e.doc,t.blockId)):void 0})),e.anchorText)}function Ss(e,t,n,o,r,i,a){if(a.hasBlockId||a.hasAnchor)return v(e,"A reply inherits its thr\
563
562
  ead's anchor: pass reply_to_comment_id and comment alone, without id or anchor.");const l=er(o,r);if(!l)return v(e,`Comment '${r}' was not found. Reply only to a <comment-thread> id you can see in loa\
564
563
  ded document content.`,De);if(l.resolved===!0)return v(e,`Comment thread '${l.id}' is resolved. Leave a new anchored comment instead of replying to a settled thread.`);const c=n.getDocumentMutator(),d=tr(
565
- o,c,l.id,i,{author:Je(t),authorType:"ai",agentName:Je(t),...t.getAgentModel?{agentModel:t.getAgentModel()}:{}}).commentId;if(!d)return v(e,`Could not reply to comment thread '${l.id}'.`);const u=$s(o,
564
+ o,c,l.id,i,{author:ze(t),authorType:"ai",agentName:ze(t),...t.getAgentModel?{agentModel:t.getAgentModel()}:{}}).commentId;if(!d)return v(e,`Could not reply to comment thread '${l.id}'.`);const u=$s(o,
566
565
  l);return u&&t.toolState.editedBlockIds.add(u),t.turnState.hasMutatedSinceLastRead=!0,t.metrics?.count("agent.comment.reply",1),H(e,`Replied ${d} in comment thread ${l.id}.`,void 0,void 0,JSON.stringify(
567
566
  {commentId:d,threadId:l.id,mode:"reply",...u?{blockId:u}:{}}))}function $s(e,t){if(t.anchorBlockId){const n=Ae(e,t.anchorBlockId);return n>=0?e.children[n]?.id??t.anchorBlockId:t.anchorBlockId}for(const n of e.
568
567
  children)if(n.id&&rr(n).has(t.id))return n.id;return null}function Cs(e,t,n,o){const r=e.arguments??{};let i=typeof r.id=="string"?r.id.trim():"";const a=typeof r.comment=="string"?r.comment.trim():"";
569
568
  let l=vs(r.anchor);const c=typeof r.reply_to_comment_id=="string"?r.reply_to_comment_id.trim():"",d=new Set((Array.isArray(r.acknowledge_existing_thread_ids)?r.acknowledge_existing_thread_ids:[]).filter(
570
569
  q=>typeof q=="string").map(q=>q.trim()).filter(Boolean));if(!a)return v(e,"leave_comment requires a non-empty comment.");if(c)return Ss(e,t,n,o,c,a,{hasBlockId:!!i,hasAnchor:!!l});if(!i)return v(e,"le\
571
- ave_comment requires id.");if(!l)return v(e,"leave_comment requires an anchor.");let u=Xe(o,i),f=null;const b=Vt(t.turnState),y=typeof l.text=="string"&&l.text.length>0?l.text:null;if(y&&u){const q=Is(
572
- {doc:o,requestedBlockId:i,anchorText:y});q&&(i=q,u=Xe(o,i))}if(y&&(!u||qt(u,y).length===0)){const q=xs({doc:o,requestedBlockId:i,anchorText:y,loadedBlockIds:b});q&&q!==i&&(f=i,i=q,u=Xe(o,i))}if(!u)return v(
573
- e,`Block '${i}' was not found.`,De);const N=Ae(o,i),L=N>=0?o.children[N]?.id:void 0;if(!$t(o,i,b))return v(e,`leave_comment targets block '${i}', which is outside the loaded <document_content> context\
574
- . Read that block first, then retry.`,Be);let O=null;if(y){const q=[...t.getConversationHistory?.()??[]].reverse().find(z=>z.role==="user")?.content,J=typeof q=="string"?ei(u,y,q):null;J&&(O=y,l={...l,
575
- text:J})}const T=n.getDocumentMutator(),D={author:Je(t),authorType:"ai",agentName:Je(t),...t.getAgentModel?{agentModel:t.getAgentModel()}:{}},A=Yo(n.getWorkingDocument(),o,T,i,a,l,D,Array.from(d));if(!A.
570
+ ave_comment requires id.");if(!l)return v(e,"leave_comment requires an anchor.");let u=Ve(o,i),f=null;const b=Vt(t.turnState),y=typeof l.text=="string"&&l.text.length>0?l.text:null;if(y&&u){const q=Is(
571
+ {doc:o,requestedBlockId:i,anchorText:y});q&&(i=q,u=Ve(o,i))}if(y&&(!u||qt(u,y).length===0)){const q=xs({doc:o,requestedBlockId:i,anchorText:y,loadedBlockIds:b});q&&q!==i&&(f=i,i=q,u=Ve(o,i))}if(!u)return v(
572
+ e,`Block '${i}' was not found.`,De);const R=Ae(o,i),L=R>=0?o.children[R]?.id:void 0;if(!$t(o,i,b))return v(e,`leave_comment targets block '${i}', which is outside the loaded <document_content> context\
573
+ . Read that block first, then retry.`,Be);let O=null;if(y){const q=[...t.getConversationHistory?.()??[]].reverse().find(z=>z.role==="user")?.content,J=typeof q=="string"?ti(u,y,q):null;J&&(O=y,l={...l,
574
+ text:J})}const T=n.getDocumentMutator(),D={author:ze(t),authorType:"ai",agentName:ze(t),...t.getAgentModel?{agentModel:t.getAgentModel()}:{}},A=Yo(n.getWorkingDocument(),o,T,i,a,l,D,Array.from(d));if(!A.
576
575
  success)return A.overlappingThreadIds?.length&&t.metrics?.count("agent.comment.overlap_blocked",1),v(e,A.error??"Could not attach comment.",A.overlappingThreadIds?.length?gs:A.errorCode);const M=A.commentId,
577
576
  I=l.whole_block===!0,C=A.range;return d.size&&t.metrics?.count("agent.comment.overlap_acknowledged",1),t.toolState.editedBlockIds.add(L??i),t.turnState.hasMutatedSinceLastRead=!0,H(e,(f?`Left comment ${M}\
578
577
  on block ${i}: the anchor text was not in block ${f}, and ${i} is the only loaded block that contains it.`:`Left comment ${M} on block ${i}.`)+(O?` The anchor ${JSON.stringify(O)} covered only part o\
@@ -585,20 +584,20 @@ ument_state"?De:void 0}function H(e,t,n,o,r){return{toolCall:e,success:!0,agentF
585
584
  name}function Ds(e){if(!e||typeof e!="object")return null;const t=typeof e.status=="string"?e.status:typeof e.message=="string"?e.message:null;if(!t)return null;const n=t.replace(/[\s\n]+/g," ").trim();
586
585
  return n.length>0?n:null}function Ps(e){if(!e||typeof e!="object")return null;const t=typeof e.context_notes=="string"?e.context_notes:null;if(!t)return null;const n=t.trim();return n.length>0?n:null}
587
586
  function Ao(e,t){for(const n of e){if(n.type==="image"&&n.id===t)return{src:n.src,sourceUrl:n.sourceUrl,alt:n.alt,width:n.width,height:n.height};if(Array.isArray(n.children)&&n.children.length>0){const o=Ao(
588
- n.children,t);if(o)return o}}return null}function He(e){if(!e||typeof e!="object")return[];const t=e,n=[],o=new Set,r=a=>{if(typeof a!="string")return;const l=a.trim();!l||o.has(l)||(o.add(l),n.push(l))};
587
+ n.children,t);if(o)return o}}return null}function We(e){if(!e||typeof e!="object")return[];const t=e,n=[],o=new Set,r=a=>{if(typeof a!="string")return;const l=a.trim();!l||o.has(l)||(o.add(l),n.push(l))};
589
588
  if(r(t.id),r(t.referenceId),r(t.reference_id),r(t.firstId),r(t.secondId),r(t.from_id),r(t.block_id),r(t.tableId),r(t.referenceRowId),r(t.after_block_id),Array.isArray(t.id))for(const a of t.id)r(a);if(Array.
590
589
  isArray(t.block_ids))for(const a of t.block_ids)r(a);Array.isArray(t.ids)&&t.ids.forEach(r);const i=Array.isArray(t.selectors)?t.selectors:[t.selectors];for(const a of i)if(typeof a=="string")for(const l of a.
591
- split(",")){const c=l.trim().match(/^#([A-Za-z0-9_-]+)(?=$|[\s:>~+])/);c&&r(c[1])}if(t.selector&&typeof t.selector=="object"&&He(t.selector).forEach(r),Array.isArray(t.replacements))for(const a of t.replacements)
592
- He(a).forEach(r);return n}function To(e){const t=He(e.arguments),n=t.length===0?"the target block":t.length===1?`block ${t[0]}`:`${t.length} blocks`;if(e.name==="set_block_attribute"||e.name==="style_\
590
+ split(",")){const c=l.trim().match(/^#([A-Za-z0-9_-]+)(?=$|[\s:>~+])/);c&&r(c[1])}if(t.selector&&typeof t.selector=="object"&&We(t.selector).forEach(r),Array.isArray(t.replacements))for(const a of t.replacements)
591
+ We(a).forEach(r);return n}function To(e){const t=We(e.arguments),n=t.length===0?"the target block":t.length===1?`block ${t[0]}`:`${t.length} blocks`;if(e.name==="set_block_attribute"||e.name==="style_\
593
592
  blocks"){const o=e.arguments&&typeof e.arguments=="object"?e.arguments:{},r=typeof o.attribute=="string"&&o.attribute.trim().length>0?o.attribute.trim():"attribute";return(typeof o.operation=="string"&&
594
593
  o.operation.trim().length>0?o.operation.trim():"set")==="remove"?`No document mutation occurred; ${r} was already removed on ${n}.`:`No document mutation occurred; ${r} was already set on ${n}.`}return e.
595
594
  name==="clear_formatting"?`No document mutation occurred; formatting was already clear on ${n}.`:e.name==="replace_block"?`No document mutation occurred; replacing ${n} produced no document change. Th\
596
595
  is result does not prove that the requested content is present; verify the current block before deciding no change is needed.`:e.name==="replace"||e.name==="replace_all"||e.name==="replace_many"?`No d\
597
596
  ocument mutation occurred; the replacement on ${n} produced no document change. This result does not prove that the requested content is present; verify the current block before deciding no change is \
598
- needed.`:"No document mutation occurred; the document already matched the requested update."}function Rs(e){const t=qs(e);return{id:e.id,name:t,arguments:is(t,e.arguments)}}function Ns(e){return e.replace(
597
+ needed.`:"No document mutation occurred; the document already matched the requested update."}function Ns(e){const t=qs(e);return{id:e.id,name:t,arguments:is(t,e.arguments)}}function Rs(e){return e.replace(
599
598
  /<[^>]*>/g," ").replace(/&nbsp;/gi," ").replace(/&amp;/gi,"&").replace(/&lt;/gi,"<").replace(/&gt;/gi,">").replace(/&quot;/gi,'"').replace(/&#39;|&apos;/gi,"'").replace(/\s+/g," ").trim()}function qo(e){
600
599
  return e.replace(/\s+/g," ").trim()}function Vt(e){const t=new Set;for(const n of[e.lastReadBlockIds,e.requestedBlockIds])if(n)for(const o of n)t.add(o);for(const n of e.docContextLedger?.delivered.keys()??
601
- [])t.add(n);return t.size>0?t:null}function Ms(e){const t=[],n=new Set;for(const o of e)for(const r of He(o.arguments))n.has(r)||(n.add(r),t.push(r));return t}function Do(e,t){const n=new Set(t),o=new Set(
600
+ [])t.add(n);return t.size>0?t:null}function Ms(e){const t=[],n=new Set;for(const o of e)for(const r of We(o.arguments))n.has(r)||(n.add(r),t.push(r));return t}function Do(e,t){const n=new Set(t),o=new Set(
602
601
  t),r=i=>{const a="id"in i?i.id:void 0;let l=!!(a&&n.has(a));if("children"in i)for(const c of i.children)r(c)&&(l=!0);return l&&a&&o.add(a),l};for(const i of[...e.children,...e.chrome??[],...e.notes??[]])
603
602
  r(i);return o}function Bs(e,t){if(e.length===1)return`block ${e[0]}`;if(e.length>1){const n=e.slice(0,4).join(", "),o=e.length>4?` (+${e.length-4} more)`:"";return`blocks ${n}${o}`}return t?`block ${t}`:
604
603
  "the target block"}function Os(e){if(e.length===0)return"";const t=Array.from(new Set(e.map(r=>`${r.fromBlockId}->${r.toBlockId}`))).map(r=>{const[i,a]=r.split("->");return`${i} -> ${a}`}),n=t.slice(0,
@@ -612,40 +611,40 @@ test(e.name)){if(e.name.endsWith("_row")){const j=typeof q.referenceRowId=="stri
612
611
  renderTableRow(C,j,t)}]:[]}const J=Ce(C),z=Number(q.columnIndex??q.referenceIndex);return J.cells.filter(j=>j.col<=z&&j.col+j.colSpan>z).map(({cell:j})=>({id:j.id,html:ae.renderSubtree(j,t)}))}if(C.type===
613
612
  "table"&&C.id!==I){const J=C.children.find(z=>z.id===I);if(J)return[{id:I,html:ae.renderTableRow(C,J,t)}]}return[{id:I,html:ae.renderSubtree(C,t)}]}):[],u=[],f=[];let b=0;for(const I of d)b+I.html.length+
614
613
  1>8e3?f.push(I.id):(u.push(I.html),b+=I.html.length+1);const y=u.join(`
615
- `),N=a.filter(I=>re(t,I)&&!re(n,I)),L=i?.changedBlockIds??a.filter(I=>{const C=re(t,I),q=re(n,I);return JSON.stringify(C??null)!==JSON.stringify(q??null)}),O=new Set,T=I=>{for(const C of I)"id"in C&&C.
614
+ `),R=a.filter(I=>re(t,I)&&!re(n,I)),L=i?.changedBlockIds??a.filter(I=>{const C=re(t,I),q=re(n,I);return JSON.stringify(C??null)!==JSON.stringify(q??null)}),O=new Set,T=I=>{for(const C of I)"id"in C&&C.
616
615
  id&&O.add(C.id),"children"in C&&T(C.children)};T(_e(t));const D=[],A=I=>{for(const C of I)"id"in C&&C.id&&!O.has(C.id)?D.push(C.id):"children"in C&&A(C.children)};A(_e(n));const M=(I,C,q=!1)=>c||q&&C.
617
616
  length>Me?{[`${I}_sample`]:C.slice(0,Me),[`${I}_omitted_count`]:Math.max(0,C.length-Me)}:{[I]:C};return JSON.stringify({tool:e.name,...l?{target_reference:l}:{},...r?{summary:r}:{},...i?{style_outcome:i.
618
617
  outcome,attribute_effects:i.attributes.map(I=>({name:I.name,applied_target_count:I.appliedBlockIds.length,skipped_target_count:new Set(I.skipped.map(C=>C.blockId)).size,...M("applied_block_ids",I.appliedBlockIds,
619
618
  !0),skipped:I.skipped.slice(0,Me),skipped_omitted_count:Math.max(0,I.skipped.length-Me)}))}:{},effect:{...i?M("affected_block_ids",i.affectedBlockIds,!0):{},requested_target_count:a.length,changed_target_count:L.
620
- length,removed_target_count:N.length,inserted_block_count:D.length,...M("target_block_ids",a),...M("changed_block_ids",L),...M("removed_block_ids",N),...M("inserted_block_ids",D),top_level_blocks_before:_e(
619
+ length,removed_target_count:R.length,inserted_block_count:D.length,...M("target_block_ids",a),...M("changed_block_ids",L),...M("removed_block_ids",R),...M("inserted_block_ids",D),top_level_blocks_before:_e(
621
620
  t).length,top_level_blocks_after:_e(n).length},...!c&&(y.trim()||f.length)?{before_block:y,...f.length?{before_block_truncated:!0,before_block_omitted_ids:f.slice(0,20),before_block_omitted_count:f.length,
622
621
  before_block_recovery:"This is a partial lookback, not a complete replacement source. For pending edits use rollback_agent_suggestions with the appropriate request/turn, then reread. Accepted content \
623
622
  requires historical edit evidence; never reconstruct it from this partial snapshot."}:{}}:{}})}function _e(e){return[...e.children,...e.notes??[]]}function Xt(e,t){return ae.extractSpecificBlocks(e,[t],
624
- void 0,ze).foundBlocks[0]?.blockIndex??-1}function Es(e){return`(${e} ${e===1?"block":"blocks"} omitted...)`}function Qt(e,t){const n=_e(e)[t];return n?.id?ae.extractSpecificBlocks(e,[n.id],void 0,ze).
623
+ void 0,Fe).foundBlocks[0]?.blockIndex??-1}function Es(e){return`(${e} ${e===1?"block":"blocks"} omitted...)`}function Qt(e,t){const n=_e(e)[t];return n?.id?ae.extractSpecificBlocks(e,[n.id],void 0,Fe).
625
624
  foundBlocks[0]??null:null}function xt(e){if(e.length===0)return 0;let t=`Showing ${e.length} block(s):
626
625
 
627
- `.length+e[0].html.length;for(let n=1;n<e.length;n+=1){const o=e[n-1],r=e[n],i=r.blockIndex-o.blockIndex-1;i>0&&(t+=1+Es(i).length),t+=1+r.html.length}return t}function Ro(e){const{doc:t,startIndex:n,
626
+ `.length+e[0].html.length;for(let n=1;n<e.length;n+=1){const o=e[n-1],r=e[n],i=r.blockIndex-o.blockIndex-1;i>0&&(t+=1+Es(i).length),t+=1+r.html.length}return t}function No(e){const{doc:t,startIndex:n,
628
627
  maxTokens:o}=e,r=[];let i=0,a=n-1,l=!1;for(let c=n;c<_e(t).length;c+=1){const d=Qt(t,c);if(!d)continue;const u=xt([...r,d]),f=u>o;if(f&&r.length>0){l=!0;break}if(r.push(d),i=u,a=d.blockIndex,f){l=!0;break}}
629
628
  return{blockIds:r.map(c=>c.id),endIndex:a,estimatedTokens:i,reachedTokenBudget:l}}function Ls(e){const{doc:t,requestedBlockIds:n,maxTokens:o}=e,r=[],i=new Set,a=new Map,l=(b,y)=>(a.has(b)||a.set(b,Qt(
630
- t,y)),a.get(b)??null),c=[];let d=0,u=!1,f=0;for(const b of n){const y=Xs(t,b);if(!y){f+=1;continue}if(i.has(y.topLevelBlockId))continue;const N=l(y.topLevelBlockId,y.topLevelIndex);if(!N){f+=1;continue}
631
- const L=xt([...c,N]),O=L>o;if(O&&r.length>0){u=!0;break}if(r.push(y.topLevelBlockId),i.add(y.topLevelBlockId),c.push(N),d=L,O){u=!0;break}}return{blockIds:r,estimatedTokens:d,reachedTokenBudget:u,missingRequestedBlocks:f}}
632
- function No(e){const{doc:t,results:n,pageSize:o,maxTokens:r}=e;if(n.length===0)return[];const i=new Map,a=b=>(i.has(b.blockId)||i.set(b.blockId,Qt(t,b.blockIndex)),i.get(b.blockId)??null),l=[];let c=[],
633
- d=[],u=0;const f=b=>{c.length!==0&&(l.push({results:c,startResultIndex:u,endResultIndexExclusive:b,estimatedTokens:xt(d)}),c=[],d=[])};for(let b=0;b<n.length;b+=1){const y=n[b],N=a(y);if(!N)continue;c.
634
- length===0&&(u=b);const L=xt([...d,N]),O=c.length>=o,T=L>r;c.length>0&&(O||T)&&(f(b),u=b),c=[...c,y],d=[...d,N]}return f(n.length),l}function Mo(e){if(e.length===0)return[];const t=[...e].sort((i,a)=>i-
629
+ t,y)),a.get(b)??null),c=[];let d=0,u=!1,f=0;for(const b of n){const y=Xs(t,b);if(!y){f+=1;continue}if(i.has(y.topLevelBlockId))continue;const R=l(y.topLevelBlockId,y.topLevelIndex);if(!R){f+=1;continue}
630
+ const L=xt([...c,R]),O=L>o;if(O&&r.length>0){u=!0;break}if(r.push(y.topLevelBlockId),i.add(y.topLevelBlockId),c.push(R),d=L,O){u=!0;break}}return{blockIds:r,estimatedTokens:d,reachedTokenBudget:u,missingRequestedBlocks:f}}
631
+ function Ro(e){const{doc:t,results:n,pageSize:o,maxTokens:r}=e;if(n.length===0)return[];const i=new Map,a=b=>(i.has(b.blockId)||i.set(b.blockId,Qt(t,b.blockIndex)),i.get(b.blockId)??null),l=[];let c=[],
632
+ d=[],u=0;const f=b=>{c.length!==0&&(l.push({results:c,startResultIndex:u,endResultIndexExclusive:b,estimatedTokens:xt(d)}),c=[],d=[])};for(let b=0;b<n.length;b+=1){const y=n[b],R=a(y);if(!R)continue;c.
633
+ length===0&&(u=b);const L=xt([...d,R]),O=c.length>=o,T=L>r;c.length>0&&(O||T)&&(f(b),u=b),c=[...c,y],d=[...d,R]}return f(n.length),l}function Mo(e){if(e.length===0)return[];const t=[...e].sort((i,a)=>i-
635
634
  a),n=[];let o=t[0],r=t[0];for(let i=1;i<t.length;i+=1){const a=t[i];if(a<=r+1){r=a;continue}n.push({start:o,end:r}),o=a,r=a}return n.push({start:o,end:r}),n}function Zt(e,t){const n=new Set;for(const o of t){
636
635
  const r=Xt(e,o);r!==-1&&n.add(r)}return Array.from(n).sort((o,r)=>o-r)}function st(e,t){const n=Ye(t,e.toolState.tableContext,e.turnState.requestedBlockIds??new Set),o=Zt(t,n),r=Mo(o),i=o.length,a=!e.
637
636
  toolState.tableContext?.scopedTableIds?.some(l=>!n.has(l))&&(e.toolState.everReadFullDocument||_e(t).length>0&&i>=_e(t).length);return{requestedBlockCount:i,readBlocksThisTurn:e.turnState.readBudgetBlockIds?.
638
- size??0,readTokenBudgetMax:We,requestedRanges:r,fullDocumentLoaded:a}}function at(e){return JSON.stringify({kind:"read_context",tool:e.tool,loaded:e.loaded,next:e.next??null,endOfDocument:e.endOfDocument,
637
+ size??0,readTokenBudgetMax:Je,requestedRanges:r,fullDocumentLoaded:a}}function at(e){return JSON.stringify({kind:"read_context",tool:e.tool,loaded:e.loaded,next:e.next??null,endOfDocument:e.endOfDocument,
639
638
  coverage:e.coverage})}function Bo(e){return JSON.stringify({kind:"search_context",tool:e.tool,...e.queries?{queries:e.queries}:{},...e.color?{color:e.color}:{},totalMatches:e.totalMatches,...e.searchResultId?
640
639
  {search_result_id:e.searchResultId}:{},page:{current:e.currentPage,total:e.totalPages,startResult:e.pageStart+1,endResult:e.pageEnd},nextPage:e.nextPage,matches:e.pageResults.map(t=>({blockId:t.blockId,
641
640
  blockIndex:t.blockIndex,...t.matchedQueries?{matchedQueries:t.matchedQueries}:{},...t.matchedColors?{matchedColors:t.matchedColors}:{}})),coverage:e.coverage})}function Us(e){return e==="account"||e===
642
- "folder"?e:"current_folder"}function Ge(e){return e.getAuthToken?.().trim()??""}function Oo(e){return typeof e.document_id=="string"?e.document_id.trim():""}function jo(e){return e.replaceAll("-","").
641
+ "folder"?e:"current_folder"}function He(e){return e.getAuthToken?.().trim()??""}function Oo(e){return typeof e.document_id=="string"?e.document_id.trim():""}function jo(e){return e.replaceAll("-","").
643
642
  toLowerCase()}function Ie(e,t){const n=Oo(e);if(!n)return"";const o=t.getCurrentDocumentId?.().trim()??"";return o&&jo(n)===jo(o)?"":n}async function Fs(e){const t=e.scope==="folder"?e.folderId:e.currentFolderId,
644
643
  n=no({query:e.query,page:e.page+1,limit:10,currentFolderId:e.scope==="account"?void 0:t}),o=await fetch(`${Kt}/documents/search?${n.toString()}`,{headers:{Authorization:`Bearer ${e.token}`}});if(!o.ok)
645
644
  throw new Error(`Document search failed with ${o.status}`);return oo(await o.json(),10)}async function zs(e){const t=no({includeFolders:!0,page:e.page+1,limit:e.limit,parentFolderId:e.parentFolderId}),
646
645
  n=await fetch(`${Kt}/documents?${t.toString()}`,{headers:{Authorization:`Bearer ${e.token}`}});if(!n.ok)throw new Error(`Document listing failed with ${n.status}`);return oo(await n.json(),e.limit)}async function St(e){
647
646
  const t=await fetch(`${Kt}/documents/${encodeURIComponent(e.documentId)}?includeTailUpdates=1&trackAccess=0`,{headers:{Authorization:`Bearer ${e.token}`}});if(!t.ok)throw new Error(`Document open fail\
648
- ed with ${t.status}`);const n=await t.json(),o=Pi({content:n.content,yjsState:n.yjsState,yjsUpdates:n.yjsUpdates,source:`agent read document ${e.documentId}`})??{type:"doc",children:[]};return o.title=
647
+ ed with ${t.status}`);const n=await t.json(),o=Ni({content:n.content,yjsState:n.yjsState,yjsUpdates:n.yjsUpdates,source:`agent read document ${e.documentId}`})??{type:"doc",children:[]};return o.title=
649
648
  n.title||o.title||"Untitled",{id:n.id||e.documentId,title:n.title||"Untitled",canonicalPath:n.canonicalPath,parentFolderId:n.parentFolderId??null,content:o}}function Js(e){return JSON.stringify({kind:"\
650
649
  account_document_search",query:e.query,scope:e.scope,searchedCurrentFolder:e.searchedCurrentFolder,folderId:e.folderId??null,page:{current:e.page,total:e.totalPages},totalMatches:e.totalCount,results:e.
651
650
  results.map(t=>({itemType:t.itemType==="folder"?"folder":"document",...t.itemType==="folder"?{folderId:t.id}:{documentId:t.id},title:t.title,canonicalPath:t.canonicalPath||`/${t.title||t.id}`,snippet:t.
@@ -661,32 +660,32 @@ queries:o})}const n=typeof t.color=="string"&&t.color.trim().length>0?t.color.tr
661
660
  matchedColors??[])t.set(o,(t.get(o)??0)+1);return t.size===0?"":Array.from(t.entries()).sort((n,o)=>o[1]-n[1]||n[0].localeCompare(o[0])).map(([n,o])=>`${o} ${n}`).join(", ")}function Gs(e,t){let n=0;for(;n<
662
661
  e.length&&n<t.length&&e[n]===t[n];)n+=1;let o=e.length-1,r=t.length-1;for(;o>=n&&r>=n&&e[o]===t[r];)o-=1,r-=1;const i=Math.max(0,o-n+1),a=Math.max(0,r-n+1);return Math.max(i,a)}function Ks(e,t){if(e.name!==
663
662
  "replace_block"||!e.arguments||typeof e.arguments!="object")return null;const n=e.arguments.id,o=e.arguments.content,r=e.arguments.count;if(typeof n!="string"||typeof r=="number"&&Number.isFinite(r)&&
664
- Math.floor(r)>1||!Array.isArray(o)||o.length!==1||typeof o[0]!="string")return null;const i=t.children.find(f=>f.id===n);if(!i)return null;const a=qo(Le(i)),l=qo(Ns(o[0]));if(!a||!l||a===l)return null;
663
+ Math.floor(r)>1||!Array.isArray(o)||o.length!==1||typeof o[0]!="string")return null;const i=t.children.find(f=>f.id===n);if(!i)return null;const a=qo(Xe(i)),l=qo(Rs(o[0]));if(!a||!l||a===l)return null;
665
664
  const c=Gs(a,l),d=Math.max(a.length,l.length);if(d<=0)return null;const u=c/d;return c>us||u>ms?null:`WARNING: replace_block only changed a small span (~${c} chars, ${(u*100).toFixed(0)}% of block). P\
666
665
  refer replace for typo, punctuation, and wording edits; reserve replace_block for full rewrites.`}function $t(e,t,n){if(!n||n.size===0)return!1;if(n.has(t))return!0;const o=ht(e,t);if(o&&n.has(o))return!0;
667
666
  const r=Ae(e,t),i=r>=0?e.children[r]?.id:void 0;return typeof i=="string"&&n.has(i)}function Vs(e,t,n){if(e.name!=="replace_block"&&e.name!=="remove_block")return{toolCall:e};if(!e.arguments||typeof e.
668
667
  arguments!="object")return{toolCall:e};const o=e.arguments.id;if(typeof o!="string"||o.trim().length===0)return{toolCall:e};const r=e.arguments.count;if(r!==void 0&&(typeof r!="number"||!Number.isFinite(
669
668
  r)||Math.floor(r)<1))return{toolCall:e};const i=r===void 0?1:Math.floor(r);if(i<=1)return{toolCall:e};const a=vn(t,o),l=a&&"children"in a?lr(a,o):-1;if(!a||l===-1)return{toolCall:e};const c=e.name==="\
670
669
  remove_block"?"remove_blocks":e.name,d=a.children[Math.min(l+i,a.children.length)-1]?.id??o;if(!n||n.size===0)return{toolCall:e,error:`${c} range '${o}' through '${d}' needs those blocks in request-le\
671
- vel document context. Read the complete range first, then retry with the same range.`};const u=new Set(Array.from(n).map(y=>Ae(t,y)).filter(y=>y!==-1));let f=0;for(let y=l;y<a.children.length;y++){const N=a.
672
- children[y]?.id;if(typeof N!="string"||N.length===0)break;const L=Ae(t,N);if(L===-1||!u.has(L))break;f+=1}if(f<=0)return{toolCall:e,error:`${e.name} targets block '${o}', which is outside the loaded <\
670
+ vel document context. Read the complete range first, then retry with the same range.`};const u=new Set(Array.from(n).map(y=>Ae(t,y)).filter(y=>y!==-1));let f=0;for(let y=l;y<a.children.length;y++){const R=a.
671
+ children[y]?.id;if(typeof R!="string"||R.length===0)break;const L=Ae(t,R);if(L===-1||!u.has(L))break;f+=1}if(f<=0)return{toolCall:e,error:`${e.name} targets block '${o}', which is outside the loaded <\
673
672
  document_content> context. Read that block first, then retry.`};if(f>=i)return{toolCall:e};const b=a.children[l+f]?.id??d;return{toolCall:e,error:`${c} range '${o}' through '${d}' includes block '${b}\
674
673
  ', which was not read in this request. Read ${b===d?`'${d}'`:`'${b}' through '${d}'`}, then retry with the same range; no partial mutation was applied.`}}function Xs(e,t){const n=Xt(e,t);if(n===-1)return null;
675
674
  const o=_e(e)[n];return o?.id?{block:o,topLevelBlockId:o.id,topLevelIndex:n}:null}function Qs(e){const t=e.toolState.editedBlockIds.size;if(t===0)return{loadedBlockCount:0,editedBlockCount:0};const n=e.
676
675
  getLatestDocument(),o=n.children.length,r=new Set;for(const c of e.toolState.editedBlockIds){const d=Ae(n,c);d!==-1&&r.add(d)}const i=new Set;for(const c of r)for(let d=Math.max(0,c-xo);d<=Math.min(o-
677
676
  1,c+xo);d++)i.add(d);const a=[],l=Array.from(i).sort((c,d)=>c-d);for(const c of l){const d=n.children[c];d?.id&&a.push(d.id)}e.turnState.requestedBlockIds||(e.turnState.requestedBlockIds=new Set);for(const c of a)
678
- e.turnState.requestedBlockIds.add(c);return e.turnState.documentRequested=!0,{loadedBlockCount:a.length,editedBlockCount:t}}async function Zs(e){const t=await Mi(e);if(t)return{id:t.id,type:t.type,content:t.
677
+ e.turnState.requestedBlockIds.add(c);return e.turnState.documentRequested=!0,{loadedBlockCount:a.length,editedBlockCount:t}}async function Zs(e){const t=await Bi(e);if(t)return{id:t.id,type:t.type,content:t.
679
678
  content,preview:t.preview,charCount:t.charCount,...t.fileName?{fileName:t.fileName}:{},...t.mimeType?{mimeType:t.mimeType}:{},...t.fileSize?{fileSize:t.fileSize}:{},...t.urls?{urls:t.urls}:{},...t.dimensions?
680
- {dimensions:t.dimensions}:{}}}function Ys(e){const t=e.loadAttachment??Zs,n=e.metrics??kr;if(!e.toolState.foreignBlockSources){e.toolState.foreignBlockSources=new Map;for(const I of e.getConversationHistory?.()??
679
+ {dimensions:t.dimensions}:{}}}function Ys(e){const t=e.loadAttachment??Zs,n=e.metrics??vr;if(!e.toolState.foreignBlockSources){e.toolState.foreignBlockSources=new Map;for(const I of e.getConversationHistory?.()??
681
680
  [])if(!(!I.toolResult?.success||!I.toolResult.output))try{const C=JSON.parse(I.toolResult.output),q=C.document?.documentId;if(typeof q!="string"||!["document_read","document_search_context"].includes(
682
681
  C.kind)||typeof C.documentContent!="string"||!Ie({document_id:q},e))continue;const J=new DOMParser().parseFromString(C.documentContent,"text/html");for(const z of J.querySelectorAll("[id]"))e.toolState.
683
682
  foreignBlockSources.set(z.id,q)}catch{}}const o=e.toolState.foreignBlockSources,r=(I,C,q)=>{const J=z=>{if(z.id&&q(z.id),"children"in z&&Array.isArray(z.children))for(const j of z.children)"id"in j&&J(
684
683
  j)};for(const z of C){const j=re(I,z);j&&J(j)}},i=(I,C,q)=>r(I,C,J=>o.set(J,q)),a=I=>{const C=e.tryAddRequestedBlocks(I);return(!C||C.code===Io)&&r(e.getLatestDocument(),I,q=>o.delete(q)),C},l=I=>{const C=a(
685
684
  I);return C&&C.code!==Io?{error:C,reread:!1}:(e.redeliverReadBlocks?.(I),{error:null,reread:!!C})},c=" These blocks were already in context; their latest content is re-sent in the next document snapsh\
686
- ot.";let d=e.turnState.currentTurn??0,u=0,f=0,b=0;const y=new Map;let N=1;const L=async()=>{e.getDocumentSession()||await e.waitForDocumentSession?.();const I=e.getDocumentSession(),C=I?.getDocumentId?.(),
685
+ ot.";let d=e.turnState.currentTurn??0,u=0,f=0,b=0;const y=new Map;let R=1;const L=async()=>{e.getDocumentSession()||await e.waitForDocumentSession?.();const I=e.getDocumentSession(),C=I?.getDocumentId?.(),
687
686
  q=e.getCurrentDocumentId?.();return I&&(!C||!q||Ie({document_id:C},e)==="")?I:null},O=I=>v(I,yo,Wi),T=new Set(["read_table","read_blocks","read_blocks_from_index","read_specific_blocks","search_docume\
688
687
  nt","find_highlights","measure_document","measure_blocks","view_image","render_document_pages"]),D=new Set(["read_blocks","read_blocks_from_index","read_specific_blocks","search_document"]),A=()=>{const I=e.
689
- turnState.currentTurn??0;I!==d&&(d=I,u=0,f=0,b=0)},M={requestId:-1,ids:new Set};return async I=>{var C,q,J,z,j;const oe=Rs(I);let h=oe.name==="remove_blocks"?{...oe,name:"remove_block"}:oe.name==="rem\
688
+ turnState.currentTurn??0;I!==d&&(d=I,u=0,f=0,b=0)},M={requestId:-1,ids:new Set};return async I=>{var C,q,J,z,j;const oe=Ns(I);let h=oe.name==="remove_blocks"?{...oe,name:"remove_block"}:oe.name==="rem\
690
689
  ove_table_rows"?{...oe,name:"remove_table_row"}:oe;const $=h.name,we=e.getExecutionPolicy?.(),pe=we?ds(we,$):null;if(pe)return v(h,pe.message,pe.code);if(e.allowCrossDocumentReads===!1&&(Oo(h.arguments??
691
690
  {}).length>0||$==="list_documents"||$==="search_documents"))return v(h,"This host only permits the supplied document. document_id routing is unavailable.","agent_tool_not_allowed");if(A(),(T.has($)||D.
692
691
  has($))&&(b+=1),$==="move_blocks"){const s=h.arguments??{};let m=s.reference_id;if(typeof m=="string"){const p=m.trim();if(m=p,p.startsWith("[")||p.startsWith('"'))try{m=JSON.parse(p)}catch{m=null}}if(Array.
@@ -696,16 +695,16 @@ tring (for example "d5BLVe", not a stringified array), and position "before" or
696
695
  block_ids.map(p=>p.trim()),reference_id:m.trim()}}}if($==="create_plan"||$==="update_plan"){if(!e.getPlanState||!e.setPlanState)return v(h,"This host does not support task plans.","plan_unavailable");
697
696
  try{const s=jn(e.getPlanState(),$,h.arguments??{});return e.setPlanState(s),e.markConversationDirty(),H(h,Mn(h.arguments??{})?`${JSON.stringify(s.plan)}
698
697
  ${Bn}`:JSON.stringify(s.plan),void 0,!0,JSON.stringify({kind:"task_plan",plan:s.plan}))}catch(s){return v(h,s instanceof Error?s.message:String(s),"invalid_plan_update")}}if(e.mutationTools.includes($)||
699
- $==="remove_block"){const s=Ie(h.arguments??{},e),m=He(h.arguments).filter(w=>o.has(w)&&Ie({document_id:o.get(w)},e)!==""),p=s||(m.length?o.get(m[0]):void 0);if(p){if(!s&&m.every(k=>re(e.getLatestDocument(),
698
+ $==="remove_block"){const s=Ie(h.arguments??{},e),m=We(h.arguments).filter(w=>o.has(w)&&Ie({document_id:o.get(w)},e)!==""),p=s||(m.length?o.get(m[0]):void 0);if(p){if(!s&&m.every(k=>re(e.getLatestDocument(),
700
699
  k)))return{...v(h,`These IDs occur in both the source and active documents. If this edit is intended for the source, do not edit here: give the user a clickable link to /docs/${p} and ask them to open\
701
700
  it. Only if the edit belongs in the active document, re-read the target IDs without document_id before editing.`,"foreign_document_id_collision"),sourceDocumentId:p};const w=e.turnState.currentRequestId??
702
701
  0;e.toolState.foreignTargetFailureState?.requestId!==w&&(e.toolState.foreignTargetFailureState={requestId:w,count:0});const g=++e.toolState.foreignTargetFailureState.count;return{...v(h,`These edits t\
703
702
  arget a read-only source document. Open /docs/${p} and continue there to edit it. The active document has not been changed by this call. Do not retry these IDs with another mutation tool. To edit the \
704
- active document instead, read its target blocks without document_id first.`,g>=2?"foreign_document_target_repeated":"foreign_document_target"),sourceDocumentId:p}}}const lt=di($,h.arguments);if(lt)return v(
705
- h,lt,li);const At=e.getLockedSelection?.()??null;if(At?.length){const s=e.getLatestDocument(),m=si(s,At,ii(s,$,h.arguments)),p=e.turnState.currentRequestId??0;M.requestId!==p&&(M.requestId=p,M.ids.clear());
706
- const w=m.filter(g=>!M.ids.has(g));if(w.length)return w.forEach(g=>M.ids.add(g)),v(h,`${w.map(g=>`'${g}'`).join(", ")} ${w.length===1?"is":"are"} outside the user's selection (${JSON.stringify(ai(At))}\
703
+ active document instead, read its target blocks without document_id first.`,g>=2?"foreign_document_target_repeated":"foreign_document_target"),sourceDocumentId:p}}}const lt=ui($,h.arguments);if(lt)return v(
704
+ h,lt,ci);const At=e.getLockedSelection?.()??null;if(At?.length){const s=e.getLatestDocument(),m=ai(s,At,si(s,$,h.arguments)),p=e.turnState.currentRequestId??0;M.requestId!==p&&(M.requestId=p,M.ids.clear());
705
+ const w=m.filter(g=>!M.ids.has(g));if(w.length)return w.forEach(g=>M.ids.add(g)),v(h,`${w.map(g=>`'${g}'`).join(", ")} ${w.length===1?"is":"are"} outside the user's selection (${JSON.stringify(li(At))}\
707
706
  ). This request refers to the selected content, so leave other content unchanged and mention it in chat instead; nothing was changed by this call. Only if the user explicitly asked to change content b\
708
- eyond the selection, send the same call again.`,ti)}const Wo=D.has($)&&Ie(h.arguments??{},e)!=="";if(e.requireDocumentSessionForReads&&T.has($)&&!Wo&&!await L())return O(h);if($==="import_attachment_i\
707
+ eyond the selection, send the same call again.`,ni)}const Wo=D.has($)&&Ie(h.arguments??{},e)!=="";if(e.requireDocumentSessionForReads&&T.has($)&&!Wo&&!await L())return O(h);if($==="import_attachment_i\
709
708
  nto_document"){const s=typeof h.arguments?.attachment_id=="string"?h.arguments.attachment_id.trim():"";if(!s)return v(h,"attachment_id is required.");const m=h.arguments?.after_block_id;if(m!=null&&typeof m!=
710
709
  "string")return v(h,"after_block_id must be a block ID string.");const p=typeof m=="string"&&m.trim()||void 0,w=e.getAllAttachments().get(s)??await t(s);if(!w)return v(h,`Attachment "${s}" was not fou\
711
710
  nd.`);if(w.type!=="docx"&&w.type!=="pdf")return v(h,"Only DOCX and PDF attachments can be imported into the document.");if(!e.importAttachmentIntoDocument)return v(h,"Attachment import is unavailable \
@@ -716,8 +715,8 @@ user's request by reading the imported content, then edit it.`)}catch(g){return
716
715
  has($)){if(!Ps(h.arguments))return v(h,'context_notes is required on every read/search call. Use "N/A" if nothing from the previous context needs to carry forward.');if(u>=1)return v(h,'Use at most on\
717
716
  e read/search tool call per turn. Continue with edits in this turn, then read/search again in the next turn with context_notes or "N/A".',fs);u+=1}if($==="measure_document"){const s=h.arguments||{},m=s.
718
717
  include_sections===!0,p=Number(s.section_offset),w=Number.isFinite(p)&&p>0?Math.floor(p):0,g=Number(s.section_limit),k=Number.isFinite(g)&&g>0?Math.min(Math.floor(g),ps):hs,S=(Array.isArray(s.heading_levels)?
719
- s.heading_levels:[]).map(se=>typeof se=="number"?se:typeof se=="string"?Number.parseInt(se,10):Number.NaN).filter(se=>se===1||se===2||se===3),R=e.getLatestDocument(),_=bo(R,{includeSections:m,...S.length>
720
- 0?{headingLevels:S}:{}}),x=e.getDocumentSession()?.getDocumentWithoutPendingSuggestions(),P=x&&x!==R?bo(x,{includeSections:!1}):null,E=P&&(P.wordCount!==_.wordCount||P.characterCount!==_.characterCount)?
718
+ s.heading_levels:[]).map(se=>typeof se=="number"?se:typeof se=="string"?Number.parseInt(se,10):Number.NaN).filter(se=>se===1||se===2||se===3),N=e.getLatestDocument(),_=bo(N,{includeSections:m,...S.length>
719
+ 0?{headingLevels:S}:{}}),x=e.getDocumentSession()?.getDocumentWithoutPendingSuggestions(),P=x&&x!==N?bo(x,{includeSections:!1}):null,E=P&&(P.wordCount!==_.wordCount||P.characterCount!==_.characterCount)?
721
720
  {wordCount:P.wordCount,characterCount:P.characterCount,paragraphCount:P.paragraphCount,pageCount:P.pageCount}:void 0,K=_.sections??[],F=K.length,U=Math.min(w,F),Z=m?K.slice(U,U+k):void 0,W=Z?.length??
722
721
  0,le=m&&U+W<F,ee=JSON.stringify({kind:"document_measurement",tool:"measure_document",measurementBasis:"pending_suggestions_applied",..._,...E?{originalReviewProjection:E}:{},...m?{sections:Z,sectionCount:F,
723
722
  sectionOffset:U,sectionLimit:k,returnedSectionCount:W,hasMoreSections:le,...le?{nextSectionOffset:U+W}:{}}:{}});n.count("agent.measure.call",1,{tool_name:$}),n.distribution("agent.measure.sections",F,
@@ -727,11 +726,11 @@ tals treat pending suggestions as accepted. The original review projection has $
727
726
  ing the user's editor view when reconciling a reported count.`:"";return{toolCall:h,success:!0,toolOutput:ee,agentFeedback:`${ie}${ge}${Q} The result includes ${te}.`,control:{shouldContinue:!0}}}if($===
728
727
  "measure_blocks"){const s=h.arguments||{},m=typeof s.mode=="string"?s.mode.trim():"inclusive";if(m!==""&&m!=="inclusive")return v(h,'measure_blocks only supports mode="inclusive".');const p=Array.isArray(
729
728
  s.ranges)?s.ranges:[];if(p.length===0)return v(h,"measure_blocks requires at least one range.");const w=p.map(x=>{const P=x&&typeof x=="object"?x:{};return{startBlockId:typeof P.start_block_id=="strin\
730
- g"?P.start_block_id:"",endBlockId:typeof P.end_block_id=="string"?P.end_block_id:void 0}}),g=zi(e.getLatestDocument(),w),k=g.ranges.length,S=g.errors.length,R=JSON.stringify({kind:"document_measuremen\
729
+ g"?P.start_block_id:"",endBlockId:typeof P.end_block_id=="string"?P.end_block_id:void 0}}),g=zi(e.getLatestDocument(),w),k=g.ranges.length,S=g.errors.length,N=JSON.stringify({kind:"document_measuremen\
731
730
  t",tool:"measure_blocks",...g});if(n.count("agent.measure.call",1,{tool_name:$}),n.distribution("agent.measure.ranges",k,void 0,{tool_name:$}),k===0){const x=g.errors.map(P=>P.error).join(" ")||"No va\
732
731
  lid inclusive ranges were measured.";return v(h,x,De)}const _=S>0?`Measured ${k} inclusive block range(s); ${S} range(s) had errors.`:`Measured ${k} inclusive block range(s).`;return H(h,_,void 0,void 0,
733
- R)}if($==="read_table"){const s=e.getLatestDocument(),m=h.arguments??{};if(typeof m.context_notes!="string")return v(h,"context_notes is required (use N/A when there is no prior context to preserve).");
734
- const p=Et(s,m,x=>ae.renderSubtree(x,s));if(p.error)return v(h,p.error);const w=vi(e.getTableTaskState?.()??e.toolState.tableTasks??Zn(),s,m,{requestId:e.turnState.currentRequestId??0,chatHistory:e.getConversationHistory?.()??
732
+ N)}if($==="read_table"){const s=e.getLatestDocument(),m=h.arguments??{};if(typeof m.context_notes!="string")return v(h,"context_notes is required (use N/A when there is no prior context to preserve).");
733
+ const p=Et(s,m,x=>ae.renderSubtree(x,s));if(p.error)return v(h,p.error);const w=Ii(e.getTableTaskState?.()??e.toolState.tableTasks??Zn(),s,m,{requestId:e.turnState.currentRequestId??0,chatHistory:e.getConversationHistory?.()??
735
734
  [],attachmentExists:x=>e.getAllAttachments().has(x)});let g;if("error"in w){const x=(e.getTableTaskState?.()??e.toolState.tableTasks)?.task;g={accepted:!1,reason:w.error,retained_scope:x&&x.tableId===
736
735
  p.table_id?{task_kind:x.kind,scope_row_start:x.declaredRowStart,scope_row_count:x.rowIds.length,scope_columns:x.columns}:null,note:x?"The existing task scope still applies; finish all of it unless the\
737
736
  user narrows it.":"No task scope is recorded for this table; no table task status will be reported until a valid declaration."}}else e.toolState.tableTasks=w.state,w.declared&&e.setTableTaskState?.(w.
@@ -739,77 +738,77 @@ state);const k=(C=e.toolState).tableContext??(C.tableContext=Un());m.mode!=="cel
739
738
  [],p.table_id])],k.requestedCells??(k.requestedCells={}),k.requestedCells[p.table_id]=[...new Set([...k.requestedCells[p.table_id]??[],...p.rows.flatMap(x=>x.cells.map(P=>P.id).filter(Boolean))])];const S=!!e.
740
739
  turnState.docContextLedger;S?(k.pendingReadCells??(k.pendingReadCells={}),k.pendingReadCells[p.table_id]=[...new Set([...k.pendingReadCells[p.table_id]??[],...p.rows.flatMap(x=>x.cells.map(P=>P.id).filter(
741
740
  Boolean))])],(q=e.turnState).requestedBlockIds??(q.requestedBlockIds=new Set),e.turnState.requestedBlockIds.add(p.table_id),(J=e.turnState).lastReadBlockIds??(J.lastReadBlockIds=new Set),e.turnState.lastReadBlockIds.
742
- add(p.table_id),e.turnState.documentRequested=!0):_t(s,k,p.table_id,p.complete_cell_ids),e.markConversationDirty();const R=p.rows.flatMap(x=>x.cells.filter(P=>P.id&&P.kind!=="covered"&&!p.complete_cell_ids.
741
+ add(p.table_id),e.turnState.documentRequested=!0):_t(s,k,p.table_id,p.complete_cell_ids),e.markConversationDirty();const N=p.rows.flatMap(x=>x.cells.filter(P=>P.id&&P.kind!=="covered"&&!p.complete_cell_ids.
743
742
  includes(P.id)).map(P=>{const E=re(s,P.id),K=E?.type==="table-cell"?E.children.map(F=>F.id):[];return{row_id:x.row_id,column:P.column,cell_id:P.id,...P.truncated&&P.text?{note:P.text}:{},...K.length?{
744
743
  nested_block_ids:K.length>40?[...K.slice(0,40),`+${K.length-40} more`]:K}:{}}})),_=S&&m.mode!=="cell_text"?{...p,rows:void 0,complete_cell_ids:void 0,delivered_rows:p.rows.map(x=>({row_id:x.row_id,columns:x.
745
- cells.filter(P=>p.complete_cell_ids.includes(P.id)).map(P=>P.column)})),delivered_cell_count:p.complete_cell_ids.length,...R.length?{undelivered_cells:R}:{},delivery:R.length?"Delivered cells arrive i\
744
+ cells.filter(P=>p.complete_cell_ids.includes(P.id)).map(P=>P.column)})),delivered_cell_count:p.complete_cell_ids.length,...N.length?{undelivered_cells:N}:{},delivery:N.length?"Delivered cells arrive i\
746
745
  n the next document snapshot; undelivered_cells will not, so follow each one's note. Summary/preview alone is not edit authorization.":"Requested cells arrive in the next document snapshot. Summary/pr\
747
746
  eview alone is not edit authorization.",...g?{task_scope_update:g}:{}}:{...p,...g?{task_scope_update:g}:{}};return H(h,g?"Table context read. The task scope declaration was rejected (see task_scope_up\
748
747
  date); the existing scope is unchanged.":m.mode==="cell_text"?"Cell text page read. cell_text is read-only: each block's text starts with its [[block_id]] marker (not document text). To edit a passage\
749
748
  , read that block with read_specific_blocks, then target its block ID.":"Table context read. Use fill counts to include gaps in earlier rows.",void 0,void 0,JSON.stringify(_))}if($==="read_blocks"){const s=h.
750
- arguments||{},m=Ie(s,e),p=s.from_id,w=m?Ge(e):"";if(m&&!w&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for signed-in documents.");let g=null;try{g=m?await(e.loadRemoteDocument?.(
751
- m)??St({token:w,documentId:m})):null}catch(F){return v(h,F instanceof Error?F.message:"Document read failed.")}const k=g?.content??e.getLatestDocument(),S=_e(k),R=S.length,_=typeof p=="string"?Xt(k,p):
752
- -1;if(_===-1)return v(h,`Block ID "${p}" not found`,De);if(_>=R)return v(h,`Start index ${_} is out of range for ${R} blocks.`);const x=Ro({doc:k,startIndex:_,maxTokens:We});if(x.blockIds.length===0||
753
- x.endIndex<_)return v(h,`No readable blocks found from index ${_}.`);if(g){i(k,x.blockIds,g.id);const F=ae.extractSpecificBlocks(k,x.blockIds,void 0,ze),U=ae.formatSpecificBlocks(F),Z=x.endIndex+1<R?x.
749
+ arguments||{},m=Ie(s,e),p=s.from_id,w=m?He(e):"";if(m&&!w&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for signed-in documents.");let g=null;try{g=m?await(e.loadRemoteDocument?.(
750
+ m)??St({token:w,documentId:m})):null}catch(F){return v(h,F instanceof Error?F.message:"Document read failed.")}const k=g?.content??e.getLatestDocument(),S=_e(k),N=S.length,_=typeof p=="string"?Xt(k,p):
751
+ -1;if(_===-1)return v(h,`Block ID "${p}" not found`,De);if(_>=N)return v(h,`Start index ${_} is out of range for ${N} blocks.`);const x=No({doc:k,startIndex:_,maxTokens:Je});if(x.blockIds.length===0||
752
+ x.endIndex<_)return v(h,`No readable blocks found from index ${_}.`);if(g){i(k,x.blockIds,g.id);const F=ae.extractSpecificBlocks(k,x.blockIds,void 0,Fe),U=ae.formatSpecificBlocks(F),Z=x.endIndex+1<N?x.
754
753
  endIndex+1:null,W=en({documentId:g.id,title:g.title,canonicalPath:g.canonicalPath,startIndex:_,endIndex:x.endIndex,estimatedTokens:x.estimatedTokens,content:U,nextIndex:Z,endOfDocument:Z===null}),le=x.
755
754
  reachedTokenBudget?" Reached per-call token budget.":"";return H(h,`Read ${x.blockIds.length} blocks from "${g.title}" (index ${_}-${x.endIndex}). Serialized characters: ~${x.estimatedTokens}.${le}${Z!==
756
755
  null?` Next: read_blocks_from_index(document_id="${g.id}", index=${Z}).`:" End of document."}`,void 0,void 0,W)}const P=l(x.blockIds);if(P.error)return v(h,P.error.message,P.error.code);e.turnState.documentRequested=
757
756
  !0,n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent.read.blocks_loaded",x.blockIds.length,void 0,{tool_name:$}),n.distribution("agent.read.tokens_loaded_estimate",x.estimatedTokens,void 0,
758
- {tool_name:$}),x.reachedTokenBudget&&n.count("agent.read.token_budget_reached",1,{tool_name:$});const E=st(e,k);if(x.endIndex+1<R){const F=x.endIndex+1,U=S[F]?.id,Z=at({tool:$,loaded:{count:x.blockIds.
757
+ {tool_name:$}),x.reachedTokenBudget&&n.count("agent.read.token_budget_reached",1,{tool_name:$});const E=st(e,k);if(x.endIndex+1<N){const F=x.endIndex+1,U=S[F]?.id,Z=at({tool:$,loaded:{count:x.blockIds.
759
758
  length,startIndex:_,endIndex:x.endIndex,estimatedTokens:x.estimatedTokens},next:{index:F,...U?{blockId:U}:{}},endOfDocument:!1,coverage:E}),W=x.reachedTokenBudget?" Reached per-call token budget.":"",
760
759
  le=U?` Next block ID: ${U}.`:"";return H(h,`Read ${x.blockIds.length} blocks (index ${_}-${x.endIndex}). Serialized characters: ~${x.estimatedTokens}.${W} Next: read_blocks_from_index(index=${F}).${le}${P.
761
760
  reread?c:""}`,void 0,P.reread,Z)}const K=at({tool:$,loaded:{count:x.blockIds.length,startIndex:_,endIndex:x.endIndex,estimatedTokens:x.estimatedTokens},endOfDocument:!0,coverage:E});return H(h,`Read ${x.
762
761
  blockIds.length} blocks (index ${_}-${x.endIndex}). Serialized characters: ~${x.estimatedTokens}. End of document.${P.reread?c:""}`,void 0,P.reread,K)}if($==="read_blocks_from_index"){const s=h.arguments||
763
- {},m=Ie(s,e),p=it(s.index,0),w=m?Ge(e):"";if(m&&!w&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for signed-in documents.");let g=null;try{g=m?await(e.loadRemoteDocument?.(
764
- m)??St({token:w,documentId:m})):null}catch(K){return v(h,K instanceof Error?K.message:"Document read failed.")}const k=g?.content??e.getLatestDocument(),S=_e(k),R=S.length;if(g&&R===0&&p===0)return H(
762
+ {},m=Ie(s,e),p=it(s.index,0),w=m?He(e):"";if(m&&!w&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for signed-in documents.");let g=null;try{g=m?await(e.loadRemoteDocument?.(
763
+ m)??St({token:w,documentId:m})):null}catch(K){return v(h,K instanceof Error?K.message:"Document read failed.")}const k=g?.content??e.getLatestDocument(),S=_e(k),N=S.length;if(g&&N===0&&p===0)return H(
765
764
  h,`Read 0 blocks from "${g.title}". End of document.`,void 0,void 0,en({documentId:g.id,title:g.title,canonicalPath:g.canonicalPath,startIndex:0,endIndex:-1,estimatedTokens:0,content:"",nextIndex:null,
766
- endOfDocument:!0}));if(p>=R)return v(h,`Start index ${p} is out of range for ${R} blocks${g?` in "${g.title}"`:""}.`);const _=Ro({doc:k,startIndex:p,maxTokens:We});if(_.blockIds.length===0||_.endIndex<
767
- p)return v(h,`No readable blocks found from index ${p}.`);if(g){i(k,_.blockIds,g.id);const K=ae.extractSpecificBlocks(k,_.blockIds,void 0,ze),F=ae.formatSpecificBlocks(K),U=_.endIndex+1<R?_.endIndex+1:
765
+ endOfDocument:!0}));if(p>=N)return v(h,`Start index ${p} is out of range for ${N} blocks${g?` in "${g.title}"`:""}.`);const _=No({doc:k,startIndex:p,maxTokens:Je});if(_.blockIds.length===0||_.endIndex<
766
+ p)return v(h,`No readable blocks found from index ${p}.`);if(g){i(k,_.blockIds,g.id);const K=ae.extractSpecificBlocks(k,_.blockIds,void 0,Fe),F=ae.formatSpecificBlocks(K),U=_.endIndex+1<N?_.endIndex+1:
768
767
  null,Z=en({documentId:g.id,title:g.title,canonicalPath:g.canonicalPath,startIndex:p,endIndex:_.endIndex,estimatedTokens:_.estimatedTokens,content:F,nextIndex:U,endOfDocument:U===null}),W=_.reachedTokenBudget?
769
768
  " Reached per-call token budget.":"";return n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent.read.blocks_loaded",_.blockIds.length,void 0,{tool_name:$}),H(h,`Read ${_.blockIds.length} \
770
769
  blocks from "${g.title}" (index ${p}-${_.endIndex}). Serialized characters: ~${_.estimatedTokens}.${W}${U!==null?` Next: read_blocks_from_index(document_id="${g.id}", index=${U}).`:" End of document."}`,
771
770
  void 0,void 0,Z)}const x=l(_.blockIds);if(x.error)return v(h,x.error.message,x.error.code);e.turnState.documentRequested=!0,n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent.read.blocks\
772
771
  _loaded",_.blockIds.length,void 0,{tool_name:$}),n.distribution("agent.read.tokens_loaded_estimate",_.estimatedTokens,void 0,{tool_name:$}),_.reachedTokenBudget&&n.count("agent.read.token_budget_reach\
773
- ed",1,{tool_name:$});const P=st(e,k);if(_.endIndex+1<R){const K=_.endIndex+1,F=S[K]?.id,U=at({tool:$,loaded:{count:_.blockIds.length,startIndex:p,endIndex:_.endIndex,estimatedTokens:_.estimatedTokens},
772
+ ed",1,{tool_name:$});const P=st(e,k);if(_.endIndex+1<N){const K=_.endIndex+1,F=S[K]?.id,U=at({tool:$,loaded:{count:_.blockIds.length,startIndex:p,endIndex:_.endIndex,estimatedTokens:_.estimatedTokens},
774
773
  next:{index:K,...F?{blockId:F}:{}},endOfDocument:!1,coverage:P}),Z=_.reachedTokenBudget?" Reached per-call token budget.":"",W=F?` Next block ID: ${F}.`:"";return H(h,`Read ${_.blockIds.length} blocks\
775
774
  (index ${p}-${_.endIndex}). Serialized characters: ~${_.estimatedTokens}.${Z} Next: read_blocks_from_index(index=${K}).${W}${x.reread?c:""}`,void 0,x.reread,U)}const E=at({tool:$,loaded:{count:_.blockIds.
776
775
  length,startIndex:p,endIndex:_.endIndex,estimatedTokens:_.estimatedTokens},endOfDocument:!0,coverage:P});return H(h,`Read ${_.blockIds.length} blocks (index ${p}-${_.endIndex}). Serialized characters:\
777
776
  ~${_.estimatedTokens}. End of document.${x.reread?c:""}`,void 0,x.reread,E)}if($==="search_document"){const s=h.arguments||{},m=Ie(s,e),p=s.queries,w=Array.isArray(p)?p.filter(ne=>typeof ne=="string"&&
778
- ne.length>0):typeof p=="string"&&p.length>0?[p]:[];if(w.length===0)return v(h,'search_document requires "queries": a non-empty array of search strings.');const g=typeof s.page=="number"?s.page:0,k=m?Ge(
777
+ ne.length>0):typeof p=="string"&&p.length>0?[p]:[];if(w.length===0)return v(h,'search_document requires "queries": a non-empty array of search strings.');const g=typeof s.page=="number"?s.page:0,k=m?He(
779
778
  e):"";if(m&&!k&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for signed-in documents.");let S=null;try{S=m?await(e.loadRemoteDocument?.(m)??St({token:k,documentId:m})):null}catch(ne){
780
- return v(h,ne instanceof Error?ne.message:"Document search failed.")}const R=S?.content??e.getLatestDocument(),_=e.searchPageSize,x=Eo("search_document",s);let P;g>0&&e.toolState.lastSearchState&&e.toolState.
781
- lastSearchState.toolName==="search_document"&&e.toolState.lastSearchState.requestKey===x?P=e.toolState.lastSearchState.allResults:P=ae.searchDocument(R,w);let E;if(!S&&P.length>0){const ne=g>0&&e.toolState.
782
- lastSearchState?.requestKey===x?e.toolState.lastSearchState.resultSetId:void 0;if(ne&&y.has(ne))E=ne;else{E=`search_result_${N++}`;const be=Array.from(new Set(P.map($e=>$e.blockId)));y.set(E,{id:E,blockIds:be,
783
- blockHashes:Dt(R,be)})}}const K=No({doc:R,results:P,pageSize:_,maxTokens:We}),F=Math.max(1,K.length),U=Math.min(g,Math.max(0,F-1)),Z=K[U]??{results:[],startResultIndex:0,endResultIndexExclusive:0},W=Z.
779
+ return v(h,ne instanceof Error?ne.message:"Document search failed.")}const N=S?.content??e.getLatestDocument(),_=e.searchPageSize,x=Eo("search_document",s);let P;g>0&&e.toolState.lastSearchState&&e.toolState.
780
+ lastSearchState.toolName==="search_document"&&e.toolState.lastSearchState.requestKey===x?P=e.toolState.lastSearchState.allResults:P=ae.searchDocument(N,w);let E;if(!S&&P.length>0){const ne=g>0&&e.toolState.
781
+ lastSearchState?.requestKey===x?e.toolState.lastSearchState.resultSetId:void 0;if(ne&&y.has(ne))E=ne;else{E=`search_result_${R++}`;const be=Array.from(new Set(P.map($e=>$e.blockId)));y.set(E,{id:E,blockIds:be,
782
+ blockHashes:Dt(N,be)})}}const K=Ro({doc:N,results:P,pageSize:_,maxTokens:Je}),F=Math.max(1,K.length),U=Math.min(g,Math.max(0,F-1)),Z=K[U]??{results:[],startResultIndex:0,endResultIndexExclusive:0},W=Z.
784
783
  startResultIndex,le=Z.endResultIndexExclusive,ee=Z.results,ie=ee.map(ne=>ne.blockId),ge=S||ie.length===0?null:a(ie);e.toolState.lastSearchState={toolName:"search_document",requestKey:x,allResults:P,currentPage:U,
785
784
  totalPages:F,...E?{resultSetId:E}:{}};let te;P.length===0?te=`No matches found${S?` in "${S.title}"`:""} for: ${w.join(", ")}`:(te=`Found ${P.length} matching blocks${S?` in "${S.title}"`:""}. Showing\
786
785
  page ${U+1}/${F} (results ${W+1}-${le} of ${P.length}).`,!S&&E&&(te+=` The full unpaginated result set is saved as ${E}; pass search_result_id="${E}" to replace, replace_block, style_blocks, or remov\
787
786
  e_blocks to target all ${P.length} matches in one call.`),U<F-1&&S&&(te+=S?` Call search_document with document_id="${S.id}" and page=${U+1} to see next page.`:` Call search_document with page=${U+1} \
788
787
  to see next page.`));const Q=ge?.code==="no_new_read_context";if(ge&&!Q){if(P.length>0){let ne=`Found ${P.length} matching blocks. Showing page ${U+1}/${F} (blocks ${W+1}-${le} of ${P.length}). Matchi\
789
788
  ng blocks could not be loaded this turn.`;return U<F-1&&(ne+=` Call search_document with page=${U+1} to see next page.`),v(h,`${ge.message} ${ne}`,ge.code)}return v(h,`${ge.message} ${te}`,ge.code)}if(Q&&
790
- P.length>0&&(te+=" Matching block content is already available in this request's cached context."),!S){const ne=mr(R.chrome??[]).filter(be=>w.some($e=>be.toLowerCase().includes($e.toLowerCase())));ne.
789
+ P.length>0&&(te+=" Matching block content is already available in this request's cached context."),!S){const ne=mr(N.chrome??[]).filter(be=>w.some($e=>be.toLowerCase().includes($e.toLowerCase())));ne.
791
790
  length>0&&(te+=` Also found in page headers/footers (not body blocks; change them with set_header_footer):
792
791
  ${ne.map(be=>`- ${be}`).join(`
793
- `)}`)}if(S){i(R,ie,S.id);const ne=ae.extractSpecificBlocks(R,ie,void 0,ze),be=ae.formatSpecificBlocks(ne),$e=JSON.stringify({kind:"document_search_context",tool:"search_document",document:{documentId:S.
792
+ `)}`)}if(S){i(N,ie,S.id);const ne=ae.extractSpecificBlocks(N,ie,void 0,Fe),be=ae.formatSpecificBlocks(ne),$e=JSON.stringify({kind:"document_search_context",tool:"search_document",document:{documentId:S.
794
793
  id,title:S.title,canonicalPath:S.canonicalPath||`/${S.title}`,href:`/docs/${S.id}`,...Yt(S.id)},queries:w,totalMatches:P.length,page:{current:U,total:F,startResult:W+1,endResult:le},nextPage:U<F-1?U+1:
795
794
  null,matches:ee.map(Ee=>({blockId:Ee.blockId,blockIndex:Ee.blockIndex,matchedQueries:Ee.matchedQueries??[]})),documentContent:be});return n.count("agent.read.search_call",1,{tool_name:$}),n.distribution(
796
795
  "agent.read.blocks_loaded",ie.length,void 0,{tool_name:$}),H(h,te,void 0,void 0,$e)}e.turnState.documentRequested=!0,n.count("agent.read.search_call",1,{tool_name:$}),n.distribution("agent.read.blocks\
797
796
  _loaded",ie.length,void 0,{tool_name:$});const se=Bo({tool:"search_document",queries:w,totalMatches:P.length,currentPage:U,totalPages:F,pageStart:W,pageEnd:le,pageResults:ee,nextPage:U<F-1?U+1:null,...E?
798
797
  {searchResultId:E}:{},coverage:st(e,e.getLatestDocument())});return H(h,te,void 0,void 0,se)}if($==="list_documents"){const s=h.arguments||{},m=typeof s.parent_folder_id=="string"&&s.parent_folder_id.
799
- trim().length>0?s.parent_folder_id.trim():null,p=it(s.page,0),w=Ge(e);if(!w)return v(h,"Document tree listing is only available for signed-in documents.");try{const g=await zs({token:w,parentFolderId:m,
800
- page:p,limit:50}),k=g.hasMore?` Call list_documents with page=${p+1} for more.`:"",S=g.items.filter(P=>P.itemType==="folder").length,R=g.items.length-S,_=g.totalCount===0?`No items found in ${m?"that \
801
- folder":"the account root"}.`:`Listed ${g.items.length} of ${g.totalCount} items in ${m?"the folder":"the account root"} (${S} folders, ${R} documents).${k}`,x=Ws({parentFolderId:m,page:p,totalCount:g.
798
+ trim().length>0?s.parent_folder_id.trim():null,p=it(s.page,0),w=He(e);if(!w)return v(h,"Document tree listing is only available for signed-in documents.");try{const g=await zs({token:w,parentFolderId:m,
799
+ page:p,limit:50}),k=g.hasMore?` Call list_documents with page=${p+1} for more.`:"",S=g.items.filter(P=>P.itemType==="folder").length,N=g.items.length-S,_=g.totalCount===0?`No items found in ${m?"that \
800
+ folder":"the account root"}.`:`Listed ${g.items.length} of ${g.totalCount} items in ${m?"the folder":"the account root"} (${S} folders, ${N} documents).${k}`,x=Ws({parentFolderId:m,page:p,totalCount:g.
802
801
  totalCount,totalPages:Math.max(1,g.totalPages),hasMore:g.hasMore,items:g.items});return n.count("agent.read.document_tree_list",1,{tool_name:$}),H(h,_,void 0,void 0,x)}catch(g){return v(h,g instanceof
803
- Error?g.message:"Document listing failed.")}}if($==="search_documents"){const s=h.arguments||{},m=typeof s.query=="string"?s.query.trim():"";if(!m)return v(h,"search_documents requires a query.");const p=Ge(
802
+ Error?g.message:"Document listing failed.")}}if($==="search_documents"){const s=h.arguments||{},m=typeof s.query=="string"?s.query.trim():"";if(!m)return v(h,"search_documents requires a query.");const p=He(
804
803
  e);if(!p)return v(h,"Cross-document search is only available for signed-in documents.");const w=Us(s.scope),g=e.getCurrentFolderId?.()??null,k=typeof s.folder_id=="string"&&s.folder_id.trim().length>0?
805
- s.folder_id.trim():null,S=w==="current_folder"&&!g||w==="folder"&&!k?"account":w,R=it(s.page,0);try{const _=await Fs({token:p,query:m,scope:S,page:R,currentFolderId:g,folderId:k}),x=S==="current_folde\
806
- r"&&!!g,P=S==="folder"&&k?"the selected folder tree":x?"the current folder tree":"the account",E=R+1<_.totalPages?` Call search_documents with page=${R+1} for more.`:"",K=_.totalCount===0?`No document\
807
- s found for "${m}" in ${P}.`:`Found ${_.totalCount} documents for "${m}" in ${P}. Showing page ${R+1}/${Math.max(1,_.totalPages)}.${E}`,F=Js({query:m,scope:S,searchedCurrentFolder:x,folderId:S==="fold\
808
- er"?k:null,page:R,totalCount:_.totalCount,totalPages:Math.max(1,_.totalPages),results:_.items});return n.count("agent.read.account_search_call",1,{tool_name:$}),H(h,K,void 0,void 0,F)}catch(_){return v(
804
+ s.folder_id.trim():null,S=w==="current_folder"&&!g||w==="folder"&&!k?"account":w,N=it(s.page,0);try{const _=await Fs({token:p,query:m,scope:S,page:N,currentFolderId:g,folderId:k}),x=S==="current_folde\
805
+ r"&&!!g,P=S==="folder"&&k?"the selected folder tree":x?"the current folder tree":"the account",E=N+1<_.totalPages?` Call search_documents with page=${N+1} for more.`:"",K=_.totalCount===0?`No document\
806
+ s found for "${m}" in ${P}.`:`Found ${_.totalCount} documents for "${m}" in ${P}. Showing page ${N+1}/${Math.max(1,_.totalPages)}.${E}`,F=Js({query:m,scope:S,searchedCurrentFolder:x,folderId:S==="fold\
807
+ er"?k:null,page:N,totalCount:_.totalCount,totalPages:Math.max(1,_.totalPages),results:_.items});return n.count("agent.read.account_search_call",1,{tool_name:$}),H(h,K,void 0,void 0,F)}catch(_){return v(
809
808
  h,_ instanceof Error?_.message:"Document search failed.")}}if($==="find_highlights"){const s=h.arguments||{},m=typeof s.color=="string"&&s.color.trim().length>0?s.color.trim().toLowerCase():void 0,p=typeof s.
810
809
  page=="number"?s.page:0,w=e.getLatestDocument(),g=e.searchPageSize,k=Eo("find_highlights",s);let S;p>0&&e.toolState.lastSearchState&&e.toolState.lastSearchState.toolName==="find_highlights"&&e.toolState.
811
- lastSearchState.requestKey===k?S=e.toolState.lastSearchState.allResults:S=ae.findHighlights(w,m);const R=No({doc:w,results:S,pageSize:g,maxTokens:We}),_=Math.max(1,R.length),x=Math.min(p,Math.max(0,_-
812
- 1)),P=R[x]??{results:[],startResultIndex:0,endResultIndexExclusive:0},E=P.startResultIndex,K=P.endResultIndexExclusive,F=P.results,U=F.map(te=>te.blockId),Z=U.length===0?null:a(U);e.toolState.lastSearchState=
810
+ lastSearchState.requestKey===k?S=e.toolState.lastSearchState.allResults:S=ae.findHighlights(w,m);const N=Ro({doc:w,results:S,pageSize:g,maxTokens:Je}),_=Math.max(1,N.length),x=Math.min(p,Math.max(0,_-
811
+ 1)),P=N[x]??{results:[],startResultIndex:0,endResultIndexExclusive:0},E=P.startResultIndex,K=P.endResultIndexExclusive,F=P.results,U=F.map(te=>te.blockId),Z=U.length===0?null:a(U);e.toolState.lastSearchState=
813
812
  {toolName:"find_highlights",requestKey:k,allResults:S,currentPage:x,totalPages:_};const W=m?`${m} highlight`:"highlighted content",le=m||S.length===0?"":` Colors: ${Hs(S)}.`;let ee;S.length===0?ee=`No\
814
813
  blocks found with ${W}.`:(ee=`Found ${S.length} blocks with ${W}. Showing page ${x+1}/${_} (results ${E+1}-${K} of ${S.length}).${le}`,x<_-1&&(ee+=` Call find_highlights with page=${x+1} to see next \
815
814
  page.`));const ie=Z?.code==="no_new_read_context";if(Z&&!ie){if(S.length>0){let te=`Found ${S.length} blocks with ${W}. Showing page ${x+1}/${_} (blocks ${E+1}-${K} of ${S.length}). Matching blocks co\
@@ -817,26 +816,26 @@ uld not be loaded this turn.`;return x<_-1&&(te+=` Call find_highlights with pag
817
816
  " Matching block content is already available in this request's cached context."),e.turnState.documentRequested=!0,n.count("agent.read.search_call",1,{tool_name:$}),n.distribution("agent.read.blocks_l\
818
817
  oaded",U.length,void 0,{tool_name:$});const ge=Bo({tool:"find_highlights",color:m??null,totalMatches:S.length,currentPage:x,totalPages:_,pageStart:E,pageEnd:K,pageResults:F,nextPage:x<_-1?x+1:null,coverage:st(
819
818
  e,e.getLatestDocument())});return H(h,ee,void 0,void 0,ge)}if($==="read_specific_blocks"){const s=h.arguments||{},m=Ie(s,e),p=s.block_ids,w=Array.isArray(p)?p.filter(W=>typeof W=="string"&&W.length>0):
820
- typeof p=="string"&&p.length>0?[p]:[];if(w.length===0)return v(h,"No block IDs provided");const g=m?Ge(e):"";if(m&&!g&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for sig\
819
+ typeof p=="string"&&p.length>0?[p]:[];if(w.length===0)return v(h,"No block IDs provided");const g=m?He(e):"";if(m&&!g&&!e.loadRemoteDocument)return v(h,"Cross-document access is only available for sig\
821
820
  ned-in documents.");let k=null;try{k=m?await(e.loadRemoteDocument?.(m)??St({token:g,documentId:m})):null}catch(W){return v(h,W instanceof Error?W.message:"Document read failed.")}const S=k?.content??e.
822
- getLatestDocument();if(!k&&e.toolState.tableContext?.scopedTableIds?.length){const W=[];Ue(S,ee=>W.push(ee));const le=ee=>[...W].reverse().find(ie=>(ie.children.length>=Vo||e.toolState.tableContext.scopedTableIds.
821
+ getLatestDocument();if(!k&&e.toolState.tableContext?.scopedTableIds?.length){const W=[];Le(S,ee=>W.push(ee));const le=ee=>[...W].reverse().find(ie=>(ie.children.length>=Vo||e.toolState.tableContext.scopedTableIds.
823
822
  includes(ie.id))&&ue(ie).includes(ee));if(w.some(ee=>le(ee))){const ee=[];let ie=0;const ge=[...new Set(w.map(Q=>{const se=re(S,Q);return se?.type==="list"&&se.children.some(ne=>ne.id===Q)?se.id:Q}))];
824
- for(const Q of ge){const se=re(S,Q),ne=le(Q);if(!se||se.id!==Q)return v(h,`Unknown or structural block '${Q}'. Use read_table with table_id and row_ids for table rows.`);let be=!1;if(Ue(se,()=>{be=!0}),
823
+ for(const Q of ge){const se=re(S,Q),ne=le(Q);if(!se||se.id!==Q)return v(h,`Unknown or structural block '${Q}'. Use read_table with table_id and row_ids for table rows.`);let be=!1;if(Le(se,()=>{be=!0}),
825
824
  be)return v(h,`Block '${Q}' contains a table. Use read_table(table_id="${ne?.id??W.find(Go=>ue(se).includes(Go.id))?.id}") for bounded row windows.`);const $e=ae.renderSubtree(se,S),Ee=JSON.stringify(
826
825
  {id:Q,html:$e}).length;if(ie+Ee>24e3)return v(h,"Requested nested content exceeds 24000 serialized characters. Read fewer blocks; for a huge cell use read_table mode=cell_text. No new edit rights were\
827
826
  granted.");ie+=Ee,ee.push({id:Q,html:$e,table_id:ne?.id})}const te=e.toolState.tableContext;for(const Q of ee)Q.table_id&&(te.scopedTableIds=[...new Set([...te.scopedTableIds??[],Q.table_id])],Ln(S,te,
828
827
  Q.table_id,Q.id),e.turnState.docContextLedger&&(te.pendingReadBlocks??(te.pendingReadBlocks={}),te.pendingReadBlocks[Q.id]=te.blocks[Q.id]),re(S,Q.id)?.type==="table-cell"&&_t(S,te,Q.table_id,[Q.id])),
829
828
  (z=e.turnState).requestedBlockIds??(z.requestedBlockIds=new Set),e.turnState.requestedBlockIds.add(Q.id);return e.turnState.documentRequested=!0,e.markConversationDirty(),H(h,`Read ${ee.length} exact \
830
829
  nested blocks. Ancestors and sibling cells remain unread. During context recovery, only blocks repeated in the next <table_recovery_window> stay editable; any it omits are listed there and are not edi\
831
- table.`,void 0,void 0,JSON.stringify({blocks:ee,serialized_characters:ie}))}}const{blockIds:R,estimatedTokens:_,reachedTokenBudget:x,missingRequestedBlocks:P}=Ls({doc:S,requestedBlockIds:w,maxTokens:We});
832
- if(R.length===0)return P>0?v(h,"None of the requested block IDs were found in the document.",De):v(h,"No readable blocks could be loaded.");if(k){i(S,R,k.id);const W=ae.extractSpecificBlocks(S,R,void 0,
833
- ze),le=ae.formatSpecificBlocks(W),ee=Zt(S,new Set(R)),ie=JSON.stringify({kind:"document_read",tool:$,document:{documentId:k.id,title:k.title,canonicalPath:k.canonicalPath||`/${k.title}`,href:`/docs/${k.
834
- id}`,...Yt(k.id)},loaded:{count:R.length,blockIds:R,blockIndices:ee,estimatedTokens:_},reachedTokenBudget:x,documentContent:le});return n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent\
835
- .read.blocks_loaded",R.length,void 0,{tool_name:$}),H(h,`Read ${R.length} specific blocks from "${k.title}". Serialized characters: ~${_}.${x?" Reached per-call token budget.":""}`,void 0,void 0,ie)}const E=l(
836
- R);if(E.error)return v(h,E.error.message,E.error.code);e.turnState.documentRequested=!0,n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent.read.blocks_loaded",R.length,void 0,{tool_name:$}),
837
- n.distribution("agent.read.tokens_loaded_estimate",_,void 0,{tool_name:$}),x&&n.count("agent.read.token_budget_reached",1,{tool_name:$});const K=Zt(S,new Set(R)),F=at({tool:$,loaded:{count:R.length,requestedCount:w.
838
- length,estimatedTokens:_,ranges:Mo(K)},endOfDocument:!1,coverage:st(e,S)}),U=x?` Reached per-call token budget; loaded ${R.length}/${w.length} requested blocks.`:"",Z=P>0?` ${P} requested block IDs we\
839
- re not found.`:"";return H(h,`Loaded ${R.length} specific blocks.${U}${Z} Serialized characters: ~${_}.${E.reread?c:""}`,void 0,E.reread,F)}if($==="get_attachment"){const s=(h.arguments||{}).attachment_id;
830
+ table.`,void 0,void 0,JSON.stringify({blocks:ee,serialized_characters:ie}))}}const{blockIds:N,estimatedTokens:_,reachedTokenBudget:x,missingRequestedBlocks:P}=Ls({doc:S,requestedBlockIds:w,maxTokens:Je});
831
+ if(N.length===0)return P>0?v(h,"None of the requested block IDs were found in the document.",De):v(h,"No readable blocks could be loaded.");if(k){i(S,N,k.id);const W=ae.extractSpecificBlocks(S,N,void 0,
832
+ Fe),le=ae.formatSpecificBlocks(W),ee=Zt(S,new Set(N)),ie=JSON.stringify({kind:"document_read",tool:$,document:{documentId:k.id,title:k.title,canonicalPath:k.canonicalPath||`/${k.title}`,href:`/docs/${k.
833
+ id}`,...Yt(k.id)},loaded:{count:N.length,blockIds:N,blockIndices:ee,estimatedTokens:_},reachedTokenBudget:x,documentContent:le});return n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent\
834
+ .read.blocks_loaded",N.length,void 0,{tool_name:$}),H(h,`Read ${N.length} specific blocks from "${k.title}". Serialized characters: ~${_}.${x?" Reached per-call token budget.":""}`,void 0,void 0,ie)}const E=l(
835
+ N);if(E.error)return v(h,E.error.message,E.error.code);e.turnState.documentRequested=!0,n.count("agent.read.call",1,{tool_name:$}),n.distribution("agent.read.blocks_loaded",N.length,void 0,{tool_name:$}),
836
+ n.distribution("agent.read.tokens_loaded_estimate",_,void 0,{tool_name:$}),x&&n.count("agent.read.token_budget_reached",1,{tool_name:$});const K=Zt(S,new Set(N)),F=at({tool:$,loaded:{count:N.length,requestedCount:w.
837
+ length,estimatedTokens:_,ranges:Mo(K)},endOfDocument:!1,coverage:st(e,S)}),U=x?` Reached per-call token budget; loaded ${N.length}/${w.length} requested blocks.`:"",Z=P>0?` ${P} requested block IDs we\
838
+ re not found.`:"";return H(h,`Loaded ${N.length} specific blocks.${U}${Z} Serialized characters: ~${_}.${E.reread?c:""}`,void 0,E.reread,F)}if($==="get_attachment"){const s=(h.arguments||{}).attachment_id;
840
839
  if(!s)return v(h,"No attachment_id provided");let m=e.getAllAttachments().get(s);return m||(m=await t(s),m&&e.getAllAttachments().set(s,m)),m?m.content?.trim()??""?H(h,`Loaded attachment "${m.id}" (${m.
841
840
  charCount} chars).`,void 0,void 0,`<attachment id="${m.id}" type="${m.type}"${m.fileName?` filename="${m.fileName}"`:""} chars="${m.charCount}">
842
841
  ${m.content}
@@ -845,16 +844,16 @@ from(e.getAllAttachments().keys()).join(", ")||"none"}`)}if($==="view_image"){co
845
844
  s);if(!p)return v(h,`Image block "${s}" not found in document`,De);const w={id:`view_image_${s}`,type:"image",content:"",preview:"",charCount:0,fileName:p.alt||`image_${s}`,urls:[p.src],dimensions:[{width:p.
846
845
  width,height:p.height}]};return H(h,`Image retrieved: ${p.alt?`"${p.alt}" `:""}(${p.width}x${p.height}px)${p.sourceUrl?` Source: ${p.sourceUrl}`:""}`,w)}if($==="render_document_pages"){if(!e.renderDocumentPages)
847
846
  return v(h,"Rendered page inspection is unavailable until the document canvas is ready.");const s=h.arguments||{},m=it(s.start_page,1),p=it(s.page_count,1),w=s.mode==="layout"?"layout":"appearance";let g=s.
848
- quality==="compact"?"compact":"detailed";const k=s.view===void 0||s.view===null?Rt:s.view;if(!sr(k))return v(h,`view must be one of ${ar.join(", ")}. Use show-tracked-changes unless you specifically n\
849
- eed the accepted or before preview.`,"invalid_view");if(m<1)return v(h,"start_page must be 1 or greater.");const S=g==="detailed"&&p>2;S&&p<=4&&(g="compact");const R=g==="compact"?4:2;if(p<1||p>R)return v(
850
- h,`page_count must be between 1 and ${R} for ${g} quality.`);try{const _=await e.renderDocumentPages({startPage:m,pageCount:p,mode:w,quality:g,view:k}),x=_.view??Rt;if(x!==k)return v(h,`This document \
847
+ quality==="compact"?"compact":"detailed";const k=s.view===void 0||s.view===null?Nt:s.view;if(!sr(k))return v(h,`view must be one of ${ar.join(", ")}. Use show-tracked-changes unless you specifically n\
848
+ eed the accepted or before preview.`,"invalid_view");if(m<1)return v(h,"start_page must be 1 or greater.");const S=g==="detailed"&&p>2;S&&p<=4&&(g="compact");const N=g==="compact"?4:2;if(p<1||p>N)return v(
849
+ h,`page_count must be between 1 and ${N} for ${g} quality.`);try{const _=await e.renderDocumentPages({startPage:m,pageCount:p,mode:w,quality:g,view:k}),x=_.view??Nt;if(x!==k)return v(h,`This document \
851
850
  surface cannot render the ${k} view (it rendered ${x}). Use show-tracked-changes, or inspect the accepted text with a read tool.`,"render_view_unsupported");if(_.placeholderImageCount||_.failedImageCount||
852
851
  _.mathPlaceholderCount)return{...v(h,`Visual inspection is incomplete: ${_.placeholderImageCount} image placeholders, ${_.failedImageCount} failed images, and ${_.mathPlaceholderCount} formula placeho\
853
852
  lders. Resolve the unavailable resources before a retry: allow pending resources to finish loading, re-upload broken images, or correct unsupported formulas. Repeating this call without fixing them wi\
854
853
  ll not verify the document.`,"visual_resource_unavailable"),failure:{code:"visual_resource_unavailable",phase:"verification",retryable:!1,mutationOutcome:"unchanged"}};const P=_.pages.length===1?`page\
855
854
  ${_.pages[0]}`:`pages ${_.pages[0]}-${_.pages[_.pages.length-1]}`,E={id:`render_document_pages_${h.id}`,type:"image",content:"",preview:"",charCount:0,fileName:`Rendered document ${P} (${w}, ${g}, ${k}\
856
855
  )`,mimeType:_.dataUrl.startsWith("data:image/png")?"image/png":"image/jpeg",urls:[_.dataUrl],dimensions:[{width:_.width,height:_.height}],visionDetail:g==="compact"?"low":"high"};return H(h,`Rendered ${P}\
857
- of ${_.totalPages} in ${w} mode at ${g} quality, ${k} view.${k===Rt?"":` This is an isolated preview with ${_.snapshot?`all ${_.snapshot.pendingSuggestionCount}`:"all"} pending suggestions ${k==="sho\
856
+ of ${_.totalPages} in ${w} mode at ${g} quality, ${k} view.${k===Nt?"":` This is an isolated preview with ${_.snapshot?`all ${_.snapshot.pendingSuggestionCount}`:"all"} pending suggestions ${k==="sho\
858
857
  w-with-tracked-changes-accepted"?"accepted":"rejected"}; no suggestion was accepted or rejected in the document, and the page count is for this view.`}${_.snapshot?.description?` ${_.snapshot.description}`:
859
858
  ""}${S?" The request was downgraded from detailed to compact quality so all requested pages fit in one bounded render.":""}`,E,void 0,JSON.stringify({pages:_.pages,totalPages:_.totalPages,mode:w,quality:g,
860
859
  view:k,..._.snapshot?{snapshot:_.snapshot}:{},placeholderImageCount:_.placeholderImageCount,failedImageCount:_.failedImageCount,mathPlaceholderCount:_.mathPlaceholderCount}))}catch(_){return v(h,_ instanceof
@@ -870,31 +869,31 @@ h,`${$} requires a final user-facing response, not only a status update.`,$o);if
870
869
  as an array.`);let p;if(s.completed_plan_item_ids!=null||s.completed_plan_steps!=null){if(!e.getPlanState||!e.setPlanState)return v(h,"This host does not support task plans.","plan_unavailable");const w=s.
871
870
  completed_plan_item_ids??[];if(!Array.isArray(w)||w.some(k=>typeof k!="string"))return v(h,"completed_plan_item_ids must be an array of current-plan item IDs.","invalid_plan_update");const g=s.completed_plan_steps??
872
871
  [];if(!Array.isArray(g)||g.some(k=>typeof k!="string"||!k.trim()))return v(h,"completed_plan_steps must be an array of new non-empty requirements.","invalid_plan_update");if(w.length>0||g.length>0)try{
873
- const k=e.getPlanState(),S=jn(k,"update_plan",{plan_id:k.plan?.id,updates:w.map(R=>({item_id:R,status:"completed"})),add_steps:g});for(const R of S.plan.items.slice(k.plan.items.length))R.status="comp\
872
+ const k=e.getPlanState(),S=jn(k,"update_plan",{plan_id:k.plan?.id,updates:w.map(N=>({item_id:N,status:"completed"})),add_steps:g});for(const N of S.plan.items.slice(k.plan.items.length))N.status="comp\
874
873
  leted";p=()=>{e.getPlanState()===k&&(e.setPlanState(S),e.markConversationDirty())}}catch(k){return v(h,k instanceof Error?k.message:String(k),"invalid_plan_update")}}return{...H(h,"Final response reco\
875
874
  rded."),...p?{commitPlanCompletion:p}:{}}}const me=await L();if(!me)return O(h);const V=e.getLatestDocument();if($==="rollback_agent_suggestions"){const s=h.arguments??{},m=s.request_id==null?void 0:s.
876
875
  request_id,p=s.turn==null?void 0:s.turn;if(m!==void 0&&(!Number.isInteger(m)||Number(m)<1))return v(h,"request_id must be a positive integer.");if(p!==void 0&&(!Number.isInteger(p)||Number(p)<1))return v(
877
876
  h,"turn must be a positive integer.");if(p!==void 0&&m===void 0)return v(h,"turn requires request_id.");const w=e.turnState.currentRequestId??0,g=e.turnState.currentTurn??0;if(m!==void 0&&Number(m)>w)
878
877
  return v(h,`request_id ${m} is in the future; the current request is ${w}.`);const k=e.getConversationId?.().trim()??"";if(!k)return v(h,"This conversation has no stable ID, so its suggestions cannot \
879
- be rolled back safely.");const S=me.getDocumentWithPendingSuggestionsApplied(),R=me.rollbackAgentSuggestions({agentConversationId:k,requestId:m===void 0?void 0:Number(m),turn:p===void 0?void 0:Number(
880
- p),currentRequestId:w,currentTurn:g});if(R.resolvedCount===0){const E=R.requestId===void 0?"any prior request":`request ${R.requestId}${R.turn===void 0?"":` turn ${R.turn}`}`;return H(h,`No still-pend\
878
+ be rolled back safely.");const S=me.getDocumentWithPendingSuggestionsApplied(),N=me.rollbackAgentSuggestions({agentConversationId:k,requestId:m===void 0?void 0:Number(m),turn:p===void 0?void 0:Number(
879
+ p),currentRequestId:w,currentTurn:g});if(N.resolvedCount===0){const E=N.requestId===void 0?"any prior request":`request ${N.requestId}${N.turn===void 0?"":` turn ${N.turn}`}`;return H(h,`No still-pend\
881
880
  ing suggestions from this conversation matched ${E}. Accepted edits and other authors' work were left untouched. Recover omitted text from historical_edit_evidence or earlier before_block snapshots, t\
882
881
  hen propose a targeted correction against the current document while preserving later edits. Searching the current document cannot recover text that was deleted.`,void 0,!0)}const _=me.getDocumentWithPendingSuggestionsApplied(),
883
882
  x=new Map(S.children.map(E=>[E.id,E])),P=new Map(_.children.map(E=>[E.id,E]));for(const E of new Set([...x.keys(),...P.keys()]))JSON.stringify(x.get(E))!==JSON.stringify(P.get(E))&&e.toolState.editedBlockIds.
884
- add(E);return e.turnState.hasMutatedSinceLastRead=!0,f+=1,e.markConversationDirty(),e.notifyListeners(),H(h,`Rolled back ${R.resolvedCount} pending suggestion${R.resolvedCount===1?"":"s"} ${R.turn===void 0?
885
- `to before request ${R.requestId}`:`from request ${R.requestId} turn ${R.turn}`}. The rollback is one user-undoable history item. Now make the corrected edits; do not ask the user to reject the old su\
883
+ add(E);return e.turnState.hasMutatedSinceLastRead=!0,f+=1,e.markConversationDirty(),e.notifyListeners(),H(h,`Rolled back ${N.resolvedCount} pending suggestion${N.resolvedCount===1?"":"s"} ${N.turn===void 0?
884
+ `to before request ${N.requestId}`:`from request ${N.requestId} turn ${N.turn}`}. The rollback is one user-undoable history item. Now make the corrected edits; do not ask the user to reject the old su\
886
885
  ggestions.`)}if($==="leave_comment"){const s=Cs(h,e,me,V);return s.success&&(f+=1),s}if(($==="insert_block"||$==="insert_table_row"||$==="insert_table_column")&&h.arguments?.position!=="before"&&h.arguments?.
887
886
  position!=="after")return v(h,`${$} has invalid "position" ${JSON.stringify(h.arguments?.position??null)}; use "before" or "after".`);if($==="set_header_footer"&&h.arguments?.side!=="header"&&h.arguments?.
888
887
  side!=="footer")return v(h,`set_header_footer has invalid "side" ${JSON.stringify(h.arguments?.side??null)}; use "header" or "footer".`);const Oe=Ye(V,e.toolState.tableContext,Vt(e.turnState)??new Set);
889
- if($==="move_blocks"){const s=He(h.arguments),m=new Set([...V.children.map(g=>g.id),...e.getDocumentSession()?.getWorkingDocument().children.map(g=>g.id)??[]]),p=s.filter(g=>!m.has(g));if(p.length){const g=V.
890
- children.length<=30?V.children.filter(k=>Oe.has(k.id)).map(k=>({id:k.id,text:Le(k).slice(0,80)})):[];return v(h,`Move targets are not current top-level block IDs: ${p.map(k=>JSON.stringify(k)).join(",\
888
+ if($==="move_blocks"){const s=We(h.arguments),m=new Set([...V.children.map(g=>g.id),...e.getDocumentSession()?.getWorkingDocument().children.map(g=>g.id)??[]]),p=s.filter(g=>!m.has(g));if(p.length){const g=V.
889
+ children.length<=30?V.children.filter(k=>Oe.has(k.id)).map(k=>({id:k.id,text:Xe(k).slice(0,80)})):[];return v(h,`Move targets are not current top-level block IDs: ${p.map(k=>JSON.stringify(k)).join(",\
891
890
  ")}. Use current IDs from the document; read the relevant range if IDs are stale. This is an invalid target, not an unread-block error.${g.length?` Current already-read blocks in document order: ${JSON.
892
891
  stringify(g)}.`:""}`,"invalid_move_target")}const w=s.filter(g=>!$t(V,g,Oe));if(w.length)return v(h,`Move targets were not read in this request: ${w.slice(0,10).join(", ")}. Read the source range and \
893
- destination before moving.`,Be)}const ct=qi({toolCall:h,docBefore:V});if(ct?.error)return v(h,ct.error,"invalid_block_range");const xe=$i({toolCall:ct?.toolCall??h,docBefore:V,isTargetAllowed:s=>$t(V,
892
+ destination before moving.`,Be)}const ct=Di({toolCall:h,docBefore:V});if(ct?.error)return v(h,ct.error,"invalid_block_range");const xe=Ci({toolCall:ct?.toolCall??h,docBefore:V,isTargetAllowed:s=>$t(V,
894
893
  s,Oe)});if(xe?.error)return v(h,xe.error,xe.errorCode);const tn=xe?.toolCall??ct?.toolCall??h,nn=new Set(Oe??[]);for(const s of xe?.targetBlockIds??[])nn.add(s);const de=Xo({toolCall:tn,docBefore:V,resultSets:y});
895
894
  if(de?.error)return v(h,de.error,de.errorCode);const je=Vs(tn,V,nn);if(je.error)return v(h,je.error,Be);const B=je.toolCall;if(B.name==="replace"&&B.arguments&&Array.isArray(B.arguments.replacements)&&
896
895
  Object.prototype.hasOwnProperty.call(B.arguments,"comment"))return v(B,'replace comment belongs on each operation inside "replacements", alongside find, replace, and occurrence.');const Ho=new Set(V.children.
897
- map(s=>s.id)),Ke=new Set(Oe??[]);for(const s of xe?.targetBlockIds??[])Ke.add(s);for(const s of de?.targetBlockIds??[])Ke.add(s);const dt=Ci(B,V,s=>$t(V,s,Ke));if(dt.error)return v(B,dt.error,dt.error.
896
+ map(s=>s.id)),Ge=new Set(Oe??[]);for(const s of xe?.targetBlockIds??[])Ge.add(s);for(const s of de?.targetBlockIds??[])Ge.add(s);const dt=Ai(B,V,s=>$t(V,s,Ge));if(dt.error)return v(B,dt.error,dt.error.
898
897
  includes("request-level document context")?Be:void 0);const ce=(j=e.toolState).tableContext??(j.tableContext=Un()),on={responseTurn:e.turnState.currentTurn,hasForeignSuggestion:s=>{const m=me.getDocumentMutator(),
899
898
  p=re(me.getWorkingDocument(),s.id);return p?m.getLiveSuggestionIdsForBlock(p).some(w=>{const g=m.getLiveSuggestion(w),k=e.getConversationId?.();return!ce.ownedSuggestionIds?.includes(w)&&!(k&&g?.agentConversationId===
900
899
  k)}):!1}},Y=B.name==="edit_table_cells"?zn(V,ce,B.arguments,on):null,rn=s=>{const m=s.filter(g=>g.reason.includes("not delivered"));if(!m.length)return{};const p=m[0].column,w=[...new Set(m.filter(g=>g.
@@ -903,36 +902,36 @@ this failed cell batch; preserve the original task and exact requested values."}
903
902
  Compaction can retire older read windows. Preserve the original task and continue until its full scope is complete.",remaining_unread_target_count:m.length-w.length}};if(Y?.errors.length)return{...v(
904
903
  B,"No cells changed. Resolve every listed target error and retry the batch.",So),toolOutput:JSON.stringify({errors:Y.errors,...rn(Y.errors),skipped:Y.skipped,changed_count:0})};const Se=Y?{actions:Y.actions.
905
904
  map((s,m)=>({...s,id:`${B.id}-${m}`})),blockId:void 0,error:void 0}:de?{actions:de.actions,blockId:void 0,error:void 0}:B.name==="remove_block"&&Array.isArray(B.arguments?.ids)?{actions:dt.actions,blockId:void 0,
906
- error:void 0}:Qo(B,{doc:V,loadedBlockIds:Ke});if(Se.error){const s="failure"in Se?Se.failure:void 0;return{...v(B,Se.error,s?.code),failure:s}}if(Se.actions.length===0)return Y?H(B,"No cells changed; \
905
+ error:void 0}:Qo(B,{doc:V,loadedBlockIds:Ge});if(Se.error){const s="failure"in Se?Se.failure:void 0;return{...v(B,Se.error,s?.code),failure:s}}if(Se.actions.length===0)return Y?H(B,"No cells changed; \
907
906
  inspect skipped and unchanged targets before continuing.",void 0,!0,JSON.stringify({changed_count:0,skipped:Y.skipped,unchanged:Y.unchanged})):H(B,`${To(B)} Continue with the remaining work; do not re\
908
- peat this unchanged operation.`,void 0,!0);const Tt=Y?{actions:Se.actions,retargets:[]}:Zo({actions:Se.actions,doc:V,loadedBlockIds:Ke}),Pe=Tt.actions,he=Array.from(new Set([...de?.targetBlockIds??[],
907
+ peat this unchanged operation.`,void 0,!0);const Tt=Y?{actions:Se.actions,retargets:[]}:Zo({actions:Se.actions,doc:V,loadedBlockIds:Ge}),Pe=Tt.actions,he=Array.from(new Set([...de?.targetBlockIds??[],
909
908
  ...xe?.targetBlockIds??[],...Ms(Pe)])),sn=s=>{if(!e.toolState.tableContext?.scopedTableIds?.length||B.name==="edit_table_cells"||["style_blocks","clear_formatting"].includes(B.name))return;const m=e.toolState.
910
- tableContext.scopedTableIds;if(["insert_table_row","insert_table_column","remove_table_row","remove_table_column"].includes(B.name))return Kr(s,e.toolState.tableContext,B.name,B.arguments)?void 0:v(B,
909
+ tableContext.scopedTableIds;if(["insert_table_row","insert_table_column","remove_table_row","remove_table_column"].includes(B.name))return Vr(s,e.toolState.tableContext,B.name,B.arguments)?void 0:v(B,
911
910
  B.name==="remove_table_row"?As(s,B.arguments):"Table geometry changed or cells affected by this deletion were not fully read. Reread the table summary for insertions, or every affected row/column cell\
912
911
  for deletions.",Be);const p=Ye(s,e.toolState.tableContext,Vt(e.turnState)??new Set);for(const w of he){if(xe?.targetBlockIds.includes(w))continue;const g=re(s,w);if(m.some(k=>{const S=re(s,k);return S&&
913
- ue(S).includes(w)||g&&ue(g).includes(k)})&&!p.has(w)){let k=!1;g&&Ue(g,()=>k=!0);const S=g&&!k&&!["table-row","table-cell"].includes(g.type)?`Read it with read_specific_blocks(block_ids=["${w}"]), the\
912
+ ue(S).includes(w)||g&&ue(g).includes(k)})&&!p.has(w)){let k=!1;g&&Le(g,()=>k=!0);const S=g&&!k&&!["table-row","table-cell"].includes(g.type)?`Read it with read_specific_blocks(block_ids=["${w}"]), the\
914
913
  n retry`:"Use read_table for its cells";return v(B,`Target '${w}' was not fully read. ${S}; a table preview or cell_text page does not authorize edits.`,Be)}}if(!he.length&&!["set_title","set_notes","\
915
914
  set_page_layout","set_header_footer","insert_block"].includes(B.name))return v(B,"This broad operation includes partially read tables. Read their cells or target fully delivered block IDs explicitly.",
916
915
  Be)},an=sn(V);if(an)return an;const ln=["insert_table_row","remove_table_row","insert_table_column","remove_table_column"].includes(B.name),cn=new Map;if((B.name==="replace_block"||B.name==="move_bloc\
917
916
  ks"||B.name==="remove_block"||ln&&!e.toolState.tableContext?.scopedTableIds?.includes(String(B.arguments.tableId)))&&e.turnState.promptBlockContentHashes)for(const s of Do(V,he)){const m=re(V,s),p=m?new Set(
918
- ue(m)):new Set,w=he.filter(k=>p.has(k));if(w.length&&w.every(k=>(ce.scopedTableIds??[]).some(S=>{const R=re(V,S);return R&&ue(R).includes(k)})))continue;const g=e.turnState.promptBlockContentHashes.get(
917
+ ue(m)):new Set,w=he.filter(k=>p.has(k));if(w.length&&w.every(k=>(ce.scopedTableIds??[]).some(S=>{const N=re(V,S);return N&&ue(N).includes(k)})))continue;const g=e.turnState.promptBlockContentHashes.get(
919
918
  s);g&&cn.set(s,g)}const dn=s=>{for(const[m,p]of cn){const w=Pt(s,m);if(w!==null&&w!==p)return v(B,`Block '${m}' was edited (likely by the user) after you last read it. Re-read the block and re-apply y\
920
- our change against its current content.`,De)}},un=dn(V);if(un)return un;const mn=B.id||`tool-${Date.now()}`,Re=await(e.rehostImages??Pn)(Pe);if(Re.failedUrls.length>0){const s=Re.failedUrls.length===1?
921
- "1 external image":`${Re.failedUrls.length} external images`,m=Re.failures.some(g=>g.status===429),p=Re.failures.length===1?Re.failures[0]:void 0,w=p?` Reason: ${p.message}${p.status?` (HTTP ${p.status}\
919
+ our change against its current content.`,De)}},un=dn(V);if(un)return un;const mn=B.id||`tool-${Date.now()}`,Ne=await(e.rehostImages??Pn)(Pe);if(Ne.failedUrls.length>0){const s=Ne.failedUrls.length===1?
920
+ "1 external image":`${Ne.failedUrls.length} external images`,m=Ne.failures.some(g=>g.status===429),p=Ne.failures.length===1?Ne.failures[0]:void 0,w=p?` Reason: ${p.message}${p.status?` (HTTP ${p.status}\
922
921
  )`:""}.`:"";return v(B,`${s} could not be copied into Revise storage, so no document changes were applied.${w} ${m?"Do not attempt more external image insertions in this request. Keep any earlier succ\
923
- essful changes and tell the user which image remains incomplete.":"Do not retry this URL. Use a different verified direct raster image URL or upload the image before trying again."}`,Re.unavailable?"a\
922
+ essful changes and tell the user which image remains incomplete.":"Do not retry this URL. Use a different verified direct raster image URL or upload the image before trying again."}`,Ne.unavailable?"a\
924
923
  gent_tool_not_allowed":void 0)}const ye=e.getLatestDocument(),hn=sn(ye);if(hn)return hn;if(Y){const s=zn(ye,ce,B.arguments,on);if(s.errors.length||JSON.stringify(s.targets)!==JSON.stringify(Y.targets))
925
924
  return{...v(B,"Table targets changed while preparing this batch; no cells changed. Reread and retry.",So),toolOutput:JSON.stringify({errors:s.errors,...rn(s.errors),skipped:s.skipped,changed_count:0})}}
926
- const pn=dn(ye);if(pn)return pn;let G;const Ve=B.name==="remove_block"?[...new Set(Pe.map(s=>typeof s.arguments?.id=="string"?ht(V,s.arguments.id):null).filter(s=>s!==null))]:[];if(Ve.length>0&&Pe.some(
925
+ const pn=dn(ye);if(pn)return pn;let G;const Ke=B.name==="remove_block"?[...new Set(Pe.map(s=>typeof s.arguments?.id=="string"?ht(V,s.arguments.id):null).filter(s=>s!==null))]:[];if(Ke.length>0&&Pe.some(
927
926
  s=>s.arguments?.count!=null&&s.arguments.count!==1||typeof s.arguments?.id!="string"||!ht(V,s.arguments.id)))return v(B,"To remove footnotes/endnotes, pass their exact note IDs in ids, or one note ID \
928
927
  as id. Remove main-document blocks separately.");for(const s of Pe){if(s.name!=="replace_block")continue;const m=ye.notes?.find(p=>p.id===s.arguments?.id);if(m&&yn(ye,m.id)===m.id)return v(B,`Note '${m.
929
- id}' contains multiple body blocks or no single editable text block. Use replace_block with an exact body block ID (${m.children.map(p=>p.id).join(", ")}) instead of replacing the note wrapper.`)}if(Ve.
928
+ id}' contains multiple body blocks or no single editable text block. Use replace_block with an exact body block ID (${m.children.map(p=>p.id).join(", ")}) instead of replacing the note wrapper.`)}if(Ke.
930
929
  length>0){const s=me.getDocumentMutator(),m=new Set(s.getLiveSuggestionIds()),p=s.suggestingMode;s.suggestingMode=!0;let w=!1;try{const{result:k}=s.withSuggestionMetadata({source:"agent",authorType:"a\
931
- i",agentName:Je(e),...e.getAgentModel?{agentModel:e.getAgentModel()}:{},agentConversationId:e.getConversationId?.(),agentRequestId:e.turnState.currentRequestId,agentTurn:e.turnState.currentTurn,commentThreadId:e.
932
- commentThreadId,historyOrigin:`live-suggestions:${mn}`},()=>Ve.every(S=>s.removeFootnote(S)));w=k}finally{s.suggestingMode=p}const g=s.getLiveSuggestionIds().filter(k=>!m.has(k));G=w?{success:!0,suggestionIds:g,
933
- agentFeedback:`Removed footnote/endnote blocks ${Ve.join(", ")} and their inline references.`}:{success:!1,error:`Footnote/endnote blocks '${Ve.join(", ")}' could not be removed.`}}else G=me.applyAgentActions(
930
+ i",agentName:ze(e),...e.getAgentModel?{agentModel:e.getAgentModel()}:{},agentConversationId:e.getConversationId?.(),agentRequestId:e.turnState.currentRequestId,agentTurn:e.turnState.currentTurn,commentThreadId:e.
931
+ commentThreadId,historyOrigin:`live-suggestions:${mn}`},()=>Ke.every(S=>s.removeFootnote(S)));w=k}finally{s.suggestingMode=p}const g=s.getLiveSuggestionIds().filter(k=>!m.has(k));G=w?{success:!0,suggestionIds:g,
932
+ agentFeedback:`Removed footnote/endnote blocks ${Ke.join(", ")} and their inline references.`}:{success:!1,error:`Footnote/endnote blocks '${Ke.join(", ")}' could not be removed.`}}else G=me.applyAgentActions(
934
933
  {message:"AI Assistant",actions:Pe.map(s=>{if((s.name==="replace"||s.name==="replace_all"||s.name==="replace_block")&&typeof s.arguments?.id=="string"){const m=yn(ye,s.arguments.id);if(m&&m!==s.arguments.
935
- id)return{...s,arguments:{...s.arguments,id:m}}}return s}),agentName:Je(e),agentModel:e.getAgentModel?.(),agentConversationId:e.getConversationId?.(),agentRequestId:e.turnState.currentRequestId,agentTurn:e.
934
+ id)return{...s,arguments:{...s.arguments,id:m}}}return s}),agentName:ze(e),agentModel:e.getAgentModel?.(),agentConversationId:e.getConversationId?.(),agentRequestId:e.turnState.currentRequestId,agentTurn:e.
936
935
  turnState.currentTurn,commentThreadId:e.commentThreadId},mn,{optimizeStyleFormatting:e.getOptimizeStyleFormatting?.()??!1,applyBlockMovesDirectly:e.toolState.directMode,directMode:e.toolState.directMode});
937
936
  if(G.resultCode==="already_satisfied")return H(B,(G.styleEffects||$==="move_blocks")&&G.agentFeedback?G.agentFeedback:"Verified that the requested state is already satisfied; no document mutation occu\
938
937
  rred. "+To(B),void 0,!0,JSON.stringify({code:"already_satisfied",mutationOutcome:"unchanged",...$==="move_blocks"&&G.agentFeedback?{summary:G.agentFeedback}:{},...G.styleEffects?JSON.parse(Po(B,V,V,G.
@@ -952,18 +951,18 @@ mment was":"their comments were"} not added: no change remains there to explain.
952
951
  ${s}`:s}if(fe){const s=Ks(B,V);s&&(X=X?`${X}
953
952
  ${s}`:s)}if(e.toolState.directMode&&fe){const s=new Set(G.commentedSuggestionIds??[]),m=(G.suggestionIds??[]).filter(p=>!s.has(p));if(m.length>0&&me.acceptLiveSuggestions(m),m.length>0&&s.size===0){const p=me.
954
953
  getDocumentMutator();p?.resetToolCallHistory&&p.resetToolCallHistory()}}if(fe){e.mutationTools.includes($)&&(f+=1);const s=me.getDocumentWithPendingSuggestionsApplied();if($==="move_blocks"&&s.children.
955
- length<=30){const m=new Set(V.children.map(w=>w.id)),p=s.children.filter(w=>Oe.has(w.id)||!m.has(w.id)).map(w=>({id:w.id,text:Le(w).slice(0,80)}));X=`${X??"Move completed."} Current already-read block\
954
+ length<=30){const m=new Set(V.children.map(w=>w.id)),p=s.children.filter(w=>Oe.has(w.id)||!m.has(w.id)).map(w=>({id:w.id,text:Xe(w).slice(0,80)}));X=`${X??"Move completed."} Current already-read block\
956
955
  s in document order: ${JSON.stringify(p)}.`}if(ln&&typeof B.arguments.tableId=="string"){const m=Et(s,{table_id:B.arguments.tableId,mode:"summary"});m.error||(ce.geometries??(ce.geometries={}),ce.geometries[m.
957
956
  table_id]=m.revision)}if(!Y){const m=Ye(ye,ce,new Set);for(const p of Object.values(ce.cells))m.has(p.cellId)&&p.blockIds.some(w=>he.includes(w))&&_t(s,ce,p.tableId,[p.cellId]);for(const[p,w]of Object.
958
957
  entries(ce.blocks??{}))m.has(p)&&w.blockIds.some(g=>he.includes(g))&&Ln(s,ce,w.tableId,p)}if(de?.resultSet&&(de.resultSet.blockHashes=Dt(s,de.resultSet.blockIds)),ut=Y?void 0:Po(B,V,s,he,X,G.styleEffects),
959
958
  Y){const m=String(B.arguments.table_id);_t(s,ce,m,Y.targets.map(S=>S.cellId));const p=e.turnState.currentTurn??0;ce.responseClaims={turn:p,cellIds:[...ce.responseClaims?.turn===p?ce.responseClaims.cellIds:
960
- [],...Y.targets.map(S=>S.cellId)]},ce.ownedSuggestionIds=[...ce.ownedSuggestionIds??[],...G.suggestionIds??[]];const w=Ii(e.getTableTaskState?.()??e.toolState.tableTasks??Zn(),{requestId:e.turnState.currentRequestId??
961
- 0,tableId:m,cellIds:Y.targets.map(S=>S.cellId)});e.toolState.tableTasks=w,e.setTableTaskState?.(w);const g=[];let k=0;if(B.arguments.mode==="replace")for(const S of Y.targets){const R=re(ye,S.paragraphId),
962
- _=R?.type==="paragraph"?R.children.map(P=>P.type==="text"?P.text:"").join(""):null,x={row_id:S.row_id,column:S.column,previous_text:_??""};_===null||JSON.stringify([...g,x]).length>8e3?k++:g.push(x)}ut=
959
+ [],...Y.targets.map(S=>S.cellId)]},ce.ownedSuggestionIds=[...ce.ownedSuggestionIds??[],...G.suggestionIds??[]];const w=xi(e.getTableTaskState?.()??e.toolState.tableTasks??Zn(),{requestId:e.turnState.currentRequestId??
960
+ 0,tableId:m,cellIds:Y.targets.map(S=>S.cellId)});e.toolState.tableTasks=w,e.setTableTaskState?.(w);const g=[];let k=0;if(B.arguments.mode==="replace")for(const S of Y.targets){const N=re(ye,S.paragraphId),
961
+ _=N?.type==="paragraph"?N.children.map(P=>P.type==="text"?P.text:"").join(""):null,x={row_id:S.row_id,column:S.column,previous_text:_??""};_===null||JSON.stringify([...g,x]).length>8e3?k++:g.push(x)}ut=
963
962
  JSON.stringify({tool:"edit_table_cells",...B.arguments.mode==="replace"?{previous_cells:g,omitted_previous_cells:k,...k?{previous_values_recovery:"Some prior values were omitted from this bounded look\
964
963
  back. For pending edits use rollback_agent_suggestions for the relevant request/turn, then reread. Accepted edits require earlier historical edit evidence; do not reconstruct missing prior text from t\
965
964
  he current document."}:{}}:{},table_id:m,proposed_cell_count:Y.targets.length,changed_count:Y.targets.length,rows:[...new Set(Y.targets.map(S=>S.row_id))],skipped:Y.skipped,unchanged:Y.unchanged,remaining_empty_in_working_document:Et(
966
- s,{table_id:m,mode:"summary"}).columns.filter(S=>Y.targets.some(R=>R.column===S.column)),status:e.toolState.directMode?"applied":"proposed_pending_review"})}if(e.turnState.hasMutatedSinceLastRead=!0,e.
965
+ s,{table_id:m,mode:"summary"}).columns.filter(S=>Y.targets.some(N=>N.column===S.column)),status:e.toolState.directMode?"applied":"proposed_pending_review"})}if(e.turnState.hasMutatedSinceLastRead=!0,e.
967
966
  mutationTools.includes($)&&$!=="set_title"&&$!=="set_notes"&&$!=="set_page_layout"){if(!de)for(const m of he)e.toolState.editedBlockIds.add(m);if(!de)for(const m of s.children)m.id&&!Ho.has(m.id)&&e.toolState.
968
967
  editedBlockIds.add(m.id);if(e.turnState.promptBlockContentHashes){const m=Do(ye,he);for(const p of m){const w=e.turnState.promptBlockContentHashes.get(p);if(w&&Pt(ye,p)!==w||!w&&!he.includes(p))continue;
969
968
  const g=Pt(s,p);g!==null?e.turnState.promptBlockContentHashes.set(p,g):e.turnState.promptBlockContentHashes.delete(p)}}de||Qs(e)}}const gn=Ts(G.error);return{toolCall:B,success:fe,error:G.error,failure:G.
@@ -994,18 +993,18 @@ tes")?t:{...t,context_notes:sa}}const zo=new Set(["get_selection","view_image"])
994
993
  e),n=t.properties;return delete n?.document_id,Array.isArray(t.required)&&(t.required=t.required.filter(o=>o!=="document_id")),t}function da(e){return e.split(/(?<=\.)\s+/).filter(t=>!la.some(n=>t.includes(
995
994
  n))).join(" ")}const Ct=ta.filter(e=>!zo.has(e.name)).map(e=>({name:e.name,description:da(e.description),inputSchema:ca(e.inputSchema)})),Jo=new WeakSet;function ua(e){Jo.add(e)}function ma(e,t){if(!t.
996
995
  documentId.trim())throw new Error("Revise: documentId is required for a server session.");const n=new Ko(t.documentId,e,void 0,{disableHistory:!0,disableProposalPersistence:!0}),o=new Set(Bt);let r=t.
997
- mode??"suggesting";n.setSuggestingMode(r==="suggesting"),n.setDocxRoundTripRequired(Jo.has(e));const i=Er(t.images),a=new ia({getDocumentSession:()=>n,mutationTools:Array.from(Bt),searchPageSize:t.searchPageSize,
996
+ mode??"suggesting";n.setSuggestingMode(r==="suggesting"),n.setDocxRoundTripRequired(Jo.has(e));const i=Lr(t.images),a=new ia({getDocumentSession:()=>n,mutationTools:Array.from(Bt),searchPageSize:t.searchPageSize,
998
997
  getAgentName:()=>t.agentName,rehostImages:T=>Pn(T,i)});let l=1,c=!1,d=Promise.resolve();const u=()=>{if(c)throw new Error("Revise: server document session is disposed.")},f=(T,D,A,M)=>({ok:!1,error:{callId:T,
999
998
  tool:D,code:A,message:M}}),b=async(T,D,A,M)=>{u();const I=`server-tool-${l++}`;if(!Ct.some(q=>q.name===T)&&!aa.has(T))return f(I,T,"unknown_tool",`Unknown or unavailable server document tool: ${T}`);if("\
1000
999
  document_id"in D)return f(I,T,"document_id_not_supported","document_id is not accepted: a server document session is bound to one document. Omit it and retry.");await hr(),u(),n.setSuggestingMode(M===
1001
1000
  "suggesting");const C=o.has(T)?new Set(n.getDocumentMutator().getLiveSuggestionIds()):null;try{const q=await a.run({id:I,name:T,arguments:D},{directMode:A.directMode??M==="editing"}),J=a.buildResult(I,
1002
1001
  T,q);return oa(J,C?n.getDocumentMutator().getLiveSuggestionIds().filter(z=>!C.has(z)):null)}catch(q){return f(I,T,"internal_error",q instanceof Error?q.message:String(q))}finally{n.setSuggestingMode(r===
1003
- "suggesting")}},y=(T,D,A)=>{const M=r,I=d.then(()=>b(T,D,A,M));return d=I.then(()=>{},()=>{}),I},N={getDefinitions:()=>(u(),Ct.map(T=>({...T,inputSchema:structuredClone(T.inputSchema)}))),execute:(T,...D)=>{
1004
- const[A={},M={}]=D;return y(T,Fo(T,A,Ct),M)},executeDynamic:(T,D={},A={})=>y(T,D,A),call:async(T,...D)=>{const[A={},M={}]=D,I=await y(T,Fo(T,A,Ct),M);if(!I.ok)throw new wr(I.error);return I.value}},L=()=>{
1002
+ "suggesting")}},y=(T,D,A)=>{const M=r,I=d.then(()=>b(T,D,A,M));return d=I.then(()=>{},()=>{}),I},R={getDefinitions:()=>(u(),Ct.map(T=>({...T,inputSchema:structuredClone(T.inputSchema)}))),execute:(T,...D)=>{
1003
+ const[A={},M={}]=D;return y(T,Fo(T,A,Ct),M)},executeDynamic:(T,D={},A={})=>y(T,D,A),call:async(T,...D)=>{const[A={},M={}]=D,I=await y(T,Fo(T,A,Ct),M);if(!I.ok)throw new kr(I.error);return I.value}},L=()=>{
1005
1004
  u();const T=n.getDocumentMutator();return T.getLiveSuggestionIds().map(D=>{const A=T.getLiveSuggestion(D),M=T.getInlineSuggestionMetadataFromDocument(D),I=A&&"blockId"in A?A.blockId:A?.type==="paragra\
1006
1005
  ph-merge"?A.firstBlockId:void 0,C={id:D,...A?.type?{type:A.type}:{},...I?{blockId:I}:{},...A?.type==="table-change"?{tableId:A.tableId}:{}};for(const q of["authorType","agentName","agentModel","source",
1007
1006
  "label","createdAt"]){const J=M?.[q]??A?.[q];J!==void 0&&Object.assign(C,{[q]:J})}return C})},O=(T,D)=>{u();const A=Array.from(new Set(D.filter(z=>typeof z=="string"&&z.trim().length>0))),M=n.getDocumentMutator(),
1008
1007
  I=new Set(M.getLiveSuggestionIds()),C=A.filter(z=>!I.has(z)),q=A.filter(z=>I.has(z));q.length>0&&(T==="accept"?n.acceptLiveSuggestions(q):n.rejectLiveSuggestions(q));const J=new Set(M.getLiveSuggestionIds());
1009
- return{resolved:q.filter(z=>!J.has(z)),missing:C,unresolved:q.filter(z=>J.has(z))}};return{getMode:()=>(u(),r),setSuggestingMode:()=>{u(),r="suggesting"},setEditingMode:()=>{u(),r="editing"},tools:N,getPendingSuggestionIds:()=>(u(),
1008
+ return{resolved:q.filter(z=>!J.has(z)),missing:C,unresolved:q.filter(z=>J.has(z))}};return{getMode:()=>(u(),r),setSuggestingMode:()=>{u(),r="suggesting"},setEditingMode:()=>{u(),r="editing"},tools:R,getPendingSuggestionIds:()=>(u(),
1010
1009
  n.getDocumentMutator().getLiveSuggestionIds()),listSuggestions:L,acceptSuggestions:T=>O("accept",T),rejectSuggestions:T=>O("reject",T),acceptAllSuggestions:()=>(u(),O("accept",n.getDocumentMutator().getLiveSuggestionIds())),
1011
1010
  rejectAllSuggestions:()=>(u(),O("reject",n.getDocumentMutator().getLiveSuggestionIds())),dispose:()=>{c||(c=!0,n.dispose())}}}export{ma as createServerDocumentSession,ua as requireDocxRoundTrip};