@yuriai/web 0.1.3 → 0.1.5

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 (74) hide show
  1. package/dist/assets/{AgentAvatar-1UO8KpCd.js → AgentAvatar-D6H7fWWf.js} +1 -1
  2. package/dist/assets/{AssistantView-BJyGm9Js.js → AssistantView-D3j8FlaF.js} +3 -3
  3. package/dist/assets/{DiagramView-BRK8rzVX.js → DiagramView-TX1QZ1-S.js} +1 -1
  4. package/dist/assets/{FadeInOnReveal-BsRKluhI.js → FadeInOnReveal-eVZbrwte.js} +1 -1
  5. package/dist/assets/{Icon-jsQQXouE.js → Icon-2cKLcXGe.js} +1 -1
  6. package/dist/assets/{ImageLoadingPlaceholder-CGHGcrEo.js → ImageLoadingPlaceholder-DmCEIw55.js} +1 -1
  7. package/dist/assets/{LoadingImage-BG9q4Tm_.js → LoadingImage-B-cD_lfU.js} +1 -1
  8. package/dist/assets/{MarkdownRenderer-D4Ba9SUF.js → MarkdownRenderer-DGUI8EIG.js} +2 -2
  9. package/dist/assets/{MarkdownRendererImpl-Dt0t56Yx.js → MarkdownRendererImpl-DndseLUT.js} +1 -1
  10. package/dist/assets/{MarkstreamRendererImpl-rGcpWsHj.js → MarkstreamRendererImpl-Ehxwt6MS.js} +1 -1
  11. package/dist/assets/{MobileDetailNavigation-Cyp_3Hha.js → MobileDetailNavigation-D7uM40jU.js} +1 -1
  12. package/dist/assets/{MobileShareBridge-BQnwoSB3.js → MobileShareBridge-BMQKnoEb.js} +1 -1
  13. package/dist/assets/MobileTabPageHeader-Cco8ToA6.js +2 -0
  14. package/dist/assets/{MultiRunWindow-rggd5jvJ.js → MultiRunWindow-CVI6D2LM.js} +1 -1
  15. package/dist/assets/{OnboardingScreen-DTr_WxYY.js → OnboardingScreen-CG2xI_UT.js} +1 -1
  16. package/dist/assets/{OverlayScrollbar-C4VUlRzo.js → OverlayScrollbar-piA-chKb.js} +1 -1
  17. package/dist/assets/{SettingsView-DWeiBwOG.js → SettingsView-Bx-5WRtO.js} +11 -11
  18. package/dist/assets/{SettingsWindow-1csE2lF6.js → SettingsWindow-Cj6sYyvK.js} +1 -1
  19. package/dist/assets/{TerminalView-mF-mbAzo.js → TerminalView-DW4OxMaM.js} +1 -1
  20. package/dist/assets/{ToolOutputDialog-BvgdBVst.js → ToolOutputDialog-DxKGYhQ6.js} +1 -1
  21. package/dist/assets/{appThemeRegistry-CiQ61T5d.js → appThemeRegistry-DlEr4DLc.js} +1 -1
  22. package/dist/assets/{button-C3292Ee6.js → button-_ReBqWzC.js} +1 -1
  23. package/dist/assets/{capgoAdapter-DLi2tcmI.js → capgoAdapter-Onw1miMh.js} +1 -1
  24. package/dist/assets/{collapsible-B0yvtXQR.js → collapsible-BRKOX_ML.js} +1 -1
  25. package/dist/assets/{diagram-Ddq5F6R_.js → diagram-C9F3kAJt.js} +1 -1
  26. package/dist/assets/{dialog-DrgcVFLG.js → dialog-NsOVcGdh.js} +1 -1
  27. package/dist/assets/{dropdown-menu.styles-CeLR2UTs.js → dropdown-menu.styles-CjPDePJF.js} +1 -1
  28. package/dist/assets/{es-D0ZhEIQm.js → es-Cu6zoTXv.js} +1 -1
  29. package/dist/assets/{fileMentionTouchSelection-C9jpvVUn.js → fileMentionTouchSelection-B26MejYr.js} +1 -1
  30. package/dist/assets/{fr-Cx3Hkjq_.js → fr-DA4Apf6C.js} +1 -1
  31. package/dist/assets/{gitApi-nArpJO6q.js → gitApi-BXhXdWkh.js} +1 -1
  32. package/dist/assets/{input-DaOOTCQd.js → input-BI3Ya8O_.js} +1 -1
  33. package/dist/assets/{insertionBoundaries-BgHgsc1p.js → insertionBoundaries-BxSGE3B7.js} +1 -1
  34. package/dist/assets/{ja-BRvZxcKF.js → ja-DHQdrjZd.js} +1 -1
  35. package/dist/assets/{ko-HRfDZwXS.js → ko-DbAl47mv.js} +1 -1
  36. package/dist/assets/{main-R2wbcT-3.js → main-BdV8Awp-.js} +2 -2
  37. package/dist/assets/{main-D5JkjH8k.js → main-CGpFMQTy.js} +4 -4
  38. package/dist/assets/{markdownHeightCache-BwSTMSRn.js → markdownHeightCache-CHFSvA8u.js} +1 -1
  39. package/dist/assets/{mcpQueries-W-LFzCOw.js → mcpQueries-uZJFBhGj.js} +1 -1
  40. package/dist/assets/{miniChat-ChGISVuo.js → miniChat-B1aBBLiq.js} +2 -2
  41. package/dist/assets/{mobile-Dv3wbcd9.js → mobile-B8U8FARq.js} +2 -2
  42. package/dist/assets/{mobileBackNavigation-BnipJtFo.js → mobileBackNavigation-D2yUxPpG.js} +1 -1
  43. package/dist/assets/{multirun-DvSn-icg.js → multirun-DKsVtdZX.js} +1 -1
  44. package/dist/assets/native-config-Bpk4DOW1.js +1 -0
  45. package/dist/assets/{pl-CxLc1wGT.js → pl-CogXecG6.js} +1 -1
  46. package/dist/assets/{projectMeta-Cm0n6vtB.js → projectMeta-yox5XHhN.js} +1 -1
  47. package/dist/assets/{pt-BR-D4Lpwv4-.js → pt-BR-Ditt0LyE.js} +1 -1
  48. package/dist/assets/{renderElectronMiniChatApp-BjQyp-u8.js → renderElectronMiniChatApp-CdEZXhzq.js} +2 -2
  49. package/dist/assets/{renderMobileApp-BEkWDH7L.js → renderMobileApp-BoV5wjPF.js} +4 -4
  50. package/dist/assets/runtimeConfig-B8s9sTX_.js +2 -0
  51. package/dist/assets/{runtimeEndpointReset-BYn28E2A.js → runtimeEndpointReset-BswmG9Bb.js} +2 -2
  52. package/dist/assets/{scheduledTaskNavigation-C6UYwVbD.js → scheduledTaskNavigation-DUskP6qh.js} +1 -1
  53. package/dist/assets/{sessionChangeSummary-DXpoQiGE.js → sessionChangeSummary-BGbmGpQw.js} +1 -1
  54. package/dist/assets/{sessionLookup-BYycaYEQ.js → sessionLookup-CGJA6W7O.js} +1 -1
  55. package/dist/assets/{sortable-tabs-strip-BMrSDJob.js → sortable-tabs-strip-Benojjgi.js} +1 -1
  56. package/dist/assets/{speechSettingsQueries-Bv08BFlI.js → speechSettingsQueries-CjTT-adl.js} +1 -1
  57. package/dist/assets/{store-CZu30-QE.js → store-szlu5Wxv.js} +2 -2
  58. package/dist/assets/{textarea-BcA4uouw.js → textarea-C5vjnZcE.js} +1 -1
  59. package/dist/assets/{tooltip-DGUZtHif.js → tooltip-C73L9gDf.js} +1 -1
  60. package/dist/assets/{types-Q_utERET.js → types-Bu1xM0fS.js} +1 -1
  61. package/dist/assets/{uk-BdjdFLjV.js → uk-DFoTnIxi.js} +1 -1
  62. package/dist/assets/{useAppFontEffects-HYIeI-xf.js → useAppFontEffects-D6yauGdg.js} +5 -5
  63. package/dist/assets/{useDesktopWindowControlsLayout-Cc-2uuN5.js → useDesktopWindowControlsLayout-SKHaFoVu.js} +1 -1
  64. package/dist/assets/{useEffectiveDirectory-BBb97raM.js → useEffectiveDirectory-D6GwXhDS.js} +1 -1
  65. package/dist/assets/{useMobileNavigationStore-CEVJSNnR.js → useMobileNavigationStore-ByrZJd5L.js} +6 -6
  66. package/dist/assets/{useWorkerHighlightedLines-D8JkeSuf.js → useWorkerHighlightedLines-CwC34Jql.js} +1 -1
  67. package/dist/assets/{zh-CN-BIC0OlRu.js → zh-CN-Cw2OYvFl.js} +1 -1
  68. package/dist/assets/{zh-TW-Bavvf14t.js → zh-TW-CPuXOw_f.js} +1 -1
  69. package/dist/index.html +5 -4
  70. package/dist/mini-chat.html +5 -4
  71. package/dist/mobile.html +5 -4
  72. package/package.json +1 -1
  73. package/dist/assets/MobileTabPageHeader-CDFE4Ws4.js +0 -2
  74. package/dist/assets/runtimeConfig-D3moXtPz.js +0 -2
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{p as t}from"./runtime-auth-ef9W7A43.js";import{c as n,f as r,i}from"./runtime-switch-CAZiOV2G.js";import{u as a}from"./queryRuntime-DKGLQtb9.js";import{it as o}from"./vendor-base-ui-CdzJ6My_.js";import{St as s}from"./platform-7bX6qtBV.js";import{n as c}from"./vendor-react-BP2cRVqX.js";import{n as l}from"./vendor-reactuses-core-BpfIZ1tg.js";import{f as u}from"./button-C3292Ee6.js";var d=`yuri:close-embedded-session-chat`,f=`yuri:embedded-visibility`,p=`yuri:embedded-visibility-request`,m=e=>new URLSearchParams(e).get(`yuriPanel`)===`session-chat`,h=(e,t,n)=>JSON.stringify({sessionID:e,directory:t||``,readOnly:n===!0}),g=(e,t,n,r)=>{if(typeof window>`u`)return``;let i=new URL(window.location.pathname,window.location.origin);return i.searchParams.set(`yuriPanel`,`session-chat`),i.searchParams.set(`surface`,`desktop`),i.searchParams.set(`sessionId`,e),n?i.searchParams.set(`readOnly`,`1`):i.searchParams.delete(`readOnly`),t&&t.trim().length>0?i.searchParams.set(`directory`,t):i.searchParams.delete(`directory`),i.searchParams.set(`themeMode`,r.mode),i.searchParams.set(`lightThemeId`,r.lightThemeId),i.searchParams.set(`darkThemeId`,r.darkThemeId),i.searchParams.set(`themeVariant`,r.currentTheme.metadata.variant===`dark`?`dark`:`light`),i.searchParams.set(`currentTheme`,JSON.stringify(r.currentTheme)),i.hash=``,i.toString()},_=(e,t,n,r,i,a)=>{let o=h(n,r,i),s=e.get(t);if(s?.signature===o)return s.src;let c=g(n,r,i,a);return e.set(t,{signature:o,src:c}),c},v=null,y=()=>{if(v!==null)return v;if(typeof window>`u`)return v=!1,!1;try{return v=new URLSearchParams(window.location.search).get(`yuriPanel`)===`session-chat`,v}catch{return v=!1,!1}},b=()=>{if(!y())return null;try{let e=new URLSearchParams(window.location.search).get(`sessionId`);return e&&e.trim().length>0?e.trim():null}catch{return null}},x=e(o(),1);async function S(e,t){let n=i(),r=await a(`/api/voice/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({kind:e}),signal:AbortSignal.any([t,AbortSignal.timeout(2e4)])});if(t.throwIfAborted(),n!==i())throw Error(`Speech runtime changed`);if(r.status===404||r.ok&&r.headers.get(`content-type`)?.includes(`text/html`))return await r.body?.cancel(),null;if(!r.ok)throw await r.body?.cancel(),Error(`Unable to create speech session`);let o=await r.json();if(t.throwIfAborted(),n!==i())throw Error(`Speech runtime changed`);if(o?.transport===`host`)return null;if(o?.transport!==`volcengine-direct`||typeof o.token!=`string`||o.token.length>16384||!/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(o.token)||typeof o.appId!=`string`||!/^[A-Za-z0-9_-]{1,128}$/.test(o.appId)||typeof o.resourceId!=`string`||!/^[A-Za-z0-9._-]{1,128}$/.test(o.resourceId)||!Number.isFinite(o.expiresAt)||o.expiresAt<=Date.now()+5e3||o.expiresAt>Date.now()+36e4||e===`tts`&&(typeof o.voice!=`string`||!/^[A-Za-z0-9_-]{1,200}$/.test(o.voice)||!Number.isFinite(o.speed)||o.speed<.5||o.speed>2||!Number.isFinite(o.pitch)||o.pitch<.5||o.pitch>2||!Number.isFinite(o.volume)||o.volume<0||o.volume>1)||e===`asr`&&o.asrContext!==void 0&&(typeof o.asrContext!=`string`||o.asrContext.length>2e3||/\0/.test(o.asrContext)))throw Error(`Invalid speech session`);return o}function C(e,t){let n=new URL(t===`asr`?`wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async`:`wss://openspeech.bytedance.com/api/v3/tts/bidirection`);return n.search=new URLSearchParams({api_app_key:e.appId,api_access_key:`Jwt; ${e.token}`,api_resource_id:e.resourceId}).toString(),n.toString()}var w=new TextEncoder,T=new TextDecoder,E=1048576;function D(e,t=!1,n=!1){let r=new Uint8Array(8+e.length);return r.set([17,(t?2:1)<<4|(n?2:0),t?0:16,0]),new DataView(r.buffer).setUint32(4,e.length),r.set(e,8),r}function O(e,t=``,n={}){let r=w.encode(t),i=w.encode(JSON.stringify(n)),a=new Uint8Array(12+i.length+(t?4+r.length:0));a.set([17,20,16,0]);let o=new DataView(a.buffer);o.setInt32(4,e);let s=8;return t&&(o.setUint32(s,r.length),a.set(r,s+4),s+=4+r.length),o.setUint32(s,i.length),a.set(i,s+4),a}async function k(e,t){if(e.byteLength<8||e.byteLength>E)throw Error(`Invalid speech frame size`);let n=new Uint8Array(e),r=new DataView(e),i=n[1]>>4,a=n[1]&15,o=n[2]&15,s=(n[0]&15)*4;if(n[0]>>4!=1||s<4||s>n.length-4)throw Error(`Invalid speech frame`);let c=()=>{if(s+4>n.length)throw Error(`Truncated speech frame`);let e=r.getUint32(s);return s+=4,e};if(i===15)throw Error(`Speech provider failed (code ${c()})`);if(i!==9&&(t!==`tts`||i!==11))throw Error(`Unexpected speech frame`);a&1&&c();let l=0,u=``;if(a&4&&(l=c(),t===`tts`)){let e=c();if(e>256||s+e>n.length)throw Error(`Invalid speech session ID`);u=T.decode(n.subarray(s,s+e)),s+=e}let d=c();if(s+d!==n.length)throw Error(`Truncated speech payload`);let f=n.slice(s);if(o===1){let e=new Blob([f]).stream().pipeThrough(new DecompressionStream(`gzip`)).getReader(),t=[],n=0;try{for(;;){let r=await e.read();if(r.done)break;if(n+=r.value.length,n>E)throw Error(`Speech payload exceeds size limit`);t.push(r.value)}}finally{await e.cancel().catch(()=>void 0),e.releaseLock()}f=new Uint8Array(n);let r=0;for(let e of t)f.set(e,r),r+=e.length}else if(o!==0)throw Error(`Unsupported speech compression`);return{type:i,event:l,sessionId:u,final:!!(a&2),payload:f}}function A(e){let t=JSON.parse(T.decode(e));if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Invalid speech response`);return t}async function j(e,t){t.throwIfAborted();let n=new WebSocket(e);n.binaryType=`arraybuffer`;let r=[],i=0,a=null,o=null,s=null,c=(e=!0)=>{t.removeEventListener(`abort`,u),n.onmessage=null,n.onclose=null,n.onerror=null,n.onopen=null,e&&(r.length=0,i=0),n.close(),o?.()},l=(e,t=!0)=>{a??=e,s?.(a),c(t)},u=()=>l(new DOMException(`Speech cancelled`,`AbortError`));t.addEventListener(`abort`,u,{once:!0}),n.onmessage=e=>{if(!(e.data instanceof ArrayBuffer)||e.data.byteLength>E){l(Error(`Invalid speech message`));return}if(i+=e.data.byteLength,i>33554432||r.length>=4096){l(Error(`Speech receive buffer exceeded`));return}r.push(e.data),o?.()},n.onerror=()=>l(Error(`Speech connection failed`)),n.onclose=()=>l(Error(`Speech connection ended before completion`),!1);let d=setTimeout(()=>l(Error(`Speech connection timed out`)),1e4);try{await new Promise((e,t)=>{s=t,n.onopen=()=>e()})}finally{clearTimeout(d),s=null}return{send(e){if(t.throwIfAborted(),a)throw a;if(n.readyState!==WebSocket.OPEN||n.bufferedAmount+e.length>E)throw Error(`Speech send buffer exceeded`);n.send(e)},async read(){let e=setTimeout(()=>l(Error(`Speech response timed out`)),6e4);try{for(;!r.length&&!a;)await new Promise(e=>{o=e});if(t.throwIfAborted(),!r.length&&a)throw a;let e=r.shift();return i-=e.byteLength,e}finally{clearTimeout(e),o=null}},close(){a??=new DOMException(`Speech closed`,`AbortError`),c()}}}var M=class{abort;partial;disconnected;socket=null;failure=null;completion=null;text=``;final=!1;finishing=!1;sequence=0;constructor(e,t,n){this.abort=e,this.partial=t,this.disconnected=n}get connected(){return this.socket!==null&&!this.failure&&!this.abort.signal.aborted}async start(e,t){if(t!==`audio/pcm;rate=16000;bits=16`)throw Error(`Direct speech requires 16 kHz PCM16 audio`);let n=await j(C(e,`asr`),this.abort.signal);this.socket=n;try{n.send(D(new TextEncoder().encode(JSON.stringify({user:{uid:`yuri`},audio:{format:`pcm`,codec:`raw`,rate:16e3,bits:16,channel:1},request:{model_name:`bigmodel`,result_type:`full`,enable_itn:!0,enable_punc:!0,enable_nonstream:!0,show_utterances:!0,...e.asrContext?.trim()?{corpus:{context:JSON.stringify({context_type:`dialog_ctx`,context_data:[{text:e.asrContext.trim()}]})}}:{}}}))))}catch(e){throw n.close(),e}this.completion=this.receive().catch(e=>{this.failure=e instanceof Error?e:Error(`Speech recognition failed`),n.close(),!this.abort.signal.aborted&&!this.finishing&&this.disconnected()})}send(e,t){if(!this.connected||this.finishing||this.final||e!==this.sequence)return!1;try{if(t.length>128e3)throw Error(`Speech audio chunk exceeds size limit`);let e=atob(t);if(e.length%2)throw Error(`Invalid PCM audio`);let n=Uint8Array.from(e,e=>e.charCodeAt(0));return this.socket.send(D(n,!0)),this.sequence++,!0}catch{return this.failure=Error(`Unable to send speech audio`),this.socket?.close(),!1}}async finish(e){if(this.failure)throw this.failure;if(!this.socket||e!==this.sequence-1)throw Error(`Incomplete speech audio`);this.finishing=!0,this.socket.send(D(new Uint8Array,!0,!0));let t=setTimeout(()=>{this.failure=Error(`Speech finalization timed out`),this.socket?.close()},3e4);try{if(await this.completion,this.abort.signal.throwIfAborted(),this.failure)throw this.failure;if(!this.final)throw Error(`Incomplete speech recognition`);return{text:this.text}}finally{clearTimeout(t),this.socket.close()}}cancel(){this.abort.abort(),this.socket?.close()}async receive(){for(;;){let e=await k(await this.socket.read(),`asr`);this.abort.signal.throwIfAborted();let t=A(e.payload);if(t.code!==void 0&&![0,1e3,2e7].includes(Number(t.code)))throw Error(`Speech recognition failed`);let n=t.result;if(n!==void 0&&(!n||typeof n!=`object`||Array.isArray(n)))throw Error(`Invalid speech transcript`);if(n&&typeof n==`object`&&`text`in n){if(typeof n.text!=`string`)throw Error(`Invalid speech transcript`);this.text=n.text,e.final||this.partial(this.text)}if(e.final){if(!this.finishing)throw Error(`Speech recognition ended unexpectedly`);this.final=!0;return}}}},N=(e,t,n)=>{let r=Error(e);return r.name=`DictationStreamError`,r.retryable=t,n&&(r.reasonCode=n),r},P=1e4,F=15e3,I=3e4,L=3e4,R=new class{socket=null;connectPromise=null;idleCloseTimer=null;pendingStarts=new Map;pendingFinishes=new Map;connectionListeners=new Set;partialListeners=new Set;activeDictations=0;directStarts=new Map;directSessions=new Map;get isConnected(){if(this.socket?.readyState===WebSocket.OPEN)return!0;for(let e of this.directSessions.values())if(e.connected)return!0;return!1}subscribeConnectionStatus(e){return this.connectionListeners.add(e),()=>{this.connectionListeners.delete(e)}}onPartial(e){return this.partialListeners.add(e),()=>{this.partialListeners.delete(e)}}async ensureConnected(){if(this.socket?.readyState!==WebSocket.OPEN){if(this.connectPromise){await this.connectPromise;return}try{await t()}catch{}this.connectPromise=new Promise((e,t)=>{let n=!1,i;try{let e=r().websocket(`/api/dictation/ws`);i=s(e)}catch(e){this.connectPromise=null,t(e instanceof Error?e:Error(String(e)));return}let a=setTimeout(()=>{if(!n){n=!0,this.connectPromise=null;try{i.close()}catch{}t(Error(`Dictation connection timed out`))}},P);i.onopen=()=>{},i.onmessage=t=>{let r;try{r=JSON.parse(String(t.data))}catch{return}if(!n&&r.type===`ready`){n=!0,clearTimeout(a),this.socket=i,this.connectPromise=null,this.notifyConnection(!0),e();return}this.handleMessage(r)},i.onerror=()=>{window.setTimeout(()=>{n||(n=!0,clearTimeout(a),this.connectPromise=null,t(Error(`Dictation connection failed`)))},250)},i.onclose=e=>{if(!n){n=!0,clearTimeout(a),this.connectPromise=null;let r=e?.reason?`: ${e.reason}`:``;t(Error(`Dictation connection failed${r}`));return}this.socket===i&&(this.socket=null,this.rejectAllPending(Error(`Dictation connection lost`)),this.notifyConnection(!1))}}),await this.connectPromise}}async startDictationStream(e,t){let n=new AbortController;this.directStarts.set(e,n);try{let r=await S(`asr`,n.signal);if(n.signal.throwIfAborted(),r){let i=new M(n,t=>{for(let n of this.partialListeners)n(e,t)},()=>{this.directSessions.delete(e),i.cancel(),this.notifyConnection(!1)});this.directSessions.set(e,i),await i.start(r,t),n.signal.throwIfAborted(),this.notifyConnection(!0);return}await this.ensureConnected(),n.signal.throwIfAborted()}catch(t){throw this.directSessions.get(e)?.cancel(),this.directSessions.delete(e),t}finally{this.directStarts.delete(e)}return this.activeDictations+=1,this.clearIdleCloseTimer(),new Promise((n,r)=>{let i=setTimeout(()=>{this.pendingStarts.delete(e),this.releaseDictation(),r(Error(`Dictation start timed out`))},F);this.pendingStarts.set(e,{resolve:()=>{clearTimeout(i),n()},reject:e=>{clearTimeout(i),this.releaseDictation(),r(e)},timeout:i}),this.send({type:`start`,dictationId:e,format:t})||(clearTimeout(i),this.pendingStarts.delete(e),this.releaseDictation(),r(Error(`Dictation connection lost`)))})}sendDictationStreamChunk(e,t,n){let r=this.directSessions.get(e);return r?r.send(t,n):this.send({type:`chunk`,dictationId:e,seq:t,audio:n})}finishDictationStream(e,t){let n=this.directSessions.get(e);return n?n.finish(t).finally(()=>{n.cancel(),this.directSessions.delete(e)}):new Promise((n,r)=>{let i={resolve:e=>{i.timeout&&clearTimeout(i.timeout),this.releaseDictation(),n(e)},reject:e=>{i.timeout&&clearTimeout(i.timeout),this.releaseDictation(),r(e)},timeout:null};i.timeout=setTimeout(()=>{this.pendingFinishes.delete(e),this.releaseDictation(),r(Error(`Timed out waiting for transcription`))},L),this.pendingFinishes.set(e,i),this.send({type:`finish`,dictationId:e,finalSeq:t})||(this.pendingFinishes.delete(e),i.reject(Error(`Dictation connection lost`)))})}cancelDictationStream(e){this.directStarts.get(e)?.abort(),this.directStarts.delete(e);let t=this.directSessions.get(e);if(t){t.cancel(),this.directSessions.delete(e);return}this.send({type:`cancel`,dictationId:e});let n=this.pendingStarts.get(e);n&&(this.pendingStarts.delete(e),n.reject(Error(`Dictation cancelled`)));let r=this.pendingFinishes.get(e);r&&(this.pendingFinishes.delete(e),r.reject(Error(`Dictation cancelled`))),this.releaseDictation(),this.scheduleIdleCloseIfReady()}handleMessage(e){let t=e.dictationId;if(t)switch(e.type){case`ack`:{let e=this.pendingStarts.get(t);e&&(this.pendingStarts.delete(t),e.resolve());return}case`partial`:for(let n of this.partialListeners)n(t,e.text??``);return;case`finish_accepted`:{let n=this.pendingFinishes.get(t);n&&typeof e.timeoutMs==`number`&&(n.timeout&&clearTimeout(n.timeout),n.timeout=setTimeout(()=>{this.pendingFinishes.delete(t),n.reject(Error(`Timed out waiting for transcription`))},e.timeoutMs+5e3));return}case`final`:{let n=this.pendingFinishes.get(t);n&&(this.pendingFinishes.delete(t),n.resolve({text:e.text??``})),this.scheduleIdleCloseIfReady();return}case`error`:{let n=N(e.error||`Dictation failed`,e.retryable!==!1,e.reasonCode),r=this.pendingStarts.get(t);r&&(this.pendingStarts.delete(t),r.reject(n));let i=this.pendingFinishes.get(t);i&&(this.pendingFinishes.delete(t),i.reject(n)),this.scheduleIdleCloseIfReady();return}}}send(e){if(!this.isConnected||!this.socket)return!1;try{return this.socket.send(JSON.stringify(e)),!0}catch{return!1}}notifyConnection(e){for(let t of this.connectionListeners)t(e)}rejectAllPending(e){for(let[t,n]of this.pendingStarts)this.pendingStarts.delete(t),n.reject(e);for(let[t,n]of this.pendingFinishes)this.pendingFinishes.delete(t),n.reject(e);this.activeDictations=0}releaseDictation(){this.activeDictations=Math.max(0,this.activeDictations-1),this.scheduleIdleCloseIfReady()}scheduleIdleCloseIfReady(){this.activeDictations>0||this.pendingFinishes.size>0||this.pendingStarts.size>0||(this.clearIdleCloseTimer(),this.idleCloseTimer=setTimeout(()=>{if(this.activeDictations===0&&this.pendingFinishes.size===0&&this.pendingStarts.size===0){let e=this.socket;if(this.socket=null,e){try{e.close(1e3,`idle`)}catch{}this.notifyConnection(!1)}}},I))}cancelAllForRuntimeSwitch(){for(let e of this.directStarts.values())e.abort();this.directStarts.clear();for(let e of this.directSessions.values())e.cancel();this.directSessions.clear(),this.clearIdleCloseTimer();let e=this.socket;if(this.socket=null,this.connectPromise=null,this.rejectAllPending(Error(`Runtime changed`)),e){try{e.close(1e3,`runtime switch`)}catch{}this.notifyConnection(!1)}}clearIdleCloseTimer(){this.idleCloseTimer&&=(clearTimeout(this.idleCloseTimer),null)}};typeof window<`u`&&window.addEventListener(`yuri:runtime-endpoint-changed`,()=>{R.cancelAllForRuntimeSwitch()});var z=128,B=`audio/pcm;rate=16000;bits=16`,V=()=>new Promise(e=>setTimeout(e,0)),H=()=>{let e=Math.random().toString(36).slice(2,10);return`dic_${Date.now().toString(16)}${e}`},ee=class{client;format;createDictationId;dictationId=null;sendSeq=0;segments=[];streamReady=!1;flushTimer=null;drainWaiters=[];startGeneration=0;startPromise=null;constructor(e){this.client=e.client,this.format=e.format??B,this.createDictationId=e.createDictationId??H}getDictationId(){return this.dictationId}getFinalSeq(){return this.segments.length-1}hasSegments(){return this.segments.length>0}clearAll(){this.dictationId&&this.client.cancelDictationStream(this.dictationId),this.clearScheduledFlush(),this.dictationId=null,this.sendSeq=0,this.segments=[],this.streamReady=!1,this.startPromise=null,this.startGeneration+=1}resetStreamForReplay(){this.dictationId&&this.client.cancelDictationStream(this.dictationId),this.clearScheduledFlush(),this.dictationId=null,this.sendSeq=0,this.streamReady=!1,this.startPromise=null,this.startGeneration+=1}enqueueSegment(e){if(this.segments.push(e),this.client.isConnected){if(!this.dictationId){this.startPromise||this.restartStream().catch(()=>{});return}this.flush()}}flush(){let e=this.dictationId;if(!this.client.isConnected||!e||!this.streamReady)return 0;let t=0;for(;this.sendSeq<this.segments.length&&t<z;){let n=this.sendSeq,r=this.segments[n];if(!this.client.sendDictationStreamChunk(e,n,r))break;this.sendSeq=n+1,t+=1}return this.hasPendingSegments()?this.scheduleFlush():this.resolveDrainWaiters(),t}async restartStream(){this.startGeneration+=1;let e=this.startGeneration,t=this.createDictationId();this.dictationId=t,this.sendSeq=0,this.streamReady=!1;let n=(async()=>{await this.client.startDictationStream(t,this.format),this.startGeneration===e&&this.dictationId===t&&(this.streamReady=!0,this.flush())})().catch(n=>{throw this.startGeneration===e&&this.dictationId===t&&(this.dictationId=null,this.streamReady=!1),n}).finally(()=>{this.startPromise===n&&(this.startPromise=null)});this.startPromise=n,await n}async finish(e){this.dictationId||await this.restartStream(),this.startPromise&&await this.startPromise;let t=this.dictationId;if(!t||!this.streamReady)throw Error(`Failed to start dictation stream`);return this.flush(),await this.waitForFlushDrain(),{dictationId:t,text:(await this.client.finishDictationStream(t,e)).text}}cancel(){this.resetStreamForReplay()}hasPendingSegments(){return this.sendSeq<this.segments.length}scheduleFlush(){this.flushTimer||=setTimeout(()=>{this.flushTimer=null,this.flush()},0)}clearScheduledFlush(){this.resolveDrainWaiters(),this.flushTimer&&=(clearTimeout(this.flushTimer),null)}async waitForFlushDrain(){for(;this.hasPendingSegments();){if(!this.client.isConnected||!this.dictationId||!this.streamReady)throw Error(`Failed to flush dictation stream`);await new Promise(e=>{this.drainWaiters.push(e)}),await V()}}resolveDrainWaiters(){let e=this.drainWaiters;this.drainWaiters=[];for(let t of e)t()}},U=c(),W=new Set;function G(e){return W.add(e),()=>{W.delete(e)}}function K(){for(let e of W)e();if(typeof window<`u`&&window.speechSynthesis?.cancel(),typeof navigator>`u`)return;let e=navigator.audioSession;if(e)try{e.type=`play-and-record`}catch{}}function te(){if(typeof navigator>`u`)return;let e=navigator.audioSession;if(e)try{e.type!==`playback`&&(e.type=`playback`)}catch{}}var q=16e3,J=q/5,Y=()=>{if(typeof window>`u`)return null;let e=window;return e.AudioContext||e.webkitAudioContext||null},X=e=>{let t=Math.max(-1,Math.min(1,e));return Math.round(t<0?t*32768:t*32767)},ne=(e,t,n)=>{if(e.length===0)return new Int16Array;if(t===n){let t=new Int16Array(e.length);for(let n=0;n<e.length;n++)t[n]=X(e[n]);return t}let r=t/n,i=Math.max(1,Math.round(e.length/r)),a=new Int16Array(i);for(let t=0;t<i;t++){let n=t*r,i=Math.floor(n),o=Math.min(e.length-1,i+1),s=n-i;a[t]=X(e[i]*(1-s)+e[o]*s)}return a},re=(e,t)=>{if(e.length===0)return t;if(t.length===0)return e;let n=new Int16Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n},Z=e=>{let t=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),n=``;for(let e=0;e<t.length;e++)n+=String.fromCharCode(t[e]);return btoa(n)},Q=()=>({stream:null,context:null,source:null,processor:null,gain:null,pending:new Int16Array,started:!1}),$=e=>{if(e)try{e.disconnect()}catch{}},ie=()=>typeof navigator>`u`||typeof window>`u`||!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!=`function`?!1:Y()!==null;function ae(e){let t=(0,U.c)(16),[n,r]=(0,x.useState)(0),i=(0,x.useRef)(e.onPcmSegment),a=(0,x.useRef)(e.onError),o,s;t[0]!==e.onError||t[1]!==e.onPcmSegment?(o=()=>{i.current=e.onPcmSegment,a.current=e.onError},s=[e.onPcmSegment,e.onError],t[0]=e.onError,t[1]=e.onPcmSegment,t[2]=o,t[3]=s):(o=t[2],s=t[3]),(0,x.useEffect)(o,s);let c;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(c=Q(),t[4]=c):c=t[4];let u=(0,x.useRef)(c),d=(0,x.useRef)(0),f;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(f=async()=>{if(u.current.started)return;if(typeof navigator>`u`||!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!=`function`)throw Error(`Microphone capture is not supported in this environment`);let e=Y();if(!e)throw Error(`AudioContext unavailable`);let t=d.current+=1;K();let n=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,noiseSuppression:!0,echoCancellation:!0,autoGainControl:!0}});if(t!==d.current){n.getTracks().forEach(ue);return}let a=new e;try{if(a.state===`suspended`&&await a.resume().catch(le),t!==d.current){n.getTracks().forEach(ce),await a.close();return}let e=a.createMediaStreamSource(n),o=a.createScriptProcessor(4096,1,1),s=a.createGain();s.gain.value=0,u.current={stream:n,context:a,source:e,processor:o,gain:s,pending:new Int16Array,started:!0},o.onaudioprocess=e=>{let t=u.current;if(!t.started)return;let n=e.inputBuffer.getChannelData(0),o=0;for(let e=0;e<n.length;e++)o+=n[e]*n[e];let s=Math.sqrt(o/Math.max(1,n.length));r(Math.min(1,Math.max(0,s*2)));let c=ne(n,a.sampleRate,q);for(t.pending=re(t.pending,c);t.pending.length>=J;){let e=t.pending.slice(0,J);t.pending=t.pending.slice(J),i.current(Z(e))}},e.connect(o),o.connect(s),s.connect(a.destination)}catch(e){let t=e;n.getTracks().forEach(se);try{await a.close()}catch{}throw u.current=Q(),t instanceof Error?t:Error(String(t))}},t[5]=f):f=t[5];let p=l(f),m;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(m=async()=>{d.current+=1;let e=u.current;if(e.started=!1,r(0),e.processor)try{e.processor.onaudioprocess=null}catch{}$(e.processor),$(e.source),$(e.gain),e.stream&&e.stream.getTracks().forEach(oe);let t=e.pending;if(e.pending=new Int16Array,t.length>0&&i.current(Z(t)),e.context)try{await e.context.close()}catch{}u.current===e&&(u.current=Q())},t[6]=m):m=t[6];let h=l(m),g,_;t[7]===h?(g=t[8],_=t[9]):(g=()=>()=>{h().catch(e=>{a.current?.(e instanceof Error?e:Error(String(e)))})},_=[h],t[7]=h,t[8]=g,t[9]=_),(0,x.useEffect)(g,_);let v;t[10]===p?v=t[11]:(v=async()=>{try{await p()}catch(e){let t=e,n=t instanceof Error?t:Error(String(t));throw a.current?.(n),n}},t[10]=p,t[11]=v);let y;return t[12]!==h||t[13]!==v||t[14]!==n?(y={start:v,stop:h,volume:n},t[12]=h,t[13]=v,t[14]=n,t[15]=y):y=t[15],y}function oe(e){try{e.stop()}catch{}}function se(e){try{e.stop()}catch{}}function ce(e){return e.stop()}function le(){}function ue(e){return e.stop()}var de=1e3,fe=e=>e instanceof Error?e:Error(String(e));function pe(e={}){let{t}=u(),{onTranscript:r,onError:i,canStart:a}=e,[o,s]=(0,x.useState)(`idle`),[c,d]=(0,x.useState)(!1),[f,p]=(0,x.useState)(``),[m,h]=(0,x.useState)(0),[g,_]=(0,x.useState)(null),[v,y]=(0,x.useState)(null),b=(0,x.useRef)(o);(0,x.useEffect)(()=>{b.current=o},[o]);let S=(0,x.useRef)(``),C=(0,x.useRef)(null),w=(0,x.useRef)({starting:!1,confirming:!1,cancelling:!1}),T=(0,x.useRef)(0),E=(0,x.useRef)(r),D=(0,x.useRef)(i);(0,x.useEffect)(()=>{E.current=r,D.current=i},[r,i]);let O=(0,x.useRef)(null);O.current||=new ee({client:R});let k=l(()=>{C.current&&=(clearInterval(C.current),null)}),A=l(()=>{C.current||=setInterval(()=>{h(e=>e+1)},de)}),j=l(e=>{let n=fe(e),r=n.name===`NotFoundError`||n.name===`DevicesNotFoundError`?Error(t(`chat.dictation.error.microphoneNotFound`),{cause:n}):n;_(r.message);let i=n.reasonCode;y(typeof i==`string`?i:null),D.current?.(r)}),M=l(()=>{_(null),y(null)}),N=l(()=>{O.current?.clearAll(),S.current=``,p(``)}),P=l(t=>e.onPartialTranscript?.(t));(0,x.useEffect)(()=>R.onPartial((e,t)=>{let n=O.current?.getDictationId();!n||e!==n||(S.current=t,p(t),P(t))}),[P]),(0,x.useEffect)(()=>R.subscribeConnectionStatus(e=>{if(!e){b.current===`recording`&&O.current?.resetStreamForReplay();return}if(b.current!==`recording`||O.current?.getDictationId())return;let t=T.current;O.current?.restartStream().catch(e=>{T.current===t&&j(e)})}),[j]);let F=ae({onPcmSegment:e=>{b.current===`recording`&&O.current?.enqueueSegment(e)},onError:e=>{D.current?.(e)}}),I=(0,x.useRef)(F.stop);(0,x.useEffect)(()=>{I.current=F.stop},[F.stop]);let L=l(e=>{h(0),s(`idle`),b.current=`idle`;let t=e.trim();return N(),t?(E.current?.(t),t):null}),z=l(e=>{O.current?.hasSegments()?(s(`failed`),b.current=`failed`):(s(`idle`),b.current=`idle`),j(e)}),B=l(async()=>{let e=w.current;if(e.starting||e.confirming||e.cancelling||b.current!==`idle`||a&&!a())return;e.starting=!0,d(!0);let t=++T.current;M(),p(``),h(0),s(`recording`),b.current=`recording`,N();try{if(await F.start(),T.current!==t||b.current!==`recording`)return;d(!1),A(),await O.current?.restartStream().catch(e=>{T.current===t&&j(e)})}catch(e){if(T.current!==t)return;await F.stop().catch(()=>void 0),k(),s(`idle`),b.current=`idle`,j(e)}finally{T.current===t&&d(!1),e.starting=!1}}),V=l(async()=>{let e=w.current;if(!e.cancelling&&(b.current===`recording`||b.current===`uploading`)){e.cancelling=!0,d(!1),T.current+=1,k(),h(0),M(),s(`idle`),b.current=`idle`;try{O.current?.cancel()}catch{}N();try{await F.stop()}catch{}finally{e.cancelling=!1}}}),H=l(async()=>{let e=w.current;if(e.confirming||b.current!==`recording`)return null;e.confirming=!0,d(!1);let t=++T.current;M(),k();try{if(await F.stop(),T.current!==t)return null;s(`uploading`),b.current=`uploading`;let e=O.current?.getFinalSeq()??-1;if(e<0)return O.current?.cancel(),L(``);let n=await O.current.finish(e);return T.current===t?L(n.text):null}catch(e){return T.current===t&&z(e),null}finally{e.confirming=!1}}),U=l(async()=>{if(b.current!==`failed`||!O.current?.hasSegments())return null;M();let e=++T.current;s(`uploading`),b.current=`uploading`;try{O.current.resetStreamForReplay();let t=O.current.getFinalSeq(),n=await O.current.finish(t);return T.current===e?L(n.text):null}catch(t){return T.current===e&&z(t),null}}),W=l(()=>{if(b.current!==`failed`)return null;let e=S.current.trim();h(0),s(`idle`),b.current=`idle`,M();try{O.current?.cancel()}catch{}return N(),e?(E.current?.(e),e):null}),G=l(()=>{h(0),s(`idle`),b.current=`idle`,M(),N()});return(0,x.useEffect)(()=>n(()=>{b.current===`failed`?(T.current+=1,G()):V()}),[V,G]),(0,x.useEffect)(()=>{if(o!==`recording`||v!==`model_download_in_progress`)return;let e=setInterval(()=>{b.current!==`recording`||O.current?.getDictationId()||O.current?.restartStream().then(()=>{M()}).catch(e=>{j(e)})},3e3);return()=>clearInterval(e)},[o,v,M,j]),(0,x.useEffect)(()=>()=>{T.current+=1,k(),I.current().catch(()=>void 0),O.current?.cancel()},[k]),{status:o,isRecording:o===`recording`,isStarting:c,isProcessing:o===`uploading`,partialTranscript:f,volume:F.volume,duration:m,error:g,errorReason:v,startDictation:B,confirmDictation:H,cancelDictation:V,retryFailedDictation:U,acceptPartialTranscript:W,discardFailedDictation:G}}var me=`app-region-no-drag transition-[opacity,transform] duration-150 ease-out data-[starting-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:scale-95 z-50 max-h-[var(--available-height)] min-w-[8rem] origin-[var(--transform-origin)] overflow-visible rounded-xl p-1 shadow-[inset_0_1px_0_0_rgba(255,255,255,0.8),inset_0_0_0_1px_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.10),0_1px_2px_-0.5px_rgba(0,0,0,0.08),0_4px_8px_-2px_rgba(0,0,0,0.08),0_12px_20px_-4px_rgba(0,0,0,0.08)] dark:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.12),inset_0_0_0_1px_rgba(255,255,255,0.08),0_0_0_1px_rgba(0,0,0,0.36),0_1px_1px_-0.5px_rgba(0,0,0,0.22),0_3px_3px_-1.5px_rgba(0,0,0,0.20),0_6px_6px_-3px_rgba(0,0,0,0.16)]`,he=`data-[highlighted]:bg-interactive-hover hover:bg-interactive-hover active:bg-interactive-active data-[variant=destructive]:text-destructive data-[variant=destructive]:hover:bg-destructive/10 dark:data-[variant=destructive]:hover:bg-destructive/20 data-[variant=destructive]:hover:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5`,ge=`data-[highlighted]:bg-interactive-hover hover:bg-interactive-hover active:bg-interactive-active [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5`,_e=`bg-border -mx-1 my-0.5 h-px`;export{m as S,f as _,pe as a,_ as b,te as c,j as d,A as f,d as g,C as h,ge as i,G as l,S as m,me as n,ie as o,O as p,_e as r,K as s,he as t,k as u,p as v,y as x,b as y};
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{p as t}from"./runtime-auth-ef9W7A43.js";import{c as n,f as r,i}from"./runtime-switch-CAZiOV2G.js";import{u as a}from"./queryRuntime-DKGLQtb9.js";import{it as o}from"./vendor-base-ui-CdzJ6My_.js";import{St as s}from"./platform-7bX6qtBV.js";import{n as c}from"./vendor-react-BP2cRVqX.js";import{n as l}from"./vendor-reactuses-core-BpfIZ1tg.js";import{f as u}from"./button-_ReBqWzC.js";var d=`yuri:close-embedded-session-chat`,f=`yuri:embedded-visibility`,p=`yuri:embedded-visibility-request`,m=e=>new URLSearchParams(e).get(`yuriPanel`)===`session-chat`,h=(e,t,n)=>JSON.stringify({sessionID:e,directory:t||``,readOnly:n===!0}),g=(e,t,n,r)=>{if(typeof window>`u`)return``;let i=new URL(window.location.pathname,window.location.origin);return i.searchParams.set(`yuriPanel`,`session-chat`),i.searchParams.set(`surface`,`desktop`),i.searchParams.set(`sessionId`,e),n?i.searchParams.set(`readOnly`,`1`):i.searchParams.delete(`readOnly`),t&&t.trim().length>0?i.searchParams.set(`directory`,t):i.searchParams.delete(`directory`),i.searchParams.set(`themeMode`,r.mode),i.searchParams.set(`lightThemeId`,r.lightThemeId),i.searchParams.set(`darkThemeId`,r.darkThemeId),i.searchParams.set(`themeVariant`,r.currentTheme.metadata.variant===`dark`?`dark`:`light`),i.searchParams.set(`currentTheme`,JSON.stringify(r.currentTheme)),i.hash=``,i.toString()},_=(e,t,n,r,i,a)=>{let o=h(n,r,i),s=e.get(t);if(s?.signature===o)return s.src;let c=g(n,r,i,a);return e.set(t,{signature:o,src:c}),c},v=null,y=()=>{if(v!==null)return v;if(typeof window>`u`)return v=!1,!1;try{return v=new URLSearchParams(window.location.search).get(`yuriPanel`)===`session-chat`,v}catch{return v=!1,!1}},b=()=>{if(!y())return null;try{let e=new URLSearchParams(window.location.search).get(`sessionId`);return e&&e.trim().length>0?e.trim():null}catch{return null}},x=e(o(),1);async function S(e,t){let n=i(),r=await a(`/api/voice/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({kind:e}),signal:AbortSignal.any([t,AbortSignal.timeout(2e4)])});if(t.throwIfAborted(),n!==i())throw Error(`Speech runtime changed`);if(r.status===404||r.ok&&r.headers.get(`content-type`)?.includes(`text/html`))return await r.body?.cancel(),null;if(!r.ok)throw await r.body?.cancel(),Error(`Unable to create speech session`);let o=await r.json();if(t.throwIfAborted(),n!==i())throw Error(`Speech runtime changed`);if(o?.transport===`host`)return null;if(o?.transport!==`volcengine-direct`||typeof o.token!=`string`||o.token.length>16384||!/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(o.token)||typeof o.appId!=`string`||!/^[A-Za-z0-9_-]{1,128}$/.test(o.appId)||typeof o.resourceId!=`string`||!/^[A-Za-z0-9._-]{1,128}$/.test(o.resourceId)||!Number.isFinite(o.expiresAt)||o.expiresAt<=Date.now()+5e3||o.expiresAt>Date.now()+36e4||e===`tts`&&(typeof o.voice!=`string`||!/^[A-Za-z0-9_-]{1,200}$/.test(o.voice)||!Number.isFinite(o.speed)||o.speed<.5||o.speed>2||!Number.isFinite(o.pitch)||o.pitch<.5||o.pitch>2||!Number.isFinite(o.volume)||o.volume<0||o.volume>1)||e===`asr`&&o.asrContext!==void 0&&(typeof o.asrContext!=`string`||o.asrContext.length>2e3||/\0/.test(o.asrContext)))throw Error(`Invalid speech session`);return o}function C(e,t){let n=new URL(t===`asr`?`wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async`:`wss://openspeech.bytedance.com/api/v3/tts/bidirection`);return n.search=new URLSearchParams({api_app_key:e.appId,api_access_key:`Jwt; ${e.token}`,api_resource_id:e.resourceId}).toString(),n.toString()}var w=new TextEncoder,T=new TextDecoder,E=1048576;function D(e,t=!1,n=!1){let r=new Uint8Array(8+e.length);return r.set([17,(t?2:1)<<4|(n?2:0),t?0:16,0]),new DataView(r.buffer).setUint32(4,e.length),r.set(e,8),r}function O(e,t=``,n={}){let r=w.encode(t),i=w.encode(JSON.stringify(n)),a=new Uint8Array(12+i.length+(t?4+r.length:0));a.set([17,20,16,0]);let o=new DataView(a.buffer);o.setInt32(4,e);let s=8;return t&&(o.setUint32(s,r.length),a.set(r,s+4),s+=4+r.length),o.setUint32(s,i.length),a.set(i,s+4),a}async function k(e,t){if(e.byteLength<8||e.byteLength>E)throw Error(`Invalid speech frame size`);let n=new Uint8Array(e),r=new DataView(e),i=n[1]>>4,a=n[1]&15,o=n[2]&15,s=(n[0]&15)*4;if(n[0]>>4!=1||s<4||s>n.length-4)throw Error(`Invalid speech frame`);let c=()=>{if(s+4>n.length)throw Error(`Truncated speech frame`);let e=r.getUint32(s);return s+=4,e};if(i===15)throw Error(`Speech provider failed (code ${c()})`);if(i!==9&&(t!==`tts`||i!==11))throw Error(`Unexpected speech frame`);a&1&&c();let l=0,u=``;if(a&4&&(l=c(),t===`tts`)){let e=c();if(e>256||s+e>n.length)throw Error(`Invalid speech session ID`);u=T.decode(n.subarray(s,s+e)),s+=e}let d=c();if(s+d!==n.length)throw Error(`Truncated speech payload`);let f=n.slice(s);if(o===1){let e=new Blob([f]).stream().pipeThrough(new DecompressionStream(`gzip`)).getReader(),t=[],n=0;try{for(;;){let r=await e.read();if(r.done)break;if(n+=r.value.length,n>E)throw Error(`Speech payload exceeds size limit`);t.push(r.value)}}finally{await e.cancel().catch(()=>void 0),e.releaseLock()}f=new Uint8Array(n);let r=0;for(let e of t)f.set(e,r),r+=e.length}else if(o!==0)throw Error(`Unsupported speech compression`);return{type:i,event:l,sessionId:u,final:!!(a&2),payload:f}}function A(e){let t=JSON.parse(T.decode(e));if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Invalid speech response`);return t}async function j(e,t){t.throwIfAborted();let n=new WebSocket(e);n.binaryType=`arraybuffer`;let r=[],i=0,a=null,o=null,s=null,c=(e=!0)=>{t.removeEventListener(`abort`,u),n.onmessage=null,n.onclose=null,n.onerror=null,n.onopen=null,e&&(r.length=0,i=0),n.close(),o?.()},l=(e,t=!0)=>{a??=e,s?.(a),c(t)},u=()=>l(new DOMException(`Speech cancelled`,`AbortError`));t.addEventListener(`abort`,u,{once:!0}),n.onmessage=e=>{if(!(e.data instanceof ArrayBuffer)||e.data.byteLength>E){l(Error(`Invalid speech message`));return}if(i+=e.data.byteLength,i>33554432||r.length>=4096){l(Error(`Speech receive buffer exceeded`));return}r.push(e.data),o?.()},n.onerror=()=>l(Error(`Speech connection failed`)),n.onclose=()=>l(Error(`Speech connection ended before completion`),!1);let d=setTimeout(()=>l(Error(`Speech connection timed out`)),1e4);try{await new Promise((e,t)=>{s=t,n.onopen=()=>e()})}finally{clearTimeout(d),s=null}return{send(e){if(t.throwIfAborted(),a)throw a;if(n.readyState!==WebSocket.OPEN||n.bufferedAmount+e.length>E)throw Error(`Speech send buffer exceeded`);n.send(e)},async read(){let e=setTimeout(()=>l(Error(`Speech response timed out`)),6e4);try{for(;!r.length&&!a;)await new Promise(e=>{o=e});if(t.throwIfAborted(),!r.length&&a)throw a;let e=r.shift();return i-=e.byteLength,e}finally{clearTimeout(e),o=null}},close(){a??=new DOMException(`Speech closed`,`AbortError`),c()}}}var M=class{abort;partial;disconnected;socket=null;failure=null;completion=null;text=``;final=!1;finishing=!1;sequence=0;constructor(e,t,n){this.abort=e,this.partial=t,this.disconnected=n}get connected(){return this.socket!==null&&!this.failure&&!this.abort.signal.aborted}async start(e,t){if(t!==`audio/pcm;rate=16000;bits=16`)throw Error(`Direct speech requires 16 kHz PCM16 audio`);let n=await j(C(e,`asr`),this.abort.signal);this.socket=n;try{n.send(D(new TextEncoder().encode(JSON.stringify({user:{uid:`yuri`},audio:{format:`pcm`,codec:`raw`,rate:16e3,bits:16,channel:1},request:{model_name:`bigmodel`,result_type:`full`,enable_itn:!0,enable_punc:!0,enable_nonstream:!0,show_utterances:!0,...e.asrContext?.trim()?{corpus:{context:JSON.stringify({context_type:`dialog_ctx`,context_data:[{text:e.asrContext.trim()}]})}}:{}}}))))}catch(e){throw n.close(),e}this.completion=this.receive().catch(e=>{this.failure=e instanceof Error?e:Error(`Speech recognition failed`),n.close(),!this.abort.signal.aborted&&!this.finishing&&this.disconnected()})}send(e,t){if(!this.connected||this.finishing||this.final||e!==this.sequence)return!1;try{if(t.length>128e3)throw Error(`Speech audio chunk exceeds size limit`);let e=atob(t);if(e.length%2)throw Error(`Invalid PCM audio`);let n=Uint8Array.from(e,e=>e.charCodeAt(0));return this.socket.send(D(n,!0)),this.sequence++,!0}catch{return this.failure=Error(`Unable to send speech audio`),this.socket?.close(),!1}}async finish(e){if(this.failure)throw this.failure;if(!this.socket||e!==this.sequence-1)throw Error(`Incomplete speech audio`);this.finishing=!0,this.socket.send(D(new Uint8Array,!0,!0));let t=setTimeout(()=>{this.failure=Error(`Speech finalization timed out`),this.socket?.close()},3e4);try{if(await this.completion,this.abort.signal.throwIfAborted(),this.failure)throw this.failure;if(!this.final)throw Error(`Incomplete speech recognition`);return{text:this.text}}finally{clearTimeout(t),this.socket.close()}}cancel(){this.abort.abort(),this.socket?.close()}async receive(){for(;;){let e=await k(await this.socket.read(),`asr`);this.abort.signal.throwIfAborted();let t=A(e.payload);if(t.code!==void 0&&![0,1e3,2e7].includes(Number(t.code)))throw Error(`Speech recognition failed`);let n=t.result;if(n!==void 0&&(!n||typeof n!=`object`||Array.isArray(n)))throw Error(`Invalid speech transcript`);if(n&&typeof n==`object`&&`text`in n){if(typeof n.text!=`string`)throw Error(`Invalid speech transcript`);this.text=n.text,e.final||this.partial(this.text)}if(e.final){if(!this.finishing)throw Error(`Speech recognition ended unexpectedly`);this.final=!0;return}}}},N=(e,t,n)=>{let r=Error(e);return r.name=`DictationStreamError`,r.retryable=t,n&&(r.reasonCode=n),r},P=1e4,F=15e3,I=3e4,L=3e4,R=new class{socket=null;connectPromise=null;idleCloseTimer=null;pendingStarts=new Map;pendingFinishes=new Map;connectionListeners=new Set;partialListeners=new Set;activeDictations=0;directStarts=new Map;directSessions=new Map;get isConnected(){if(this.socket?.readyState===WebSocket.OPEN)return!0;for(let e of this.directSessions.values())if(e.connected)return!0;return!1}subscribeConnectionStatus(e){return this.connectionListeners.add(e),()=>{this.connectionListeners.delete(e)}}onPartial(e){return this.partialListeners.add(e),()=>{this.partialListeners.delete(e)}}async ensureConnected(){if(this.socket?.readyState!==WebSocket.OPEN){if(this.connectPromise){await this.connectPromise;return}try{await t()}catch{}this.connectPromise=new Promise((e,t)=>{let n=!1,i;try{let e=r().websocket(`/api/dictation/ws`);i=s(e)}catch(e){this.connectPromise=null,t(e instanceof Error?e:Error(String(e)));return}let a=setTimeout(()=>{if(!n){n=!0,this.connectPromise=null;try{i.close()}catch{}t(Error(`Dictation connection timed out`))}},P);i.onopen=()=>{},i.onmessage=t=>{let r;try{r=JSON.parse(String(t.data))}catch{return}if(!n&&r.type===`ready`){n=!0,clearTimeout(a),this.socket=i,this.connectPromise=null,this.notifyConnection(!0),e();return}this.handleMessage(r)},i.onerror=()=>{window.setTimeout(()=>{n||(n=!0,clearTimeout(a),this.connectPromise=null,t(Error(`Dictation connection failed`)))},250)},i.onclose=e=>{if(!n){n=!0,clearTimeout(a),this.connectPromise=null;let r=e?.reason?`: ${e.reason}`:``;t(Error(`Dictation connection failed${r}`));return}this.socket===i&&(this.socket=null,this.rejectAllPending(Error(`Dictation connection lost`)),this.notifyConnection(!1))}}),await this.connectPromise}}async startDictationStream(e,t){let n=new AbortController;this.directStarts.set(e,n);try{let r=await S(`asr`,n.signal);if(n.signal.throwIfAborted(),r){let i=new M(n,t=>{for(let n of this.partialListeners)n(e,t)},()=>{this.directSessions.delete(e),i.cancel(),this.notifyConnection(!1)});this.directSessions.set(e,i),await i.start(r,t),n.signal.throwIfAborted(),this.notifyConnection(!0);return}await this.ensureConnected(),n.signal.throwIfAborted()}catch(t){throw this.directSessions.get(e)?.cancel(),this.directSessions.delete(e),t}finally{this.directStarts.delete(e)}return this.activeDictations+=1,this.clearIdleCloseTimer(),new Promise((n,r)=>{let i=setTimeout(()=>{this.pendingStarts.delete(e),this.releaseDictation(),r(Error(`Dictation start timed out`))},F);this.pendingStarts.set(e,{resolve:()=>{clearTimeout(i),n()},reject:e=>{clearTimeout(i),this.releaseDictation(),r(e)},timeout:i}),this.send({type:`start`,dictationId:e,format:t})||(clearTimeout(i),this.pendingStarts.delete(e),this.releaseDictation(),r(Error(`Dictation connection lost`)))})}sendDictationStreamChunk(e,t,n){let r=this.directSessions.get(e);return r?r.send(t,n):this.send({type:`chunk`,dictationId:e,seq:t,audio:n})}finishDictationStream(e,t){let n=this.directSessions.get(e);return n?n.finish(t).finally(()=>{n.cancel(),this.directSessions.delete(e)}):new Promise((n,r)=>{let i={resolve:e=>{i.timeout&&clearTimeout(i.timeout),this.releaseDictation(),n(e)},reject:e=>{i.timeout&&clearTimeout(i.timeout),this.releaseDictation(),r(e)},timeout:null};i.timeout=setTimeout(()=>{this.pendingFinishes.delete(e),this.releaseDictation(),r(Error(`Timed out waiting for transcription`))},L),this.pendingFinishes.set(e,i),this.send({type:`finish`,dictationId:e,finalSeq:t})||(this.pendingFinishes.delete(e),i.reject(Error(`Dictation connection lost`)))})}cancelDictationStream(e){this.directStarts.get(e)?.abort(),this.directStarts.delete(e);let t=this.directSessions.get(e);if(t){t.cancel(),this.directSessions.delete(e);return}this.send({type:`cancel`,dictationId:e});let n=this.pendingStarts.get(e);n&&(this.pendingStarts.delete(e),n.reject(Error(`Dictation cancelled`)));let r=this.pendingFinishes.get(e);r&&(this.pendingFinishes.delete(e),r.reject(Error(`Dictation cancelled`))),this.releaseDictation(),this.scheduleIdleCloseIfReady()}handleMessage(e){let t=e.dictationId;if(t)switch(e.type){case`ack`:{let e=this.pendingStarts.get(t);e&&(this.pendingStarts.delete(t),e.resolve());return}case`partial`:for(let n of this.partialListeners)n(t,e.text??``);return;case`finish_accepted`:{let n=this.pendingFinishes.get(t);n&&typeof e.timeoutMs==`number`&&(n.timeout&&clearTimeout(n.timeout),n.timeout=setTimeout(()=>{this.pendingFinishes.delete(t),n.reject(Error(`Timed out waiting for transcription`))},e.timeoutMs+5e3));return}case`final`:{let n=this.pendingFinishes.get(t);n&&(this.pendingFinishes.delete(t),n.resolve({text:e.text??``})),this.scheduleIdleCloseIfReady();return}case`error`:{let n=N(e.error||`Dictation failed`,e.retryable!==!1,e.reasonCode),r=this.pendingStarts.get(t);r&&(this.pendingStarts.delete(t),r.reject(n));let i=this.pendingFinishes.get(t);i&&(this.pendingFinishes.delete(t),i.reject(n)),this.scheduleIdleCloseIfReady();return}}}send(e){if(!this.isConnected||!this.socket)return!1;try{return this.socket.send(JSON.stringify(e)),!0}catch{return!1}}notifyConnection(e){for(let t of this.connectionListeners)t(e)}rejectAllPending(e){for(let[t,n]of this.pendingStarts)this.pendingStarts.delete(t),n.reject(e);for(let[t,n]of this.pendingFinishes)this.pendingFinishes.delete(t),n.reject(e);this.activeDictations=0}releaseDictation(){this.activeDictations=Math.max(0,this.activeDictations-1),this.scheduleIdleCloseIfReady()}scheduleIdleCloseIfReady(){this.activeDictations>0||this.pendingFinishes.size>0||this.pendingStarts.size>0||(this.clearIdleCloseTimer(),this.idleCloseTimer=setTimeout(()=>{if(this.activeDictations===0&&this.pendingFinishes.size===0&&this.pendingStarts.size===0){let e=this.socket;if(this.socket=null,e){try{e.close(1e3,`idle`)}catch{}this.notifyConnection(!1)}}},I))}cancelAllForRuntimeSwitch(){for(let e of this.directStarts.values())e.abort();this.directStarts.clear();for(let e of this.directSessions.values())e.cancel();this.directSessions.clear(),this.clearIdleCloseTimer();let e=this.socket;if(this.socket=null,this.connectPromise=null,this.rejectAllPending(Error(`Runtime changed`)),e){try{e.close(1e3,`runtime switch`)}catch{}this.notifyConnection(!1)}}clearIdleCloseTimer(){this.idleCloseTimer&&=(clearTimeout(this.idleCloseTimer),null)}};typeof window<`u`&&window.addEventListener(`yuri:runtime-endpoint-changed`,()=>{R.cancelAllForRuntimeSwitch()});var z=128,B=`audio/pcm;rate=16000;bits=16`,V=()=>new Promise(e=>setTimeout(e,0)),H=()=>{let e=Math.random().toString(36).slice(2,10);return`dic_${Date.now().toString(16)}${e}`},ee=class{client;format;createDictationId;dictationId=null;sendSeq=0;segments=[];streamReady=!1;flushTimer=null;drainWaiters=[];startGeneration=0;startPromise=null;constructor(e){this.client=e.client,this.format=e.format??B,this.createDictationId=e.createDictationId??H}getDictationId(){return this.dictationId}getFinalSeq(){return this.segments.length-1}hasSegments(){return this.segments.length>0}clearAll(){this.dictationId&&this.client.cancelDictationStream(this.dictationId),this.clearScheduledFlush(),this.dictationId=null,this.sendSeq=0,this.segments=[],this.streamReady=!1,this.startPromise=null,this.startGeneration+=1}resetStreamForReplay(){this.dictationId&&this.client.cancelDictationStream(this.dictationId),this.clearScheduledFlush(),this.dictationId=null,this.sendSeq=0,this.streamReady=!1,this.startPromise=null,this.startGeneration+=1}enqueueSegment(e){if(this.segments.push(e),this.client.isConnected){if(!this.dictationId){this.startPromise||this.restartStream().catch(()=>{});return}this.flush()}}flush(){let e=this.dictationId;if(!this.client.isConnected||!e||!this.streamReady)return 0;let t=0;for(;this.sendSeq<this.segments.length&&t<z;){let n=this.sendSeq,r=this.segments[n];if(!this.client.sendDictationStreamChunk(e,n,r))break;this.sendSeq=n+1,t+=1}return this.hasPendingSegments()?this.scheduleFlush():this.resolveDrainWaiters(),t}async restartStream(){this.startGeneration+=1;let e=this.startGeneration,t=this.createDictationId();this.dictationId=t,this.sendSeq=0,this.streamReady=!1;let n=(async()=>{await this.client.startDictationStream(t,this.format),this.startGeneration===e&&this.dictationId===t&&(this.streamReady=!0,this.flush())})().catch(n=>{throw this.startGeneration===e&&this.dictationId===t&&(this.dictationId=null,this.streamReady=!1),n}).finally(()=>{this.startPromise===n&&(this.startPromise=null)});this.startPromise=n,await n}async finish(e){this.dictationId||await this.restartStream(),this.startPromise&&await this.startPromise;let t=this.dictationId;if(!t||!this.streamReady)throw Error(`Failed to start dictation stream`);return this.flush(),await this.waitForFlushDrain(),{dictationId:t,text:(await this.client.finishDictationStream(t,e)).text}}cancel(){this.resetStreamForReplay()}hasPendingSegments(){return this.sendSeq<this.segments.length}scheduleFlush(){this.flushTimer||=setTimeout(()=>{this.flushTimer=null,this.flush()},0)}clearScheduledFlush(){this.resolveDrainWaiters(),this.flushTimer&&=(clearTimeout(this.flushTimer),null)}async waitForFlushDrain(){for(;this.hasPendingSegments();){if(!this.client.isConnected||!this.dictationId||!this.streamReady)throw Error(`Failed to flush dictation stream`);await new Promise(e=>{this.drainWaiters.push(e)}),await V()}}resolveDrainWaiters(){let e=this.drainWaiters;this.drainWaiters=[];for(let t of e)t()}},U=c(),W=new Set;function G(e){return W.add(e),()=>{W.delete(e)}}function K(){for(let e of W)e();if(typeof window<`u`&&window.speechSynthesis?.cancel(),typeof navigator>`u`)return;let e=navigator.audioSession;if(e)try{e.type=`play-and-record`}catch{}}function te(){if(typeof navigator>`u`)return;let e=navigator.audioSession;if(e)try{e.type!==`playback`&&(e.type=`playback`)}catch{}}var q=16e3,J=q/5,Y=()=>{if(typeof window>`u`)return null;let e=window;return e.AudioContext||e.webkitAudioContext||null},X=e=>{let t=Math.max(-1,Math.min(1,e));return Math.round(t<0?t*32768:t*32767)},ne=(e,t,n)=>{if(e.length===0)return new Int16Array;if(t===n){let t=new Int16Array(e.length);for(let n=0;n<e.length;n++)t[n]=X(e[n]);return t}let r=t/n,i=Math.max(1,Math.round(e.length/r)),a=new Int16Array(i);for(let t=0;t<i;t++){let n=t*r,i=Math.floor(n),o=Math.min(e.length-1,i+1),s=n-i;a[t]=X(e[i]*(1-s)+e[o]*s)}return a},re=(e,t)=>{if(e.length===0)return t;if(t.length===0)return e;let n=new Int16Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n},Z=e=>{let t=new Uint8Array(e.buffer,e.byteOffset,e.byteLength),n=``;for(let e=0;e<t.length;e++)n+=String.fromCharCode(t[e]);return btoa(n)},Q=()=>({stream:null,context:null,source:null,processor:null,gain:null,pending:new Int16Array,started:!1}),$=e=>{if(e)try{e.disconnect()}catch{}},ie=()=>typeof navigator>`u`||typeof window>`u`||!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!=`function`?!1:Y()!==null;function ae(e){let t=(0,U.c)(16),[n,r]=(0,x.useState)(0),i=(0,x.useRef)(e.onPcmSegment),a=(0,x.useRef)(e.onError),o,s;t[0]!==e.onError||t[1]!==e.onPcmSegment?(o=()=>{i.current=e.onPcmSegment,a.current=e.onError},s=[e.onPcmSegment,e.onError],t[0]=e.onError,t[1]=e.onPcmSegment,t[2]=o,t[3]=s):(o=t[2],s=t[3]),(0,x.useEffect)(o,s);let c;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(c=Q(),t[4]=c):c=t[4];let u=(0,x.useRef)(c),d=(0,x.useRef)(0),f;t[5]===Symbol.for(`react.memo_cache_sentinel`)?(f=async()=>{if(u.current.started)return;if(typeof navigator>`u`||!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!=`function`)throw Error(`Microphone capture is not supported in this environment`);let e=Y();if(!e)throw Error(`AudioContext unavailable`);let t=d.current+=1;K();let n=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,noiseSuppression:!0,echoCancellation:!0,autoGainControl:!0}});if(t!==d.current){n.getTracks().forEach(ue);return}let a=new e;try{if(a.state===`suspended`&&await a.resume().catch(le),t!==d.current){n.getTracks().forEach(ce),await a.close();return}let e=a.createMediaStreamSource(n),o=a.createScriptProcessor(4096,1,1),s=a.createGain();s.gain.value=0,u.current={stream:n,context:a,source:e,processor:o,gain:s,pending:new Int16Array,started:!0},o.onaudioprocess=e=>{let t=u.current;if(!t.started)return;let n=e.inputBuffer.getChannelData(0),o=0;for(let e=0;e<n.length;e++)o+=n[e]*n[e];let s=Math.sqrt(o/Math.max(1,n.length));r(Math.min(1,Math.max(0,s*2)));let c=ne(n,a.sampleRate,q);for(t.pending=re(t.pending,c);t.pending.length>=J;){let e=t.pending.slice(0,J);t.pending=t.pending.slice(J),i.current(Z(e))}},e.connect(o),o.connect(s),s.connect(a.destination)}catch(e){let t=e;n.getTracks().forEach(se);try{await a.close()}catch{}throw u.current=Q(),t instanceof Error?t:Error(String(t))}},t[5]=f):f=t[5];let p=l(f),m;t[6]===Symbol.for(`react.memo_cache_sentinel`)?(m=async()=>{d.current+=1;let e=u.current;if(e.started=!1,r(0),e.processor)try{e.processor.onaudioprocess=null}catch{}$(e.processor),$(e.source),$(e.gain),e.stream&&e.stream.getTracks().forEach(oe);let t=e.pending;if(e.pending=new Int16Array,t.length>0&&i.current(Z(t)),e.context)try{await e.context.close()}catch{}u.current===e&&(u.current=Q())},t[6]=m):m=t[6];let h=l(m),g,_;t[7]===h?(g=t[8],_=t[9]):(g=()=>()=>{h().catch(e=>{a.current?.(e instanceof Error?e:Error(String(e)))})},_=[h],t[7]=h,t[8]=g,t[9]=_),(0,x.useEffect)(g,_);let v;t[10]===p?v=t[11]:(v=async()=>{try{await p()}catch(e){let t=e,n=t instanceof Error?t:Error(String(t));throw a.current?.(n),n}},t[10]=p,t[11]=v);let y;return t[12]!==h||t[13]!==v||t[14]!==n?(y={start:v,stop:h,volume:n},t[12]=h,t[13]=v,t[14]=n,t[15]=y):y=t[15],y}function oe(e){try{e.stop()}catch{}}function se(e){try{e.stop()}catch{}}function ce(e){return e.stop()}function le(){}function ue(e){return e.stop()}var de=1e3,fe=e=>e instanceof Error?e:Error(String(e));function pe(e={}){let{t}=u(),{onTranscript:r,onError:i,canStart:a}=e,[o,s]=(0,x.useState)(`idle`),[c,d]=(0,x.useState)(!1),[f,p]=(0,x.useState)(``),[m,h]=(0,x.useState)(0),[g,_]=(0,x.useState)(null),[v,y]=(0,x.useState)(null),b=(0,x.useRef)(o);(0,x.useEffect)(()=>{b.current=o},[o]);let S=(0,x.useRef)(``),C=(0,x.useRef)(null),w=(0,x.useRef)({starting:!1,confirming:!1,cancelling:!1}),T=(0,x.useRef)(0),E=(0,x.useRef)(r),D=(0,x.useRef)(i);(0,x.useEffect)(()=>{E.current=r,D.current=i},[r,i]);let O=(0,x.useRef)(null);O.current||=new ee({client:R});let k=l(()=>{C.current&&=(clearInterval(C.current),null)}),A=l(()=>{C.current||=setInterval(()=>{h(e=>e+1)},de)}),j=l(e=>{let n=fe(e),r=n.name===`NotFoundError`||n.name===`DevicesNotFoundError`?Error(t(`chat.dictation.error.microphoneNotFound`),{cause:n}):n;_(r.message);let i=n.reasonCode;y(typeof i==`string`?i:null),D.current?.(r)}),M=l(()=>{_(null),y(null)}),N=l(()=>{O.current?.clearAll(),S.current=``,p(``)}),P=l(t=>e.onPartialTranscript?.(t));(0,x.useEffect)(()=>R.onPartial((e,t)=>{let n=O.current?.getDictationId();!n||e!==n||(S.current=t,p(t),P(t))}),[P]),(0,x.useEffect)(()=>R.subscribeConnectionStatus(e=>{if(!e){b.current===`recording`&&O.current?.resetStreamForReplay();return}if(b.current!==`recording`||O.current?.getDictationId())return;let t=T.current;O.current?.restartStream().catch(e=>{T.current===t&&j(e)})}),[j]);let F=ae({onPcmSegment:e=>{b.current===`recording`&&O.current?.enqueueSegment(e)},onError:e=>{D.current?.(e)}}),I=(0,x.useRef)(F.stop);(0,x.useEffect)(()=>{I.current=F.stop},[F.stop]);let L=l(e=>{h(0),s(`idle`),b.current=`idle`;let t=e.trim();return N(),t?(E.current?.(t),t):null}),z=l(e=>{O.current?.hasSegments()?(s(`failed`),b.current=`failed`):(s(`idle`),b.current=`idle`),j(e)}),B=l(async()=>{let e=w.current;if(e.starting||e.confirming||e.cancelling||b.current!==`idle`||a&&!a())return;e.starting=!0,d(!0);let t=++T.current;M(),p(``),h(0),s(`recording`),b.current=`recording`,N();try{if(await F.start(),T.current!==t||b.current!==`recording`)return;d(!1),A(),await O.current?.restartStream().catch(e=>{T.current===t&&j(e)})}catch(e){if(T.current!==t)return;await F.stop().catch(()=>void 0),k(),s(`idle`),b.current=`idle`,j(e)}finally{T.current===t&&d(!1),e.starting=!1}}),V=l(async()=>{let e=w.current;if(!e.cancelling&&(b.current===`recording`||b.current===`uploading`)){e.cancelling=!0,d(!1),T.current+=1,k(),h(0),M(),s(`idle`),b.current=`idle`;try{O.current?.cancel()}catch{}N();try{await F.stop()}catch{}finally{e.cancelling=!1}}}),H=l(async()=>{let e=w.current;if(e.confirming||b.current!==`recording`)return null;e.confirming=!0,d(!1);let t=++T.current;M(),k();try{if(await F.stop(),T.current!==t)return null;s(`uploading`),b.current=`uploading`;let e=O.current?.getFinalSeq()??-1;if(e<0)return O.current?.cancel(),L(``);let n=await O.current.finish(e);return T.current===t?L(n.text):null}catch(e){return T.current===t&&z(e),null}finally{e.confirming=!1}}),U=l(async()=>{if(b.current!==`failed`||!O.current?.hasSegments())return null;M();let e=++T.current;s(`uploading`),b.current=`uploading`;try{O.current.resetStreamForReplay();let t=O.current.getFinalSeq(),n=await O.current.finish(t);return T.current===e?L(n.text):null}catch(t){return T.current===e&&z(t),null}}),W=l(()=>{if(b.current!==`failed`)return null;let e=S.current.trim();h(0),s(`idle`),b.current=`idle`,M();try{O.current?.cancel()}catch{}return N(),e?(E.current?.(e),e):null}),G=l(()=>{h(0),s(`idle`),b.current=`idle`,M(),N()});return(0,x.useEffect)(()=>n(()=>{b.current===`failed`?(T.current+=1,G()):V()}),[V,G]),(0,x.useEffect)(()=>{if(o!==`recording`||v!==`model_download_in_progress`)return;let e=setInterval(()=>{b.current!==`recording`||O.current?.getDictationId()||O.current?.restartStream().then(()=>{M()}).catch(e=>{j(e)})},3e3);return()=>clearInterval(e)},[o,v,M,j]),(0,x.useEffect)(()=>()=>{T.current+=1,k(),I.current().catch(()=>void 0),O.current?.cancel()},[k]),{status:o,isRecording:o===`recording`,isStarting:c,isProcessing:o===`uploading`,partialTranscript:f,volume:F.volume,duration:m,error:g,errorReason:v,startDictation:B,confirmDictation:H,cancelDictation:V,retryFailedDictation:U,acceptPartialTranscript:W,discardFailedDictation:G}}var me=`app-region-no-drag transition-[opacity,transform] duration-150 ease-out data-[starting-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:scale-95 z-50 max-h-[var(--available-height)] min-w-[8rem] origin-[var(--transform-origin)] overflow-visible rounded-xl p-1 shadow-[inset_0_1px_0_0_rgba(255,255,255,0.8),inset_0_0_0_1px_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.10),0_1px_2px_-0.5px_rgba(0,0,0,0.08),0_4px_8px_-2px_rgba(0,0,0,0.08),0_12px_20px_-4px_rgba(0,0,0,0.08)] dark:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.12),inset_0_0_0_1px_rgba(255,255,255,0.08),0_0_0_1px_rgba(0,0,0,0.36),0_1px_1px_-0.5px_rgba(0,0,0,0.22),0_3px_3px_-1.5px_rgba(0,0,0,0.20),0_6px_6px_-3px_rgba(0,0,0,0.16)]`,he=`data-[highlighted]:bg-interactive-hover hover:bg-interactive-hover active:bg-interactive-active data-[variant=destructive]:text-destructive data-[variant=destructive]:hover:bg-destructive/10 dark:data-[variant=destructive]:hover:bg-destructive/20 data-[variant=destructive]:hover:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5`,ge=`data-[highlighted]:bg-interactive-hover hover:bg-interactive-hover active:bg-interactive-active [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 typography-ui-label outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5`,_e=`bg-border -mx-1 my-0.5 h-px`;export{m as S,f as _,pe as a,_ as b,te as c,j as d,A as f,d as g,C as h,ge as i,G as l,S as m,me as n,ie as o,O as p,_e as r,K as s,he as t,k as u,p as v,y as x,b as y};
@@ -1,4 +1,4 @@
1
- var e={"sessions.order.saveFailed":`No se pudo guardar el orden de las conversaciones. Inténtalo de nuevo.`,"commandPalette.index.progress":`Indexando los últimos 30 días de todos los proyectos: {completed}/{total} conversaciones`,"commandPalette.index.ready":`Todos los proyectos · últimos 30 días · {count} mensajes indexados`,"commandPalette.index.partial":`No se pudo indexar parte del historial. Se muestran los resultados disponibles y se reintenta automáticamente.`,"mobile.notifications.service":`Servicio de notificaciones de tareas en segundo plano`,"mobile.notifications.connected":`Se mantiene la conexión para recibir notificaciones de tareas mientras la aplicación está en segundo plano.`,"mobile.notifications.unavailable":`No se pudieron iniciar las notificaciones en segundo plano. Vuelve a abrir la aplicación e inténtalo de nuevo.`,"mobile.notifications.auth":`Se denegó el acceso a las notificaciones. Vuelve a conectar o emparejar este servidor.`,"mobile.notifications.endpoint":`No se encuentra el punto de acceso a notificaciones. Actualiza y reinicia Yuri en el ordenador; si ya está actualizado, revisa la ruta del proxy.`,"mobile.notifications.response":`El servidor no devolvió un flujo de notificaciones válido. Comprueba la versión de la aplicación del ordenador y la configuración del proxy.`,"mobile.notifications.server":`El servidor no está disponible temporalmente o está ocupado. Se reintentará automáticamente.`,"mobile.notifications.relay":`La conexión de retransmisión no está disponible. Comprueba que Yuri esté conectado en tu ordenador; se reintentará automáticamente.`,"mobile.notifications.identity":`La identidad del servidor no coincide con el dispositivo emparejado. Vuelve a conectar o emparejar.`,"mobile.notifications.gap":`Es posible que se hayan perdido notificaciones durante la desconexión. Abre la aplicación para consultar los resultados de las tareas.`,"chat.chatInput.stopUnconfirmed":`La detención aún no está confirmada. Inténtalo de nuevo.`,"chat.response.rateLimit":`Se alcanzó el límite de solicitudes del proveedor`,"chat.response.auth":`Falló la autenticación del proveedor. Inicia sesión de nuevo y reintenta.`,"chat.response.quota":`Cuota del proveedor agotada`,"chat.response.contentFilter":`El proveedor bloqueó la respuesta`,"chat.response.transport":`Falló la conexión con el proveedor`,"chat.response.internal":`Error interno del proveedor`,"chat.response.invalidOutput":`Respuesta no válida del proveedor`,"chat.response.invalidRequest":`El proveedor rechazó la solicitud`,"chat.response.unsupportedOperation":`El proveedor no admite esta operación`,"chat.response.noRoute":`Modelo o configuración del proveedor no disponible`,"chat.response.providerUnknown":`Error del proveedor`,"chat.response.timeout":`La solicitud al proveedor agotó el tiempo de espera`,"chat.response.permissionRejected":`Permiso denegado`,"chat.response.toolExecution":`Falló la ejecución de la herramienta`,"chat.response.compactionFailed":`Falló la compactación del contexto`,"chat.response.compactionUnavailable":`Todavía no hay contenido para compactar`,"chat.response.compactionInterrupted":`Compactación del contexto interrumpida`,"chat.response.compactionCancelled":`Compactación del contexto cancelada`,"chat.response.stopped":`Detenido por el usuario`,"chat.response.interrupted":`Respuesta interrumpida`,"chat.response.toolInterrupted":`Ejecución de la herramienta interrumpida`,"chat.response.resumeExhausted":`Recuperación automática detenida tras interrupciones repetidas`,"chat.response.retrying":`Reintentando automáticamente`,"chat.response.failed":`La ejecución falló`,"chat.response.continuingAfterRestart":`Continuando después del reinicio`,"chat.queuedMessage.inheritsSessionSelection":`Hereda el modelo, el agente y la variante de la sesión al ejecutarse.`,"chat.sessionRecovery.awaitingConfirmation":`Servicio reiniciado. Esperando confirmar el estado de la tarea.`,"chat.btw.title":`BTW`,"chat.btw.failed":`Error al generar la respuesta. Vuelve a intentarlo.`,"chat.btw.description":`Pregunta sobre la conversación manteniendo su historial intacto.`,"chat.btw.placeholder":`Pregunta en BTW…`,"chat.btw.removeQuoteAria":`Quitar cita`,"chat.message.conversationQuotesLabel":`Citado de la conversación`,"chat.btw.sessionRequired":`Abre una conversación existente para iniciar BTW.`,"chat.btw.plainTextRequired":`Usa texto sin formato. Tus referencias se conservan en el editor.`,"chat.btw.pending":`Preparando la respuesta…`,"chat.btw.cancelled":`Respuesta cancelada. Vuelve a intentarlo para preguntar de nuevo.`,"chat.btw.resize":`Cambiar el tamaño del panel de BTW`,"settings.voice.volcengine.save":`Guardar`,"settings.voice.volcengine.saveFailed":`No se pudo guardar. Tus cambios se conservan; vuelve a intentarlo.`,"settings.voice.volcengine.loadFailed":`No se pudieron cargar los ajustes de voz de este servidor.`,"settings.voice.volcengine.retry":`Reintentar`,"chat.dictation.error.microphoneNotFound":`No se detectó un micrófono. Conecta uno e inténtalo de nuevo.`,"settings.voice.volcengine.name":`Volcengine (Doubao)`,"settings.voice.volcengine.providerOption":`Volcengine Doubao (Recomendado | De pago)`,"settings.voice.volcengine.keyHelp":`Obtener aquí:`,"settings.voice.volcengine.openLink":`Haz clic para abrir`,"settings.voice.volcengine.asrResource":`ID de recurso ASR en tiempo real`,"settings.voice.volcengine.asrContext":`Contexto de reconocimiento`,"settings.voice.volcengine.asrContextHelp":`Describe el tema y la terminología. Vacía para desactivar; guarda para la próxima grabación. Hasta 2.000 caracteres.`,"settings.voice.volcengine.custom":`ID personalizado`,"settings.voice.volcengine.durationHelp":`Plan por horas, facturado por duración del reconocimiento.`,"settings.voice.volcengine.concurrentHelp":`Plan de concurrencia, utiliza la capacidad adquirida.`,"settings.voice.volcengine.resource":`ID de recurso TTS`,"settings.voice.volcengine.speaker":`ID de voz TTS`,"settings.voice.volcengine.asrTest":`Prueba de micrófono`,"settings.voice.volcengine.testHelp":`Graba con los ajustes actuales y consulta la transcripción en directo.`,"settings.voice.volcengine.startRecording":`Iniciar grabación`,"settings.voice.volcengine.finishRecording":`Detener y transcribir`,"settings.voice.volcengine.recordingUnsupported":`No se puede grabar aquí. Usa HTTPS o la aplicación móvil.`,"settings.voice.volcengine.fileLimit":`WAV, MP3 u OGG, hasta 20 MB. Prueba el reconocimiento de archivos, no los subtítulos en vivo.`,"settings.voice.volcengine.invalidTranscript":`Respuesta de transcripción no válida`,"settings.voice.volcengine.silence":`No se detectó voz`,"settings.voice.volcengine.stop":`Detener`,"settings.voice.volcengine.setup":`Abrir la consola de voz`,"settings.remoteInstances.pairing.advanced":`Ajustes avanzados`,"settings.remoteInstances.pairing.relayHint":`Configura el servidor de retransmisión para Internet. No se utiliza en conexiones locales directas.`,"settings.remoteInstances.pairing.downloadStep":`Instalar app`,"settings.remoteInstances.pairing.name":`Nombre del servidor`,"settings.remoteInstances.pairing.anywhere":`En casa o fuera`,"settings.remoteInstances.pairing.lan":`En la misma red Wi-Fi`,"settings.remoteInstances.pairing.local":`En este ordenador`,"settings.remoteInstances.quick.sshTitle":`Trabaja con los proyectos de otro ordenador`,"settings.remoteInstances.quick.sshHint":`Añade una dirección SSH para ejecutar Yuri en otro ordenador y abrir sus proyectos aquí. Prepara los datos de acceso SSH de ese ordenador.`,"settings.remoteInstances.quick.emptyHint":`Conecta tu teléfono u otro ordenador para continuar trabajando desde cualquier lugar.`,"settings.remoteInstances.quick.title":`Dispositivos conectados`,"settings.remoteInstances.quick.error":`No se pudo actualizar el estado de los dispositivos.`,"settings.remoteInstances.quick.download":`Descargar la aplicación Yuri`,"settings.usage.magpie.url":`URL adicional de Magpie`,"settings.usage.magpie.description":`Magpie se detecta automáticamente en este servidor. Inicia Magpie y actualiza el uso. No requiere configuración.`,"settings.usage.magpie.connected":`Conectado · proveedores: {count}`,"settings.usage.magpie.manual":`Conectar otro Magpie…`,"settings.usage.magpie.unavailable":`Magpie no está disponible temporalmente. Actualiza para reintentar.`,"settings.usage.magpie.cached":`Lectura en caché; esperando datos de cuota recientes`,"settings.usage.magpie.save":`Guardar`,"settings.remoteInstances.clientAuth.edit.title":`Editar dispositivo`,"settings.remoteInstances.clientAuth.edit.action":`Editar`,"settings.remoteInstances.clientAuth.edit.name":`Nombre del dispositivo`,"settings.yuri.about.opencodeGuidance.manualGlobal":`Actualiza el CLI de OpenCode configurado con su gestor de paquetes y reinicia el servicio.`,"settings.yuri.about.opencodeGuidance.manualExternal":`Solicita al responsable del servicio externo de OpenCode que lo actualice y reinicie.`,"settings.yuri.about.opencodeGuidance.bundled":`Actualiza Yuri Desktop para actualizar su OpenCode integrado.`,"settings.permissions.saved.retry":`Reintentar`,"settings.chat.questionDelegate.label":`Delegar automáticamente las preguntas pendientes`,"settings.chat.questionDelegate.description":`Tras 30 segundos sin respuesta, pedir al modelo que decida y continúe. Interactuar con una pregunta pausa su cuenta atrás.`,"settings.chat.questionDelegate.saveFailed":`Error al guardar la delegación automática. Comprueba el estado actual antes de reintentar.`,"settings.globalConfig.title":`Configuración global`,"settings.globalConfig.description":`Edita los archivos de configuración activos en ~/.config/opencode.`,"settings.globalConfig.actions.reload":`Recargar archivo`,"settings.globalConfig.restartHint":`Reinicia OpenCode después de guardar para aplicar los cambios de configuración.`,"settings.globalConfig.toast.loadFailed":`No se pudo cargar el archivo de configuración`,"settings.globalConfig.toast.saveFailed":`No se pudo guardar el archivo de configuración`,"settings.globalConfig.toast.saved":`Configuración guardada.`,"settings.providers.page.openCodeGo.title":`Seguimiento de uso de OpenCode Go`,"settings.providers.page.openCodeGo.description":`Conecta el panel de OpenCode Go para ver las cuotas móvil, semanal y mensual.`,"settings.providers.page.openCodeGo.workspaceId":`ID del espacio de trabajo`,"settings.providers.page.openCodeGo.authCookie":`Cookie de autenticación`,"settings.providers.page.openCodeGo.consoleSignIn":`Iniciar sesión con OpenCode Console`,"settings.providers.page.openCodeGo.consoleConnected":`OpenCode Console está conectado. OpenCode Go puede usar estas credenciales.`,"settings.providers.page.openCodeGo.consoleHint":`OpenCode Go inicia sesión a través de OpenCode Console. Las claves de cuenta de servicio de abajo siguen disponibles.`,"settings.providers.page.openCodeGo.help":`Copia el ID desde la URL del panel y la cookie auth desde las herramientas del navegador. Yuri nunca examina las cookies del navegador.`,"settings.providers.page.openCodeGo.save":`Guardar y validar`,"settings.providers.page.openCodeGo.replace":`Reemplazar`,"settings.providers.page.openCodeGo.validate":`Validar`,"settings.providers.page.openCodeGo.delete":`Eliminar`,"settings.providers.page.quotaCredentials.saved":`Credenciales de {provider} guardadas.`,"settings.providers.page.openCodeGo.saveFailed":`No se pudieron validar las credenciales de OpenCode Go.`,"settings.providers.page.openCodeGo.valid":`Las credenciales de OpenCode Go son válidas.`,"settings.providers.page.openCodeGo.invalid":`Las credenciales de OpenCode Go no son válidas o han caducado.`,"settings.providers.page.openCodeGo.deleted":`Credenciales de OpenCode Go eliminadas.`,"settings.providers.page.openCodeGo.deleteFailed":`No se pudieron eliminar las credenciales de OpenCode Go.`,"settings.appearance.language.label":`Idioma`,"settings.appearance.language.description":`Elige el idioma de la interfaz.`,"settings.appearance.language.select":`Seleccionar idioma`,"settings.window.description":`Ventana de configuración de Yuri.`,"settings.view.home.title":`Configuración`,"settings.view.home.description":`Saltar a páginas comunes.`,"settings.view.home.cards.providers.title":`Proveedores`,"settings.view.home.cards.providers.description":`Conectar modelos + credenciales`,"settings.view.home.cards.agents.title":`Configuración de agentes`,"settings.view.home.cards.agents.description":`Indicaciones, permisos y límites de ejecución`,"settings.view.home.cards.skillsCatalog.title":`Catálogo de habilidades`,"settings.view.home.cards.skillsCatalog.description":`Instalar habilidades desde catálogos`,"settings.view.home.cards.mcp.title":`MCP`,"settings.view.home.cards.mcp.description":`Configurar servidores + conexiones MCP`,"settings.view.home.cards.plugins.title":`Plugins`,"settings.view.home.cards.plugins.description":`Manage opencode plugins`,"settings.view.home.cards.usage.title":`Uso`,"settings.view.home.cards.usage.description":`Cuota + visibilidad del gasto`,"settings.view.unavailable.title":`No disponible`,"settings.view.unavailable.description":`Esta página de configuración no está disponible en este entorno de ejecución.`,"settings.view.badge.beta":`beta`,"settings.view.actions.reloadOpenCode":`Recargar OpenCode`,"settings.view.actions.reloadOpenCodeTooltip":`Recargar la configuración del entorno de OpenCode sin reiniciar el servicio.`,"settings.view.actions.backToSettings":`Volver a Configuración`,"settings.view.actions.closeSettings":`Cerrar configuración`,"settings.view.actions.openSectionList":`Abrir lista de secciones`,"settings.view.actions.closeSettingsWithShortcut":`Cerrar configuración ({shortcut}+,)`,"settings.view.actions.back":`Atrás`,"settings.view.actions.resizeNavigation":`Ajustar tamaño de la navegación`,"settings.view.navigation.groups.connection":`Conexión`,"settings.view.navigation.groups.personalization":`Personalización`,"settings.view.navigation.groups.workspace":`Espacio de trabajo`,"settings.view.navigation.groups.opencode":`OpenCode`,"settings.view.navigation.groups.content":`Contenido y automatización`,"settings.view.navigation.groups.system":`Sistema`,"settings.view.search.placeholder":`Buscar configuración`,"settings.view.search.aria":`Buscar configuración`,"settings.view.search.clear":`Borrar búsqueda de configuración`,"settings.view.search.noResults":`No hay configuraciones coincidentes`,"settings.page.projects.title":`Proyectos`,"settings.page.remoteInstances.title":`Instancias remotas`,"settings.page.providers.title":`Proveedores`,"settings.page.usage.title":`Uso`,"settings.page.agents.title":`Configuración de agentes`,"settings.page.commands.title":`Comandos`,"settings.page.mcp.title":`MCP`,"settings.page.plugins.title":`Plugins`,"settings.page.skills.title":`Habilidades`,"settings.page.skillsCatalog.title":`Catálogo de habilidades`,"settings.page.git.title":`Git`,"settings.page.appearance.title":`Apariencia`,"settings.page.chat.title":`Chat`,"settings.page.shortcuts.title":`Atajos`,"settings.page.sessions.title":`Sesiones`,"settings.page.archivedSessions.title":`Sesiones archivadas`,"settings.page.summaryAI.title":`Resúmenes de IA`,"settings.page.magicPrompts.title":`Prompts mágicos`,"settings.page.notifications.title":`Notificaciones`,"settings.page.voice.title":`Voz`,"settings.page.about.title":`Acerca de`,"settings.magicPrompts.sidebar.title":`Prompts mágicos`,"settings.magicPrompts.sidebar.description":`Selecciona una plantilla de prompt para editar.`,"settings.magicPrompts.sidebar.group.git":`Git`,"settings.magicPrompts.sidebar.group.github":`GitHub`,"settings.magicPrompts.sidebar.group.session":`Sesión`,"settings.magicPrompts.sidebar.item.gitCommitGenerate":`Generación de commit`,"settings.magicPrompts.sidebar.item.gitPrGenerate":`Generación de PR`,"settings.magicPrompts.sidebar.item.gitConflictResolve":`Resolución de conflicto de merge/rebase`,"settings.magicPrompts.sidebar.item.gitCherrypickConflictResolve":`Resolución de conflicto de cherry-pick`,"settings.magicPrompts.sidebar.item.githubPrReview":`Revisión de PR`,"settings.magicPrompts.sidebar.item.githubIssueReview":`Revisión de issue`,"settings.magicPrompts.sidebar.item.githubPrFailedChecksReview":`Revisión de PR con comprobaciones fallidas`,"settings.magicPrompts.sidebar.item.githubPrCommentsReview":`Revisión de comentarios de PR`,"settings.magicPrompts.sidebar.item.githubSinglePrCommentReview":`Revisión de comentario único de PR`,"settings.magicPrompts.sidebar.item.sessionSummary":`Resumen de sesión`,"settings.magicPrompts.sidebar.item.sessionWorkspaceReview":`Revisión del espacio de trabajo`,"settings.magicPrompts.sidebar.item.sessionExplore":`Recorrido del código`,"settings.magicPrompts.sidebar.item.sessionCraftGoal":`Creación de Goal`,"settings.magicPrompts.page.group.sessionCraftGoal.title":`Creación de Goal`,"settings.magicPrompts.page.group.sessionCraftGoal.description":`Prompts usados por el comando /craft-goal: mensaje visible del usuario + instrucciones ocultas. Convierte una idea o tarea en un Goal claro y verificable mediante un diálogo guiado.`,"settings.magicPrompts.sidebar.item.sessionCatchUp":`Ponerse al día`,"settings.magicPrompts.sidebar.item.sessionDebug":`Depuración`,"settings.magicPrompts.sidebar.item.sessionWeigh":`Comparar enfoques`,"settings.magicPrompts.sidebar.item.sessionFusion":`Fusion`,"settings.remoteInstances.sidebar.title":`Instancias remotas`,"settings.remoteInstances.sidebar.description":`Conéctate a otros servidores de Yuri con un enlace de importación o SSH.`,"settings.remoteInstances.sidebar.empty":`Aún no hay instancias remotas. Importa un enlace o añade una conexión SSH.`,"settings.remoteInstances.channel.link":`Enlace`,"settings.remoteInstances.channel.ssh":`SSH`,"settings.remoteInstances.sidebar.total":`Total {count}`,"settings.remoteInstances.sidebar.newSshInstanceName":`Nueva conexión SSH`,"settings.remoteInstances.sidebar.actions.addSshInstance":`Añadir conexión SSH`,"settings.remoteInstances.sidebar.actions.connect":`Conectar`,"settings.remoteInstances.sidebar.actions.disconnect":`Desconectar`,"settings.remoteInstances.sidebar.actions.retry":`Reintentar`,"settings.remoteInstances.sidebar.actions.remove":`Eliminar`,"settings.remoteInstances.sidebar.confirm.localPortInUseRetry":`El puerto local ya está en uso. ¿Elegir un puerto libre aleatorio y reintentar?`,"settings.remoteInstances.sidebar.toast.createFailed":`No se pudo crear la conexión SSH`,"settings.remoteInstances.sidebar.toast.retriedWithRandomPort":`Reintentado con un puerto local aleatorio`,"settings.remoteInstances.sidebar.toast.connectFailed":`No se pudo conectar la instancia`,"settings.remoteInstances.sidebar.toast.disconnectFailed":`No se pudo desconectar la instancia`,"settings.remoteInstances.sidebar.toast.retryFailed":`No se pudo reintentar la conexión`,"settings.remoteInstances.sidebar.toast.removeFailed":`No se pudo eliminar la instancia`,"settings.remoteInstances.direct.sidebarTitle":`Enlaces a servidores`,"settings.remoteInstances.direct.sidebarDescription":`Conecta con un enlace de emparejamiento`,"settings.remoteInstances.direct.title":`Otros servidores de Yuri`,"settings.remoteInstances.direct.description":`Servidores a los que esta aplicación puede cambiar. Importa un enlace de conexión de otro servidor.`,"settings.remoteInstances.direct.import.description":`Pega un enlace de conexión de otro servidor de Yuri.`,"settings.remoteInstances.direct.import.placeholder":`yuri://connect?...`,"settings.remoteInstances.direct.import.action":`Importar enlace`,"settings.remoteInstances.direct.error.invalidConnectLink":`Enlace de conexión de Yuri no válido.`,"settings.remoteInstances.direct.state.loading":`Cargando servidores...`,"settings.remoteInstances.direct.state.empty":`Todavía no se han importado otros servidores.`,"settings.remoteInstances.clientAuth.title":`Conectarse a este servidor`,"settings.remoteInstances.clientAuth.description":`Crea un enlace o token seguro para que Yuri Desktop pueda conectarse a este servidor.`,"settings.remoteInstances.clientAuth.field.labelPlaceholder":`Nombre de la instancia — p. ej. Mac de casa`,"settings.remoteInstances.clientAuth.field.labelHint":`El otro dispositivo mostrará este nombre para este servidor.`,"settings.remoteInstances.clientAuth.actions.create":`Crear token`,"settings.remoteInstances.clientAuth.actions.pair":`Crear enlace`,"settings.remoteInstances.clientAuth.actions.revoke":`Revocar`,"settings.remoteInstances.clientAuth.actions.clearRevoked":`Borrar revocados`,"settings.remoteInstances.clientAuth.qrAlt":`Yuri connection QR code`,"settings.remoteInstances.clientAuth.qrEnlarge":`Ampliar código QR`,"settings.remoteInstances.clientAuth.qrScanHint":`Escanéalo con la app de Yuri en tu otro dispositivo. Es de un solo uso y caduca.`,"settings.remoteInstances.clientAuth.qrDialogTitle":`Escanear para conectar`,"settings.remoteInstances.clientAuth.actions.addDevice":`Añadir un dispositivo`,"settings.remoteInstances.clientAuth.actions.copied":`Copiado`,"settings.remoteInstances.clientAuth.addDevice.transportLabel":`¿Dónde usarás este dispositivo?`,"settings.remoteInstances.clientAuth.addDevice.subtitle":`Crea un código QR de un solo uso que conecta otro dispositivo a este servidor.`,"settings.remoteInstances.clientAuth.addDevice.transport.local":`Solo este equipo`,"settings.remoteInstances.clientAuth.addDevice.transport.localHint":`Para aplicaciones en esta misma máquina.`,"settings.remoteInstances.clientAuth.addDevice.transport.lan":`Solo red doméstica`,"settings.remoteInstances.clientAuth.addDevice.transport.lanHint":`Se conecta directamente por tu Wi-Fi. No funciona fuera de esta red.`,"settings.remoteInstances.clientAuth.addDevice.transport.relay":`En cualquier lugar`,"settings.remoteInstances.clientAuth.addDevice.transport.relayHint":`Funciona en casa y fuera. Fuera de casa el tráfico pasa por Yuri Private Relay, un túnel cifrado de extremo a extremo. Sin configuración.`,"settings.remoteInstances.clientAuth.addDevice.fallback.relay":`Permitir también el relay cifrado fuera de casa`,"settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal":`Preferir la conexión doméstica directa cuando esté disponible`,"settings.remoteInstances.clientAuth.addDevice.relayUrlLabel":`Servidor Relay`,"settings.remoteInstances.clientAuth.addDevice.relayUrlHint":`Usa el Relay oficial de Yuri o introduce tu propio endpoint ws:// o wss://. El dispositivo guardará el endpoint incluido en el código QR.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlDeployLink":`Despliega tu propio Relay.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlLockedHint":`Este servidor fija el endpoint Relay mediante YURI_RELAY_URL.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlRemoteHostHint":`Lo define el host conectado. El emparejamiento usa el endpoint Relay actual de ese host.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlCustomOption":`Endpoint personalizado…`,"settings.remoteInstances.clientAuth.addDevice.relayUrlInvalid":`Introduce un endpoint Relay válido que empiece por ws:// o wss://.`,"settings.remoteInstances.clientAuth.addDevice.create":`Crear código QR`,"settings.remoteInstances.clientAuth.addDevice.targetLabel":`Instancia de destino`,"settings.remoteInstances.clientAuth.addDevice.target.local":`Este escritorio`,"settings.remoteInstances.clientAuth.addDevice.target.sshEmpty":`No hay instancias SSH conectadas`,"settings.remoteInstances.clientAuth.addDevice.target.sshNotReady":`Conecta primero la instancia SSH`,"settings.remoteInstances.sidebar.actions.switchInstanceDisabled":`Conecta esta instancia SSH antes de cambiar`,"settings.remoteInstances.sidebar.actions.syncConfigDisabled":`Conecta esta instancia para sincronizar su configuración`,"settings.remoteInstances.sidebar.actions.syncConfig":`Sincronizar configuración`,"settings.remoteInstances.clientAuth.addDevice.done":`Listo`,"settings.remoteInstances.clientAuth.addDevice.connectedToast":`Dispositivo conectado.`,"settings.remoteInstances.clientAuth.pairingUrl":`Enlace de conexión`,"settings.remoteInstances.clientAuth.createdToken":`Copia este token ahora. Por seguridad, no se volverá a mostrar.`,"settings.remoteInstances.clientAuth.state.loading":`Cargando tokens...`,"settings.remoteInstances.clientAuth.state.empty":`Todavía no hay dispositivos conectados.`,"settings.remoteInstances.clientAuth.state.revoked":`Revocado`,"settings.remoteInstances.clientAuth.state.thisDevice":`Este dispositivo`,"settings.remoteInstances.clientAuth.state.pending":`Esperando conexión…`,"settings.remoteInstances.clientAuth.state.viaRelay":`Relay`,"settings.remoteInstances.clientAuth.state.connectedDirect":`Conectado · Red local`,"settings.remoteInstances.clientAuth.state.connectedRelay":`Conectado · Relay`,"settings.remoteInstances.clientAuth.lastUsed":`Último uso {date}`,"settings.remoteInstances.clientAuth.neverUsed":`Nunca usado`,"settings.remoteInstances.relay.title":`Yuri Relay`,"settings.remoteInstances.relay.autoHint":`Se activa automáticamente al vincular un dispositivo por relay.`,"settings.remoteInstances.relay.description":`Permite que tus otros dispositivos se conecten desde cualquier lugar sin abrir puertos. El tráfico está cifrado de extremo a extremo: el relay no puede leerlo.`,"settings.remoteInstances.relay.enableHint":`No se comparte nada hasta que actives el relay en este servidor.`,"settings.remoteInstances.relay.actions.enable":`Activar Relay`,"settings.remoteInstances.relay.actions.disable":`Desactivar`,"settings.remoteInstances.relay.confirm.disable":`¿Desactivar el relay? Los dispositivos conectados a través de él se desconectarán de inmediato.`,"settings.remoteInstances.relay.state.loading":`Comprobando el estado del relay...`,"settings.remoteInstances.relay.state.disabled":`Desactivado`,"settings.remoteInstances.relay.state.connecting":`Conectando`,"settings.remoteInstances.relay.state.connected":`Conectado`,"settings.remoteInstances.relay.state.reconnecting":`Reconectando`,"settings.remoteInstances.relay.state.error":`Error`,"settings.remoteInstances.relay.status.clientsOne":`{count} dispositivo conectado`,"settings.remoteInstances.relay.status.clientsMany":`{count} dispositivos conectados`,"settings.remoteInstances.relay.pair.title":`Emparejar un dispositivo`,"settings.remoteInstances.relay.pair.labelPlaceholder":`Nombre del dispositivo (opcional)`,"settings.remoteInstances.relay.pair.includeToken":`Incluir token de acceso (emparejamiento con un solo escaneo)`,"settings.remoteInstances.relay.pair.noTokenHint":`Sin token, el dispositivo inicia sesión con la contraseña de la interfaz de este servidor tras conectarse.`,"settings.remoteInstances.relay.pair.generate":`Crear enlace de emparejamiento`,"settings.remoteInstances.relay.pair.requiresConnected":`El emparejamiento estará disponible cuando el relay esté conectado.`,"settings.remoteInstances.relay.pair.linkLabel":`Enlace de emparejamiento`,"settings.remoteInstances.relay.pair.warning":`Este enlace concede acceso a este servidor. No lo compartas.`,"settings.remoteInstances.relay.pair.qrAlt":`Código QR de emparejamiento del relay`,"settings.remoteInstances.relay.pair.showQr":`Mostrar código QR`,"settings.remoteInstances.relay.pair.qrDialogTitle":`Escanear para emparejar`,"settings.remoteInstances.relay.pair.qrDialogDescription":`Escanea este código QR con la app de Yuri en tu otro dispositivo.`,"settings.remoteInstances.relay.pair.manageHint":`Gestiona o revoca los dispositivos emparejados en la lista «Conexión a este servidor» de arriba.`,"settings.remoteInstances.relay.toast.enableFailed":`No se pudo activar el relay`,"settings.remoteInstances.relay.toast.disableFailed":`No se pudo desactivar el relay`,"settings.remoteInstances.relay.toast.offerFailed":`No se pudo crear el enlace de emparejamiento`,"settings.remoteInstances.relay.toast.linkCopied":`Enlace de emparejamiento copiado`,"settings.remoteInstances.sidebar.phase.ready":`Listo`,"settings.remoteInstances.sidebar.phase.error":`Error`,"settings.remoteInstances.sidebar.phase.reconnect":`Reconectar`,"settings.remoteInstances.sidebar.phase.installing":`Instalando`,"settings.remoteInstances.sidebar.phase.updating":`Actualizando`,"settings.remoteInstances.sidebar.phase.forwarding":`Redirigiendo`,"settings.remoteInstances.sidebar.phase.starting":`Iniciando`,"settings.remoteInstances.sidebar.phase.connecting":`Conectando`,"settings.remoteInstances.sidebar.phase.idle":`Inactivo`,"settings.remoteInstances.page.section.instance":`Instancia`,"settings.remoteInstances.page.section.instanceDescription":`Choose the SSH command and a display name for this connection.`,"settings.remoteInstances.page.field.mode":`Modo`,"settings.remoteInstances.page.field.modeHint":`Elige si Yuri debe iniciar el servidor por ti o conectarse a uno que ya está en marcha.`,"settings.remoteInstances.page.field.modePlaceholder":`Seleccionar modo`,"settings.remoteInstances.page.field.modeManaged":`Iniciarlo por mí`,"settings.remoteInstances.page.field.modeExternal":`Ya está en marcha`,"settings.remoteInstances.page.field.preferredRemotePort":`Puerto remoto preferido`,"settings.remoteInstances.page.field.preferredRemotePortHint":`Port to use on the remote machine. Leave empty to choose one automatically.`,"settings.remoteInstances.page.field.keepServerRunning":`Mantener servidor en ejecución`,"settings.remoteInstances.page.field.keepServerRunningHint":`Keep Yuri running on the remote machine after you disconnect.`,"settings.remoteInstances.page.field.bindHost":`Host de enlace`,"settings.remoteInstances.page.field.bindHostHint":`Where the local connection should listen. Use 127.0.0.1 or localhost unless you need LAN access.`,"settings.remoteInstances.page.field.preferredLocalPort":`Puerto local preferido`,"settings.remoteInstances.page.field.preferredLocalPortHint":`Local port to open for this connection. Leave empty to choose one automatically.`,"settings.remoteInstances.page.field.forwardType":`Tipo de redirección`,"settings.remoteInstances.page.field.localListen":`Escucha local`,"settings.remoteInstances.page.field.localTarget":`Destino local`,"settings.remoteInstances.page.field.remoteListen":`Escucha remota`,"settings.remoteInstances.page.field.remoteTarget":`Destino remoto`,"settings.remoteInstances.page.field.localHostPlaceholder":`127.0.0.1`,"settings.remoteInstances.page.field.remoteHostPlaceholder":`127.0.0.1`,"settings.remoteInstances.page.field.auto":`Automático`,"settings.remoteInstances.page.confirm.bindAllInterfaces":`Vincular a 0.0.0.0 expone los puertos redirigidos a tu red local. ¿Continuar?`,"settings.remoteInstances.page.preview.localSocks5":`(local SOCKS5)`,"settings.remoteInstances.page.preview.local":`(local)`,"settings.remoteInstances.page.preview.remote":`(remoto)`,"settings.remoteInstances.page.toast.openLocalEndpointFailed":`No se pudo abrir la dirección local`,"settings.remoteInstances.page.toast.localUrlCopied":`URL local copiada`,"settings.remoteInstances.page.actions.copyLocalUrl":`Copiar URL local`,"settings.remoteInstances.page.actions.open":`Abrir`,"settings.remoteInstances.page.logsDialog.selectedInstanceFallback":`Instancia seleccionada`,"settings.remoteInstances.page.patternDialog.descriptionWithHost":`{host} requiere un destino concreto.`,"settings.remoteInstances.page.patternDialog.description":`Introduce destino.`,"settings.common.actions.cancel":`Cancelar`,"settings.common.actions.create":`Crear`,"settings.common.actions.delete":`Eliminar`,"settings.common.actions.reset":`Restablecer`,"settings.common.actions.rename":`Cambiar nombre`,"settings.common.actions.duplicate":`Duplicar`,"settings.common.actions.import":`Importar`,"settings.common.actions.copyAll":`Copiar todo`,"settings.common.actions.clear":`Limpiar`,"settings.common.actions.saving":`Guardando...`,"settings.common.actions.saveChanges":`Guardar cambios`,"settings.common.scope.global":`Global`,"settings.common.scope.project":`Proyecto`,"settings.common.field.description":`Descripción`,"settings.common.badge.new":`Nuevo`,"settings.common.badge.modified":`Modificado`,"settings.common.permission.allow":`Permitir`,"settings.common.permission.ask":`Preguntar`,"settings.common.permission.deny":`Denegar`,"settings.common.state.comingSoon":`Próximamente...`,"settings.projects.actions.title":`Acciones`,"settings.projects.actions.description":`Comandos por proyecto mostrados en el encabezado junto al nombre del proyecto.`,"settings.projects.actions.validation.fillNameAndCommand":`Completa el nombre de la acción y el comando antes de guardar.`,"settings.projects.actions.state.loading":`Cargando...`,"settings.projects.actions.state.empty":`No hay acciones configuradas aún.`,"settings.projects.actions.state.untitled":`Acción sin título`,"settings.projects.actions.state.noDesktopSshForwards":`No hay forwards SSH locales habilitados disponibles.`,"settings.projects.actions.field.selectIconAria":`Seleccionar icono`,"settings.projects.actions.field.iconAria":`Icono {icon}`,"settings.projects.actions.field.actionNamePlaceholder":`Nombre de la acción`,"settings.projects.actions.field.command":`Comando`,"settings.projects.actions.field.commandPlaceholder":`p. ej. bun run lint`,"settings.projects.actions.field.autoOpenUrl":`Abrir URL automáticamente`,"settings.projects.actions.field.autoOpenUrlForAria":`Abrir URL automáticamente para {title}`,"settings.projects.actions.field.autoOpenUrlDescription":`Abrir URL desde la salida o la URL personalizada de abajo`,"settings.projects.actions.field.overrideUrlPlaceholder":`URL de reemplazo (opcional)`,"settings.projects.actions.field.overrideUrlTooltip":`Si este campo está lleno, se usa la URL personalizada. Si está vacío, la aplicación abre la mejor URL de la salida.`,"settings.projects.actions.field.desktopSshForward":`Forward SSH de escritorio`,"settings.projects.actions.field.useOutputManualUrl":`Usar URL de salida/manual`,"settings.projects.actions.actions.add":`Añadir acción`,"settings.projects.actions.actions.save":`Guardar acciones`,"settings.projects.actions.toast.saveFailed":`No se pudieron guardar las acciones`,"settings.projects.actions.toast.saved":`Acciones del proyecto guardadas`,"settings.yuri.about.title":`Acerca de Yuri`,"settings.yuri.about.field.version":`Versión`,"settings.yuri.about.field.clientVersion":`Cliente`,"settings.yuri.about.field.webBundle":`Paquete web`,"settings.yuri.about.field.instanceYuriVersion":`Yuri`,"settings.yuri.about.field.instanceOpenCodeVersion":`OpenCode`,"settings.yuri.about.field.openCodeVersion":`Versión de OpenCode`,"settings.yuri.about.opencodeVersionWithManagement":`{version} ({management})`,"settings.yuri.about.opencodeManagement.manual-global":`CLI global — actualizar manualmente`,"settings.yuri.about.opencodeManagement.manual-external":`serve externo — gestionar fuera de la app`,"settings.yuri.about.opencodeManagement.bundled":`incluido con la aplicación`,"settings.yuri.about.opencodeManagement.in-app":`gestionado por Yuri`,"settings.yuri.about.opencodeManagement.none":`propiedad desconocida`,"settings.yuri.about.state.checking":`Comprobando...`,"settings.yuri.about.state.upToDate":`Actualizado`,"settings.yuri.about.state.unknown":`desconocido`,"settings.yuri.about.state.builtin":`integrado`,"settings.yuri.about.actions.checkUpdates":`Comprobar actualizaciones`,"settings.yuri.about.actions.update":`Actualizar`,"settings.yuri.about.actions.updateToVersion":`Actualizar a {version}`,"settings.yuri.about.actions.applyOtaToVersion":`Actualizar ahora a {version}`,"settings.yuri.about.actions.installNativeToVersion":`Instalar {version}`,"settings.yuri.about.actions.checkForUpdates":`Comprobar actualizaciones`,"settings.yuri.about.actions.submitFeedback":`Enviar comentarios`,"settings.yuri.about.toast.latestVersion":`Ya estás en la última versión`,"settings.yuri.about.toast.checkFailed":`No se pudo comprobar actualizaciones`,"settings.yuri.about.betaUpdates.label":`Unirse a las actualizaciones beta`,"settings.yuri.about.betaUpdates.description":`Recibe antes las actualizaciones de la aplicación en este dispositivo.`,"settings.yuri.about.betaUpdates.rollback.title":`¿Volver a la versión estable?`,"settings.yuri.about.betaUpdates.rollback.description":`Estás usando una versión beta. Al desactivar las actualizaciones beta, Yuri volverá a la versión estable v{version}. Reinicia la aplicación para aplicar el cambio.`,"settings.yuri.about.betaUpdates.rollback.actions.cancel":`Mantener beta`,"settings.yuri.about.betaUpdates.rollback.actions.confirm":`Volver a estable`,"settings.yuri.about.diagnostics.label":`Registro de diagnóstico`,"settings.yuri.about.diagnostics.description":`Exporta los feat de diagnóstico locales para analizar problemas de visualización y sincronización. No incluye cuerpos de mensajes ni tokens.`,"settings.yuri.about.diagnostics.export":`Exportar registro`,"settings.yuri.about.diagnostics.exporting":`Exportando…`,"settings.yuri.about.diagnostics.enable":`Registrar feat de diagnóstico`,"settings.yuri.about.diagnostics.enableHint":`Disponible en versiones beta. Registra en este dispositivo el ciclo de sincronización y visualización de la sesión, sin el cuerpo del mensaje.`,"settings.yuri.about.diagnostics.toast.exported":`Registro de diagnóstico exportado`,"settings.yuri.about.diagnostics.toast.failed":`No se pudo exportar el registro de diagnóstico`,"settings.yuri.about.diagnostics.toast.empty":`Registro de diagnóstico exportado. Aún no se registró ningún evento.`,"settings.agents.sidebar.title":`Configuración de agentes`,"settings.agents.sidebar.total":`Total {count}`,"settings.agents.sidebar.empty.title":`No hay agentes configurados`,"settings.agents.sidebar.empty.description":`Usa el botón + arriba para crear uno`,"settings.agents.sidebar.section.builtIn":`Agentes incorporados`,"settings.agents.sidebar.section.custom":`Agentes personalizados`,"settings.agents.sidebar.badge.system":`sistema`,"settings.agents.sidebar.badge.disabled":`Desactivado`,"settings.agents.sidebar.dialog.deleteTitle":`Eliminar agente`,"settings.agents.sidebar.dialog.resetTitle":`Restablecer agente`,"settings.agents.sidebar.dialog.deleteDescription":`¿Seguro que quieres eliminar el agente "{name}"?`,"settings.agents.sidebar.dialog.resetDescription":`¿Seguro que quieres restablecer el agente "{name}" a su configuración predeterminada?`,"settings.agents.sidebar.renameDialog.title":`Cambiar nombre del agente`,"settings.agents.sidebar.renameDialog.description":`Introduce un nuevo nombre para el agente "@{name}"`,"settings.agents.sidebar.renameDialog.placeholder":`Nuevo nombre del agente...`,"settings.agents.sidebar.toast.builtInCannotDelete":`Los agentes incorporados no pueden eliminarse`,"settings.agents.sidebar.toast.agentDeleted":`Agente "{name}" eliminado correctamente`,"settings.agents.sidebar.toast.agentReset":`Agente "{name}" restablecido a la configuración predeterminada`,"settings.agents.sidebar.toast.deleteFailed":`No se pudo eliminar el agente`,"settings.agents.sidebar.toast.definitionNotFound":`No se encontró la definición del agente. No se cambió nada.`,"settings.agents.sidebar.toast.resetFailed":`No se pudo restablecer el agente`,"settings.agents.sidebar.toast.agentNameRequired":`Se requiere el nombre del agente`,"settings.agents.sidebar.toast.agentExists":`Ya existe un agente con este nombre`,"settings.agents.sidebar.toast.removeOldAfterRenameFailed":`No se pudo eliminar el antiguo agente después del cambio de nombre`,"settings.agents.sidebar.toast.renameFailed":`No se pudo cambiar el nombre del agente`,"settings.agents.sidebar.toast.agentRenamed":`Agente renombrado a "{name}"`,"settings.agents.page.toast.permissionNameRequired":`Se requiere el nombre del permiso`,"settings.agents.page.toast.created":`Agente creado correctamente`,"settings.agents.page.toast.updated":`Agente actualizado correctamente`,"settings.agents.page.toast.createFailed":`No se pudo crear el agente`,"settings.agents.page.toast.updateFailed":`No se pudo actualizar el agente`,"settings.agents.page.toast.saveUnexpectedError":`Ocurrió un error al guardar`,"settings.agents.page.toast.savedManualRestart":`Guardado en disco. Reinicia tu servidor OpenCode conectado para aplicar los cambios.`,"settings.agents.page.empty.title":`Selecciona un agente desde la barra lateral`,"settings.agents.page.empty.description":`o crea uno nuevo`,"settings.agents.page.title.new":`Nuevo agente`,"settings.agents.page.subtitle.new":`Configura una nueva asistente`,"settings.agents.page.subtitle.edit":`Editar configuración del agente`,"settings.agents.page.section.identityRole":`Identidad y rol`,"settings.agents.page.section.modelParameters":`Modelo`,"settings.agents.page.section.runtime":`Ejecución`,"settings.agents.page.field.steps":`Límite de pasos`,"settings.agents.page.field.stepsHint":`Vacío significa sin límite. Al llegar al límite, la siguiente petición solo puede responder con texto.`,"settings.agents.page.field.hidden":`Oculto`,"settings.agents.page.field.hiddenHint":`Oculta este agente del selector principal y de las menciones @. La tarea aún puede llamarlo si los permisos lo permiten.`,"settings.agents.page.field.disabled":`Desactivado`,"settings.agents.page.field.disabledHint":`Quita este agente del catálogo. Desactívalo y guarda para devolverlo a la lista.`,"settings.agents.page.field.color":`Color`,"settings.agents.page.field.colorHint":`Color hexadecimal, como #FF6B6B.`,"settings.agents.page.field.colorInvalid":`Escribe un color hexadecimal como #FF6B6B.`,"settings.agents.page.field.clearColorAria":`Borrar color`,"settings.agents.page.field.modelHint":`Déjalo vacío para conservar el modelo de quien llama. La variante se guarda con el modelo.`,"settings.agents.page.system.inheritHint":`Vacío conserva la indicación integrada. El texto de aquí la sustituye. Las instrucciones del proyecto se añaden después.`,"settings.agents.page.apply.hint":`Se aplica en la siguiente petición y en las sesiones nuevas. Una sesión que ya está en curso conserva su modelo.`,"settings.agents.page.legacy.convertible":`Al guardar, este archivo de agente se convierte al formato actual.`,"settings.agents.page.legacy.dropped":`Estos campos no se conservarán: {fields}. No cambian la siguiente petición.`,"settings.agents.page.legacy.confirmDrop":`Convertir y descartar esos campos`,"settings.agents.page.toast.savedNextRequest":`Guardado. La siguiente petición y las sesiones nuevas usan este agente. Una sesión en curso conserva su modelo.`,"settings.agents.page.section.systemPrompt":`Prompt del sistema`,"settings.agents.page.section.toolPermissions":`Permisos de herramientas`,"settings.agents.page.field.agentName":`Nombre del agente`,"settings.agents.page.field.agentNamePlaceholder":`nombre-agente`,"settings.agents.page.field.scope":`Ámbito`,"settings.agents.page.field.scopePlaceholder":`Ámbito`,"settings.agents.page.field.descriptionPlaceholder":`¿Qué hace este agente?`,"settings.agents.page.field.mode":`Modo`,"settings.agents.page.field.modeTooltip":`Visibilidad principal vs subagente`,"settings.agents.page.field.overrideModel":`Sobrescribir modelo`,"settings.agents.page.field.variant":`Variante de pensamiento`,"settings.agents.page.field.variantTooltip":`Opcional. Si el modelo admite razonamiento, la variante controla la profundidad del razonamiento.`,"settings.agents.page.field.variantHint":`Específico del modelo (p. ej. variante de Anthropic)`,"settings.agents.page.field.variantPlaceholder":`p. ej. high, max, low, none`,"settings.agents.page.field.temperature":`Temperatura`,"settings.agents.page.field.temperatureTooltip":`Controla la aleatoriedad. Mayor = más creativo, menor = más enfocado.`,"settings.agents.page.field.temperatureRange":`0.0 a 2.0`,"settings.agents.page.field.clearTemperatureAria":`Limpiar sobrescritura de temperatura`,"settings.agents.page.field.topP":`Top P`,"settings.agents.page.field.topPTooltip":`Diversidad de muestreo del núcleo. Más bajo = solo tokens más probables.`,"settings.agents.page.field.topPRange":`0.0 a 1.0`,"settings.agents.page.field.clearTopPAria":`Limpiar sobrescritura de top p`,"settings.agents.page.field.systemPromptPlaceholder":`Eres un asistente experto en programación...`,"settings.agents.page.mode.primary":`Primario`,"settings.agents.page.mode.subagent":`Subagente`,"settings.agents.page.mode.all":`Todos`,"settings.agents.page.permissions.defaultLabel":`Predeterminado`,"settings.agents.page.permissions.shell":`Shell`,"settings.agents.page.permissions.subagent":`Subagente`,"settings.agents.page.permissions.edit":`Editar`,"settings.agents.page.permissions.externalDirectory":`Directorio externo`,"settings.agents.page.permissions.question":`Pregunta`,"settings.agents.page.permissions.read":`Leer`,"settings.agents.page.permissions.glob":`Buscar archivos`,"settings.agents.page.permissions.grep":`Buscar texto`,"settings.agents.page.permissions.skill":`Skill`,"settings.agents.page.permissions.webfetch":`Obtener URL`,"settings.agents.page.permissions.websearch":`Búsqueda web`,"settings.agents.page.permissions.execute":`Ejecutar`,"settings.agents.page.permissions.browser":`Navegador`,"settings.agents.page.permissions.hideEditor":`Ocultar editor`,"settings.agents.page.permissions.advancedEditor":`Editor avanzado`,"settings.agents.page.permissions.globalSummary":`Global: {summary}`,"settings.agents.page.permissions.rulesSummary":`Reglas: {summary}`,"settings.agents.page.permissions.globalDefault":`Predeterminado global`,"settings.agents.page.permissions.pattern":`Patrón`,"settings.agents.page.permissions.addCustomRule":`Añadir regla personalizada`,"settings.agents.page.permissions.permissionPlaceholder":`Permiso...`,"settings.agents.page.permissions.patternPlaceholder":`Patrón (ej. *)`,"settings.permissions.saved.title":`Permisos de proyecto guardados`,"settings.permissions.saved.empty":`No hay permisos guardados para este proyecto`,"settings.permissions.saved.delete":`Eliminar`,"settings.permissions.saved.deleteFailed":`No se pudo eliminar el permiso guardado`,"settings.permissions.saved.loadFailed":`No se pudieron cargar los permisos guardados`,"settings.agents.page.permissions.lastMatchHint":`Gana la última regla coincidente`,"settings.page.behavior.title":`Comportamiento`,"settings.behavior.page.title":`Comportamiento`,"settings.behavior.page.warning.title":`Las reglas globales se combinan con las reglas del proyecto`,"settings.behavior.page.warning.description":`Los cambios realizados aquí actualizan {path}. OpenCode también incluye cualquier AGENTS.md a nivel de proyecto cuando existe.`,"settings.behavior.page.section.systemPrompt":`AGENTS.md global`,"settings.behavior.page.field.systemPromptPlaceholder":`Eres un asistente de IA útil...
1
+ var e={"sessions.order.saveFailed":`No se pudo guardar el orden de las conversaciones. Inténtalo de nuevo.`,"commandPalette.index.progress":`Indexando los últimos 30 días de todos los proyectos: {completed}/{total} conversaciones`,"commandPalette.index.ready":`Todos los proyectos · últimos 30 días · {count} mensajes indexados`,"commandPalette.index.partial":`No se pudo indexar parte del historial. Se muestran los resultados disponibles y se reintenta automáticamente.`,"mobile.notifications.service":`Servicio de notificaciones de tareas en segundo plano`,"mobile.notifications.connected":`Se mantiene la conexión para recibir notificaciones de tareas mientras la aplicación está en segundo plano.`,"mobile.notifications.unavailable":`No se pudieron iniciar las notificaciones en segundo plano. Vuelve a abrir la aplicación e inténtalo de nuevo.`,"mobile.notifications.auth":`Se denegó el acceso a las notificaciones. Vuelve a conectar o emparejar este servidor.`,"mobile.notifications.endpoint":`No se encuentra el punto de acceso a notificaciones. Actualiza y reinicia Yuri en el ordenador; si ya está actualizado, revisa la ruta del proxy.`,"mobile.notifications.response":`El servidor no devolvió un flujo de notificaciones válido. Comprueba la versión de la aplicación del ordenador y la configuración del proxy.`,"mobile.notifications.server":`El servidor no está disponible temporalmente o está ocupado. Se reintentará automáticamente.`,"mobile.notifications.relay":`La conexión de retransmisión no está disponible. Comprueba que Yuri esté conectado en tu ordenador; se reintentará automáticamente.`,"mobile.notifications.identity":`La identidad del servidor no coincide con el dispositivo emparejado. Vuelve a conectar o emparejar.`,"mobile.notifications.gap":`Es posible que se hayan perdido notificaciones durante la desconexión. Abre la aplicación para consultar los resultados de las tareas.`,"chat.chatInput.stopUnconfirmed":`La detención aún no está confirmada. Inténtalo de nuevo.`,"chat.response.rateLimit":`Se alcanzó el límite de solicitudes del proveedor`,"chat.response.auth":`Falló la autenticación del proveedor. Inicia sesión de nuevo y reintenta.`,"chat.response.quota":`Cuota del proveedor agotada`,"chat.response.contentFilter":`El proveedor bloqueó la respuesta`,"chat.response.transport":`Falló la conexión con el proveedor`,"chat.response.internal":`Error interno del proveedor`,"chat.response.invalidOutput":`Respuesta no válida del proveedor`,"chat.response.invalidRequest":`El proveedor rechazó la solicitud`,"chat.response.unsupportedOperation":`El proveedor no admite esta operación`,"chat.response.noRoute":`Modelo o configuración del proveedor no disponible`,"chat.response.providerUnknown":`Error del proveedor`,"chat.response.timeout":`La solicitud al proveedor agotó el tiempo de espera`,"chat.response.permissionRejected":`Permiso denegado`,"chat.response.toolExecution":`Falló la ejecución de la herramienta`,"chat.response.compactionFailed":`Falló la compactación del contexto`,"chat.response.compactionUnavailable":`Todavía no hay contenido para compactar`,"chat.response.compactionInterrupted":`Compactación del contexto interrumpida`,"chat.response.compactionCancelled":`Compactación del contexto cancelada`,"chat.response.stopped":`Detenido por el usuario`,"chat.response.interrupted":`Respuesta interrumpida`,"chat.response.toolInterrupted":`Ejecución de la herramienta interrumpida`,"chat.response.resumeExhausted":`Recuperación automática detenida tras interrupciones repetidas`,"chat.response.retrying":`Reintentando automáticamente`,"chat.response.failed":`La ejecución falló`,"chat.response.continuingAfterRestart":`Continuando después del reinicio`,"chat.queuedMessage.inheritsSessionSelection":`Hereda el modelo, el agente y la variante de la sesión al ejecutarse.`,"chat.sessionRecovery.awaitingConfirmation":`Servicio reiniciado. Esperando confirmar el estado de la tarea.`,"chat.btw.title":`BTW`,"chat.btw.failed":`Error al generar la respuesta. Vuelve a intentarlo.`,"chat.btw.description":`Pregunta sobre la conversación manteniendo su historial intacto.`,"chat.btw.placeholder":`Pregunta en BTW…`,"chat.btw.removeQuoteAria":`Quitar cita`,"chat.message.conversationQuotesLabel":`Citado de la conversación`,"chat.btw.sessionRequired":`Abre una conversación existente para iniciar BTW.`,"chat.btw.plainTextRequired":`Usa texto sin formato. Tus referencias se conservan en el editor.`,"chat.btw.pending":`Preparando la respuesta…`,"chat.btw.cancelled":`Respuesta cancelada. Vuelve a intentarlo para preguntar de nuevo.`,"chat.btw.resize":`Cambiar el tamaño del panel de BTW`,"settings.voice.volcengine.save":`Guardar`,"settings.voice.volcengine.saveFailed":`No se pudo guardar. Tus cambios se conservan; vuelve a intentarlo.`,"settings.voice.volcengine.loadFailed":`No se pudieron cargar los ajustes de voz de este servidor.`,"settings.voice.volcengine.retry":`Reintentar`,"chat.dictation.error.microphoneNotFound":`No se detectó un micrófono. Conecta uno e inténtalo de nuevo.`,"settings.voice.volcengine.name":`Volcengine (Doubao)`,"settings.voice.volcengine.providerOption":`Volcengine Doubao (Recomendado | De pago)`,"settings.voice.volcengine.keyHelp":`Obtener aquí:`,"settings.voice.volcengine.openLink":`Haz clic para abrir`,"settings.voice.volcengine.asrResource":`ID de recurso ASR en tiempo real`,"settings.voice.volcengine.asrContext":`Contexto de reconocimiento`,"settings.voice.volcengine.asrContextHelp":`Describe el tema y la terminología. Vacía para desactivar; guarda para la próxima grabación. Hasta 2.000 caracteres.`,"settings.voice.volcengine.custom":`ID personalizado`,"settings.voice.volcengine.durationHelp":`Plan por horas, facturado por duración del reconocimiento.`,"settings.voice.volcengine.concurrentHelp":`Plan de concurrencia, utiliza la capacidad adquirida.`,"settings.voice.volcengine.resource":`ID de recurso TTS`,"settings.voice.volcengine.speaker":`ID de voz TTS`,"settings.voice.volcengine.asrTest":`Prueba de micrófono`,"settings.voice.volcengine.testHelp":`Graba con los ajustes actuales y consulta la transcripción en directo.`,"settings.voice.volcengine.startRecording":`Iniciar grabación`,"settings.voice.volcengine.finishRecording":`Detener y transcribir`,"settings.voice.volcengine.recordingUnsupported":`No se puede grabar aquí. Usa HTTPS o la aplicación móvil.`,"settings.voice.volcengine.fileLimit":`WAV, MP3 u OGG, hasta 20 MB. Prueba el reconocimiento de archivos, no los subtítulos en vivo.`,"settings.voice.volcengine.invalidTranscript":`Respuesta de transcripción no válida`,"settings.voice.volcengine.silence":`No se detectó voz`,"settings.voice.volcengine.stop":`Detener`,"settings.voice.volcengine.setup":`Abrir la consola de voz`,"settings.remoteInstances.pairing.advanced":`Ajustes avanzados`,"settings.remoteInstances.pairing.relayHint":`Configura el servidor de retransmisión para Internet. No se utiliza en conexiones locales directas.`,"settings.remoteInstances.pairing.downloadStep":`Instalar app`,"settings.remoteInstances.pairing.name":`Nombre del servidor`,"settings.remoteInstances.pairing.anywhere":`En casa o fuera`,"settings.remoteInstances.pairing.lan":`En la misma red Wi-Fi`,"settings.remoteInstances.pairing.local":`En este ordenador`,"settings.remoteInstances.quick.sshTitle":`Trabaja con los proyectos de otro ordenador`,"settings.remoteInstances.quick.sshHint":`Añade una dirección SSH para ejecutar Yuri en otro ordenador y abrir sus proyectos aquí. Prepara los datos de acceso SSH de ese ordenador.`,"settings.remoteInstances.quick.emptyHint":`Conecta tu teléfono u otro ordenador para continuar trabajando desde cualquier lugar.`,"settings.remoteInstances.quick.title":`Dispositivos conectados`,"settings.remoteInstances.quick.error":`No se pudo actualizar el estado de los dispositivos.`,"settings.remoteInstances.quick.download":`Descargar la aplicación Yuri`,"settings.usage.magpie.url":`URL adicional de Magpie`,"settings.usage.magpie.description":`Magpie se detecta automáticamente en este servidor. Inicia Magpie y actualiza el uso. No requiere configuración.`,"settings.usage.magpie.connected":`Conectado · proveedores: {count}`,"settings.usage.magpie.manual":`Conectar otro Magpie…`,"settings.usage.magpie.unavailable":`Magpie no está disponible temporalmente. Actualiza para reintentar.`,"settings.usage.magpie.cached":`Lectura en caché; esperando datos de cuota recientes`,"settings.usage.magpie.save":`Guardar`,"settings.remoteInstances.clientAuth.edit.title":`Editar dispositivo`,"settings.remoteInstances.clientAuth.edit.action":`Editar`,"settings.remoteInstances.clientAuth.edit.name":`Nombre del dispositivo`,"settings.yuri.about.opencodeGuidance.manualGlobal":`Actualiza el CLI de OpenCode configurado con su gestor de paquetes y reinicia el servicio.`,"settings.yuri.about.opencodeGuidance.manualExternal":`Solicita al responsable del servicio externo de OpenCode que lo actualice y reinicie.`,"settings.yuri.about.opencodeGuidance.bundled":`Actualiza Yuri Desktop para actualizar su OpenCode integrado.`,"settings.permissions.saved.retry":`Reintentar`,"settings.chat.questionDelegate.label":`Delegar automáticamente las preguntas pendientes`,"settings.chat.questionDelegate.description":`Tras 30 segundos sin respuesta, pedir al modelo que decida y continúe. Interactuar con una pregunta pausa su cuenta atrás.`,"settings.chat.questionDelegate.saveFailed":`Error al guardar la delegación automática. Comprueba el estado actual antes de reintentar.`,"settings.globalConfig.title":`Configuración global`,"settings.globalConfig.description":`Edita los archivos de configuración activos en ~/.config/opencode.`,"settings.globalConfig.actions.reload":`Recargar archivo`,"settings.globalConfig.restartHint":`Reinicia OpenCode después de guardar para aplicar los cambios de configuración.`,"settings.globalConfig.toast.loadFailed":`No se pudo cargar el archivo de configuración`,"settings.globalConfig.toast.saveFailed":`No se pudo guardar el archivo de configuración`,"settings.globalConfig.toast.saved":`Configuración guardada.`,"settings.providers.page.openCodeGo.title":`Seguimiento de uso de OpenCode Go`,"settings.providers.page.openCodeGo.description":`Conecta el panel de OpenCode Go para ver las cuotas móvil, semanal y mensual.`,"settings.providers.page.openCodeGo.workspaceId":`ID del espacio de trabajo`,"settings.providers.page.openCodeGo.authCookie":`Cookie de autenticación`,"settings.providers.page.openCodeGo.consoleSignIn":`Iniciar sesión con OpenCode Console`,"settings.providers.page.openCodeGo.consoleConnected":`OpenCode Console está conectado. OpenCode Go puede usar estas credenciales.`,"settings.providers.page.openCodeGo.consoleHint":`OpenCode Go inicia sesión a través de OpenCode Console. Las claves de cuenta de servicio de abajo siguen disponibles.`,"settings.providers.page.openCodeGo.help":`Copia el ID desde la URL del panel y la cookie auth desde las herramientas del navegador. Yuri nunca examina las cookies del navegador.`,"settings.providers.page.openCodeGo.save":`Guardar y validar`,"settings.providers.page.openCodeGo.replace":`Reemplazar`,"settings.providers.page.openCodeGo.validate":`Validar`,"settings.providers.page.openCodeGo.delete":`Eliminar`,"settings.providers.page.quotaCredentials.saved":`Credenciales de {provider} guardadas.`,"settings.providers.page.openCodeGo.saveFailed":`No se pudieron validar las credenciales de OpenCode Go.`,"settings.providers.page.openCodeGo.valid":`Las credenciales de OpenCode Go son válidas.`,"settings.providers.page.openCodeGo.invalid":`Las credenciales de OpenCode Go no son válidas o han caducado.`,"settings.providers.page.openCodeGo.deleted":`Credenciales de OpenCode Go eliminadas.`,"settings.providers.page.openCodeGo.deleteFailed":`No se pudieron eliminar las credenciales de OpenCode Go.`,"settings.appearance.language.label":`Idioma`,"settings.appearance.language.description":`Elige el idioma de la interfaz.`,"settings.appearance.language.select":`Seleccionar idioma`,"settings.window.description":`Ventana de configuración de Yuri.`,"settings.view.home.title":`Configuración`,"settings.view.home.description":`Saltar a páginas comunes.`,"settings.view.home.cards.providers.title":`Proveedores`,"settings.view.home.cards.providers.description":`Conectar modelos + credenciales`,"settings.view.home.cards.agents.title":`Configuración de agentes`,"settings.view.home.cards.agents.description":`Indicaciones, permisos y límites de ejecución`,"settings.view.home.cards.skillsCatalog.title":`Catálogo de habilidades`,"settings.view.home.cards.skillsCatalog.description":`Instalar habilidades desde catálogos`,"settings.view.home.cards.mcp.title":`MCP`,"settings.view.home.cards.mcp.description":`Configurar servidores + conexiones MCP`,"settings.view.home.cards.plugins.title":`Plugins`,"settings.view.home.cards.plugins.description":`Manage opencode plugins`,"settings.view.home.cards.usage.title":`Uso`,"settings.view.home.cards.usage.description":`Cuota + visibilidad del gasto`,"settings.view.unavailable.title":`No disponible`,"settings.view.unavailable.description":`Esta página de configuración no está disponible en este entorno de ejecución.`,"settings.view.badge.beta":`beta`,"settings.view.actions.reloadOpenCode":`Recargar OpenCode`,"settings.view.actions.reloadOpenCodeTooltip":`Recargar la configuración del entorno de OpenCode sin reiniciar el servicio.`,"settings.view.actions.backToSettings":`Volver a Configuración`,"settings.view.actions.closeSettings":`Cerrar configuración`,"settings.view.actions.openSectionList":`Abrir lista de secciones`,"settings.view.actions.closeSettingsWithShortcut":`Cerrar configuración ({shortcut}+,)`,"settings.view.actions.back":`Atrás`,"settings.view.actions.resizeNavigation":`Ajustar tamaño de la navegación`,"settings.view.navigation.groups.connection":`Conexión`,"settings.view.navigation.groups.personalization":`Personalización`,"settings.view.navigation.groups.workspace":`Espacio de trabajo`,"settings.view.navigation.groups.opencode":`OpenCode`,"settings.view.navigation.groups.content":`Contenido y automatización`,"settings.view.navigation.groups.system":`Sistema`,"settings.view.search.placeholder":`Buscar configuración`,"settings.view.search.aria":`Buscar configuración`,"settings.view.search.clear":`Borrar búsqueda de configuración`,"settings.view.search.noResults":`No hay configuraciones coincidentes`,"settings.page.projects.title":`Proyectos`,"settings.page.remoteInstances.title":`Instancias remotas`,"settings.page.providers.title":`Proveedores`,"settings.page.usage.title":`Uso`,"settings.page.agents.title":`Configuración de agentes`,"settings.page.commands.title":`Comandos`,"settings.page.mcp.title":`MCP`,"settings.page.plugins.title":`Plugins`,"settings.page.skills.title":`Habilidades`,"settings.page.skillsCatalog.title":`Catálogo de habilidades`,"settings.page.git.title":`Git`,"settings.page.appearance.title":`Apariencia`,"settings.page.chat.title":`Chat`,"settings.page.shortcuts.title":`Atajos`,"settings.page.sessions.title":`Sesiones`,"settings.page.archivedSessions.title":`Sesiones archivadas`,"settings.page.summaryAI.title":`Resúmenes de IA`,"settings.page.magicPrompts.title":`Prompts mágicos`,"settings.page.notifications.title":`Notificaciones`,"settings.page.voice.title":`Voz`,"settings.page.about.title":`Acerca de`,"settings.magicPrompts.sidebar.title":`Prompts mágicos`,"settings.magicPrompts.sidebar.description":`Selecciona una plantilla de prompt para editar.`,"settings.magicPrompts.sidebar.group.git":`Git`,"settings.magicPrompts.sidebar.group.github":`GitHub`,"settings.magicPrompts.sidebar.group.session":`Sesión`,"settings.magicPrompts.sidebar.item.gitCommitGenerate":`Generación de commit`,"settings.magicPrompts.sidebar.item.gitPrGenerate":`Generación de PR`,"settings.magicPrompts.sidebar.item.gitConflictResolve":`Resolución de conflicto de merge/rebase`,"settings.magicPrompts.sidebar.item.gitCherrypickConflictResolve":`Resolución de conflicto de cherry-pick`,"settings.magicPrompts.sidebar.item.githubPrReview":`Revisión de PR`,"settings.magicPrompts.sidebar.item.githubIssueReview":`Revisión de issue`,"settings.magicPrompts.sidebar.item.githubPrFailedChecksReview":`Revisión de PR con comprobaciones fallidas`,"settings.magicPrompts.sidebar.item.githubPrCommentsReview":`Revisión de comentarios de PR`,"settings.magicPrompts.sidebar.item.githubSinglePrCommentReview":`Revisión de comentario único de PR`,"settings.magicPrompts.sidebar.item.sessionSummary":`Resumen de sesión`,"settings.magicPrompts.sidebar.item.sessionWorkspaceReview":`Revisión del espacio de trabajo`,"settings.magicPrompts.sidebar.item.sessionExplore":`Recorrido del código`,"settings.magicPrompts.sidebar.item.sessionCraftGoal":`Creación de Goal`,"settings.magicPrompts.page.group.sessionCraftGoal.title":`Creación de Goal`,"settings.magicPrompts.page.group.sessionCraftGoal.description":`Prompts usados por el comando /craft-goal: mensaje visible del usuario + instrucciones ocultas. Convierte una idea o tarea en un Goal claro y verificable mediante un diálogo guiado.`,"settings.magicPrompts.sidebar.item.sessionCatchUp":`Ponerse al día`,"settings.magicPrompts.sidebar.item.sessionDebug":`Depuración`,"settings.magicPrompts.sidebar.item.sessionWeigh":`Comparar enfoques`,"settings.magicPrompts.sidebar.item.sessionFusion":`Fusion`,"settings.remoteInstances.sidebar.title":`Instancias remotas`,"settings.remoteInstances.sidebar.description":`Conéctate a otros servidores de Yuri con un enlace de importación o SSH.`,"settings.remoteInstances.sidebar.empty":`Aún no hay instancias remotas. Importa un enlace o añade una conexión SSH.`,"settings.remoteInstances.channel.link":`Enlace`,"settings.remoteInstances.channel.ssh":`SSH`,"settings.remoteInstances.sidebar.total":`Total {count}`,"settings.remoteInstances.sidebar.newSshInstanceName":`Nueva conexión SSH`,"settings.remoteInstances.sidebar.actions.addSshInstance":`Añadir conexión SSH`,"settings.remoteInstances.sidebar.actions.connect":`Conectar`,"settings.remoteInstances.sidebar.actions.disconnect":`Desconectar`,"settings.remoteInstances.sidebar.actions.retry":`Reintentar`,"settings.remoteInstances.sidebar.actions.remove":`Eliminar`,"settings.remoteInstances.sidebar.confirm.localPortInUseRetry":`El puerto local ya está en uso. ¿Elegir un puerto libre aleatorio y reintentar?`,"settings.remoteInstances.sidebar.toast.createFailed":`No se pudo crear la conexión SSH`,"settings.remoteInstances.sidebar.toast.retriedWithRandomPort":`Reintentado con un puerto local aleatorio`,"settings.remoteInstances.sidebar.toast.connectFailed":`No se pudo conectar la instancia`,"settings.remoteInstances.sidebar.toast.disconnectFailed":`No se pudo desconectar la instancia`,"settings.remoteInstances.sidebar.toast.retryFailed":`No se pudo reintentar la conexión`,"settings.remoteInstances.sidebar.toast.removeFailed":`No se pudo eliminar la instancia`,"settings.remoteInstances.direct.sidebarTitle":`Enlaces a servidores`,"settings.remoteInstances.direct.sidebarDescription":`Conecta con un enlace de emparejamiento`,"settings.remoteInstances.direct.title":`Otros servidores de Yuri`,"settings.remoteInstances.direct.description":`Servidores a los que esta aplicación puede cambiar. Importa un enlace de conexión de otro servidor.`,"settings.remoteInstances.direct.import.description":`Pega un enlace de conexión de otro servidor de Yuri.`,"settings.remoteInstances.direct.import.placeholder":`yuri://connect?...`,"settings.remoteInstances.direct.import.action":`Importar enlace`,"settings.remoteInstances.direct.error.invalidConnectLink":`Enlace de conexión de Yuri no válido.`,"settings.remoteInstances.direct.error.pairingFailed":`No se pudo completar el emparejamiento. Comprueba que el servidor esté conectado y vuelve a intentarlo con un nuevo enlace de conexión.`,"settings.remoteInstances.direct.state.loading":`Cargando servidores...`,"settings.remoteInstances.direct.state.empty":`Todavía no se han importado otros servidores.`,"settings.remoteInstances.clientAuth.title":`Conectarse a este servidor`,"settings.remoteInstances.clientAuth.description":`Crea un enlace o token seguro para que Yuri Desktop pueda conectarse a este servidor.`,"settings.remoteInstances.clientAuth.field.labelPlaceholder":`Nombre de la instancia — p. ej. Mac de casa`,"settings.remoteInstances.clientAuth.field.labelHint":`El otro dispositivo mostrará este nombre para este servidor.`,"settings.remoteInstances.clientAuth.actions.create":`Crear token`,"settings.remoteInstances.clientAuth.actions.pair":`Crear enlace`,"settings.remoteInstances.clientAuth.actions.revoke":`Revocar`,"settings.remoteInstances.clientAuth.actions.clearRevoked":`Borrar revocados`,"settings.remoteInstances.clientAuth.qrAlt":`Yuri connection QR code`,"settings.remoteInstances.clientAuth.qrEnlarge":`Ampliar código QR`,"settings.remoteInstances.clientAuth.qrScanHint":`Escanéalo con la app de Yuri en tu otro dispositivo. Es de un solo uso y caduca.`,"settings.remoteInstances.clientAuth.qrDialogTitle":`Escanear para conectar`,"settings.remoteInstances.clientAuth.actions.addDevice":`Añadir un dispositivo`,"settings.remoteInstances.clientAuth.actions.copied":`Copiado`,"settings.remoteInstances.clientAuth.addDevice.transportLabel":`¿Dónde usarás este dispositivo?`,"settings.remoteInstances.clientAuth.addDevice.subtitle":`Crea un código QR de un solo uso que conecta otro dispositivo a este servidor.`,"settings.remoteInstances.clientAuth.addDevice.transport.local":`Solo este equipo`,"settings.remoteInstances.clientAuth.addDevice.transport.localHint":`Para aplicaciones en esta misma máquina.`,"settings.remoteInstances.clientAuth.addDevice.transport.lan":`Solo red doméstica`,"settings.remoteInstances.clientAuth.addDevice.transport.lanHint":`Se conecta directamente por tu Wi-Fi. No funciona fuera de esta red.`,"settings.remoteInstances.clientAuth.addDevice.transport.relay":`En cualquier lugar`,"settings.remoteInstances.clientAuth.addDevice.transport.relayHint":`Funciona en casa y fuera. Fuera de casa el tráfico pasa por Yuri Private Relay, un túnel cifrado de extremo a extremo. Sin configuración.`,"settings.remoteInstances.clientAuth.addDevice.fallback.relay":`Permitir también el relay cifrado fuera de casa`,"settings.remoteInstances.clientAuth.addDevice.fallback.preferLocal":`Preferir la conexión doméstica directa cuando esté disponible`,"settings.remoteInstances.clientAuth.addDevice.relayUrlLabel":`Servidor Relay`,"settings.remoteInstances.clientAuth.addDevice.relayUrlHint":`Usa el Relay oficial de Yuri o introduce tu propio endpoint ws:// o wss://. El dispositivo guardará el endpoint incluido en el código QR.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlDeployLink":`Despliega tu propio Relay.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlLockedHint":`Este servidor fija el endpoint Relay mediante YURI_RELAY_URL.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlRemoteHostHint":`Lo define el host conectado. El emparejamiento usa el endpoint Relay actual de ese host.`,"settings.remoteInstances.clientAuth.addDevice.relayUrlCustomOption":`Endpoint personalizado…`,"settings.remoteInstances.clientAuth.addDevice.relayUrlInvalid":`Introduce un endpoint Relay válido que empiece por ws:// o wss://.`,"settings.remoteInstances.clientAuth.addDevice.create":`Crear código QR`,"settings.remoteInstances.clientAuth.addDevice.targetLabel":`Instancia de destino`,"settings.remoteInstances.clientAuth.addDevice.target.local":`Este escritorio`,"settings.remoteInstances.clientAuth.addDevice.target.sshEmpty":`No hay instancias SSH conectadas`,"settings.remoteInstances.clientAuth.addDevice.target.sshNotReady":`Conecta primero la instancia SSH`,"settings.remoteInstances.sidebar.actions.switchInstanceDisabled":`Conecta esta instancia SSH antes de cambiar`,"settings.remoteInstances.sidebar.actions.syncConfigDisabled":`Conecta esta instancia para sincronizar su configuración`,"settings.remoteInstances.sidebar.actions.syncConfig":`Sincronizar configuración`,"settings.remoteInstances.clientAuth.addDevice.done":`Listo`,"settings.remoteInstances.clientAuth.addDevice.connectedToast":`Dispositivo conectado.`,"settings.remoteInstances.clientAuth.pairingUrl":`Enlace de conexión`,"settings.remoteInstances.clientAuth.createdToken":`Copia este token ahora. Por seguridad, no se volverá a mostrar.`,"settings.remoteInstances.clientAuth.state.loading":`Cargando tokens...`,"settings.remoteInstances.clientAuth.state.empty":`Todavía no hay dispositivos conectados.`,"settings.remoteInstances.clientAuth.state.revoked":`Revocado`,"settings.remoteInstances.clientAuth.state.thisDevice":`Este dispositivo`,"settings.remoteInstances.clientAuth.state.pending":`Esperando conexión…`,"settings.remoteInstances.clientAuth.state.viaRelay":`Relay`,"settings.remoteInstances.clientAuth.state.connectedDirect":`Conectado · Red local`,"settings.remoteInstances.clientAuth.state.connectedRelay":`Conectado · Relay`,"settings.remoteInstances.clientAuth.lastUsed":`Último uso {date}`,"settings.remoteInstances.clientAuth.neverUsed":`Nunca usado`,"settings.remoteInstances.relay.title":`Yuri Relay`,"settings.remoteInstances.relay.autoHint":`Se activa automáticamente al vincular un dispositivo por relay.`,"settings.remoteInstances.relay.description":`Permite que tus otros dispositivos se conecten desde cualquier lugar sin abrir puertos. El tráfico está cifrado de extremo a extremo: el relay no puede leerlo.`,"settings.remoteInstances.relay.enableHint":`No se comparte nada hasta que actives el relay en este servidor.`,"settings.remoteInstances.relay.actions.enable":`Activar Relay`,"settings.remoteInstances.relay.actions.disable":`Desactivar`,"settings.remoteInstances.relay.confirm.disable":`¿Desactivar el relay? Los dispositivos conectados a través de él se desconectarán de inmediato.`,"settings.remoteInstances.relay.state.loading":`Comprobando el estado del relay...`,"settings.remoteInstances.relay.state.disabled":`Desactivado`,"settings.remoteInstances.relay.state.connecting":`Conectando`,"settings.remoteInstances.relay.state.connected":`Conectado`,"settings.remoteInstances.relay.state.reconnecting":`Reconectando`,"settings.remoteInstances.relay.state.error":`Error`,"settings.remoteInstances.relay.status.clientsOne":`{count} dispositivo conectado`,"settings.remoteInstances.relay.status.clientsMany":`{count} dispositivos conectados`,"settings.remoteInstances.relay.pair.title":`Emparejar un dispositivo`,"settings.remoteInstances.relay.pair.labelPlaceholder":`Nombre del dispositivo (opcional)`,"settings.remoteInstances.relay.pair.includeToken":`Incluir token de acceso (emparejamiento con un solo escaneo)`,"settings.remoteInstances.relay.pair.noTokenHint":`Sin token, el dispositivo inicia sesión con la contraseña de la interfaz de este servidor tras conectarse.`,"settings.remoteInstances.relay.pair.generate":`Crear enlace de emparejamiento`,"settings.remoteInstances.relay.pair.requiresConnected":`El emparejamiento estará disponible cuando el relay esté conectado.`,"settings.remoteInstances.relay.pair.linkLabel":`Enlace de emparejamiento`,"settings.remoteInstances.relay.pair.warning":`Este enlace concede acceso a este servidor. No lo compartas.`,"settings.remoteInstances.relay.pair.qrAlt":`Código QR de emparejamiento del relay`,"settings.remoteInstances.relay.pair.showQr":`Mostrar código QR`,"settings.remoteInstances.relay.pair.qrDialogTitle":`Escanear para emparejar`,"settings.remoteInstances.relay.pair.qrDialogDescription":`Escanea este código QR con la app de Yuri en tu otro dispositivo.`,"settings.remoteInstances.relay.pair.manageHint":`Gestiona o revoca los dispositivos emparejados en la lista «Conexión a este servidor» de arriba.`,"settings.remoteInstances.relay.toast.enableFailed":`No se pudo activar el relay`,"settings.remoteInstances.relay.toast.disableFailed":`No se pudo desactivar el relay`,"settings.remoteInstances.relay.toast.offerFailed":`No se pudo crear el enlace de emparejamiento`,"settings.remoteInstances.relay.toast.linkCopied":`Enlace de emparejamiento copiado`,"settings.remoteInstances.sidebar.phase.ready":`Listo`,"settings.remoteInstances.sidebar.phase.error":`Error`,"settings.remoteInstances.sidebar.phase.reconnect":`Reconectar`,"settings.remoteInstances.sidebar.phase.installing":`Instalando`,"settings.remoteInstances.sidebar.phase.updating":`Actualizando`,"settings.remoteInstances.sidebar.phase.forwarding":`Redirigiendo`,"settings.remoteInstances.sidebar.phase.starting":`Iniciando`,"settings.remoteInstances.sidebar.phase.connecting":`Conectando`,"settings.remoteInstances.sidebar.phase.idle":`Inactivo`,"settings.remoteInstances.page.section.instance":`Instancia`,"settings.remoteInstances.page.section.instanceDescription":`Choose the SSH command and a display name for this connection.`,"settings.remoteInstances.page.field.mode":`Modo`,"settings.remoteInstances.page.field.modeHint":`Elige si Yuri debe iniciar el servidor por ti o conectarse a uno que ya está en marcha.`,"settings.remoteInstances.page.field.modePlaceholder":`Seleccionar modo`,"settings.remoteInstances.page.field.modeManaged":`Iniciarlo por mí`,"settings.remoteInstances.page.field.modeExternal":`Ya está en marcha`,"settings.remoteInstances.page.field.preferredRemotePort":`Puerto remoto preferido`,"settings.remoteInstances.page.field.preferredRemotePortHint":`Port to use on the remote machine. Leave empty to choose one automatically.`,"settings.remoteInstances.page.field.keepServerRunning":`Mantener servidor en ejecución`,"settings.remoteInstances.page.field.keepServerRunningHint":`Keep Yuri running on the remote machine after you disconnect.`,"settings.remoteInstances.page.field.bindHost":`Host de enlace`,"settings.remoteInstances.page.field.bindHostHint":`Where the local connection should listen. Use 127.0.0.1 or localhost unless you need LAN access.`,"settings.remoteInstances.page.field.preferredLocalPort":`Puerto local preferido`,"settings.remoteInstances.page.field.preferredLocalPortHint":`Local port to open for this connection. Leave empty to choose one automatically.`,"settings.remoteInstances.page.field.forwardType":`Tipo de redirección`,"settings.remoteInstances.page.field.localListen":`Escucha local`,"settings.remoteInstances.page.field.localTarget":`Destino local`,"settings.remoteInstances.page.field.remoteListen":`Escucha remota`,"settings.remoteInstances.page.field.remoteTarget":`Destino remoto`,"settings.remoteInstances.page.field.localHostPlaceholder":`127.0.0.1`,"settings.remoteInstances.page.field.remoteHostPlaceholder":`127.0.0.1`,"settings.remoteInstances.page.field.auto":`Automático`,"settings.remoteInstances.page.confirm.bindAllInterfaces":`Vincular a 0.0.0.0 expone los puertos redirigidos a tu red local. ¿Continuar?`,"settings.remoteInstances.page.preview.localSocks5":`(local SOCKS5)`,"settings.remoteInstances.page.preview.local":`(local)`,"settings.remoteInstances.page.preview.remote":`(remoto)`,"settings.remoteInstances.page.toast.openLocalEndpointFailed":`No se pudo abrir la dirección local`,"settings.remoteInstances.page.toast.localUrlCopied":`URL local copiada`,"settings.remoteInstances.page.actions.copyLocalUrl":`Copiar URL local`,"settings.remoteInstances.page.actions.open":`Abrir`,"settings.remoteInstances.page.logsDialog.selectedInstanceFallback":`Instancia seleccionada`,"settings.remoteInstances.page.patternDialog.descriptionWithHost":`{host} requiere un destino concreto.`,"settings.remoteInstances.page.patternDialog.description":`Introduce destino.`,"settings.common.actions.cancel":`Cancelar`,"settings.common.actions.create":`Crear`,"settings.common.actions.delete":`Eliminar`,"settings.common.actions.reset":`Restablecer`,"settings.common.actions.rename":`Cambiar nombre`,"settings.common.actions.duplicate":`Duplicar`,"settings.common.actions.import":`Importar`,"settings.common.actions.copyAll":`Copiar todo`,"settings.common.actions.clear":`Limpiar`,"settings.common.actions.saving":`Guardando...`,"settings.common.actions.saveChanges":`Guardar cambios`,"settings.common.scope.global":`Global`,"settings.common.scope.project":`Proyecto`,"settings.common.field.description":`Descripción`,"settings.common.badge.new":`Nuevo`,"settings.common.badge.modified":`Modificado`,"settings.common.permission.allow":`Permitir`,"settings.common.permission.ask":`Preguntar`,"settings.common.permission.deny":`Denegar`,"settings.common.state.comingSoon":`Próximamente...`,"settings.projects.actions.title":`Acciones`,"settings.projects.actions.description":`Comandos por proyecto mostrados en el encabezado junto al nombre del proyecto.`,"settings.projects.actions.validation.fillNameAndCommand":`Completa el nombre de la acción y el comando antes de guardar.`,"settings.projects.actions.state.loading":`Cargando...`,"settings.projects.actions.state.empty":`No hay acciones configuradas aún.`,"settings.projects.actions.state.untitled":`Acción sin título`,"settings.projects.actions.state.noDesktopSshForwards":`No hay forwards SSH locales habilitados disponibles.`,"settings.projects.actions.field.selectIconAria":`Seleccionar icono`,"settings.projects.actions.field.iconAria":`Icono {icon}`,"settings.projects.actions.field.actionNamePlaceholder":`Nombre de la acción`,"settings.projects.actions.field.command":`Comando`,"settings.projects.actions.field.commandPlaceholder":`p. ej. bun run lint`,"settings.projects.actions.field.autoOpenUrl":`Abrir URL automáticamente`,"settings.projects.actions.field.autoOpenUrlForAria":`Abrir URL automáticamente para {title}`,"settings.projects.actions.field.autoOpenUrlDescription":`Abrir URL desde la salida o la URL personalizada de abajo`,"settings.projects.actions.field.overrideUrlPlaceholder":`URL de reemplazo (opcional)`,"settings.projects.actions.field.overrideUrlTooltip":`Si este campo está lleno, se usa la URL personalizada. Si está vacío, la aplicación abre la mejor URL de la salida.`,"settings.projects.actions.field.desktopSshForward":`Forward SSH de escritorio`,"settings.projects.actions.field.useOutputManualUrl":`Usar URL de salida/manual`,"settings.projects.actions.actions.add":`Añadir acción`,"settings.projects.actions.actions.save":`Guardar acciones`,"settings.projects.actions.toast.saveFailed":`No se pudieron guardar las acciones`,"settings.projects.actions.toast.saved":`Acciones del proyecto guardadas`,"settings.yuri.about.title":`Acerca de Yuri`,"settings.yuri.about.field.version":`Versión`,"settings.yuri.about.field.clientVersion":`Cliente`,"settings.yuri.about.field.webBundle":`Paquete web`,"settings.yuri.about.field.instanceYuriVersion":`Yuri`,"settings.yuri.about.field.instanceOpenCodeVersion":`OpenCode`,"settings.yuri.about.field.openCodeVersion":`Versión de OpenCode`,"settings.yuri.about.opencodeVersionWithManagement":`{version} ({management})`,"settings.yuri.about.opencodeManagement.manual-global":`CLI global — actualizar manualmente`,"settings.yuri.about.opencodeManagement.manual-external":`serve externo — gestionar fuera de la app`,"settings.yuri.about.opencodeManagement.bundled":`incluido con la aplicación`,"settings.yuri.about.opencodeManagement.in-app":`gestionado por Yuri`,"settings.yuri.about.opencodeManagement.none":`propiedad desconocida`,"settings.yuri.about.state.checking":`Comprobando...`,"settings.yuri.about.state.upToDate":`Actualizado`,"settings.yuri.about.state.unknown":`desconocido`,"settings.yuri.about.state.builtin":`integrado`,"settings.yuri.about.actions.checkUpdates":`Comprobar actualizaciones`,"settings.yuri.about.actions.update":`Actualizar`,"settings.yuri.about.actions.updateToVersion":`Actualizar a {version}`,"settings.yuri.about.actions.applyOtaToVersion":`Actualizar ahora a {version}`,"settings.yuri.about.actions.installNativeToVersion":`Instalar {version}`,"settings.yuri.about.actions.checkForUpdates":`Comprobar actualizaciones`,"settings.yuri.about.actions.submitFeedback":`Enviar comentarios`,"settings.yuri.about.toast.latestVersion":`Ya estás en la última versión`,"settings.yuri.about.toast.checkFailed":`No se pudo comprobar actualizaciones`,"settings.yuri.about.betaUpdates.label":`Unirse a las actualizaciones beta`,"settings.yuri.about.betaUpdates.description":`Recibe antes las actualizaciones de la aplicación en este dispositivo.`,"settings.yuri.about.betaUpdates.rollback.title":`¿Volver a la versión estable?`,"settings.yuri.about.betaUpdates.rollback.description":`Estás usando una versión beta. Al desactivar las actualizaciones beta, Yuri volverá a la versión estable v{version}. Reinicia la aplicación para aplicar el cambio.`,"settings.yuri.about.betaUpdates.rollback.actions.cancel":`Mantener beta`,"settings.yuri.about.betaUpdates.rollback.actions.confirm":`Volver a estable`,"settings.yuri.about.diagnostics.label":`Registro de diagnóstico`,"settings.yuri.about.diagnostics.description":`Exporta los feat de diagnóstico locales para analizar problemas de visualización y sincronización. No incluye cuerpos de mensajes ni tokens.`,"settings.yuri.about.diagnostics.export":`Exportar registro`,"settings.yuri.about.diagnostics.exporting":`Exportando…`,"settings.yuri.about.diagnostics.enable":`Registrar feat de diagnóstico`,"settings.yuri.about.diagnostics.enableHint":`Disponible en versiones beta. Registra en este dispositivo el ciclo de sincronización y visualización de la sesión, sin el cuerpo del mensaje.`,"settings.yuri.about.diagnostics.toast.exported":`Registro de diagnóstico exportado`,"settings.yuri.about.diagnostics.toast.failed":`No se pudo exportar el registro de diagnóstico`,"settings.yuri.about.diagnostics.toast.empty":`Registro de diagnóstico exportado. Aún no se registró ningún evento.`,"settings.agents.sidebar.title":`Configuración de agentes`,"settings.agents.sidebar.total":`Total {count}`,"settings.agents.sidebar.empty.title":`No hay agentes configurados`,"settings.agents.sidebar.empty.description":`Usa el botón + arriba para crear uno`,"settings.agents.sidebar.section.builtIn":`Agentes incorporados`,"settings.agents.sidebar.section.custom":`Agentes personalizados`,"settings.agents.sidebar.badge.system":`sistema`,"settings.agents.sidebar.badge.disabled":`Desactivado`,"settings.agents.sidebar.dialog.deleteTitle":`Eliminar agente`,"settings.agents.sidebar.dialog.resetTitle":`Restablecer agente`,"settings.agents.sidebar.dialog.deleteDescription":`¿Seguro que quieres eliminar el agente "{name}"?`,"settings.agents.sidebar.dialog.resetDescription":`¿Seguro que quieres restablecer el agente "{name}" a su configuración predeterminada?`,"settings.agents.sidebar.renameDialog.title":`Cambiar nombre del agente`,"settings.agents.sidebar.renameDialog.description":`Introduce un nuevo nombre para el agente "@{name}"`,"settings.agents.sidebar.renameDialog.placeholder":`Nuevo nombre del agente...`,"settings.agents.sidebar.toast.builtInCannotDelete":`Los agentes incorporados no pueden eliminarse`,"settings.agents.sidebar.toast.agentDeleted":`Agente "{name}" eliminado correctamente`,"settings.agents.sidebar.toast.agentReset":`Agente "{name}" restablecido a la configuración predeterminada`,"settings.agents.sidebar.toast.deleteFailed":`No se pudo eliminar el agente`,"settings.agents.sidebar.toast.definitionNotFound":`No se encontró la definición del agente. No se cambió nada.`,"settings.agents.sidebar.toast.resetFailed":`No se pudo restablecer el agente`,"settings.agents.sidebar.toast.agentNameRequired":`Se requiere el nombre del agente`,"settings.agents.sidebar.toast.agentExists":`Ya existe un agente con este nombre`,"settings.agents.sidebar.toast.removeOldAfterRenameFailed":`No se pudo eliminar el antiguo agente después del cambio de nombre`,"settings.agents.sidebar.toast.renameFailed":`No se pudo cambiar el nombre del agente`,"settings.agents.sidebar.toast.agentRenamed":`Agente renombrado a "{name}"`,"settings.agents.page.toast.permissionNameRequired":`Se requiere el nombre del permiso`,"settings.agents.page.toast.created":`Agente creado correctamente`,"settings.agents.page.toast.updated":`Agente actualizado correctamente`,"settings.agents.page.toast.createFailed":`No se pudo crear el agente`,"settings.agents.page.toast.updateFailed":`No se pudo actualizar el agente`,"settings.agents.page.toast.saveUnexpectedError":`Ocurrió un error al guardar`,"settings.agents.page.toast.savedManualRestart":`Guardado en disco. Reinicia tu servidor OpenCode conectado para aplicar los cambios.`,"settings.agents.page.empty.title":`Selecciona un agente desde la barra lateral`,"settings.agents.page.empty.description":`o crea uno nuevo`,"settings.agents.page.title.new":`Nuevo agente`,"settings.agents.page.subtitle.new":`Configura una nueva asistente`,"settings.agents.page.subtitle.edit":`Editar configuración del agente`,"settings.agents.page.section.identityRole":`Identidad y rol`,"settings.agents.page.section.modelParameters":`Modelo`,"settings.agents.page.section.runtime":`Ejecución`,"settings.agents.page.field.steps":`Límite de pasos`,"settings.agents.page.field.stepsHint":`Vacío significa sin límite. Al llegar al límite, la siguiente petición solo puede responder con texto.`,"settings.agents.page.field.hidden":`Oculto`,"settings.agents.page.field.hiddenHint":`Oculta este agente del selector principal y de las menciones @. La tarea aún puede llamarlo si los permisos lo permiten.`,"settings.agents.page.field.disabled":`Desactivado`,"settings.agents.page.field.disabledHint":`Quita este agente del catálogo. Desactívalo y guarda para devolverlo a la lista.`,"settings.agents.page.field.color":`Color`,"settings.agents.page.field.colorHint":`Color hexadecimal, como #FF6B6B.`,"settings.agents.page.field.colorInvalid":`Escribe un color hexadecimal como #FF6B6B.`,"settings.agents.page.field.clearColorAria":`Borrar color`,"settings.agents.page.field.modelHint":`Déjalo vacío para conservar el modelo de quien llama. La variante se guarda con el modelo.`,"settings.agents.page.system.inheritHint":`Vacío conserva la indicación integrada. El texto de aquí la sustituye. Las instrucciones del proyecto se añaden después.`,"settings.agents.page.apply.hint":`Se aplica en la siguiente petición y en las sesiones nuevas. Una sesión que ya está en curso conserva su modelo.`,"settings.agents.page.legacy.convertible":`Al guardar, este archivo de agente se convierte al formato actual.`,"settings.agents.page.legacy.dropped":`Estos campos no se conservarán: {fields}. No cambian la siguiente petición.`,"settings.agents.page.legacy.confirmDrop":`Convertir y descartar esos campos`,"settings.agents.page.toast.savedNextRequest":`Guardado. La siguiente petición y las sesiones nuevas usan este agente. Una sesión en curso conserva su modelo.`,"settings.agents.page.section.systemPrompt":`Prompt del sistema`,"settings.agents.page.section.toolPermissions":`Permisos de herramientas`,"settings.agents.page.field.agentName":`Nombre del agente`,"settings.agents.page.field.agentNamePlaceholder":`nombre-agente`,"settings.agents.page.field.scope":`Ámbito`,"settings.agents.page.field.scopePlaceholder":`Ámbito`,"settings.agents.page.field.descriptionPlaceholder":`¿Qué hace este agente?`,"settings.agents.page.field.mode":`Modo`,"settings.agents.page.field.modeTooltip":`Visibilidad principal vs subagente`,"settings.agents.page.field.overrideModel":`Sobrescribir modelo`,"settings.agents.page.field.variant":`Variante de pensamiento`,"settings.agents.page.field.variantTooltip":`Opcional. Si el modelo admite razonamiento, la variante controla la profundidad del razonamiento.`,"settings.agents.page.field.variantHint":`Específico del modelo (p. ej. variante de Anthropic)`,"settings.agents.page.field.variantPlaceholder":`p. ej. high, max, low, none`,"settings.agents.page.field.temperature":`Temperatura`,"settings.agents.page.field.temperatureTooltip":`Controla la aleatoriedad. Mayor = más creativo, menor = más enfocado.`,"settings.agents.page.field.temperatureRange":`0.0 a 2.0`,"settings.agents.page.field.clearTemperatureAria":`Limpiar sobrescritura de temperatura`,"settings.agents.page.field.topP":`Top P`,"settings.agents.page.field.topPTooltip":`Diversidad de muestreo del núcleo. Más bajo = solo tokens más probables.`,"settings.agents.page.field.topPRange":`0.0 a 1.0`,"settings.agents.page.field.clearTopPAria":`Limpiar sobrescritura de top p`,"settings.agents.page.field.systemPromptPlaceholder":`Eres un asistente experto en programación...`,"settings.agents.page.mode.primary":`Primario`,"settings.agents.page.mode.subagent":`Subagente`,"settings.agents.page.mode.all":`Todos`,"settings.agents.page.permissions.defaultLabel":`Predeterminado`,"settings.agents.page.permissions.shell":`Shell`,"settings.agents.page.permissions.subagent":`Subagente`,"settings.agents.page.permissions.edit":`Editar`,"settings.agents.page.permissions.externalDirectory":`Directorio externo`,"settings.agents.page.permissions.question":`Pregunta`,"settings.agents.page.permissions.read":`Leer`,"settings.agents.page.permissions.glob":`Buscar archivos`,"settings.agents.page.permissions.grep":`Buscar texto`,"settings.agents.page.permissions.skill":`Skill`,"settings.agents.page.permissions.webfetch":`Obtener URL`,"settings.agents.page.permissions.websearch":`Búsqueda web`,"settings.agents.page.permissions.execute":`Ejecutar`,"settings.agents.page.permissions.browser":`Navegador`,"settings.agents.page.permissions.hideEditor":`Ocultar editor`,"settings.agents.page.permissions.advancedEditor":`Editor avanzado`,"settings.agents.page.permissions.globalSummary":`Global: {summary}`,"settings.agents.page.permissions.rulesSummary":`Reglas: {summary}`,"settings.agents.page.permissions.globalDefault":`Predeterminado global`,"settings.agents.page.permissions.pattern":`Patrón`,"settings.agents.page.permissions.addCustomRule":`Añadir regla personalizada`,"settings.agents.page.permissions.permissionPlaceholder":`Permiso...`,"settings.agents.page.permissions.patternPlaceholder":`Patrón (ej. *)`,"settings.permissions.saved.title":`Permisos de proyecto guardados`,"settings.permissions.saved.empty":`No hay permisos guardados para este proyecto`,"settings.permissions.saved.delete":`Eliminar`,"settings.permissions.saved.deleteFailed":`No se pudo eliminar el permiso guardado`,"settings.permissions.saved.loadFailed":`No se pudieron cargar los permisos guardados`,"settings.agents.page.permissions.lastMatchHint":`Gana la última regla coincidente`,"settings.page.behavior.title":`Comportamiento`,"settings.behavior.page.title":`Comportamiento`,"settings.behavior.page.warning.title":`Las reglas globales se combinan con las reglas del proyecto`,"settings.behavior.page.warning.description":`Los cambios realizados aquí actualizan {path}. OpenCode también incluye cualquier AGENTS.md a nivel de proyecto cuando existe.`,"settings.behavior.page.section.systemPrompt":`AGENTS.md global`,"settings.behavior.page.field.systemPromptPlaceholder":`Eres un asistente de IA útil...
2
2
 
3
3
  Usa este espacio para definir reglas absolutas sobre cómo la IA debe comportarse en todas las sesiones y proveedores.`,"settings.behavior.page.section.responseStyle":`Estilo de respuesta`,"settings.behavior.page.responseStyle.tooltip":`Cuando está habilitado, estas instrucciones guían cómo responde el asistente en cada conversación nueva. Se envían con tu primer mensaje y no cambian tus reglas globales de AGENTS.md.`,"settings.behavior.page.responseStyle.enableAria":`Habilitar instrucciones de estilo de respuesta`,"settings.behavior.page.responseStyle.enable":`Agregar instrucciones de estilo de respuesta a conversaciones nuevas`,"settings.behavior.page.responseStyle.preset":`Preset`,"settings.behavior.page.responseStyle.option.concise":`Conciso`,"settings.behavior.page.responseStyle.option.detailed":`Detallado`,"settings.behavior.page.responseStyle.option.mentor":`Mentor`,"settings.behavior.page.responseStyle.option.pushback":`Réplica`,"settings.behavior.page.responseStyle.option.noFiller":`Sin relleno`,"settings.behavior.page.responseStyle.option.matchEnergy":`Igualar mi tono`,"settings.behavior.page.responseStyle.option.warmPeer":`Colega cercano`,"settings.behavior.page.responseStyle.option.custom":`Personalizado`,"settings.behavior.page.responseStyle.customPlaceholder":`Escribe la instrucción que se agregará al primer mensaje...`,"settings.behavior.page.toast.saved":`Comportamiento guardado correctamente`,"settings.behavior.page.toast.saveFailed":`Error al guardar el comportamiento`,"settings.commands.sidebar.title":`Comandos`,"settings.commands.sidebar.total":`Total {count}`,"settings.commands.sidebar.empty.title":`No hay comandos configurados`,"settings.commands.sidebar.empty.description":`Usa el botón + arriba para crear uno`,"settings.commands.sidebar.section.builtIn":`Comandos incorporados`,"settings.commands.sidebar.section.custom":`Comandos personalizados`,"settings.commands.sidebar.dialog.deleteTitle":`Eliminar comando`,"settings.commands.sidebar.dialog.resetTitle":`Restablecer comando`,"settings.commands.sidebar.dialog.deleteDescription":`¿Estás seguro de que quieres eliminar el comando "{name}"?`,"settings.commands.sidebar.dialog.resetDescription":`¿Estás seguro de que quieres restablecer el comando "{name}" a su configuración predeterminada?`,"settings.commands.sidebar.renameDialog.title":`Cambiar nombre del comando`,"settings.commands.sidebar.renameDialog.description":`Introduce un nuevo nombre para el comando "/{name}"`,"settings.commands.sidebar.renameDialog.placeholder":`Nuevo nombre del comando...`,"settings.commands.sidebar.toast.builtInCannotDelete":`Los comandos incorporados no pueden eliminarse`,"settings.commands.sidebar.toast.commandDeleted":`Comando "{name}" eliminado`,"settings.commands.sidebar.toast.commandReset":`Comando "{name}" restablecido al valor predeterminado`,"settings.commands.sidebar.toast.deleteFailed":`No se pudo eliminar el comando`,"settings.commands.sidebar.toast.resetFailed":`No se pudo restablecer el comando`,"settings.commands.sidebar.toast.commandNameRequired":`Se requiere nombre del comando`,"settings.commands.sidebar.toast.commandExists":`Ya existe un comando con este nombre`,"settings.commands.sidebar.toast.removeOldAfterRenameFailed":`No se pudo eliminar el comando antiguo después del cambio de nombre`,"settings.commands.sidebar.toast.renameFailed":`No se pudo cambiar el nombre del comando`,"settings.commands.page.toast.templateRequired":`Se requiere plantilla del comando`,"settings.commands.page.toast.created":`Comando creado`,"settings.commands.page.toast.updated":`Comando actualizado`,"settings.commands.page.toast.createFailed":`No se pudo crear el comando`,"settings.commands.page.toast.updateFailed":`No se pudo actualizar el comando`,"settings.commands.page.toast.saveUnexpectedError":`Ocurrió un error al guardar`,"settings.commands.page.empty.title":`Selecciona un comando de la barra lateral`,"settings.commands.page.empty.description":`o crea uno nuevo`,"settings.commands.page.title.new":`Nuevo comando`,"settings.commands.page.subtitle.new":`Configura un nuevo comando slash`,"settings.commands.page.subtitle.edit":`Editar configuración del comando`,"settings.commands.page.section.identity":`Identidad`,"settings.commands.page.section.executionContext":`Contexto de ejecución`,"settings.commands.page.section.template":`Plantilla del comando`,"settings.commands.page.field.commandName":`Nombre del comando`,"settings.commands.page.field.commandNamePlaceholder":`nombre-del-comando`,"settings.commands.page.field.descriptionPlaceholder":`¿Qué hace este comando?`,"settings.commands.page.field.overrideAgent":`Sobrescribir agente`,"settings.commands.page.field.templatePlaceholder":`Tu plantilla de comando aquí...
4
4
 
@@ -1,2 +1,2 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{st as t}from"./persistence-Dzooc9Xg.js";import{it as n,nt as r,rt as i}from"./vendor-base-ui-CdzJ6My_.js";import{n as a}from"./vendor-react-BP2cRVqX.js";import{r as o}from"./button-C3292Ee6.js";import{st as s}from"./useMobileNavigationStore-CEVJSNnR.js";import{r as c,t as l}from"./Icon-jsQQXouE.js";import{t as u}from"./vendor-fuzzysort-ukaRp9PC.js";var d=e=>{switch(e.name){case`new`:return`add`;case`init`:return`file`;case`undo`:return`arrow-go-back`;case`redo`:return`arrow-go-forward`;case`timeline`:return`time`;case`compact`:return`scissors`;case`reload`:return`refresh`;case`goal`:return`target`;case`review`:return`search-eye`;case`test`:case`build`:case`run`:return`terminal-box`;default:return e.isBuiltIn?`flashlight`:`command`}},f=()=>`book-open`,p=e=>{if(e.isDirectory)return`folder-3-fill`;switch(e.extension?.toLowerCase()){case`ts`:case`tsx`:case`js`:case`jsx`:case`json`:return`code`;case`md`:case`mdx`:return`file`;case`png`:case`jpg`:case`jpeg`:case`gif`:case`svg`:return`file-image`;default:return`file-pdf`}},m=()=>`ai-agent`,h=()=>`chat-thread`,g=32,_=(e,t)=>{let n=c[e];return typeof n!=`string`||n.length===0?null:`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="${t}" stroke-width="${l}" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`},v=(e,t)=>{let n=_(e,t);return!n||typeof document>`u`?Promise.resolve(null):new Promise(e=>{let t=new Image;t.decoding=`async`,t.onload=()=>{try{let n=document.createElement(`canvas`);n.width=g,n.height=g;let r=n.getContext(`2d`);if(!r){e(null);return}r.clearRect(0,0,g,g),r.drawImage(t,0,0,g,g);let i=n.toDataURL(`image/png`),a=i.indexOf(`,`);e(a>=0?i.slice(a+1):null)}catch{e(null)}},t.onerror=()=>e(null),t.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(n)}`})},y=e(u(),1),b=(e,t)=>e.map(e=>{let n=e.isSkill?t.skill:e.isYuri?`Yuri`:e.isBuiltIn?t.system:e.scope||e.agent||t.command;return{id:e.id,title:`/${e.name}`,subtitle:e.description,badge:n,iconName:d(e)}}),x=({skills:e=[],agents:t,sessions:n,recentFiles:r,pathHits:i,untitledSession:a,sessionBadge:o,skillBadge:s,searchQuery:c=``})=>{let l=[];for(let t of e)l.push({id:`skill:${t.name}-${t.scope}`,title:`@${t.name}`,subtitle:t.description,badge:s??t.scope,iconName:f()});for(let e of t)l.push({id:`agent:${e.name}`,title:`@${e.name}`,subtitle:e.description,iconName:m(),agentName:e.name});let u=c.trim(),d=u?y.default.go(u,l,{keys:[`title`,e=>e.id.startsWith(`skill:`)?e.subtitle??``:``],threshold:.5,limit:10,scoreFn:e=>{let t=e[0],n=(t?.score??0)*(t?.target.startsWith(`@${u}`)?2:1);return n>=.5?1+n:e[1]?.score??0}}).map(e=>e.obj):l.slice();l.length=0;for(let e of r)l.push({id:`recent:${e.path}`,title:e.relativePath||e.name,iconName:p(e)});for(let e of i)l.push({id:`file:${e.path}`,title:e.relativePath||e.name,iconName:p(e)});for(let e of n)l.push({id:`session:${e.id}`,title:e.title||a,badge:o,iconName:h()});return u?[...d,...l].slice(0,10):[...d,...l]},S=(e,n)=>{if(!e.includes(`/`)||n.size===0)return[];let r=RegExp(`(^|\\s)/(${t})?([A-Za-z0-9][A-Za-z0-9_-]*)(?=$|\\s)`,`g`),i=[],a;for(;(a=r.exec(e))!==null;){let e=a[3]??``;if(!n.has(e.toLowerCase()))continue;let t=a[2]??``,r=a.index+(a[1]?.length??0);i.push({start:r,end:r+1+t.length+e.length,name:e,hasSlot:t.length>0})}return i},C=(e,n,r=e.length)=>{let i=S(e,n).filter(e=>!e.hasSlot);if(i.length===0)return null;let a=e,o=r;for(let e=i.length-1;e>=0;--e){let n=i[e].start+1;a=`${a.slice(0,n)}${t}${a.slice(n)}`,o>n&&(o+=t.length)}return a===e?null:{text:a,caret:o}},w=e=>e.startsWith(t)?e.slice(t.length):e,T=e=>{if(e.inputMode===`shell`)return null;let t=e.text,n=Math.max(0,Math.min(e.cursor,t.length));if(t.startsWith(`/`)){let e=t.indexOf(` `),r=t.indexOf(`
1
+ import{r as e}from"./rolldown-runtime-hePW80VL.js";import{st as t}from"./persistence-Dzooc9Xg.js";import{it as n,nt as r,rt as i}from"./vendor-base-ui-CdzJ6My_.js";import{n as a}from"./vendor-react-BP2cRVqX.js";import{r as o}from"./button-_ReBqWzC.js";import{st as s}from"./useMobileNavigationStore-ByrZJd5L.js";import{r as c,t as l}from"./Icon-2cKLcXGe.js";import{t as u}from"./vendor-fuzzysort-ukaRp9PC.js";var d=e=>{switch(e.name){case`new`:return`add`;case`init`:return`file`;case`undo`:return`arrow-go-back`;case`redo`:return`arrow-go-forward`;case`timeline`:return`time`;case`compact`:return`scissors`;case`reload`:return`refresh`;case`goal`:return`target`;case`review`:return`search-eye`;case`test`:case`build`:case`run`:return`terminal-box`;default:return e.isBuiltIn?`flashlight`:`command`}},f=()=>`book-open`,p=e=>{if(e.isDirectory)return`folder-3-fill`;switch(e.extension?.toLowerCase()){case`ts`:case`tsx`:case`js`:case`jsx`:case`json`:return`code`;case`md`:case`mdx`:return`file`;case`png`:case`jpg`:case`jpeg`:case`gif`:case`svg`:return`file-image`;default:return`file-pdf`}},m=()=>`ai-agent`,h=()=>`chat-thread`,g=32,_=(e,t)=>{let n=c[e];return typeof n!=`string`||n.length===0?null:`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="${t}" stroke-width="${l}" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`},v=(e,t)=>{let n=_(e,t);return!n||typeof document>`u`?Promise.resolve(null):new Promise(e=>{let t=new Image;t.decoding=`async`,t.onload=()=>{try{let n=document.createElement(`canvas`);n.width=g,n.height=g;let r=n.getContext(`2d`);if(!r){e(null);return}r.clearRect(0,0,g,g),r.drawImage(t,0,0,g,g);let i=n.toDataURL(`image/png`),a=i.indexOf(`,`);e(a>=0?i.slice(a+1):null)}catch{e(null)}},t.onerror=()=>e(null),t.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(n)}`})},y=e(u(),1),b=(e,t)=>e.map(e=>{let n=e.isSkill?t.skill:e.isYuri?`Yuri`:e.isBuiltIn?t.system:e.scope||e.agent||t.command;return{id:e.id,title:`/${e.name}`,subtitle:e.description,badge:n,iconName:d(e)}}),x=({skills:e=[],agents:t,sessions:n,recentFiles:r,pathHits:i,untitledSession:a,sessionBadge:o,skillBadge:s,searchQuery:c=``})=>{let l=[];for(let t of e)l.push({id:`skill:${t.name}-${t.scope}`,title:`@${t.name}`,subtitle:t.description,badge:s??t.scope,iconName:f()});for(let e of t)l.push({id:`agent:${e.name}`,title:`@${e.name}`,subtitle:e.description,iconName:m(),agentName:e.name});let u=c.trim(),d=u?y.default.go(u,l,{keys:[`title`,e=>e.id.startsWith(`skill:`)?e.subtitle??``:``],threshold:.5,limit:10,scoreFn:e=>{let t=e[0],n=(t?.score??0)*(t?.target.startsWith(`@${u}`)?2:1);return n>=.5?1+n:e[1]?.score??0}}).map(e=>e.obj):l.slice();l.length=0;for(let e of r)l.push({id:`recent:${e.path}`,title:e.relativePath||e.name,iconName:p(e)});for(let e of i)l.push({id:`file:${e.path}`,title:e.relativePath||e.name,iconName:p(e)});for(let e of n)l.push({id:`session:${e.id}`,title:e.title||a,badge:o,iconName:h()});return u?[...d,...l].slice(0,10):[...d,...l]},S=(e,n)=>{if(!e.includes(`/`)||n.size===0)return[];let r=RegExp(`(^|\\s)/(${t})?([A-Za-z0-9][A-Za-z0-9_-]*)(?=$|\\s)`,`g`),i=[],a;for(;(a=r.exec(e))!==null;){let e=a[3]??``;if(!n.has(e.toLowerCase()))continue;let t=a[2]??``,r=a.index+(a[1]?.length??0);i.push({start:r,end:r+1+t.length+e.length,name:e,hasSlot:t.length>0})}return i},C=(e,n,r=e.length)=>{let i=S(e,n).filter(e=>!e.hasSlot);if(i.length===0)return null;let a=e,o=r;for(let e=i.length-1;e>=0;--e){let n=i[e].start+1;a=`${a.slice(0,n)}${t}${a.slice(n)}`,o>n&&(o+=t.length)}return a===e?null:{text:a,caret:o}},w=e=>e.startsWith(t)?e.slice(t.length):e,T=e=>{if(e.inputMode===`shell`)return null;let t=e.text,n=Math.max(0,Math.min(e.cursor,t.length));if(t.startsWith(`/`)){let e=t.indexOf(` `),r=t.indexOf(`
2
2
  `),i=Math.min(e===-1?t.length:e,r===-1?t.length:r);if(n<=i&&e===-1)return{kind:`slash-command`,query:w(t.substring(1,i)),tokenStart:0,tokenEnd:i}}let r=t.substring(0,n),i=s({value:t,cursorPosition:n,inputSource:e.mentionInputSource??`manual`,insertedText:e.insertedText});return i===null?null:{kind:`mention`,query:i,tokenStart:r.lastIndexOf(`@`),tokenEnd:n}},E=e=>e===`mention`?`@`:`/`,D=(e,t,n)=>{if(n&&n.tokenStart>=0&&n.tokenEnd>=n.tokenStart&&n.tokenEnd<=e.length&&e.startsWith(E(n.kind),n.tokenStart))return{start:n.tokenStart,end:n.tokenEnd};let r=T({text:e,cursor:t});return r?{start:r.tokenStart,end:r.tokenEnd}:null},O=e(n(),1),k=a(),A=e(r(),1),j=`absolute z-[100] min-w-0 w-full bottom-full mb-2 left-0 flex flex-col rounded-xl`,M=`pointer-events-auto absolute z-[100] min-w-0 flex flex-col rounded-xl`;function N(e,t){return o(e?M:j,`yuri-mobile-overlay-surface yuri-mobile-overlay-surface--translucent yuri-composer-autocomplete-surface`,t)}function P(e,t){return e?`yuri-composer-autocomplete-row`:o(`mx-1.5 hover:bg-[color-mix(in_srgb,var(--interactive-selection)_40%,transparent)]`,t&&`bg-[color-mix(in_srgb,var(--interactive-selection)_40%,transparent)]`)}var F=.4,I=e=>{let t=e.gap??8,n=Math.min(e.composerTop-t,e.visibleBottom-t);return{left:e.composerLeft,width:e.composerWidth,bottom:Math.max(0,e.fixedContainingBottom-n),maxHeight:L({popupBottom:n,boundaryTop:e.boundaryTop,viewportHeight:e.viewportHeight,gap:t})}},L=e=>{let t=e.gap??8,n=Math.max(0,e.popupBottom-e.boundaryTop-t),r=e.viewportHeight*F,i=Math.floor(Math.min(n,r));return n>=120?Math.min(n,Math.max(120,i)):i},R=(e,t=0)=>{let n=e.closest(`main`);if(!n)return null;let r=(e.closest(`.mobile-chat-screen__content`)?.parentElement??n.parentElement?.closest(`main`)??n).querySelector(`:scope > .yuri-mobile-detail-navigation`)?.getBoundingClientRect().bottom,i=n.getBoundingClientRect().top;return Math.max(r===void 0?i:Math.max(r,i),t)},z=(e,t)=>{let n=(0,k.c)(5),[r,i]=O.useState(void 0),a;n[0]!==t||n[1]!==e?(a=()=>{if(!t){i(void 0);return}let n=0,r=0,a=()=>{let t=e.current?.parentElement;if(!t)return;let n=t.getBoundingClientRect(),r=window.visualViewport,a=r?.offsetTop??0,o=r?.height??window.innerHeight,s=window.innerHeight,c=a+o,l=R(t,a)??a,u=I({composerTop:n.top,composerLeft:n.left,composerWidth:n.width,fixedContainingBottom:s,visibleBottom:c,boundaryTop:l,viewportHeight:o});i(e=>e&&e.left===u.left&&e.width===u.width&&e.bottom===u.bottom&&e.maxHeight===u.maxHeight?e:u)},o=()=>{a(),n&&window.cancelAnimationFrame(n),r&&window.clearTimeout(r),n=window.requestAnimationFrame(()=>{a(),r=window.setTimeout(a,220)})};return a(),window.addEventListener(`resize`,a),window.addEventListener(`yuri:keyboard-settled`,o),window.addEventListener(`yuri:keyboard-anim`,o),window.visualViewport?.addEventListener(`resize`,a),window.visualViewport?.addEventListener(`scroll`,a),()=>{n&&window.cancelAnimationFrame(n),r&&window.clearTimeout(r),window.removeEventListener(`resize`,a),window.removeEventListener(`yuri:keyboard-settled`,o),window.removeEventListener(`yuri:keyboard-anim`,o),window.visualViewport?.removeEventListener(`resize`,a),window.visualViewport?.removeEventListener(`scroll`,a)}},n[0]=t,n[1]=e,n[2]=a):a=n[2];let o;return n[3]===t?o=n[4]:(o=[t],n[3]=t,n[4]=o),O.useLayoutEffect(a,o),t?r:void 0},B=i(),V=O.forwardRef((e,t)=>{let n=(0,k.c)(24),{isMobile:r,className:i,style:a,children:o}=e,s=O.useRef(null),c=z(s,r),l=typeof document<`u`?document.body:null;if(!r){let e;n[0]===i?e=n[1]:(e=N(!1,i),n[0]=i,n[1]=e);let r;return n[2]!==o||n[3]!==t||n[4]!==a||n[5]!==e?(r=(0,B.jsx)(`div`,{ref:t,className:e,style:a,children:o}),n[2]=o,n[3]=t,n[4]=a,n[5]=e,n[6]=r):r=n[6],r}let u;n[7]===i?u=n[8]:(u=N(!0,i),n[7]=i,n[8]=u);let d;n[9]===c?d=n[10]:(d=c?{left:c.left,width:c.width,bottom:c.bottom,maxHeight:c.maxHeight,overflow:`hidden`}:{visibility:`hidden`},n[9]=c,n[10]=d);let f;n[11]!==a||n[12]!==d?(f={...a,...d},n[11]=a,n[12]=d,n[13]=f):f=n[13];let p;n[14]!==o||n[15]!==t||n[16]!==u||n[17]!==f?(p=(0,B.jsx)(`div`,{className:`pointer-events-none fixed inset-0 z-[100]`,children:(0,B.jsx)(`div`,{ref:t,className:u,style:f,children:o})}),n[14]=o,n[15]=t,n[16]=u,n[17]=f,n[18]=p):p=n[18];let m=p,h;n[19]===Symbol.for(`react.memo_cache_sentinel`)?(h=(0,B.jsx)(`span`,{ref:s,className:`hidden`,"aria-hidden":!0}),n[19]=h):h=n[19];let g;n[20]===m?g=n[21]:(g=l?(0,A.createPortal)(m,l):m,n[20]=m,n[21]=g);let _;return n[22]===g?_=n[23]:(_=(0,B.jsxs)(B.Fragment,{children:[h,g]}),n[22]=g,n[23]=_),_});V.displayName=`ComposerAutocompleteLayer`;var H=()=>{let e=null,t=!1,n=!1;return{pointerDown:(n,r)=>{e={x:n,y:r},t=!1},pointerMove:(n,r)=>{e&&Math.hypot(n-e.x,r-e.y)>6&&(t=!0)},pointerCancel:()=>{e=null,t=!1},pointerUp:r=>{if(!e)return!1;let i=!t;return e=null,t=!1,i?(n=!0,r(),!0):(n=!0,!1)},click:e=>n?(n=!1,!1):(e(),!0)}};export{T as a,x as c,d,D as i,b as l,V as n,C as o,P as r,w as s,H as t,v as u};