@volter/supercode-terminal 0.2.62 → 0.2.63

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 (2) hide show
  1. package/index.mjs +15 -4
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1843,13 +1843,23 @@ function composerMatches(value, wanted) {
1843
1843
  return offsets.has(wanted.length);
1844
1844
  }
1845
1845
 
1846
+ /** Claude collapses a multi-line paste to `[Pasted text #N +K lines]`, and its composer then shows that placeholder,
1847
+ * never the text. It stands for `text` when K is the pasted text's line breaks (the trimmed text's, or the sent
1848
+ * payload's with its closing newline): a placeholder whose count differs is another paste. */
1849
+ function pastePlaceholderMatches(composer, text) {
1850
+ const placeholder=/^\[Pasted text #\d+ \+(\d+) lines?\]$/u.exec(String(composer??'').trim());
1851
+ if(!placeholder)return false;
1852
+ const breaks=value=>(value.match(/\n/gu)??[]).length;
1853
+ return [breaks(String(text).trim()),breaks(`${text}\n`)].includes(Number(placeholder[1]));
1854
+ }
1855
+
1846
1856
  /** Undo only text this input wrote, including when a turn started meanwhile.
1847
1857
  * Never Enter, Escape, or Ctrl-C: restoration must not submit or stop work. */
1848
1858
  export async function restoreComposerInput(host, sessionId, kind, text) {
1849
1859
  const read=async()=>composerText(kind,await host.capture(sessionId,{preserveEscapes:true}));
1850
1860
  let remaining=await read();
1851
1861
  if(remaining==='')return {restored:true};
1852
- if(!composerMatches(remaining,String(text).trim()))return {restored:false,reason:'composer-changed-or-unreadable'};
1862
+ if(!composerMatches(remaining,String(text).trim())&&!pastePlaceholderMatches(remaining,text))return {restored:false,reason:'composer-changed-or-unreadable'};
1853
1863
  const lines=remaining.split('\n').length+2;
1854
1864
  for(let line=0;line<lines;line++) {
1855
1865
  if(await read()!==remaining)return {restored:false,reason:'composer-changed',remaining};
@@ -1884,6 +1894,7 @@ export async function deliverComposerInput(host, sessionId, kind, text, { deadli
1884
1894
  };
1885
1895
  if(expired())return failed('deadline');
1886
1896
  const wanted=String(text).trim();
1897
+ const holds=composer=>composerMatches(composer,wanted)||pastePlaceholderMatches(composer,text);
1887
1898
  if(!wanted||/[\x00-\x08\x0b-\x1f\x7f]/u.test(text))return failed('unsupported-text');
1888
1899
  for(let check=0;check<2;check++) {
1889
1900
  const screen=await capture(),before=composerText(kind,screen);
@@ -1897,20 +1908,20 @@ export async function deliverComposerInput(host, sessionId, kind, text, { deadli
1897
1908
  let pasted=false;
1898
1909
  for(let attempt=0;attempt<10&&!expired();attempt++) {
1899
1910
  await sleep(100);
1900
- if(composerMatches(await read(),wanted)){pasted=true;break;}
1911
+ if(holds(await read())){pasted=true;break;}
1901
1912
  }
1902
1913
  if(!pasted)return failed('paste-unconfirmed');
1903
1914
  for(let attempt=0;attempt<3;attempt++) {
1904
1915
  if(expired())return failed('deadline');
1905
1916
  const screen=await capture();
1906
- if(!composerMatches(composerText(kind,screen),wanted))return failed('composer-changed');
1917
+ if(!holds(composerText(kind,screen)))return failed('composer-changed');
1907
1918
  if(expired())return failed('deadline');
1908
1919
  await host.sendInput(sessionId,'\r',{submitMode:'single',deadlineMs});
1909
1920
  for(let poll=0;poll<10&&!expired();poll++) {
1910
1921
  await sleep(100);
1911
1922
  const current=await read();
1912
1923
  if(current==='')return kind === 'claude-code' ? {delivered:true,delivery,path:'composer_submit'} : {delivered:false,reason:'native-transcript-confirmation-required',delivery};
1913
- if(!composerMatches(current,wanted))return failed('submission-unconfirmed');
1924
+ if(!holds(current))return failed('submission-unconfirmed');
1914
1925
  }
1915
1926
  }
1916
1927
  return failed('submit-unconfirmed');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-terminal",
3
- "version": "0.2.62",
3
+ "version": "0.2.63",
4
4
  "type": "module",
5
5
  "description": "Optional leak-safe terminal and tmux host adapter for Volter Harness frontends",
6
6
  "exports": {