@cerebriline/core 4.100.276 → 4.100.277

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.
@@ -348,7 +348,7 @@ Use it when you are unsure:
348
348
  - how complex the task is, before deciding to escalate or delegate it.
349
349
 
350
350
  Arguments:
351
- - `context` — the situation, in plain text: what the user asked, what you found, what you are deciding. Only what the questions need; unrelated text makes the answers worse.
351
+ - `context` — the situation, in plain text: what the user asked, what you found, what you are deciding. Only what the questions need; unrelated text makes the answers worse. Jev reads at most 24,000 characters of it; past that the middle is cut, and the result says so.
352
352
  - `questions` — 1 to 10, all asked in one call. Each has an `id`, a `kind` and a `question`:
353
353
  - `yes_no` — a yes/no question. Returns the probability of yes.
354
354
  - `choice` — pick one of `options` (2 to 50). Include a "none of these" option when that is possible: a choice always picks something.
@@ -1,11 +1,11 @@
1
- import{execFile as sn}from"node:child_process";import{basename as To,resolve as on}from"node:path";import{promisify as rn}from"node:util";import{processWorkspaceInfo as Ho}from"@cerebriline/shared";import Ke from"simple-git";var an=rn(sn);function dn(e,t){return an("git",e,{cwd:t.cwd,encoding:"utf8",windowsHide:!0,signal:t.signal,timeout:15000,maxBuffer:10485760,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||"ssh -o BatchMode=yes"}})}function K(e){if(!e||typeof e!=="object"||!("stderr"in e))return"";return typeof e.stderr==="string"?e.stderr.trim():""}function Q(e){if(!e||typeof e!=="object"||!("code"in e))return;return typeof e.code==="number"?e.code:void 0}function Qe(e){let t=Ye(e.cwd),n=e.git??dn,s=async(i)=>(await n(i,{cwd:t,signal:e.signal})).stdout,o=async(i)=>(await s(i)).trim();return{async isInsideWorkTree(){try{return await o(["rev-parse","--is-inside-work-tree"])==="true"}catch(i){if(Q(i)===128&&/not a git repository|Kein Git-Repository/i.test(K(i)))return!1;throw i}},remotes:()=>Ke({baseDir:t}).getRemotes(!0),displayBranch:async()=>(await Ke({baseDir:t}).branch()).current.trim(),symbolicBranch:()=>o(["symbolic-ref","--quiet","--short","HEAD"]),headSha:()=>o(["rev-parse","HEAD"]),workspacePrefix:async()=>(await s(["rev-parse","--show-prefix"])).replace(/[\r\n]+$/,""),worktreeStatus:()=>o(["status","--porcelain=v1","--untracked-files=all","--ignore-submodules=none"]),branchRemote:(i)=>o(["config","--get",`branch.${i}.remote`]),branchMergeRef:(i)=>o(["config","--get",`branch.${i}.merge`]),remoteUrl:(i)=>o(["remote","get-url",i]),remoteRefs:(i,r)=>o(["ls-remote","--exit-code",i,r])}}function Ye(e){return on(e)}class _ extends Error{code;constructor(e,t,n){super(t,n);this.code=e;this.name="CloudHandoffGitPreflightError"}}function Xe(e){let t=0,n=e.length;while(t<n&&e[t]==="/")t+=1;while(n>t&&e[n-1]==="/")n-=1;let s=e.slice(t,n);return s.toLowerCase().endsWith(".git")?s.slice(0,-4):s}function Ze(e){let t=e.trim();if(!t)return null;let n=t.match(/^(?:[^@/\s]+@)?github\.com:([^\s]+)$/i);if(n?.[1]){let s=Xe(n[1]);return s.split("/").length===2?`https://github.com/${s}`:null}try{let s=new URL(t);if(s.hostname.toLowerCase()!=="github.com")return null;if(!new Set(["https:","http:","ssh:","git:"]).has(s.protocol))return null;let o=Xe(s.pathname);return o.split("/").length===2?`https://github.com/${o}`:null}catch{return null}}async function O(e,t,n){try{return await e()}catch(s){let o=K(s);throw new _(t,o?`${n} (${o})`:n,{cause:s})}}function cn(e,t){let n=`refs/heads/${t}`;for(let s of e.split(`
1
+ import{execFile as sn}from"node:child_process";import{basename as To,resolve as on}from"node:path";import{promisify as rn}from"node:util";import{processWorkspaceInfo as Ho}from"@cerebriline/shared";import{simpleGit as Ke}from"simple-git";var an=rn(sn);function dn(e,t){return an("git",e,{cwd:t.cwd,encoding:"utf8",windowsHide:!0,signal:t.signal,timeout:15000,maxBuffer:10485760,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||"ssh -o BatchMode=yes"}})}function K(e){if(!e||typeof e!=="object"||!("stderr"in e))return"";return typeof e.stderr==="string"?e.stderr.trim():""}function Q(e){if(!e||typeof e!=="object"||!("code"in e))return;return typeof e.code==="number"?e.code:void 0}function Qe(e){let t=Ye(e.cwd),n=e.git??dn,s=async(i)=>(await n(i,{cwd:t,signal:e.signal})).stdout,o=async(i)=>(await s(i)).trim();return{async isInsideWorkTree(){try{return await o(["rev-parse","--is-inside-work-tree"])==="true"}catch(i){if(Q(i)===128&&/not a git repository|Kein Git-Repository/i.test(K(i)))return!1;throw i}},remotes:()=>Ke({baseDir:t}).getRemotes(!0),displayBranch:async()=>(await Ke({baseDir:t}).branch()).current.trim(),symbolicBranch:()=>o(["symbolic-ref","--quiet","--short","HEAD"]),headSha:()=>o(["rev-parse","HEAD"]),workspacePrefix:async()=>(await s(["rev-parse","--show-prefix"])).replace(/[\r\n]+$/,""),worktreeStatus:()=>o(["status","--porcelain=v1","--untracked-files=all","--ignore-submodules=none"]),branchRemote:(i)=>o(["config","--get",`branch.${i}.remote`]),branchMergeRef:(i)=>o(["config","--get",`branch.${i}.merge`]),remoteUrl:(i)=>o(["remote","get-url",i]),remoteRefs:(i,r)=>o(["ls-remote","--exit-code",i,r])}}function Ye(e){return on(e)}class _ extends Error{code;constructor(e,t,n){super(t,n);this.code=e;this.name="CloudHandoffGitPreflightError"}}function Xe(e){let t=0,n=e.length;while(t<n&&e[t]==="/")t+=1;while(n>t&&e[n-1]==="/")n-=1;let s=e.slice(t,n);return s.toLowerCase().endsWith(".git")?s.slice(0,-4):s}function Ze(e){let t=e.trim();if(!t)return null;let n=t.match(/^(?:[^@/\s]+@)?github\.com:([^\s]+)$/i);if(n?.[1]){let s=Xe(n[1]);return s.split("/").length===2?`https://github.com/${s}`:null}try{let s=new URL(t);if(s.hostname.toLowerCase()!=="github.com")return null;if(!new Set(["https:","http:","ssh:","git:"]).has(s.protocol))return null;let o=Xe(s.pathname);return o.split("/").length===2?`https://github.com/${o}`:null}catch{return null}}async function O(e,t,n){try{return await e()}catch(s){let o=K(s);throw new _(t,o?`${n} (${o})`:n,{cause:s})}}function cn(e,t){let n=`refs/heads/${t}`;for(let s of e.split(`
2
2
  `)){let[o,i]=s.trim().split(/\s+/,2);if(i===n&&/^[0-9a-f]{40,64}$/i.test(o??""))return o??null}return null}function un(e){let t=e.replace(/[\r\n]+$/,"").replace(/\/+$/,"");if(!t)return;let n=t.split("/");if(t.startsWith("/")||n.some((s)=>!s||s==="."||s===".."))throw new _("git_command_failed","Could not resolve the workspace path relative to the Git repository.");return t}async function Uo(e){let t=Qe(e);if(!await O(t.isInsideWorkTree,"not_git_repository","Cloud handoff requires a Git repository."))throw new _("not_git_repository","Cloud handoff requires a Git working tree.");let s=un(await O(t.workspacePrefix,"git_command_failed","Could not resolve the workspace path relative to the Git repository.")),o=await O(t.worktreeStatus,"git_command_failed","Could not inspect the Git worktree.");if(o){let l=o.split(`
3
3
  `).filter(Boolean),m=l.slice(0,5).join(`
4
4
  `),y=l.length>5?`
5
5
  ...and ${l.length-5} more`:"";throw new _("dirty_worktree",`Commit and push local changes before handing off to cloud. Uncommitted files are not transferred.
6
6
 
7
7
  ${m}${y}`)}let i;try{i=await t.symbolicBranch()}catch(l){let m=Q(l)===1,y=K(l),w=m?"Cloud handoff requires a checked-out branch; detached HEAD is not supported.":"Could not inspect the current Git branch.";throw new _(m?"detached_head":"git_command_failed",y?`${w} (${y})`:w,{cause:l})}if(!i)throw new _("detached_head","Cloud handoff requires a checked-out branch; detached HEAD is not supported.");let[r,a,d]=await Promise.all([O(()=>t.branchRemote(i),"missing_upstream",`Branch ${i} has no upstream. Push it with -u before handing off.`),O(()=>t.branchMergeRef(i),"missing_upstream",`Branch ${i} has no upstream. Push it with -u before handing off.`),O(t.headSha,"git_command_failed","Could not resolve the current commit.")]);if(!r||r==="."||!a.startsWith("refs/heads/"))throw new _("missing_upstream",`Branch ${i} has no remote branch upstream. Push it with -u before handing off.`);let u=a.slice(11),f=r;if(!Ze(r))try{f=await t.remoteUrl(r)}catch{throw new _("missing_upstream","Could not resolve the upstream remote.")}let c=Ze(f);if(!c)throw new _("unsupported_remote","Cloud handoff currently requires a github.com upstream remote.");let h;try{h=await t.remoteRefs(r,a)}catch(l){let m=Q(l)===2,y=m?`The upstream branch ${u} was not found. Push it before handing off.`:"Could not verify the remote branch. Check your network and GitHub authentication, then try again.";throw new _(m?"remote_branch_missing":"git_command_failed",y)}let p=cn(h,u);if(!p)throw new _("remote_branch_missing",`The upstream branch ${u} was not found. Push it before handing off.`);if(p.toLowerCase()!==d.toLowerCase())throw new _("unpushed_commits",`Local HEAD does not match the upstream branch ${u}. Push the current commit before handing off.`);return{repoUrl:c,branch:u,headSha:d,...s?{workspaceRelativePath:s}:{}}}function fe(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function x(e){if(typeof e!=="string")return;return e.trim()||void 0}function ln(e){return typeof e==="string"&&e.length>0?e:void 0}function pn(e){let t=x(e.repoUrl),n=x(e.branch),s=x(e.headSha),o=x(e.modelId);if(!t||!n||!s||!o)throw Error("Cloud handoff fingerprint fields cannot be empty.");let i=x(e.organizationId),r=ln(e.workspaceRelativePath),a=e.mode;return{repoUrl:t,branch:n,headSha:s,modelId:o,...i?{organizationId:i}:{},...r?{workspaceRelativePath:r}:{},...a?{mode:a}:{}}}function Do(e,t){return e!==void 0&&t!==void 0&&e.repoUrl===t.repoUrl&&e.branch===t.branch&&e.headSha.toLowerCase()===t.headSha.toLowerCase()&&e.modelId===t.modelId&&e.organizationId===t.organizationId&&e.workspaceRelativePath===t.workspaceRelativePath&&e.mode===t.mode}function fn(e){let t=fe(e);if(!t||typeof t.repoUrl!=="string"||typeof t.branch!=="string"||typeof t.headSha!=="string"||typeof t.modelId!=="string")return;try{return pn({repoUrl:t.repoUrl,branch:t.branch,headSha:t.headSha,modelId:t.modelId,...typeof t.organizationId==="string"?{organizationId:t.organizationId}:{},...typeof t.workspaceRelativePath==="string"?{workspaceRelativePath:t.workspaceRelativePath}:{},...t.mode==="plan"||t.mode==="yolo"||t.mode==="zen"?{mode:t.mode}:{}})}catch{return}}function Bo(e){let t=fe(fe(e)?.handoff);if(!t)return;let n=x(t.toCloudSessionId),s=x(t.handedOffAt),o=t.status;if(!n||!s||o!=="pending"&&o!=="complete")return;let i=x(t.innerSessionId),r=x(t.dashboardUrl),a=fn(t.fingerprint);return{toCloudSessionId:n,handedOffAt:s,status:o,...i?{innerSessionId:i}:{},...r?{dashboardUrl:r}:{},...a?{fingerprint:a}:{}}}function qo(e,t){return{...e??{},handoff:t}}function No(e){let{handoff:t,cloudHandoffIntent:n,cloudHandoffSeedDispatched:s,...o}=e??{};return o}function $o(e,t){let n=t.trim();if(!n)throw Error("Cloud session id cannot be empty.");let s=new URL("/agents",e);return s.searchParams.set("sessionId",n),s.toString()}function et(e){return e.map((t)=>{let n=t&&typeof t==="object"?t:{};return{role:n.role,content:n.content}})}function he(e,t){return e.length===t.length&&JSON.stringify(et(e))===JSON.stringify(et(t))}class me extends Error{constructor(e,t){super(`Cloud transcript verification failed (local ${e} messages, cloud ${t}).`);this.name="CloudHandoffTranscriptMismatchError"}}import{randomUUID as hn}from"node:crypto";import{decodeJwtPayload as mn}from"@cerebriline/shared";var gn=610000,yn=3000,B=15000,bn="CLOUD_SESSION_ERROR:",st="__cline_create_request__:";function ot(e){return(e.trim().split(`
8
- `)[0]??"").trim().slice(0,72)}class g extends Error{code;detail;connectUrl;status;constructor(e,t,n,s){super(`${bn}${JSON.stringify({code:e,message:t,connectUrl:n})}`);this.code=e;this.detail=t;this.connectUrl=n;this.status=s;this.name="CloudSessionError"}}class it extends Error{constructor(e){super(e instanceof Error?e.message:"Cloud handoff creation was rejected.",{cause:e});this.name="CloudHandoffCreationRejectedError"}}function be(e){let t=e.length;while(t>0&&e[t-1]==="/")t--;return e.slice(0,t)}function wn(e){return`${st}${e}`.slice(0,255)}function tt(e){return e?.startsWith(st)===!0}function we(e){switch(e){case"provisioning":case"cloning_repo":case"agent_starting":case"ready":case"failed":return e;default:return}}function ge(e){let t=mn(e.replace(/^workos:/,""));return typeof t?.sub==="string"&&t.sub.trim()?t.sub.trim():void 0}function nt(e){return new Promise((t,n)=>{if(e.aborted){n(e.reason);return}let s=()=>{clearTimeout(o),n(e.reason)},o=setTimeout(()=>{e.removeEventListener("abort",s),t()},yn);e.addEventListener("abort",s,{once:!0})})}function vn(e,t){if(e&&typeof e==="object"){let n=e.error;if(typeof n==="string"&&n.trim())return n.trim()}return t}function ye(e,t,n,s){let o=vn(t,`Cloud session request failed (${e})`);if(e===401)return new g("authentication_required",o);if(e===404)return new g("session_not_found",o);if(e===410)return new g("session_expired",o);if(e===412)return new g("github_not_connected",o,s??`${be(n)}/dashboard/integrations`);if(e===403&&o.trim().toLowerCase()==="forbidden")return new g("request_failed","Your active account or organization cannot create cloud sessions. Switch to Personal or another organization in Settings → Account, then try again.",void 0,e);return new g("request_failed",o,void 0,e)}class Cn{options;apiBaseUrl;appBaseUrl;fetchImpl;createTimeoutMs;unconfirmedHandoffCreates=new Set;completedHandoffCreates=new Map;constructor(e){this.options=e;this.apiBaseUrl=be(e.apiBaseUrl),this.appBaseUrl=be(e.appBaseUrl),this.fetchImpl=e.fetch??fetch,this.createTimeoutMs=e.createTimeoutMs??gn}async request(e,t={},n,s,o){let i=!1,r;while(!0){let a;try{a=typeof s==="string"?s:await this.options.getAuthToken()}catch(f){if(r)throw ye(401,void 0,this.appBaseUrl,n);throw f}if(!a?.trim())throw new g("authentication_required","Sign in to Cline before starting a cloud session.");if(a.trim()===r)throw new g("authentication_required","The cloud session credential was rejected. Sign in again.");if(typeof s==="object"){if(s.subject?ge(a.trim())!==s.subject:a.trim()!==s.token)throw new g("authentication_required","The signed-in account changed during cloud session creation.");s.token=a.trim()}o?.();let d=await this.fetchImpl(`${this.apiBaseUrl}${e}`,{...t,signal:t.signal??AbortSignal.timeout(B),headers:{Accept:"application/json",Authorization:`Bearer ${a.trim()}`,...t.body?{"Content-Type":"application/json"}:{},...t.headers}}),u=d.status===204?void 0:await d.json().catch(()=>{return});if(!d.ok){if(d.status===401&&typeof s==="object"&&!i&&s.subject){i=!0,r=a.trim();continue}throw ye(d.status,u,this.appBaseUrl,n)}return u?.data}}async list(e){return await this.listWithToken(e)}async listWithToken(e,t,n=!1){let s=e?.trim()?`?organizationId=${encodeURIComponent(e.trim())}`:"";return(await this.request(`/api/v1/session${s}`,{},void 0,t)??[]).flatMap((i)=>{if(!i||typeof i!=="object"||typeof i.id!=="string")return[];return[{...i,title:!n&&tt(i.title)?void 0:i.title,repoContext:i.repoContext&&typeof i.repoContext==="object"?i.repoContext:{},metadata:{...i.metadata&&typeof i.metadata==="object"?i.metadata:{},...!n&&tt(i.title)?{createRequestTitle:i.title}:{}}}]})}async listRepositories(e){let t=e?.trim(),n=t?`${this.appBaseUrl}/dashboard/organization/integrations`:`${this.appBaseUrl}/dashboard/integrations`,s=t?`/api/v1/organizations/${encodeURIComponent(t)}/integrations/github/repositories`:"/api/v1/integrations/github/repositories";try{let o=await this.request(s)??[];return{connected:!0,connectUrl:n,repositories:o.flatMap((i)=>{let r=Number(i.id),a=String(i.html_url??i.clone_url??"").trim();if(!Number.isSafeInteger(r)||r<=0||!a)return[];let d=String(i.name??"").trim();return[{id:r,name:d,fullName:String(i.full_name??(d||a)).trim(),url:a,defaultBranch:String(i.default_branch??"").trim()}]})}}catch(o){if(o instanceof g&&o.code==="session_not_found")return{connected:!1,connectUrl:n,repositories:[]};throw o}}async listBranches(e,t,n={}){if(!Number.isSafeInteger(e)||e<=0)throw new g("request_failed","Select a GitHub repository before loading branches.");let s=t?.trim(),o=s?`/api/v1/organizations/${encodeURIComponent(s)}/integrations/github/repositories/${e}/branches`:`/api/v1/integrations/github/repositories/${e}/branches`,i=new URLSearchParams,r=n.query?.trim(),a=n.cursor?.trim();if(r)i.set("query",r);if(a)i.set("cursor",a);let d=i.size>0?`${o}?${i}`:o;try{let u=await this.request(d),f=Array.isArray(u)?u:Array.isArray(u?.items)?u.items:[],c=r?.toLowerCase();return{available:!0,branches:f.flatMap((h)=>{let p=String(h.name??"").trim();return p&&(!Array.isArray(u)||!c||p.toLowerCase().includes(c))?[p]:[]}),nextToken:Array.isArray(u)?"":String(u?.nextToken??"").trim()}}catch(u){if(u instanceof g&&u.code==="session_not_found")return{available:!1,branches:[]};throw u}}async status(e,t={}){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:t.signal?AbortSignal.any([t.signal,AbortSignal.timeout(B)]):void 0},void 0,t.authToken)}async create(e){if(e.handoff&&typeof e.handoff.onCreating!=="function")throw new g("request_failed","Cloud handoff requires an onCreating callback to persist creation intent before dispatch.");let t=(await this.options.getAuthToken())?.trim();if(!t)throw new g("authentication_required","Sign in to Cline before starting a cloud session.");let n={token:t,subject:ge(t)},s=wn(e.requestId?.trim()||hn()),o=e.handoff?`${n.subject??t}/${e.organizationId??""}/${e.requestId?.trim()??""}`:void 0;if(e.handoff&&!e.requestId?.trim())throw new g("request_failed","A stable request id is required for cloud handoff creation.");let i=async()=>(await this.listWithToken(e.organizationId??void 0,n,!0)).filter((c)=>c.title===s&&c.repoContext.repoUrl===e.repoUrl&&c.metadata.modelId===e.modelId&&(!e.branch?.trim()||c.repoContext.branch===e.branch.trim())),r=async(c)=>{if(c.status==="failed"||c.expiredAt&&Date.parse(c.expiredAt)<=Date.now()){let p=new g(c.status==="failed"?"session_failed":"session_expired","The recovered cloud handoff workspace is no longer usable.");try{await this.deleteWithAuth(c.id,n)}catch(l){if(!(l instanceof g&&(l.code==="session_not_found"||l.code==="session_expired")))throw AggregateError([p,l],"The unusable recovered cloud handoff workspace could not be removed.")}if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.delete(o);throw await e.handoff?.onOuterSessionRemoved?.(c.id),p}await e.handoff?.onOuterSessionCreated(c.id,{created:!1});let h={sessionId:c.id,status:c.status,sandboxUrl:c.sandboxUrl,cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,h);return h};if(o){let c=await i();if(c.length>1)throw new g("request_failed","Cloud handoff creation is ambiguous; inspect your cloud session list before continuing.");if(c[0])return await r(c[0]);let h=this.completedHandoffCreates.get(o);if(h){try{await this.request(`/api/v1/session/${encodeURIComponent(h.sessionId)}/status`,{},void 0,n)}catch(p){if(p instanceof g&&(p.code==="session_not_found"||p.code==="session_expired"))await e.handoff?.onOuterSessionRemoved?.(h.sessionId),this.completedHandoffCreates.delete(o),this.unconfirmedHandoffCreates.delete(o);throw p}return await e.handoff?.onOuterSessionCreated(h.sessionId,{created:!1}),{...h,cleanupAuthToken:n.token}}if(this.unconfirmedHandoffCreates.has(o))throw new g("request_failed","Cloud handoff creation is still unconfirmed. Recover the original request before creating another workspace.");this.unconfirmedHandoffCreates.add(o)}try{await e.handoff?.onCreating()}catch(c){if(o)this.unconfirmedHandoffCreates.delete(o);throw c}let a=new AbortController,d=setTimeout(()=>a.abort(),this.createTimeoutMs),u,f=!1;try{let c=await this.request("/api/v1/session",{method:"POST",body:JSON.stringify({modelId:e.modelId,repoUrl:e.repoUrl,...e.sandboxType?{sandboxType:e.sandboxType}:{},title:s,...e.branch?.trim()?{branch:e.branch.trim()}:{},...e.organizationId?.trim()?{organizationId:e.organizationId.trim()}:{}}),signal:a.signal},e.organizationId?.trim()?`${this.appBaseUrl}/dashboard/organization/integrations`:void 0,n,()=>{f=!0}),h=c?.sessionId?.trim();if(!h)throw new g("request_failed","The cloud session service returned no session id.");u=h,await this.persistHandoffOuterSession(e,h,n,o);let p={sessionId:h,status:c.status?.trim()||"provisioning",sandboxUrl:c.sandboxUrl?.trim()??"",cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,p);return p}catch(c){if(u)throw c;let h=!f||c instanceof g&&(c.status!==void 0&&c.status>=400&&c.status<500&&c.status!==408&&c.status!==409||["authentication_required","github_not_connected","session_not_found","session_expired"].includes(c.code));if(o&&h)throw this.unconfirmedHandoffCreates.delete(o),new it(c);if(a.signal.aborted||!(c instanceof g)||c instanceof g&&c.code==="request_failed"&&(c.status===void 0||c.status>=500||c.status===408||c.status===409)){let l=[];try{l=await i()}catch(y){if(e.handoff)throw AggregateError([c,y],"Cloud handoff creation is unconfirmed and its session list could not be checked.")}if(l.length>1)throw new g("request_failed","Cloud session creation had an ambiguous result. Check your cloud session list before trying again.");let m=l[0];if(m){if(e.handoff)return await r(m);return{sessionId:m.id,status:m.status,sandboxUrl:m.sandboxUrl,cleanupAuthToken:n.token}}}else if(o)this.unconfirmedHandoffCreates.delete(o);throw c}finally{clearTimeout(d)}}async persistHandoffOuterSession(e,t,n,s){if(!e.handoff)return;try{await e.handoff.onOuterSessionCreated(t,{created:!0})}catch(o){try{await this.deleteWithAuth(t,n.token)}catch(i){if(!(i instanceof g&&(i.code==="session_not_found"||i.code==="session_expired")))throw AggregateError([o,i],`Cloud session ${t} was created but its recovery record could not be saved or its sandbox removed.`)}if(s)this.unconfirmedHandoffCreates.delete(s);throw await e.handoff.onOuterSessionRemoved?.(t),o}}async waitUntilReady(e,t,n){t=AbortSignal.any([t,AbortSignal.timeout(this.createTimeoutMs)]);let s=await this.options.getAuthToken(),o=s?{token:s,subject:ge(s)}:void 0;while(!t.aborted){let i;try{i=await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:AbortSignal.any([t,AbortSignal.timeout(B)])},void 0,o)}catch(a){if(t.aborted)throw a;if(a instanceof g&&a.code!=="request_failed")throw a;await nt(t);continue}let r=i?.status?.trim().toLowerCase();if(n?.({phase:we(i?.phase)}),r==="ready"||r==="active")return;if(r==="failed")throw new g("session_failed",i?.statusReason?.trim()||"The cloud sandbox could not be prepared.");if(r!=="provisioning")throw new g("request_failed","The cloud session service returned an unexpected provisioning status.");await nt(t)}throw t.reason}async resume(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/resume`,{method:"POST",signal:t?AbortSignal.any([t,AbortSignal.timeout(B)]):void 0})}async delete(e,t){await this.deleteWithAuth(e,t)}async deleteWithAuth(e,t){let n;try{await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"DELETE"},void 0,t)}catch(s){if(!(s instanceof g)||s.code!=="session_not_found"&&s.code!=="session_expired")throw s;n=s}for(let[s,o]of this.completedHandoffCreates)if(o.sessionId===e)this.completedHandoffCreates.delete(s),this.unconfirmedHandoffCreates.delete(s);if(n)throw n}async updateTitle(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({title:t})})}async history(e){let t=await this.options.getAuthToken();if(!t?.trim())throw new g("authentication_required","Sign in to Cline to load this session's history.");let n=await this.fetchImpl(`${this.apiBaseUrl}/api/v1/session/${encodeURIComponent(e)}/history`,{headers:{Accept:"application/json",Authorization:`Bearer ${t.trim()}`},signal:AbortSignal.timeout(B)});if(n.status===404)return null;let s=await n.json().catch(()=>{return});if(!n.ok)throw ye(n.status,s,this.appBaseUrl);if(!s||typeof s!=="object"||!("version"in s)||s.version!==1||!("messages"in s)||!Array.isArray(s.messages))throw new g("request_failed","Invalid archived session history");return s.messages}}import{randomUUID as yo}from"node:crypto";import{posix as le}from"node:path";import{createSessionId as qs,ensureLoopbackProxyBypass as qt,isHubProtocolCompatible as Ns,resolveClineBuildEnv as $s,resolveHubCommandTimeoutMs as Ws}from"@cerebriline/shared";import js from"ws";var q={name:"@cerebriline/core",description:"Cline Core SDK for Node Runtime",version:"0.0.92",repository:{type:"git",url:"https://github.com/cline/cline",directory:"sdk/packages/core"},type:"module",types:"./dist/index.d.ts",main:"./dist/index.js",private:!1,publishConfig:{access:"public"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./hub":{types:"./dist/hub/index.d.ts",import:"./dist/hub/index.js"},"./hub/daemon-entry":{types:"./dist/hub/daemon/entry.d.ts",import:"./dist/hub/daemon/entry.js"},"./telemetry":{types:"./dist/services/telemetry/index.d.ts",import:"./dist/services/telemetry/index.js"},"./services/feature-flags/posthog":{types:"./dist/services/feature-flags/posthog.d.ts",import:"./dist/services/feature-flags/posthog.js"},"./remote/helper-entry":{types:"./dist/remote/remote-helper-entry.d.ts",import:"./dist/remote/remote-helper-entry.js"},"./cloud":{types:"./dist/cloud/index.d.ts",import:"./dist/cloud/index.js"},"./remote/helper":{types:"./dist/remote/remote-helper.d.ts",import:"./dist/remote/remote-helper.js"}},scripts:{build:"bun run ./bun.mts && bun tsc -p tsconfig.build.json && bun run ./scripts/verify-runtime-build-id.ts",typecheck:"bun tsc -p tsconfig.dev.json --noEmit && bun run typecheck:smoke","typecheck:smoke":"bun tsc -p tsconfig.smoke.json --noEmit",test:"bun run test:unit && bun run test:e2e","test:live":"vitest run --config vitest.config.ts src/extensions/context/compaction.live.test.ts","test:compaction":"bun --conditions=development run scripts/compact-session.ts","test:unit":"vitest run --config vitest.config.ts","test:e2e":"vitest run --config vitest.e2e.config.ts","verify:routines":"zsh -lc 'bunx vitest run src/cron/schedule-service.test.ts --config vitest.config.ts'","test:watch":"vitest --config vitest.config.ts"},dependencies:{"@cerebriline/agents":"workspace:*","@cerebriline/llms":"workspace:*","@cerebriline/shared":"workspace:*","@joplin/turndown-plugin-gfm":"1.0.68","@lingo-reader/epub-parser":"0.4.6","@lingo-reader/fb2-parser":"0.4.6","@lingo-reader/mobi-parser":"0.4.6","@modelcontextprotocol/sdk":"^1.29.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.214.0","@opentelemetry/exporter-logs-otlp-http":"^0.214.0","@opentelemetry/exporter-metrics-otlp-http":"^0.214.0","@opentelemetry/exporter-trace-otlp-http":"^0.214.0","@opentelemetry/resources":"^2.6.1","@opentelemetry/sdk-logs":"^0.214.0","@opentelemetry/sdk-metrics":"^2.6.1","@opentelemetry/sdk-trace-base":"^2.6.1","@opentelemetry/sdk-trace-node":"^2.6.1","@opentelemetry/semantic-conventions":"^1.40.0","@tesseract.js-data/eng":"1.0.0",cfb:"1.2.2","fast-png":"8.0.0",jiti:"^2.7.0",nanoid:"^5.1.7","node-machine-id":"^1.1.12",officeparser:"8.0.0","pdfjs-dist":"6.2.108","simple-git":"3.36.0","tesseract.js":"7.0.0","tree-sitter-wasms":"^0.1.12",turndown:"7.2.0","web-tree-sitter":"^0.25.0",ws:"^8.20.0",yaml:"^2.8.2",zod:"^4.3.6"},peerDependencies:{"posthog-node":"^5.8.0"},peerDependenciesMeta:{"posthog-node":{optional:!0}},devDependencies:{"@types/turndown":"^5.0.6","@types/ws":"^8.18.1","posthog-node":"^5.8.0"},engines:{node:">=22"},files:["assets","dist","scripts/document-reader-assets.mjs","!dist/**/*.d.ts.map"]};var rt="session_not_found";class Y extends Error{sessionId;code="session_not_found";constructor(e,t){super(t??(e?`session not found: ${e}`:"session not found"));this.sessionId=e;this.name="SessionNotFoundError"}}function ve(e){return e instanceof Y||typeof e==="object"&&e!==null&&"code"in e&&e.code==="session_not_found"}import{spawn as os}from"node:child_process";import{closeSync as is,mkdirSync as rs,openSync as as,readFileSync as ds,unlinkSync as cs}from"node:fs";import{basename as us,dirname as ls,join as ps}from"node:path";import{fileURLToPath as fs}from"node:url";import{CLINE_RUN_AS_HUB_DAEMON_ENV as hs,isBunEmbeddedModulePath as ms,isHubDaemonProcess as gs,resolveClineBuildEnv as Et,withResolvedClineBuildEnv as ys}from"@cerebriline/shared";import{createHash as kn,randomBytes as Rn}from"node:crypto";import{mkdir as Se,open as at,readFile as pt,rename as _n,rm as ke,writeFile as Pn}from"node:fs/promises";import{dirname as ft,join as Re}from"node:path";import{ensureLoopbackProxyBypass as An,isHubProtocolCompatible as Tn}from"@cerebriline/shared";import{resolveClineDataDir as N,resolveClineDir as ii}from"@cerebriline/shared/storage";var xn="CLINE_HUB_DISCOVERY_PATH",En="CLINE_HUB_BUILD_ID",Hn="CLINE_HUB_BUILD_EPOCH_MS",In=30000,Mn=15000,dt=100;function On(e){return e.replace(/[^a-zA-Z0-9_.-]+/g,"_")}function Un(e){return kn("sha256").update(e).digest("hex").slice(0,12)}function Ln(e){if(!Number.isInteger(e)||!e||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t instanceof Error&&"code"in t?String(t.code)==="EPERM":!1}}function ct(e){return new Promise((t)=>setTimeout(t,e))}function Dn(e){return`${e}.lock`}async function Bn(e){try{let t=JSON.parse(await pt(Re(e,"owner.json"),"utf8"));if(typeof t.pid!=="number"||typeof t.acquiredAt!=="string")return;return{pid:t.pid,acquiredAt:t.acquiredAt}}catch{return}}async function Ce(e){await ke(e,{recursive:!0,force:!0}).catch(()=>{return})}function U(){let e=process.env[En]?.trim();if(e)return e;return"sdk-v1-d70a53e60a51848baa4d382e98c5b4d9802a03a57d2bbb1c948887ac3e4ee94b".trim()||`source-${String(q.version)}`}function qn(){let e=Number(process.env[Hn]);if(Number.isFinite(e)&&e>0)return e;return Number.isFinite(1794145572502)?1794145572502:void 0}function X(e,t=U()){let n=Tn(e);if(!n.compatible)return n;let s=e.buildId?.trim();if(!s)return{compatible:!1,reason:"missing_build"};if(s!==t)return{compatible:!1,reason:"build_mismatch"};return{compatible:!0}}function ut(e){return typeof e==="number"&&Number.isFinite(e)&&e>0?e:void 0}function lt(e){let t=e?.trim().split(/[-+]/,1)[0];if(!t)return;let n=t.split(".").map((s)=>Number(s));if(n.length===0||n.some((s)=>!Number.isInteger(s)||s<0))return;return n}function Nn(e,t){for(let n=0;n<Math.max(e.length,t.length);n++){let s=e[n]??0,o=t[n]??0;if(s!==o)return s<o?-1:1}return 0}function ht(e,t){let n=e.buildId?.trim(),s=t.buildId?.trim();if(n&&s&&n===s)return 0;let o=ut(e.buildEpochMs),i=ut(t.buildEpochMs);if(o!==void 0&&i!==void 0&&o!==i)return o<i?-1:1;let r=lt(e.coreVersion),a=lt(t.coreVersion);if(r&&a){let d=Nn(r,a);if(d!==0)return d}if(n&&s&&n!==s)return n<s?-1:1;return 0}function mt(){return{buildId:U(),buildEpochMs:qn(),coreVersion:String(q.version)}}function Z(e,t){let n=t?.self??mt(),s=X(e,n.buildId??"");if(s.compatible)return!0;if(s.reason!=="build_mismatch"&&s.reason!=="missing_build")return!1;return ht(n,e)<=0}function gt(e=process.argv[1]?.trim()||process.cwd()){let t=`hub-${Un(e)}`,n=process.env[xn]?.trim()||Re(N(),"locks","hub","owners",`${On(t)}.json`);return{ownerId:t,discoveryPath:n}}async function I(e){try{let t=JSON.parse(await pt(e,"utf8"));if(typeof t.hubId!=="string"||typeof t.protocolVersion!=="string"||typeof t.authToken!=="string"||typeof t.host!=="string"||typeof t.port!=="number"||typeof t.url!=="string"||typeof t.startedAt!=="string"||typeof t.updatedAt!=="string")return;return{hubId:t.hubId,protocolVersion:t.protocolVersion,minClientProtocolVersion:typeof t.minClientProtocolVersion==="string"?t.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof t.maxClientProtocolVersion==="string"?t.maxClientProtocolVersion:void 0,capabilities:Array.isArray(t.capabilities)?t.capabilities.filter((n)=>typeof n==="string"):void 0,coreVersion:typeof t.coreVersion==="string"?t.coreVersion:void 0,buildId:typeof t.buildId==="string"?t.buildId:void 0,buildEpochMs:typeof t.buildEpochMs==="number"?t.buildEpochMs:void 0,authToken:t.authToken,host:t.host,port:t.port,url:t.url,pid:typeof t.pid==="number"?t.pid:void 0,startedAt:t.startedAt,updatedAt:t.updatedAt}}catch{return}}async function yt(e,t,n){await wt(e,async()=>{let s=ft(e);await Se(s,{recursive:!0});let o=`${e}.${process.pid}.${Rn(6).toString("hex")}.tmp`,i;try{i=await at(o,"wx",384),await i.writeFile(`${JSON.stringify(t,null,2)}
8
+ `)[0]??"").trim().slice(0,72)}class g extends Error{code;detail;connectUrl;status;constructor(e,t,n,s){super(`${bn}${JSON.stringify({code:e,message:t,connectUrl:n})}`);this.code=e;this.detail=t;this.connectUrl=n;this.status=s;this.name="CloudSessionError"}}class it extends Error{constructor(e){super(e instanceof Error?e.message:"Cloud handoff creation was rejected.",{cause:e});this.name="CloudHandoffCreationRejectedError"}}function be(e){let t=e.length;while(t>0&&e[t-1]==="/")t--;return e.slice(0,t)}function wn(e){return`${st}${e}`.slice(0,255)}function tt(e){return e?.startsWith(st)===!0}function we(e){switch(e){case"provisioning":case"cloning_repo":case"agent_starting":case"ready":case"failed":return e;default:return}}function ge(e){let t=mn(e.replace(/^workos:/,""));return typeof t?.sub==="string"&&t.sub.trim()?t.sub.trim():void 0}function nt(e){return new Promise((t,n)=>{if(e.aborted){n(e.reason);return}let s=()=>{clearTimeout(o),n(e.reason)},o=setTimeout(()=>{e.removeEventListener("abort",s),t()},yn);e.addEventListener("abort",s,{once:!0})})}function vn(e,t){if(e&&typeof e==="object"){let n=e.error;if(typeof n==="string"&&n.trim())return n.trim()}return t}function ye(e,t,n,s){let o=vn(t,`Cloud session request failed (${e})`);if(e===401)return new g("authentication_required",o);if(e===404)return new g("session_not_found",o);if(e===410)return new g("session_expired",o);if(e===412)return new g("github_not_connected",o,s??`${be(n)}/dashboard/integrations`);if(e===403&&o.trim().toLowerCase()==="forbidden")return new g("request_failed","Your active account or organization cannot create cloud sessions. Switch to Personal or another organization in Settings → Account, then try again.",void 0,e);return new g("request_failed",o,void 0,e)}class Cn{options;apiBaseUrl;appBaseUrl;fetchImpl;createTimeoutMs;unconfirmedHandoffCreates=new Set;completedHandoffCreates=new Map;constructor(e){this.options=e;this.apiBaseUrl=be(e.apiBaseUrl),this.appBaseUrl=be(e.appBaseUrl),this.fetchImpl=e.fetch??fetch,this.createTimeoutMs=e.createTimeoutMs??gn}async request(e,t={},n,s,o){let i=!1,r;while(!0){let a;try{a=typeof s==="string"?s:await this.options.getAuthToken()}catch(f){if(r)throw ye(401,void 0,this.appBaseUrl,n);throw f}if(!a?.trim())throw new g("authentication_required","Sign in to Cline before starting a cloud session.");if(a.trim()===r)throw new g("authentication_required","The cloud session credential was rejected. Sign in again.");if(typeof s==="object"){if(s.subject?ge(a.trim())!==s.subject:a.trim()!==s.token)throw new g("authentication_required","The signed-in account changed during cloud session creation.");s.token=a.trim()}o?.();let d=await this.fetchImpl(`${this.apiBaseUrl}${e}`,{...t,signal:t.signal??AbortSignal.timeout(B),headers:{Accept:"application/json",Authorization:`Bearer ${a.trim()}`,...t.body?{"Content-Type":"application/json"}:{},...t.headers}}),u=d.status===204?void 0:await d.json().catch(()=>{return});if(!d.ok){if(d.status===401&&typeof s==="object"&&!i&&s.subject){i=!0,r=a.trim();continue}throw ye(d.status,u,this.appBaseUrl,n)}return u?.data}}async list(e){return await this.listWithToken(e)}async listWithToken(e,t,n=!1){let s=e?.trim()?`?organizationId=${encodeURIComponent(e.trim())}`:"";return(await this.request(`/api/v1/session${s}`,{},void 0,t)??[]).flatMap((i)=>{if(!i||typeof i!=="object"||typeof i.id!=="string")return[];return[{...i,title:!n&&tt(i.title)?void 0:i.title,repoContext:i.repoContext&&typeof i.repoContext==="object"?i.repoContext:{},metadata:{...i.metadata&&typeof i.metadata==="object"?i.metadata:{},...!n&&tt(i.title)?{createRequestTitle:i.title}:{}}}]})}async listRepositories(e){let t=e?.trim(),n=t?`${this.appBaseUrl}/dashboard/organization/integrations`:`${this.appBaseUrl}/dashboard/integrations`,s=t?`/api/v1/organizations/${encodeURIComponent(t)}/integrations/github/repositories`:"/api/v1/integrations/github/repositories";try{let o=await this.request(s)??[];return{connected:!0,connectUrl:n,repositories:o.flatMap((i)=>{let r=Number(i.id),a=String(i.html_url??i.clone_url??"").trim();if(!Number.isSafeInteger(r)||r<=0||!a)return[];let d=String(i.name??"").trim();return[{id:r,name:d,fullName:String(i.full_name??(d||a)).trim(),url:a,defaultBranch:String(i.default_branch??"").trim()}]})}}catch(o){if(o instanceof g&&o.code==="session_not_found")return{connected:!1,connectUrl:n,repositories:[]};throw o}}async listBranches(e,t,n={}){if(!Number.isSafeInteger(e)||e<=0)throw new g("request_failed","Select a GitHub repository before loading branches.");let s=t?.trim(),o=s?`/api/v1/organizations/${encodeURIComponent(s)}/integrations/github/repositories/${e}/branches`:`/api/v1/integrations/github/repositories/${e}/branches`,i=new URLSearchParams,r=n.query?.trim(),a=n.cursor?.trim();if(r)i.set("query",r);if(a)i.set("cursor",a);let d=i.size>0?`${o}?${i}`:o;try{let u=await this.request(d),f=Array.isArray(u)?u:Array.isArray(u?.items)?u.items:[],c=r?.toLowerCase();return{available:!0,branches:f.flatMap((h)=>{let p=String(h.name??"").trim();return p&&(!Array.isArray(u)||!c||p.toLowerCase().includes(c))?[p]:[]}),nextToken:Array.isArray(u)?"":String(u?.nextToken??"").trim()}}catch(u){if(u instanceof g&&u.code==="session_not_found")return{available:!1,branches:[]};throw u}}async status(e,t={}){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:t.signal?AbortSignal.any([t.signal,AbortSignal.timeout(B)]):void 0},void 0,t.authToken)}async create(e){if(e.handoff&&typeof e.handoff.onCreating!=="function")throw new g("request_failed","Cloud handoff requires an onCreating callback to persist creation intent before dispatch.");let t=(await this.options.getAuthToken())?.trim();if(!t)throw new g("authentication_required","Sign in to Cline before starting a cloud session.");let n={token:t,subject:ge(t)},s=wn(e.requestId?.trim()||hn()),o=e.handoff?`${n.subject??t}/${e.organizationId??""}/${e.requestId?.trim()??""}`:void 0;if(e.handoff&&!e.requestId?.trim())throw new g("request_failed","A stable request id is required for cloud handoff creation.");let i=async()=>(await this.listWithToken(e.organizationId??void 0,n,!0)).filter((c)=>c.title===s&&c.repoContext.repoUrl===e.repoUrl&&c.metadata.modelId===e.modelId&&(!e.branch?.trim()||c.repoContext.branch===e.branch.trim())),r=async(c)=>{if(c.status==="failed"||c.expiredAt&&Date.parse(c.expiredAt)<=Date.now()){let p=new g(c.status==="failed"?"session_failed":"session_expired","The recovered cloud handoff workspace is no longer usable.");try{await this.deleteWithAuth(c.id,n)}catch(l){if(!(l instanceof g&&(l.code==="session_not_found"||l.code==="session_expired")))throw AggregateError([p,l],"The unusable recovered cloud handoff workspace could not be removed.")}if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.delete(o);throw await e.handoff?.onOuterSessionRemoved?.(c.id),p}await e.handoff?.onOuterSessionCreated(c.id,{created:!1});let h={sessionId:c.id,status:c.status,sandboxUrl:c.sandboxUrl,cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,h);return h};if(o){let c=await i();if(c.length>1)throw new g("request_failed","Cloud handoff creation is ambiguous; inspect your cloud session list before continuing.");if(c[0])return await r(c[0]);let h=this.completedHandoffCreates.get(o);if(h){try{await this.request(`/api/v1/session/${encodeURIComponent(h.sessionId)}/status`,{},void 0,n)}catch(p){if(p instanceof g&&(p.code==="session_not_found"||p.code==="session_expired"))await e.handoff?.onOuterSessionRemoved?.(h.sessionId),this.completedHandoffCreates.delete(o),this.unconfirmedHandoffCreates.delete(o);throw p}return await e.handoff?.onOuterSessionCreated(h.sessionId,{created:!1}),{...h,cleanupAuthToken:n.token}}if(this.unconfirmedHandoffCreates.has(o))throw new g("request_failed","Cloud handoff creation is still unconfirmed. Recover the original request before creating another workspace.");this.unconfirmedHandoffCreates.add(o)}try{await e.handoff?.onCreating()}catch(c){if(o)this.unconfirmedHandoffCreates.delete(o);throw c}let a=new AbortController,d=setTimeout(()=>a.abort(),this.createTimeoutMs),u,f=!1;try{let c=await this.request("/api/v1/session",{method:"POST",body:JSON.stringify({modelId:e.modelId,repoUrl:e.repoUrl,...e.sandboxType?{sandboxType:e.sandboxType}:{},title:s,...e.branch?.trim()?{branch:e.branch.trim()}:{},...e.organizationId?.trim()?{organizationId:e.organizationId.trim()}:{}}),signal:a.signal},e.organizationId?.trim()?`${this.appBaseUrl}/dashboard/organization/integrations`:void 0,n,()=>{f=!0}),h=c?.sessionId?.trim();if(!h)throw new g("request_failed","The cloud session service returned no session id.");u=h,await this.persistHandoffOuterSession(e,h,n,o);let p={sessionId:h,status:c.status?.trim()||"provisioning",sandboxUrl:c.sandboxUrl?.trim()??"",cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,p);return p}catch(c){if(u)throw c;let h=!f||c instanceof g&&(c.status!==void 0&&c.status>=400&&c.status<500&&c.status!==408&&c.status!==409||["authentication_required","github_not_connected","session_not_found","session_expired"].includes(c.code));if(o&&h)throw this.unconfirmedHandoffCreates.delete(o),new it(c);if(a.signal.aborted||!(c instanceof g)||c instanceof g&&c.code==="request_failed"&&(c.status===void 0||c.status>=500||c.status===408||c.status===409)){let l=[];try{l=await i()}catch(y){if(e.handoff)throw AggregateError([c,y],"Cloud handoff creation is unconfirmed and its session list could not be checked.")}if(l.length>1)throw new g("request_failed","Cloud session creation had an ambiguous result. Check your cloud session list before trying again.");let m=l[0];if(m){if(e.handoff)return await r(m);return{sessionId:m.id,status:m.status,sandboxUrl:m.sandboxUrl,cleanupAuthToken:n.token}}}else if(o)this.unconfirmedHandoffCreates.delete(o);throw c}finally{clearTimeout(d)}}async persistHandoffOuterSession(e,t,n,s){if(!e.handoff)return;try{await e.handoff.onOuterSessionCreated(t,{created:!0})}catch(o){try{await this.deleteWithAuth(t,n.token)}catch(i){if(!(i instanceof g&&(i.code==="session_not_found"||i.code==="session_expired")))throw AggregateError([o,i],`Cloud session ${t} was created but its recovery record could not be saved or its sandbox removed.`)}if(s)this.unconfirmedHandoffCreates.delete(s);throw await e.handoff.onOuterSessionRemoved?.(t),o}}async waitUntilReady(e,t,n){t=AbortSignal.any([t,AbortSignal.timeout(this.createTimeoutMs)]);let s=await this.options.getAuthToken(),o=s?{token:s,subject:ge(s)}:void 0;while(!t.aborted){let i;try{i=await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:AbortSignal.any([t,AbortSignal.timeout(B)])},void 0,o)}catch(a){if(t.aborted)throw a;if(a instanceof g&&a.code!=="request_failed")throw a;await nt(t);continue}let r=i?.status?.trim().toLowerCase();if(n?.({phase:we(i?.phase)}),r==="ready"||r==="active")return;if(r==="failed")throw new g("session_failed",i?.statusReason?.trim()||"The cloud sandbox could not be prepared.");if(r!=="provisioning")throw new g("request_failed","The cloud session service returned an unexpected provisioning status.");await nt(t)}throw t.reason}async resume(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/resume`,{method:"POST",signal:t?AbortSignal.any([t,AbortSignal.timeout(B)]):void 0})}async delete(e,t){await this.deleteWithAuth(e,t)}async deleteWithAuth(e,t){let n;try{await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"DELETE"},void 0,t)}catch(s){if(!(s instanceof g)||s.code!=="session_not_found"&&s.code!=="session_expired")throw s;n=s}for(let[s,o]of this.completedHandoffCreates)if(o.sessionId===e)this.completedHandoffCreates.delete(s),this.unconfirmedHandoffCreates.delete(s);if(n)throw n}async updateTitle(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({title:t})})}async history(e){let t=await this.options.getAuthToken();if(!t?.trim())throw new g("authentication_required","Sign in to Cline to load this session's history.");let n=await this.fetchImpl(`${this.apiBaseUrl}/api/v1/session/${encodeURIComponent(e)}/history`,{headers:{Accept:"application/json",Authorization:`Bearer ${t.trim()}`},signal:AbortSignal.timeout(B)});if(n.status===404)return null;let s=await n.json().catch(()=>{return});if(!n.ok)throw ye(n.status,s,this.appBaseUrl);if(!s||typeof s!=="object"||!("version"in s)||s.version!==1||!("messages"in s)||!Array.isArray(s.messages))throw new g("request_failed","Invalid archived session history");return s.messages}}import{randomUUID as yo}from"node:crypto";import{posix as le}from"node:path";import{createSessionId as qs,ensureLoopbackProxyBypass as qt,isHubProtocolCompatible as Ns,resolveClineBuildEnv as $s,resolveHubCommandTimeoutMs as Ws}from"@cerebriline/shared";import js from"ws";var q={name:"@cerebriline/core",description:"Cline Core SDK for Node Runtime",version:"0.0.92",repository:{type:"git",url:"https://github.com/cline/cline",directory:"sdk/packages/core"},type:"module",types:"./dist/index.d.ts",main:"./dist/index.js",private:!1,publishConfig:{access:"public"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./hub":{types:"./dist/hub/index.d.ts",import:"./dist/hub/index.js"},"./hub/daemon-entry":{types:"./dist/hub/daemon/entry.d.ts",import:"./dist/hub/daemon/entry.js"},"./telemetry":{types:"./dist/services/telemetry/index.d.ts",import:"./dist/services/telemetry/index.js"},"./services/feature-flags/posthog":{types:"./dist/services/feature-flags/posthog.d.ts",import:"./dist/services/feature-flags/posthog.js"},"./remote/helper-entry":{types:"./dist/remote/remote-helper-entry.d.ts",import:"./dist/remote/remote-helper-entry.js"},"./cloud":{types:"./dist/cloud/index.d.ts",import:"./dist/cloud/index.js"},"./remote/helper":{types:"./dist/remote/remote-helper.d.ts",import:"./dist/remote/remote-helper.js"}},scripts:{build:"bun run ./bun.mts && bun tsc -p tsconfig.build.json && bun run ./scripts/verify-runtime-build-id.ts",typecheck:"bun tsc -p tsconfig.dev.json --noEmit && bun run typecheck:smoke","typecheck:smoke":"bun tsc -p tsconfig.smoke.json --noEmit",test:"bun run test:unit && bun run test:e2e","test:live":"vitest run --config vitest.config.ts src/extensions/context/compaction.live.test.ts","test:compaction":"bun --conditions=development run scripts/compact-session.ts","test:unit":"vitest run --config vitest.config.ts","test:e2e":"vitest run --config vitest.e2e.config.ts","verify:routines":"zsh -lc 'bunx vitest run src/cron/schedule-service.test.ts --config vitest.config.ts'","test:watch":"vitest --config vitest.config.ts"},dependencies:{"@cerebriline/agents":"workspace:*","@cerebriline/llms":"workspace:*","@cerebriline/shared":"workspace:*","@joplin/turndown-plugin-gfm":"1.0.68","@lingo-reader/epub-parser":"0.4.6","@lingo-reader/fb2-parser":"0.4.6","@lingo-reader/mobi-parser":"0.4.6","@modelcontextprotocol/sdk":"^1.29.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.214.0","@opentelemetry/exporter-logs-otlp-http":"^0.214.0","@opentelemetry/exporter-metrics-otlp-http":"^0.214.0","@opentelemetry/exporter-trace-otlp-http":"^0.214.0","@opentelemetry/resources":"^2.6.1","@opentelemetry/sdk-logs":"^0.214.0","@opentelemetry/sdk-metrics":"^2.6.1","@opentelemetry/sdk-trace-base":"^2.6.1","@opentelemetry/sdk-trace-node":"^2.6.1","@opentelemetry/semantic-conventions":"^1.40.0","@tesseract.js-data/eng":"1.0.0",cfb:"1.2.2","fast-png":"8.0.0",jiti:"^2.7.0",nanoid:"^5.1.7","node-machine-id":"^1.1.12",officeparser:"8.0.0","pdfjs-dist":"6.2.108","simple-git":"4.0.2","tesseract.js":"7.0.0","tree-sitter-wasms":"^0.1.12",turndown:"7.2.0","web-tree-sitter":"^0.25.0",ws:"^8.20.0",yaml:"^2.8.2",zod:"^4.6.6"},peerDependencies:{"posthog-node":"^5.8.0","puppeteer-core":"^23.4.0"},peerDependenciesMeta:{"posthog-node":{optional:!0},"puppeteer-core":{optional:!0}},devDependencies:{"@types/turndown":"^5.0.6","@types/ws":"^8.18.1","posthog-node":"^5.8.0"},engines:{node:">=22"},files:["assets","dist","scripts/document-reader-assets.mjs","!dist/**/*.d.ts.map"]};var rt="session_not_found";class Y extends Error{sessionId;code="session_not_found";constructor(e,t){super(t??(e?`session not found: ${e}`:"session not found"));this.sessionId=e;this.name="SessionNotFoundError"}}function ve(e){return e instanceof Y||typeof e==="object"&&e!==null&&"code"in e&&e.code==="session_not_found"}import{spawn as os}from"node:child_process";import{closeSync as is,mkdirSync as rs,openSync as as,readFileSync as ds,unlinkSync as cs}from"node:fs";import{basename as us,dirname as ls,join as ps}from"node:path";import{fileURLToPath as fs}from"node:url";import{CLINE_RUN_AS_HUB_DAEMON_ENV as hs,isBunEmbeddedModulePath as ms,isHubDaemonProcess as gs,resolveClineBuildEnv as Et,withResolvedClineBuildEnv as ys}from"@cerebriline/shared";import{createHash as kn,randomBytes as Rn}from"node:crypto";import{mkdir as Se,open as at,readFile as pt,rename as _n,rm as ke,writeFile as Pn}from"node:fs/promises";import{dirname as ft,join as Re}from"node:path";import{ensureLoopbackProxyBypass as An,isHubProtocolCompatible as Tn}from"@cerebriline/shared";import{resolveClineDataDir as N,resolveClineDir as ii}from"@cerebriline/shared/storage";var xn="CLINE_HUB_DISCOVERY_PATH",En="CLINE_HUB_BUILD_ID",Hn="CLINE_HUB_BUILD_EPOCH_MS",In=30000,Mn=15000,dt=100;function On(e){return e.replace(/[^a-zA-Z0-9_.-]+/g,"_")}function Un(e){return kn("sha256").update(e).digest("hex").slice(0,12)}function Ln(e){if(!Number.isInteger(e)||!e||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t instanceof Error&&"code"in t?String(t.code)==="EPERM":!1}}function ct(e){return new Promise((t)=>setTimeout(t,e))}function Dn(e){return`${e}.lock`}async function Bn(e){try{let t=JSON.parse(await pt(Re(e,"owner.json"),"utf8"));if(typeof t.pid!=="number"||typeof t.acquiredAt!=="string")return;return{pid:t.pid,acquiredAt:t.acquiredAt}}catch{return}}async function Ce(e){await ke(e,{recursive:!0,force:!0}).catch(()=>{return})}function U(){let e=process.env[En]?.trim();if(e)return e;return"sdk-v1-32471bf702ab204c5f5d7dcdea528856b698f68f95ba3f57549b9d2c36dde8e3".trim()||`source-${String(q.version)}`}function qn(){let e=Number(process.env[Hn]);if(Number.isFinite(e)&&e>0)return e;return Number.isFinite(1794516541414)?1794516541414:void 0}function X(e,t=U()){let n=Tn(e);if(!n.compatible)return n;let s=e.buildId?.trim();if(!s)return{compatible:!1,reason:"missing_build"};if(s!==t)return{compatible:!1,reason:"build_mismatch"};return{compatible:!0}}function ut(e){return typeof e==="number"&&Number.isFinite(e)&&e>0?e:void 0}function lt(e){let t=e?.trim().split(/[-+]/,1)[0];if(!t)return;let n=t.split(".").map((s)=>Number(s));if(n.length===0||n.some((s)=>!Number.isInteger(s)||s<0))return;return n}function Nn(e,t){for(let n=0;n<Math.max(e.length,t.length);n++){let s=e[n]??0,o=t[n]??0;if(s!==o)return s<o?-1:1}return 0}function ht(e,t){let n=e.buildId?.trim(),s=t.buildId?.trim();if(n&&s&&n===s)return 0;let o=ut(e.buildEpochMs),i=ut(t.buildEpochMs);if(o!==void 0&&i!==void 0&&o!==i)return o<i?-1:1;let r=lt(e.coreVersion),a=lt(t.coreVersion);if(r&&a){let d=Nn(r,a);if(d!==0)return d}if(n&&s&&n!==s)return n<s?-1:1;return 0}function mt(){return{buildId:U(),buildEpochMs:qn(),coreVersion:String(q.version)}}function Z(e,t){let n=t?.self??mt(),s=X(e,n.buildId??"");if(s.compatible)return!0;if(s.reason!=="build_mismatch"&&s.reason!=="missing_build")return!1;return ht(n,e)<=0}function gt(e=process.argv[1]?.trim()||process.cwd()){let t=`hub-${Un(e)}`,n=process.env[xn]?.trim()||Re(N(),"locks","hub","owners",`${On(t)}.json`);return{ownerId:t,discoveryPath:n}}async function I(e){try{let t=JSON.parse(await pt(e,"utf8"));if(typeof t.hubId!=="string"||typeof t.protocolVersion!=="string"||typeof t.authToken!=="string"||typeof t.host!=="string"||typeof t.port!=="number"||typeof t.url!=="string"||typeof t.startedAt!=="string"||typeof t.updatedAt!=="string")return;return{hubId:t.hubId,protocolVersion:t.protocolVersion,minClientProtocolVersion:typeof t.minClientProtocolVersion==="string"?t.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof t.maxClientProtocolVersion==="string"?t.maxClientProtocolVersion:void 0,capabilities:Array.isArray(t.capabilities)?t.capabilities.filter((n)=>typeof n==="string"):void 0,coreVersion:typeof t.coreVersion==="string"?t.coreVersion:void 0,buildId:typeof t.buildId==="string"?t.buildId:void 0,buildEpochMs:typeof t.buildEpochMs==="number"?t.buildEpochMs:void 0,authToken:t.authToken,host:t.host,port:t.port,url:t.url,pid:typeof t.pid==="number"?t.pid:void 0,startedAt:t.startedAt,updatedAt:t.updatedAt}}catch{return}}async function yt(e,t,n){await wt(e,async()=>{let s=ft(e);await Se(s,{recursive:!0});let o=`${e}.${process.pid}.${Rn(6).toString("hex")}.tmp`,i;try{i=await at(o,"wx",384),await i.writeFile(`${JSON.stringify(t,null,2)}
9
9
  `,{encoding:"utf8"}),await i.sync(),await i.close(),i=void 0,n?.beforePublish?.(),await _n(o,e);let r;try{r=await at(s,"r"),await r.sync()}catch{}finally{await r?.close().catch(()=>{return})}}catch(r){throw await i?.close().catch(()=>{return}),await ke(o,{force:!0}).catch(()=>{return}),r}})}async function L(e){await wt(e,async()=>{await ke(e,{force:!0}).catch(()=>{return})})}async function bt(e,t,n){let s=Dn(e);await Se(ft(s),{recursive:!0});let o=Date.now()+Mn;while(!0){try{await Se(s,{recursive:!1})}catch(i){if((i instanceof Error&&"code"in i?String(i.code):"")!=="EEXIST")throw i;let a=await Bn(s);if(!a){if(Date.now()>=o){await Ce(s);continue}await ct(dt);continue}let d=Date.now()-Date.parse(a.acquiredAt);if(!Ln(a.pid)||d>In){await Ce(s);continue}if(Date.now()>=o)throw Error(`Timed out waiting for hub ${t} lock ${s}`);await ct(dt);continue}try{return await Pn(Re(s,"owner.json"),`${JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()},null,2)}
10
10
  `,"utf8"),await n()}finally{await Ce(s)}}}function wt(e,t){return bt(`${e}.mutation`,"discovery mutation",t)}function vt(e,t){return bt(e,"startup",t)}async function ee(e,t){An();try{let n=await fetch(t?.authToken?$n(e):St(e),{headers:t?.authToken?{authorization:`Bearer ${t.authToken}`}:void 0,signal:t?.signal});if(!n.ok)return;let s=await n.json();if(typeof s.protocolVersion!=="string"||typeof s.host!=="string"||typeof s.port!=="number"||typeof s.url!=="string")return;return{protocolVersion:s.protocolVersion,minClientProtocolVersion:typeof s.minClientProtocolVersion==="string"?s.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof s.maxClientProtocolVersion==="string"?s.maxClientProtocolVersion:void 0,capabilities:Array.isArray(s.capabilities)?s.capabilities.filter((o)=>typeof o==="string"):void 0,coreVersion:typeof s.coreVersion==="string"?s.coreVersion:void 0,buildId:typeof s.buildId==="string"?s.buildId:void 0,buildEpochMs:typeof s.buildEpochMs==="number"?s.buildEpochMs:void 0,host:s.host,port:s.port,url:s.url,hubId:typeof s.hubId==="string"?s.hubId:void 0,authToken:typeof s.authToken==="string"?s.authToken:void 0,pid:typeof s.pid==="number"?s.pid:void 0,startedAt:typeof s.startedAt==="string"?s.startedAt:void 0,updatedAt:typeof s.updatedAt==="string"?s.updatedAt:void 0}}catch{return}}function Ct(e,t,n="/hub"){return new URL(`ws://${e}:${t}${n}`).toString()}function St(e){let t=new URL(e);return t.protocol=t.protocol==="wss:"?"https:":"http:",t.pathname="/health",t.search="",t.toString()}function $n(e){let t=new URL(St(e));return t.pathname="/status",t.toString()}import{CLINE_HUB_DEV_PORT as Wn,CLINE_HUB_PORT as jn,resolveClineBuildEnv as Fn}from"@cerebriline/shared";var zn="CLINE_HUB_HOST",Vn="CLINE_HUB_PORT",Gn="CLINE_HUB_PATHNAME",Jn="127.0.0.1",Kn=jn,Qn="/hub";function kt(e){return Fn(e)==="development"?Wn:Kn}function Yn(e={}){return(e.env??process.env)[zn]?.trim()||Jn}function Xn(e={}){let n=(e.env??process.env)[Vn]?.trim();if(!n)return kt(e);let s=Number.parseInt(n,10);if(!Number.isInteger(s)||s<1||s>65535)return kt(e);return s}function Zn(e={}){return(e.env??process.env)[Gn]?.trim()||Qn}function Rt(e={},t={}){return{host:e.host??Yn(t),port:e.port??Xn(t),pathname:e.pathname??Zn(t)}}import{join as es}from"node:path";var ts="shared:cline",ns="CLINE_HUB_DISCOVERY_PATH",ss="hub-production";function W(e=ts){return gt(`${e}@${U()}`)}function te(){return{ownerId:ss,discoveryPath:process.env[ns]?.trim()||es(N(),"locks","hub","production.json")}}var _t=15000,bs=200,Pt=3000,ws=100,vs=[100,250,500,1000,2000],Cs="--cline-hub-daemon",Ss=3,ks=60000,At=new Map;function Rs(e,t=Date.now()){let n=At.get(e);if(!n||t-n.windowStartedAt>ks)return At.set(e,{count:1,windowStartedAt:t}),!0;return n.count+=1,n.count<=Ss}function _s(e){return[...e.host?["--host",e.host]:[],...typeof e.port==="number"?["--port",String(e.port)]:[],...e.pathname?["--pathname",e.pathname]:[]]}function Ps(){try{let e=ps(N(),"logs","hub-daemon.log");return rs(ls(e),{recursive:!0}),{fd:as(e,"a"),logPath:e}}catch{return}}function As(){return Et()==="production"?te():W()}function j(e){return Z(e)}function Ts(e){try{let t=JSON.parse(ds(`${e}.superseded`,"utf8"));return{url:typeof t.url==="string"?t.url:void 0,authToken:typeof t.authToken==="string"?t.authToken:void 0,pid:typeof t.pid==="number"?t.pid:void 0}}catch{return}}function _e(e){try{cs(`${e}.superseded`)}catch{}}function Tt(e,t,n){if(!t||t.url!==n)return e;return{...e,authToken:e.authToken??t.authToken,pid:e.pid??t.pid}}async function F(e,t){try{return await ee(e,{authToken:t})}catch{return}}async function xt(e,t){let n=Date.now()+t;while(Date.now()<n){if(!(await F(e))?.url)return!0;await new Promise((o)=>setTimeout(o,ws))}return!1}async function Ae(e,t){if(!Rs(e.url))return!1;await z(e.url,e.authToken,"retired by newer install").catch(()=>!1),await Mt(e.url,e.authToken).catch(()=>!1);let n=await xt(e.url,Pt);if(!n&&e.pid&&xs(e.pid)){try{process.kill(e.pid,"SIGTERM")}catch{}n=await xt(e.url,Pt)}if(n)await L(t).catch(()=>{return});return n}function xs(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function Es(e){try{return(await Te(e.url,e.authToken)).activeSessionCount>0}catch{return!1}}async function Pe(e,t){if(j(e))return"reusable";let n=await z(e.url,e.authToken,"retired by newer install").catch(()=>!1);if(await Es(e)){if(n)await z(e.url,e.authToken,"hub retirement deferred",{off:!0}).catch(()=>!1);return"deferred_busy"}let s=await Ae(e,t);if(!s&&n)await z(e.url,e.authToken,"hub retirement failed",{off:!0}).catch(()=>!1);return s?"retired":"failed"}async function Hs(e){if(Et()!=="production")return;let t=W();if(t.discoveryPath===e.discoveryPath)return;let n=await I(t.discoveryPath);if(n?.url)await Ae(n,t.discoveryPath);else await L(t.discoveryPath).catch(()=>{return})}function Is(){let e=import.meta.url.endsWith(".ts")?"ts":"js";return fs(new URL(`./entry.${e}`,import.meta.url))}function Ms(e,t){if(ms(e))return[Cs];return[...t&&e.toLowerCase().endsWith(".ts")?["--conditions=development"]:[],e]}function Os(e,t){let n=Is(),s=process.execPath?.trim();if(!s)throw Error("unable to resolve runtime executable for hub daemon");let o=us(s).toLowerCase().includes("bun"),i=Ms(n,o);return{launcher:s,args:[...i,"--cwd",e,..._s(t),...t.manageConnectors===!1?["--no-connectors"]:[]],cwd:e,env:{...ys(process.env),CLINE_NO_INTERACTIVE:"1",[hs]:"1"}}}function Us(e){if(!e||typeof e!=="object")return!1;if(("code"in e?e.code:void 0)==="ETXTBSY")return!0;let n="message"in e?e.message:void 0;return typeof n==="string"&&n.includes("ETXTBSY")}function Ls(e,t={}){if(gs())return;let n=Os(e,t),s=Ps();try{os(n.launcher,n.args,{detached:!0,stdio:s?["ignore",s.fd,s.fd]:"ignore",env:n.env,cwd:n.cwd,windowsHide:!0}).unref()}finally{if(s)is(s.fd)}}async function Ds(e,t={}){for(let n=0;;n++)try{Ls(e,t);return}catch(s){let o=vs[n];if(!Us(s)||o===void 0)throw s;await new Promise((i)=>setTimeout(i,o))}}async function Bs(e,t,n={}){let s=n.host!==void 0||n.port!==void 0||n.pathname!==void 0||!!process.env.CLINE_HUB_PORT?.trim(),o=Rt(n),i=Ct(o.host,o.port,o.pathname),r=(l)=>{if(!s)ne(l.url,l.authToken);else It(l.url,l.authToken);return l};await Hs(e).catch(()=>{return});let a=await I(e.discoveryPath),d=a?.url?void 0:Ts(e.discoveryPath),u=!1;if(a?.url){let l=a.authToken;if(!l)u=!0,await Ae(a,e.discoveryPath);else{let m=await F(a.url,l);if(m?.url&&j(m)&&await E(m.url,{authToken:l}))return _e(e.discoveryPath),r({url:m.url,authToken:l});if(m?.url){if(await Pe({...m,authToken:l},e.discoveryPath)==="deferred_busy"&&await E(m.url,{authToken:l}))return r({url:m.url,authToken:l})}else await L(e.discoveryPath).catch(()=>{return})}}let f=await F(i);if(f?.url){let l=Tt(f,a??d,i);if(j(f)){let y=[f.authToken,a?.authToken,d?.authToken].filter((v)=>typeof v==="string"&&v.trim().length>0);for(let v of y){if(!await E(f.url,{authToken:v}))continue;let P={hubId:f.hubId??`repaired-${f.port}`,protocolVersion:f.protocolVersion,minClientProtocolVersion:f.minClientProtocolVersion,maxClientProtocolVersion:f.maxClientProtocolVersion,capabilities:f.capabilities,coreVersion:f.coreVersion,buildId:f.buildId,authToken:v,host:f.host,port:f.port,url:f.url,pid:f.pid??a?.pid??d?.pid,startedAt:f.startedAt??new Date().toISOString(),updatedAt:new Date().toISOString()};try{await yt(e.discoveryPath,P)}catch{}return _e(e.discoveryPath),r({url:f.url,authToken:v})}throw Error(`A compatible Cline Hub is already running at ${i}, but its discovery record is missing or unreadable and no usable auth token is available. Run 'cline doctor fix' to repair local hub discovery.${u?" This can happen immediately after upgrading from a build that wrote an empty hub auth token; run 'cline doctor fix' to stop the old daemon and repair local hub discovery.":""}`)}let m=await Pe(l,e.discoveryPath);if(m==="deferred_busy"){for(let y of[l.authToken,a?.authToken].filter((w)=>typeof w==="string"&&w.trim().length>0))if(await E(f.url,{authToken:y}))return r({url:f.url,authToken:y});if(n.allowPortFallback!==!0&&o.port!==0)throw Error(`An older Cline Hub is running at ${i} and is still serving active sessions, so it was not replaced, but no usable auth token is available to attach to it. Finish those sessions, or run 'cline doctor fix' to stop the hub.`)}if(m==="failed"&&n.allowPortFallback!==!0&&o.port!==0)throw Error(`An incompatible Cline Hub is already running at ${i} and could not be retired automatically. Run 'cline doctor fix' to stop stale hub daemons before starting a new hub.`)}let h=n.allowPortFallback===!0&&o.port!==0?{...o,port:0}:o;await Ds(t,{...h,manageConnectors:n.manageConnectors});let p=Date.now()+_t;while(Date.now()<p){let l=await I(e.discoveryPath);if(l?.url&&l.authToken){let y=await F(l.url,l.authToken);if(y?.url&&j(y)&&await E(y.url,{authToken:l.authToken}))return _e(e.discoveryPath),r({url:y.url,authToken:l.authToken})}let m=await F(i);if(m?.url&&!j(m)){let y=Tt(m,l??d,i),w=await Pe(y,e.discoveryPath);if(w==="deferred_busy"&&l?.authToken&&await E(m.url,{authToken:l.authToken}))return r({url:m.url,authToken:l.authToken});if(w==="failed"&&n.allowPortFallback!==!0&&o.port!==0)throw Error(`An incompatible Cline Hub is still running at ${i} and could not be retired automatically. Run 'cline doctor fix' to stop stale hub daemons before starting a new hub.`)}await new Promise((y)=>setTimeout(y,bs))}throw Error(`Timed out after ${_t}ms waiting for detached hub startup.`)}async function Ht(e,t={}){let n=As();return await vt(n.discoveryPath,async()=>Bs(n,e,t))}function Fs(){return $s()==="production"?te():W()}function zs(){let e=globalThis.WebSocket;if(!e)throw Error("Global WebSocket is not available in this runtime. Node 22+ is required for hub mode.");return e}function Nt(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return Buffer.from(e).toString();if(e instanceof ArrayBuffer)return Buffer.from(e).toString();if(Array.isArray(e))return Buffer.concat(e.map((t)=>Buffer.from(t))).toString();if(e&&typeof e==="object"&&"data"in e&&typeof e.data<"u")return Nt(e.data);return String(e)}function Vs(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return Buffer.from(e).toString("utf8");if(e instanceof ArrayBuffer)return Buffer.from(e).toString("utf8");return""}function Ot(e){let t=e,n=Vs(t.reason);return new k("hub_connection_closed",t.code||n?`Hub connection closed (code=${t.code??0}${n?`, reason=${n}`:""})`:Ee,{closeCode:t.code,closeReason:n||void 0})}function Ut(e,t){if(e instanceof k)return e;if(e instanceof Error)return new k("hub_connect_failed",e.message);if(e&&typeof e==="object"&&"error"in e&&e.error instanceof Error)return new k("hub_connect_failed",e.error.message);let n=e&&typeof e==="object"&&"message"in e&&typeof e.message==="string"?e.message.trim():"";if(n)return new k("hub_connect_failed",n);let s=e&&typeof e==="object"&&"type"in e&&typeof e.type==="string"?e.type.trim():"";return new k("hub_connect_failed",s?`Failed to connect to hub at ${t.toString()} (${s} event before socket open).`:`Failed to connect to hub at ${t.toString()}.`)}var xe="*",se=8000,Gs="cline-hub-auth.",Me=new Map,$t=new Set,Js=3000;var Ee="Hub connection closed",Ks=250,Qs=5000,Lt=0.5;class k extends Error{code;details;constructor(e,t,n){super(t);this.code=e;this.details=n;this.name="HubTransportError"}}function Ys(e){return e instanceof k}class He extends Error{command;code;constructor(e,t,n){super(n);this.command=e;this.code=t;this.name="HubCommandError"}}function Oe(e,t={}){let n=e.searchParams.get("authToken")?.trim();if(e.searchParams.delete("authToken"),n)return n;if(t.skipRegistry)return;let s=oe(e.toString());return s?Me.get(s):void 0}function Xs(e){try{let n=new URL(e).hostname.toLowerCase().replace(/^\[|\]$/g,"");return n==="localhost"||n==="127.0.0.1"||n==="::1"}catch{return!1}}function oe(e){if(!Xs(e))return;let t=new URL(Wt(e));return t.search="",t.hash="",t.toString()}function Dt(e){let t=oe(e);return!!t&&$t.has(t)}function ne(e,t){let n=oe(e);if(n){if($t.add(n),t?.trim())Me.set(n,t)}return e}function It(e,t){let n=oe(e);if(n&&t?.trim())Me.set(n,t)}class V{options;socket;connectPromise;clientId;currentUrl;recoveryPromise;pendingReplies=new Map;listeners=new Set;subscriptionCounts=new Map;lastEventSequenceByKey=new Map;reconnectTimer;reconnectAttempt=0;closedByClient=!1;connectGeneration=0;lastCloseError=new k("hub_connection_closed",Ee);sawSocketClose=!1;registered=!1;capabilities;constructor(e){this.options=e;if(e.authToken?.trim()&&e.resolveConnectionHeaders)throw Error("Hub connection headers cannot be combined with authToken authentication.");this.clientId=e.clientId??`core-${Math.random().toString(36).slice(2,10)}-${Date.now().toString(36)}`,this.currentUrl=e.url,this.capabilities=[...e.capabilities??[]]}getClientId(){return this.clientId}getUrl(){return this.currentUrl}isConnected(){return this.socket?.readyState===1&&this.registered}getConnectionError(){return this.isConnected()?null:this.lastCloseError}async updateCapabilities(e){if(this.capabilities=e.map((t)=>({...t})),!this.registered)return;await this.command("client.update",{capabilities:this.capabilities})}async connect(){if(this.connectPromise)return this.connectPromise;if(this.socket&&(this.socket.readyState===1||this.socket.readyState===0))return this.connectPromise??Promise.resolve();this.closedByClient=!1,this.clearReconnectTimer();let e=new URL(this.currentUrl),t=this.options.authToken?.trim()||Oe(e,{skipRegistry:Boolean(this.options.resolveConnectionHeaders)});if(e.hash="",t&&this.options.resolveConnectionHeaders)throw Error("Hub connection headers cannot be combined with authToken authentication.");let n=++this.connectGeneration,s=this.openSocket(e,t,n),o;this.connectPromise=s.then(async(r)=>{if(o=r,await this.commandOnce("client.register",{clientId:this.clientId,clientType:this.options.clientType??"core",displayName:this.options.displayName??"core",transport:"native",actorKind:"client",capabilities:this.capabilities,metadata:{...this.options.metadata,version:this.options.clientVersion??String(q.version),pid:process.pid},workspaceContext:{workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd}},void 0,void 0,!1),n!==this.connectGeneration||this.closedByClient){try{r.close()}catch{}throw this.lastCloseError}this.registered=!0;for(let a of this.subscriptionCounts.keys())this.sendSubscriptionFrame("stream.subscribe",this.subscriptionSessionIdFromKey(a));this.reconnectAttempt=0});let i=this.connectPromise;try{await i}catch(r){if(this.connectPromise===i)this.connectPromise=void 0;if(o&&this.socket===o){this.lastCloseError=Ut(r,e),this.registered=!1,this.sawSocketClose=!1,this.socket=void 0;try{o.close()}catch{}}if(!this.closedByClient&&this.hasActiveSubscriptions())this.scheduleReconnect();throw r}}async openSocket(e,t,n){let s=this.options.resolveConnectionHeaders,o;if(s){let d;try{o=await Promise.race([Promise.resolve().then(()=>s()),new Promise((u,f)=>{d=setTimeout(()=>{f(new k("hub_connect_timeout",`Timed out resolving hub connection headers after ${se}ms`))},se)})])}catch(u){let f=u instanceof k?u:new k("hub_connect_failed",u instanceof Error?u.message:String(u));if(n===this.connectGeneration)this.lastCloseError=f;throw f}finally{clearTimeout(d)}}if(n!==this.connectGeneration||this.closedByClient)throw this.lastCloseError;if(o&&Object.keys(o).some((d)=>d.toLowerCase()==="sec-websocket-protocol")){let d=new k("hub_connect_failed","Hub connection headers cannot set Sec-WebSocket-Protocol.");if(n===this.connectGeneration)this.lastCloseError=d;throw d}let i=o?new js(e.toString(),{headers:{...o}}):new(zs())(e.toString(),t?[`${Gs}${t}`]:void 0);this.socket=i;let r=!1,a=new Promise((d,u)=>{let f=!1,c=setTimeout(()=>{if(f)return;f=!0,r=!0;let h=new k("hub_connect_timeout",`Timed out connecting to hub after ${se}ms`);if(this.socket===i)this.lastCloseError=h,this.sawSocketClose=!1,this.connectPromise=void 0,this.socket=void 0;try{i.close()}catch{}u(h)},se);i.addEventListener("open",()=>{if(f)return;f=!0,clearTimeout(c),d()}),i.addEventListener("error",(h)=>{if(f)return;f=!0,clearTimeout(c);let p=Ut(h,e);if(this.socket===i)this.lastCloseError=p,this.sawSocketClose=!1,this.connectPromise=void 0,this.socket=void 0;u(p)}),i.addEventListener("close",(h)=>{if(f)return;f=!0,clearTimeout(c);let p=r?this.lastCloseError:Ot(h);if(this.socket===i){if(!r)this.lastCloseError=p,this.sawSocketClose=!0;this.connectPromise=void 0,this.socket=void 0}u(p)})});return i.addEventListener("message",(d)=>{this.handleFrame(JSON.parse(Nt(d)))}),i.addEventListener("close",(d)=>{if(this.socket!==i)return;if(!r)this.lastCloseError=Ot(d),this.sawSocketClose=!0;this.registered=!1;for(let u of this.pendingReplies.values())u.reject(this.lastCloseError);if(this.pendingReplies.clear(),this.connectPromise=void 0,this.socket=void 0,!this.closedByClient&&this.hasActiveSubscriptions())this.scheduleReconnect()}),await a,i}subscribe(e,t){let n=t?.sessionId?.trim()||void 0,s={listener:e,sessionId:n};return this.listeners.add(s),this.adjustSubscriptionCount(n,1),()=>{if(!this.listeners.delete(s))return;this.adjustSubscriptionCount(n,-1)}}async command(e,t,n,s){let o=0,i=e!=="client.register"&&e!=="client.unregister";while(!0)try{return await this.commandOnce(e,t,n,s)}catch(r){if(!i||o>=1||!await this.recoverLocalHubTransport(r))throw r;o+=1}}async commandOnce(e,t,n,s,o=!0){if(o)await this.connect();s?.beforeDispatch?.();let i=qs("hubreq_");s?.onDispatch?.(i);let r=Ws(e,s?.timeoutMs),a=new Promise((u,f)=>{let c=r===null?void 0:setTimeout(()=>{if(!this.pendingReplies.delete(i))return;f(new He(e,"hub_command_timeout",`Hub command ${e} timed out after ${r}ms (hub=${this.currentUrl}, requestId=${i}, clientId=${this.clientId}). Check hub-daemon.log for matching command.start/command.slow entries, or run 'cline doctor fix' to restart the hub.`))},r);this.pendingReplies.set(i,{resolve:(h)=>{if(c)clearTimeout(c);u(h)},reject:(h)=>{if(c)clearTimeout(c);f(h)}})});try{this.sendFrame({kind:"command",envelope:{version:"v1",command:e,requestId:i,clientId:this.clientId,sessionId:n,timeoutMs:r,payload:t}})}catch(u){throw this.pendingReplies.delete(i),u}let d=await a;if(!d.ok){if(d.error?.code===rt){let u=n??(typeof t?.sessionId==="string"?t.sessionId:void 0);throw new Y(u,d.error.message)}throw new He(e,d.error?.code,d.error?.message??`Hub command ${e} failed`)}return d}async recoverLocalHubTransport(e){if(!Dt(this.currentUrl)||!Ys(e))return!1;if(this.recoveryPromise)return await this.recoveryPromise;return this.recoveryPromise=(async()=>{let t=await Bt({workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd}).catch(()=>{return});if(!t)return!1;return this.currentUrl=t,this.close(),!0})().finally(()=>{this.recoveryPromise=void 0}),await this.recoveryPromise}hasActiveSubscriptions(){return this.subscriptionCounts.size>0}clearReconnectTimer(){if(!this.reconnectTimer)return;clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0}scheduleReconnect(){if(this.reconnectTimer||this.closedByClient||!this.hasActiveSubscriptions())return;let e=Math.min(Ks*2**this.reconnectAttempt,Qs),t=Math.round(e*(1-Lt)+Math.random()*e*Lt);this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=void 0,this.reconnectSubscribedTransport()},t)}async reconnectSubscribedTransport(){if(this.closedByClient||!this.hasActiveSubscriptions())return;try{await this.connect(),this.reconnectAttempt=0}catch{if(!Dt(this.currentUrl)){this.reconnectAttempt+=1,this.scheduleReconnect();return}try{let e=await Bt({workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd});if(e){this.currentUrl=e,await this.connect(),this.reconnectAttempt=0;return}}catch{}this.reconnectAttempt+=1,this.scheduleReconnect()}}close(){let e=this.socket;if(this.closedByClient=!0,this.connectGeneration+=1,this.clearReconnectTimer(),this.registered=!1,e)this.lastCloseError=new k("hub_connection_closed",Ee);for(let t of this.pendingReplies.values())t.reject(this.lastCloseError);if(this.pendingReplies.clear(),this.connectPromise=void 0,!e)return;this.sawSocketClose=!1,this.socket=void 0;try{e.close()}catch{}}async dispose(){if(this.socket?.readyState===1&&this.registered)try{await this.command("client.unregister",void 0,void 0,{timeoutMs:2000})}catch{}this.close()}sendFrame(e){if(!this.socket||this.socket.readyState!==1){if(this.lastCloseError.code==="hub_connection_closed"&&!this.sawSocketClose)throw new k("hub_connection_not_open","Hub connection is not open.");throw this.lastCloseError}this.socket.send(JSON.stringify(e))}sendSubscriptionFrame(e,t){let n=e==="stream.subscribe"?this.lastEventSequenceByKey.get(this.subscriptionKeyForSessionId(t)):void 0;this.sendFrame({kind:e,clientId:this.clientId,...t?{sessionId:t}:{},...n!==void 0?{sinceSequence:n}:{}})}adjustSubscriptionCount(e,t){let n=this.subscriptionKeyForSessionId(e),s=(this.subscriptionCounts.get(n)??0)+t;if(s<=0){if(this.subscriptionCounts.delete(n),!this.hasActiveSubscriptions())this.clearReconnectTimer();if(t<0&&this.socket?.readyState===1)this.sendSubscriptionFrame("stream.unsubscribe",e);return}if(this.subscriptionCounts.set(n,s),t>0&&s===1&&this.socket?.readyState===1)this.sendSubscriptionFrame("stream.subscribe",e)}subscriptionKeyForSessionId(e){return e??xe}subscriptionSessionIdFromKey(e){return e===xe?void 0:e}handleFrame(e){switch(e.kind){case"reply":{let t=e.envelope.requestId;if(!t)return;let n=this.pendingReplies.get(t);if(!n)return;this.pendingReplies.delete(t),n.resolve(e.envelope);return}case"event":{let t=e.envelope.sequence;if(typeof t==="number"){let n=e.envelope.sessionId?.trim();for(let s of[xe,n]){if(!s||!this.subscriptionCounts.has(s))continue;let o=this.lastEventSequenceByKey.get(s)??0;if(t>o)this.lastEventSequenceByKey.set(s,t)}}for(let n of this.listeners){if(n.sessionId&&n.sessionId!==e.envelope.sessionId?.trim())continue;n.listener(e.envelope)}return}case"command":case"stream.subscribe":case"stream.unsubscribe":return}}}function Wt(e){let t=new URL(e);if(t.protocol==="http:")t.protocol="ws:";else if(t.protocol==="https:")t.protocol="wss:";return t.toString()}async function E(e,t){let n=new V({url:e,authToken:t?.authToken,clientType:"hub-healthcheck",displayName:"hub healthcheck",workspaceRoot:t?.workspaceRoot,cwd:t?.cwd});try{return await n.connect(),!0}catch{return!1}finally{n.close()}}async function Ie(e,t){let n=Wt(e),s=await ee(n,{authToken:t?.authToken});if(!s)return{status:"unreachable",url:n};if(t?.requireCurrentBuild){let o=U(),i=X(s,o);if(!i.compatible&&!Z(s))return{status:i.reason==="unsupported_protocol"?"protocol_mismatch":"build_mismatch",url:n}}else if(!Ns(s).compatible)return{status:"protocol_mismatch",url:n};if(t?.verifyConnection===!0&&!await E(n,{workspaceRoot:t.workspaceRoot,cwd:t.cwd,authToken:t.authToken}))return{status:"unreachable",url:n};return{status:"compatible",url:n}}function Zs(e){let t=e&&typeof e==="object"&&Array.isArray(e.sessions)?e.sessions:[],n=0,s=new Set;for(let o of t){if(!o||typeof o!=="object")continue;let i=o.participants;if(!Array.isArray(i)||i.length===0)continue;n+=1;for(let r of i){let a=r&&typeof r==="object"?r.clientId:void 0;if(typeof a==="string"&&a.trim())s.add(a)}}return{activeSessionCount:n,participantClientCount:s.size}}async function Te(e,t,n){let s=new V({url:e,authToken:t,clientType:"hub-recovery-check",displayName:"hub recovery check",workspaceRoot:n?.workspaceRoot,cwd:n?.cwd});try{let o=await s.command("session.list",{limit:500},void 0,{timeoutMs:Js});return Zs(o.payload)}finally{await s.dispose().catch(()=>{return})}}async function eo(e,t,n){try{return(await Te(e,t,n)).activeSessionCount===0}catch{return!1}}async function to(e,t){let n=`${e.discoveryPath}.superseded`,s=await I(n);if(!s?.url||!s.authToken)return;let o=await Ie(s.url,{authToken:s.authToken});if(o.status!=="compatible")return;if(await eo(o.url,s.authToken,t))return;return ne(o.url,s.authToken)}async function no(e={}){if(e.endpoint?.trim()){let o=await Ie(e.endpoint);return o.status==="compatible"?o.url:void 0}let t=Fs(),n=await I(t.discoveryPath);if(!n?.url)return await to(t,e);let s=await Ie(n.url,{authToken:n.authToken,requireCurrentBuild:!0});if(s.status==="compatible")return ne(s.url,n.authToken);if(s.status==="protocol_mismatch")await L(t.discoveryPath).catch(()=>{return});return}async function Bt(e={}){let t=await no(e);if(t&&await E(t,{workspaceRoot:e.workspaceRoot,cwd:e.cwd}))return t;if(e.endpoint?.trim())return;try{return(await Ht(e.workspaceRoot??process.cwd())).url}catch(n){e.onStartupError?.(n);return}}async function z(e,t,n,s){qt();let o=new URL(e),i=t?.trim()||Oe(o);if(o.protocol==="ws:")o.protocol="http:";else if(o.protocol==="wss:")o.protocol="https:";if(o.pathname="/drain",o.hash="",n)o.searchParams.set("reason",n);if(s?.off)o.searchParams.set("off","1");return(await fetch(o,{method:"POST",headers:i?{authorization:`Bearer ${i}`}:void 0})).ok}async function Mt(e,t){qt();let n=new URL(e),s=t?.trim()||Oe(n);if(n.protocol==="ws:")n.protocol="http:";else if(n.protocol==="wss:")n.protocol="https:";return n.pathname="/shutdown",n.hash="",(await fetch(n,{method:"POST",headers:s?{authorization:`Bearer ${s}`}:void 0})).ok}function so(e,t){if(!e||typeof e!=="object")return;let n=e,s=typeof n.id==="string"?n.id.trim():"";if(!s)return;let o=typeof n.display_name==="string"?n.display_name.trim():typeof n.displayName==="string"?n.displayName.trim():"",i=typeof n.name==="string"?n.name.trim():"";return{id:s,name:o||i||s,catalogId:t}}function Ue(e,t){return Array.isArray(e)?e.flatMap((n)=>{let s=so(n,t);return s?[s]:[]}):[]}async function jt(e,t={}){let n=e.trim(),s=n.length;while(s>0&&n[s-1]==="/")s--;let o=n.slice(0,s),i=async(m)=>{let y=await(t.fetchImpl??fetch)(`${o}${m}`,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!y.ok)throw Error(`HTTP ${y.status}`);return await y.json()},r,a;try{[r,a]=await Promise.all([i("/api/v1/ai/cline/models"),i("/api/v1/ai/cline/recommended-models")])}catch(m){throw Error("Could not load the cloud model catalog.",{cause:m})}let d=r&&typeof r==="object"?r:void 0,u=Ue(Array.isArray(r)?r:d?.data,"cline"),f=a&&typeof a==="object"?a:void 0,c=f?.data&&typeof f.data==="object"?f.data:f,h=Ue(c?.clinePass,"cline-pass"),p=Ue(c?.clineCloud,"cline-cloud"),l=new Set;return[...t.isOrganizationSession?[]:h,...p,...u].filter((m)=>{if(l.has(m.id))return!1;return l.add(m.id),!0})}import{formatDisplayUserInput as Ft}from"@cerebriline/shared";var oo=new Set(["auto_compaction","compaction_budget_emergency","completion_reminder","loop_detection_notice","manual_compaction","mistake_stop_notice","recovery_notice"]);function io(e){switch(e){case"user":case"assistant":case"tool":case"system":case"status":case"error":return e;default:return"assistant"}}function ro(e){return e.metadata&&typeof e.metadata==="object"&&!Array.isArray(e.metadata)?e.metadata:void 0}function ao(e){let t=e?.userRunSpan;return typeof t==="number"&&Number.isInteger(t)&&t>=0?t:void 0}function co(e){if(typeof e.content==="string")return{hasAttachment:!1,text:e.content};if(!Array.isArray(e.content))return{hasAttachment:!1,text:"unknown"};let t=!1,n=!1,s=[];for(let o of e.content){if(!o||typeof o!=="object"||Array.isArray(o))continue;let i=o;if(i.type==="text"&&typeof i.text==="string")s.push(i.text);else if(i.type==="tool_result"||i.type==="tool-result")n=!0;else if(i.type==="file"||i.type==="image")t=!0}return{hasAttachment:t&&!n,text:s.join(`
11
11
  `)}}function uo(e){let t=Ft(e);return t.startsWith("[TASK RESUMPTION]")||t==="The user approved switching to act mode. Continue with the approved plan now."}function lo(e){if(io(e.role)!=="user")return 0;let t=ro(e),n=typeof t?.kind==="string"?t.kind:void 0,s=ao(t);if(n==="compaction"||n==="compaction_summary")return s??1;if(s!==void 0)return s;if(n&&oo.has(n))return 0;let o=co(e);if(!o.hasAttachment&&!Ft(o.text))return 0;if(!o.hasAttachment&&uo(o.text))return 0;return 1}function zt(e){return lo(e)>0}function ae(e){return Array.isArray(e?.sessions)?e.sessions.filter((t)=>Boolean(t)&&typeof t==="object"&&!Array.isArray(t)):[]}function Le(e){let t=e.updatedAt;return typeof t==="number"?t:Date.parse(String(t??""))||0}function De(e){let t=e?.metadata&&typeof e.metadata==="object"?e.metadata:void 0;return String(t?.model??e?.model??"").trim()}function de(e){let t=e.metadata&&typeof e.metadata==="object"?e.metadata:void 0;return!String(t?.parentSessionId??e.parentSessionId??"").trim()}function Kt(e,t="text"){if(!e||typeof e!=="object"||Array.isArray(e))return"";let n=e.content;if(typeof n==="string")return t==="text"?n.trim():"";if(!Array.isArray(n))return"";return n.map((s)=>s&&typeof s==="object"&&!Array.isArray(s)?t==="thinking"&&s.type==="redacted_thinking"?"[redacted]":String(s[t]??""):"").join("").trim()}function ie(e){let t=e.trim(),n=t.match(/^<user_input\b[^>]*>([\s\S]*)<\/user_input>$/);return(n?n[1]:t).trim()}function G(e,t,n){let s=ie(n);return e.filter((o)=>Boolean(o)&&typeof o==="object"&&!Array.isArray(o)&&String(o.role??"").toLowerCase()==="user"&&(s!==""||zt(o))&&ie(Kt(o))===s).length+t.filter((o)=>ie(o.prompt)===s).length}function Be(e){return e.flatMap((t)=>{if(t.event!=="session.pending_prompt_submitted")return[];let n=t.payload?.prompt&&typeof t.payload.prompt==="object"&&!Array.isArray(t.payload.prompt)?t.payload.prompt:void 0,s=String(n?.id??"").trim();if(!s)return[];return[{id:s,prompt:String(n?.prompt??""),steer:n?.delivery==="steer",attachmentCount:typeof n?.attachmentCount==="number"?n.attachmentCount:0,userImages:Array.isArray(n?.userImages)?n.userImages.filter((o)=>typeof o==="string"):void 0}]})}var po=new Set(["run.completed","run.aborted","run.failed"]),fo=new Set(["assistant.delta","assistant.finished","reasoning.delta","reasoning.finished"]);function Vt(e,t){return e.filter((n)=>Boolean(n)&&typeof n==="object"&&!Array.isArray(n)&&String(n.role??"").toLowerCase()==="assistant").map((n)=>Kt(n,t)).filter(Boolean)}function Gt(e,t,n="text"){let s=new Map;for(let o of Vt(t,n))s.set(o,(s.get(o)??0)+1);return Vt(e,n).filter((o)=>{let i=s.get(o)??0;if(i===0)return!0;if(i===1)s.delete(o);else s.set(o,i-1);return!1})}function re(e,t,n=new Set){if(!e||typeof e!=="object")return n;if(Array.isArray(e)){for(let i of e)re(i,t,n);return n}let s=e,o=t==="tool_use"?s.id:s.tool_use_id;if(s.type===t&&typeof o==="string")n.add(o);for(let i of Object.values(s))re(i,t,n);return n}function Jt(e,t="assistant"){let n="",s="";for(let o of e)if(o.event===`${t}.delta`)s+=t==="reasoning"&&o.payload?.redacted&&!o.payload?.text?"[redacted]":typeof o.payload?.text==="string"?o.payload.text:"";else if(o.event===`${t}.finished`){let i=o.payload?.[t==="assistant"?"text":"reasoning"],r=typeof i==="string"&&i?i:s;if(r)n=r;s=""}return(n||s).trim()}function Qt(e,t,n={}){let s=n.queueSnapshotApplied!==!1,o=Gt(t,n.baselineMessages??[]),i=Gt(t,n.baselineMessages??[],"thinking"),r=re(t,"tool_use"),a=re(t,"tool_result"),d=new Set(e.slice(0,n.messagesSnapshotEventCutoff??e.length)),u=new Set,f=new Map;for(let y of e.slice(0,n.messagesSnapshotEventCutoff??e.length)){let w=Be([y])[0];if(!w)continue;let v=ie(w.prompt),P=f.get(v)??Math.max(0,G(t,[],v)-G(n.baselineMessages??[],[],v));if(f.set(v,Math.max(0,P-1)),P>0)u.add(y)}let h=[...s?e.slice(n.queueSnapshotEventCutoff??e.length):e].reverse().find((y)=>y.event==="session.pending_prompts"),p=[],l=[],m=(y)=>{if(l.length===0)return;let w=l.filter((A)=>d.has(A)),v=(A)=>{if(!y)return-1;let S=[...w].reverse().findIndex((nn)=>nn.event===`${A}.finished`),D=S<0?-1:w.length-1-S;return D>=0||l.at(-1)?.event==="run.aborted"?D:w.length-1},P=v("assistant"),H=v("reasoning"),b=Jt(w.slice(0,P+1)),R=b?o.findIndex((A)=>A.endsWith(b)):-1,M=R>=0;if(M)o.splice(R,1);let J=Jt(w.slice(0,H+1),"reasoning"),pe=J?i.findIndex((A)=>A.endsWith(J)):-1;if(pe>=0)i.splice(pe,1);for(let[A,S]of l.entries()){if(u.has(S)){p.push({...S,payload:{...S.payload,transcriptReflected:!0}});continue}if(d.has(S)&&fo.has(S.event)&&(S.event.startsWith("reasoning.")?pe>=0&&A<=H:M&&A<=P))continue;if(S.event==="session.pending_prompts"&&S!==h)continue;if(d.has(S)&&S.event.startsWith("tool.")){let D=String(S.payload?.toolCallId??"").trim();if(a.has(D)||S.event==="tool.started"&&r.has(D))continue}p.push(S)}l=[]};for(let y of e)if(l.push(y),po.has(y.event))m(!0);return m(!1),p}import{formatDisplayUserInput as ho}from"@cerebriline/shared";function ce(e){let t=structuredClone(e),n=(s)=>{if(!s||typeof s!=="object"||Object.isFrozen(s))return;for(let o of Object.values(s))n(o);Object.freeze(s)};return n(t),t}function ue(e){let t=e?.trim();return t?ho(t).slice(0,120):void 0}function qe(e){if(typeof e==="string")return e;if(Array.isArray(e)){let t=[];for(let n of e){if(typeof n==="string"){if(n.trim())t.push(n);continue}if(!n||typeof n!=="object")continue;let s=n,o=typeof s.type==="string"?s.type:"",i=o==="text"?String(s.text??""):o==="thinking"?String(s.thinking??""):o==="tool_use"?`[tool] ${String(s.name??"tool_call")}`:o==="tool_result"?`[tool_result]
@@ -0,0 +1,50 @@
1
+ import type { BrowserDriver } from "../tools/browser";
2
+ /** The extension's local-mode user agent. */
3
+ export declare const CHROME_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36";
4
+ /**
5
+ * Where Chrome usually is, in the order a Linux or macOS box tends to have it.
6
+ * Built on each call so an environment set after import is read.
7
+ */
8
+ export declare function chromeCandidates(): string[];
9
+ /**
10
+ * The browser this machine already has. No download: a host that silently
11
+ * pulled 150 MB on the first tool call would be a worse surprise than a clear
12
+ * message saying which paths were tried.
13
+ */
14
+ export declare function findChrome(): string | undefined;
15
+ export declare class MissingChromeError extends Error {
16
+ constructor();
17
+ }
18
+ /**
19
+ * How a host hands over puppeteer: `() => import("puppeteer-core")` written in
20
+ * the host's own code, so its bundler sees the import and includes the module.
21
+ */
22
+ export type PuppeteerLoader = () => Promise<unknown>;
23
+ /**
24
+ * Load puppeteer-core, or say what is missing. Kept in one place so both
25
+ * drivers fail the same way when a host was installed without it.
26
+ */
27
+ export declare function loadPuppeteer(loader?: PuppeteerLoader): Promise<unknown>;
28
+ export interface ChromeBrowserDriverOptions {
29
+ headless?: boolean;
30
+ /** Chrome's executable. Defaults to the first of `chromeCandidates()` that exists. */
31
+ chromePath?: string;
32
+ launchTimeoutMs?: number;
33
+ /**
34
+ * Arguments Chrome starts with. The default disables the sandbox, because
35
+ * a CLI is routinely run as root in a container, where Chrome's sandbox
36
+ * refuses to start; this browser only opens pages the model could already
37
+ * read off disk.
38
+ */
39
+ args?: string[];
40
+ /** How to load puppeteer-core. Defaults to resolving the installed peer. */
41
+ loadPuppeteer?: PuppeteerLoader;
42
+ }
43
+ export declare const DEFAULT_CHROME_ARGS: string[];
44
+ /**
45
+ * A driver that launches Chrome on first use and keeps it for the session,
46
+ * answering every action as the extension's `BrowserSession` (local mode)
47
+ * does. The tool owns the lifecycle -- it builds the driver lazily and calls
48
+ * `closeBrowser` at the end.
49
+ */
50
+ export declare function createChromeBrowserDriver(options?: ChromeBrowserDriverOptions): BrowserDriver;
@@ -0,0 +1,36 @@
1
+ import { type RenderDriver, type RenderRequest, type RenderResult } from "../tools/render-image";
2
+ import { type PuppeteerLoader } from "./chrome-browser-driver";
3
+ /**
4
+ * One render in a headless Chrome: the browser half of `render_image` (and of
5
+ * `transform_image`, which renders through the same driver).
6
+ *
7
+ * Moved here from the extension so any host can offer both tools: Chrome's
8
+ * path, its arguments and the Mermaid script are given, not looked up in VS
9
+ * Code's settings. A browser is started for the render and closed after it --
10
+ * a few hundred milliseconds beside a render that is rarely the tenth of a
11
+ * session, and a browser that is never kept is never left running.
12
+ */
13
+ export interface RenderEnvironment {
14
+ executablePath: string;
15
+ /** `mermaid.min.js`. Absent: a diagram is refused with the reason. */
16
+ mermaidScriptPath?: string;
17
+ args?: string[];
18
+ /** How to load puppeteer-core. Defaults to resolving the installed peer. */
19
+ loadPuppeteer?: PuppeteerLoader;
20
+ }
21
+ export declare function renderWithChrome(request: RenderRequest, environment: RenderEnvironment): Promise<RenderResult>;
22
+ export interface ChromeRenderDriverOptions {
23
+ /**
24
+ * Chrome's executable, or how to find it per render (the extension asks
25
+ * its browser settings each time). Defaults to `findChrome()`.
26
+ */
27
+ executablePath?: string | (() => string | undefined | Promise<string | undefined>);
28
+ /** `mermaid.min.js`; without it a Mermaid diagram is refused with the reason. */
29
+ mermaidScriptPath?: string | (() => string | undefined);
30
+ /** Chrome's arguments, or how to read them per render. Defaults to `DEFAULT_CHROME_ARGS`. */
31
+ args?: string[] | (() => string[] | Promise<string[]>);
32
+ /** How to load puppeteer-core. Defaults to resolving the installed peer. */
33
+ loadPuppeteer?: PuppeteerLoader;
34
+ }
35
+ /** A `RenderDriver` over `renderWithChrome`, for `render_image` and `transform_image`. */
36
+ export declare function createChromeRenderDriver(options?: ChromeRenderDriverOptions): RenderDriver;
@@ -0,0 +1,99 @@
1
+ import { type AgentTool } from "@cerebriline/shared";
2
+ import { type LintCommandResult } from "../tools/check-file";
3
+ import type { ReadDiagnostics, ReadText, TouchDocument } from "./types";
4
+ /**
5
+ * `check_file` answered from language-server diagnostics: the extension's
6
+ * tool, moved here so the CLI and automaticum's runner offer the same one.
7
+ *
8
+ * Core's other `check_file` (`tools/check-file.ts`) parses the file itself and
9
+ * answers a narrower question -- syntax and brackets, not types. A host with
10
+ * language servers -- VS Code's, or the ones `createLspHost` starts -- builds
11
+ * this one instead, and may hand the files no server covers to that one
12
+ * through `describeUnserved`.
13
+ *
14
+ * Everything about *reading* diagnostics -- waiting for the server to settle,
15
+ * dropping hint-level noise, capping and rendering a file's problems -- is the
16
+ * post-edit report's, imported from there. Two different answers to "what is
17
+ * wrong with this file" would be worse than either.
18
+ */
19
+ /**
20
+ * Deliberately written at the model that gets this wrong: `run_commands` is
21
+ * the tool it reaches for by reflex, so the alternatives it would otherwise
22
+ * type are named here, and so is every word a question about it uses -- a
23
+ * tool the model cannot name is a tool it does not have.
24
+ */
25
+ export declare const DIAGNOSTICS_CHECK_FILE_TOOL_DESCRIPTION = "Check files for errors and warnings, using the editor's own language servers (LSP). **This is the linter.** It is also the type checker, the syntax check, and the source of the problems that would show in a Problems panel \u2014 whichever of those words the question uses, this is the tool that answers it. The results are live and follow your edits: one is current as of the moment you ask, so if it still reports a problem after an edit, the problem is still there. Restarting a language server is neither possible nor necessary from here.\n\nAsk this before running a checker yourself. For a file whose language a language server covers, it answers the same question as `tsc`, `eslint`, `biome`, `ruff`, `mypy`, `go build` or `cargo check` would \u2014 for the files you name, in milliseconds, without building the project.\n\nWhen to call it:\n- Whenever the question is about the linter, lint errors, diagnostics, problems, warnings, type errors, syntax errors or compile errors \u2014 \"how many errors is the linter reporting?\", \"is it clean now?\", \"what is still broken?\". You have no other way to know, and the report you were shown after an earlier edit does not answer it: that was true then, and you have edited since.\n- After editing a file, to confirm the edit is valid before moving on.\n- Before reporting a task finished, on every file you changed.\n- On a file you are about to change, when you want to know what was already wrong with it.\n\nPass every file you want checked in one call.\n\nRead a clean result carefully. \"No problems reported by the editor\" is conclusive only where a language server covers that file, and it does not for every language on every machine. If this reports nothing and you have reason to expect a problem, or the project has a checker the language servers do not run, run that checker with `run_commands`. Tests and builds are always `run_commands`; this tool does not run them.\n\nOutput: plain text, one section per file you named, each problem on its own line as `file:line:column` with its severity and message. A file with nothing wrong says so in one line. Problems being listed is this tool working, not failing.\n\nA parse error is reported where the parser gave up. That is where the code stopped making sense to it, which is often but not always where the mistake is: a bracket left open earlier makes it give up later. When a file's brackets do not match, a `Delimiter scan` section adds the lines where they stop pairing up and how many each line is out by, one line per place the trouble starts \u2014 read both before you edit, and work through every line listed before re-checking. A count says where brackets stop pairing, not which bracket is wrong, so read the code at those lines rather than editing them blind. The scan reads the whole file from line 1, and names each bracket by its line, its column and the text just before it: find it by that text rather than by counting columns. Do not count brackets yourself \u2014 the scan skips strings, comments and regex literals, which counting characters does not. It runs whether or not the editor reported anything, so it can appear beneath a file the editor called clean \u2014 no language server checks the script inside an `.html` file, and there this is the only report you will get.";
26
+ export declare const DIAGNOSTICS_CHECK_FILE_TOOL_INPUT_SCHEMA: {
27
+ readonly type: "object";
28
+ readonly properties: {
29
+ readonly paths: {
30
+ readonly type: "array";
31
+ readonly items: {
32
+ readonly type: "string";
33
+ };
34
+ readonly description: "Files to check. Absolute, or relative to the working directory. Pass all of them in one call.";
35
+ };
36
+ };
37
+ readonly required: readonly ["paths"];
38
+ };
39
+ /**
40
+ * A shorter settle budget than the post-edit report uses: that one runs the
41
+ * instant a write lands; this one usually runs against a file that has been
42
+ * sitting still, so the server has already had its chance.
43
+ */
44
+ export declare const CHECK_SETTLE_BUDGET: {
45
+ pollMs: number;
46
+ timeoutMs: number;
47
+ };
48
+ /** What the editor holds for a file: the text its language server checks. */
49
+ export interface LoadedDocument {
50
+ text: string;
51
+ /** The user has changes to it they have not saved. */
52
+ dirty: boolean;
53
+ }
54
+ export interface DiagnosticsCheckFileToolOptions {
55
+ cwd: string;
56
+ readDiagnostics: ReadDiagnostics;
57
+ /**
58
+ * Hand a file to its server before reading its diagnostics: a file the
59
+ * server has never seen has none, and none reads as clean. For a host
60
+ * whose servers are its own (`LspHost.touch`).
61
+ */
62
+ touch?: TouchDocument;
63
+ /**
64
+ * Make the editor load a file it may never have opened, and report its
65
+ * copy, which is compared with the disk (VS Code). Nothing returned skips
66
+ * the comparison.
67
+ */
68
+ loadDocument?: (filePath: string) => Promise<LoadedDocument | undefined>;
69
+ /**
70
+ * Whether a server answers for a file. With `describeUnserved`, a file no
71
+ * server answers for gets that answer instead of "no problems reported".
72
+ */
73
+ serves?: (filePath: string) => boolean;
74
+ /** The answer for a file no server covers -- core's syntax check, say. */
75
+ describeUnserved?: (absolutePath: string, displayPath: string) => Promise<string | undefined>;
76
+ /** The user's lint command, if they set one. */
77
+ resolveLintCommand?: () => string | undefined;
78
+ /** Runs the configured command. Injected so tests never spawn anything. */
79
+ runLintCommand?: (template: string, filePath: string, signal?: AbortSignal) => Promise<LintCommandResult>;
80
+ /**
81
+ * What reported paths are written relative to. Defaults to `cwd`; the
82
+ * extension writes them relative to the workspace root it reports.
83
+ */
84
+ displayCwd?: () => string | Promise<string>;
85
+ /** Replaces the description, for a host that words it for its own setting. */
86
+ description?: string;
87
+ /** The disk, as the host reads it. Defaults to the real one. */
88
+ readFile?: ReadText;
89
+ /** Injection point for tests; defaults to a real timer. */
90
+ delay?: (ms: number) => Promise<void>;
91
+ onError?: (message: string, error: unknown) => void;
92
+ }
93
+ interface CheckFileInput {
94
+ paths?: unknown;
95
+ }
96
+ /** Accept the shapes a model actually sends, not only the documented one. */
97
+ export declare function readRequestedPaths(input: CheckFileInput | undefined): string[];
98
+ export declare function createDiagnosticsCheckFileTool(options: DiagnosticsCheckFileToolOptions): AgentTool;
99
+ export {};
@@ -0,0 +1,125 @@
1
+ import { type AgentHooks } from "@cerebriline/shared";
2
+ import type { DiagnosticSeverityName, HostDiagnostic, HostFileDiagnostics, ReadDiagnostics, ReadText, TouchDocument } from "./types";
3
+ /**
4
+ * Severities worth a turn of the model's attention.
5
+ *
6
+ * Errors and warnings are claims that something is wrong. Information and hint
7
+ * diagnostics are mostly editor affordances -- "convert to template literal",
8
+ * "this import could be type-only" -- and a model handed them will act on them,
9
+ * turning every edit into a style refactor nobody asked for.
10
+ */
11
+ export declare const REPORTED_SEVERITIES: readonly DiagnosticSeverityName[];
12
+ /**
13
+ * Diagnostics reported per file. A truncated list still says "this edit broke
14
+ * something, look here", which is the whole job. An untruncated one can be
15
+ * longer than the file.
16
+ */
17
+ export declare const MAX_DIAGNOSTICS_PER_FILE = 20;
18
+ /**
19
+ * How long to wait for the language server to catch up with the write.
20
+ *
21
+ * Diagnostics are published asynchronously and a request issued the instant an
22
+ * edit lands reads the state before it. The wait ends early as soon as the
23
+ * file's diagnostics stop changing, so the common case costs one poll interval
24
+ * rather than the whole budget. Small on purpose: this sits between the model
25
+ * and its next turn, and a slow linter must not become a slow agent.
26
+ */
27
+ export declare const SETTLE_POLL_MS = 250;
28
+ export declare const SETTLE_TIMEOUT_MS = 2000;
29
+ export declare const sleep: (ms: number) => Promise<void>;
30
+ /**
31
+ * Extract the files a file-writing tool call is about.
32
+ *
33
+ * `editor` names its file directly. `apply_patch` carries a patch body whose
34
+ * grammar names the files in its headers, which is the only place they appear.
35
+ */
36
+ export declare function readTargetPaths(toolName: string, input: unknown): string[];
37
+ /**
38
+ * Whether a file is one an editor diagnostic can say something useful about.
39
+ * A rejection list rather than an allow list: the set of things an editor
40
+ * lints grows with every extension installed, and a Dockerfile, a Makefile or
41
+ * a `.env` has no extension to allow in the first place.
42
+ */
43
+ export declare function isLintableFile(filePath: string): boolean;
44
+ /**
45
+ * A path in the form used to compare two paths for identity.
46
+ *
47
+ * Windows filesystems are case-insensitive, and the two sides come from
48
+ * different places: the editor reports the path as the workspace has it, and
49
+ * the model types it. Measured: the workspace was `c:\Users\...` and the model
50
+ * asked about `C:\Users\...`, and six `check_file` calls answered "no problems"
51
+ * for a file `node --check` rejects. Only the case is normalized; this is a
52
+ * comparison key, not a canonical path.
53
+ */
54
+ export declare function comparablePath(filePath: string): string;
55
+ /** Whether two paths name the same file, as this platform judges it. */
56
+ export declare function samePath(a: string, b: string): boolean;
57
+ export declare function filterToPaths(diagnostics: readonly HostFileDiagnostics[], absolutePaths: ReadonlySet<string>): HostFileDiagnostics[];
58
+ /** The diagnostics as the editor reports them, without a host's `pending` mark. */
59
+ export declare function withoutPending(files: readonly HostFileDiagnostics[]): HostFileDiagnostics[];
60
+ export declare function isReportableDiagnostic(diagnostic: HostDiagnostic): boolean;
61
+ /**
62
+ * Render one file's reportable diagnostics, or an empty string when there are
63
+ * none -- silence is the correct output for a clean edit, and the cheapest.
64
+ */
65
+ export declare function renderFileDiagnostics(cwd: string, filePath: string, diagnostics: readonly HostDiagnostic[], readText?: ReadText): Promise<string>;
66
+ export declare function formatIntroducedDiagnostics(cwd: string, before: readonly HostFileDiagnostics[], after: readonly HostFileDiagnostics[]): Promise<string>;
67
+ /**
68
+ * Append a rendered block to a tool result without destroying its shape.
69
+ *
70
+ * The file-writing tools return a `ToolOperationResult`, whose `result` field is
71
+ * what the model reads; anything else is stringified by the transport, so the
72
+ * block goes where a string will survive.
73
+ */
74
+ export declare function appendToOutput(output: unknown, block: string): unknown;
75
+ /**
76
+ * Mark a tool result as having made the file worse.
77
+ *
78
+ * The loop tracker asked "did it get anywhere?" from failure alone, which is
79
+ * blind to eight `editor` calls returning `success: true` while the file's
80
+ * diagnostics went 2 -> 20. An edit that adds problems did not get anywhere,
81
+ * whatever its envelope says. The flag rides on the result so the runtime can
82
+ * read it without this module knowing about the loop tracker.
83
+ */
84
+ export declare function markRegressed(output: unknown): unknown;
85
+ /**
86
+ * Read the files' diagnostics once the language servers have stopped
87
+ * changing their mind, or once the budget runs out -- whichever comes first.
88
+ * A file changed after its server last reported on it is `pending`, and a
89
+ * pending answer is not a settled one however long it has stayed the same.
90
+ */
91
+ export declare function readSettledDiagnostics(absolutePaths: ReadonlySet<string>, read: ReadDiagnostics, delay: (ms: number) => Promise<void>, budget?: {
92
+ pollMs?: number;
93
+ timeoutMs?: number;
94
+ }): Promise<HostFileDiagnostics[]>;
95
+ export interface EditorDiagnosticsHooksOptions {
96
+ cwd: string;
97
+ readDiagnostics: ReadDiagnostics;
98
+ /**
99
+ * For a host whose servers do not watch the disk: hand a file over before
100
+ * the edit (so what was already wrong with it is known, as it is for a
101
+ * file open in an editor) and after it, as saved. Left out, the host's
102
+ * diagnostics are read as they stand -- VS Code reloads the file itself.
103
+ */
104
+ touch?: TouchDocument;
105
+ /** Only files this says a server answers for are watched. */
106
+ serves?: (filePath: string) => boolean;
107
+ /** Injection point for tests; defaults to a real timer. */
108
+ delay?: (ms: number) => Promise<void>;
109
+ /** One record per edit, for a host's trace: what was asked and found. */
110
+ trace?: (entry: Record<string, unknown>) => void;
111
+ /** Where a failure of this feature goes. It never fails the edit. */
112
+ onError?: (message: string, error: unknown) => void;
113
+ /**
114
+ * What reported paths are written relative to. Defaults to `cwd`; the
115
+ * extension writes them relative to the workspace root it reports.
116
+ */
117
+ displayCwd?: () => string | Promise<string>;
118
+ }
119
+ /**
120
+ * Hooks that report an edit's new diagnostics back to the model.
121
+ *
122
+ * Composed with whatever hooks the host already has rather than folded into
123
+ * them: this is not optional in the way user-authored hook scripts are.
124
+ */
125
+ export declare function createEditorDiagnosticsHooks(options: EditorDiagnosticsHooksOptions): AgentHooks;
@@ -0,0 +1,25 @@
1
+ import type { DiagnosticSeverityName, HostDiagnostic, HostFileDiagnostics, ReadText } from "./types";
2
+ /**
3
+ * How a file's diagnostics are written for a model.
4
+ *
5
+ * One renderer for every host: `check_file` and the post-edit report say the
6
+ * same thing about the same file whether VS Code or a language server the CLI
7
+ * started produced it. Moved here from the extension's
8
+ * `integrations/diagnostics`, which now delegates to it.
9
+ */
10
+ /** The disk, read as text. */
11
+ export declare const defaultReadText: ReadText;
12
+ /** Two diagnostics are the same claim when every field they carry matches. */
13
+ export declare function sameDiagnostic(a: HostDiagnostic, b: HostDiagnostic): boolean;
14
+ /** The diagnostics in `after` that were not in `before`, per file. */
15
+ export declare function getNewDiagnostics(before: readonly HostFileDiagnostics[], after: readonly HostFileDiagnostics[]): HostFileDiagnostics[];
16
+ /**
17
+ * Every file's problems of the given severities, or an empty string when there
18
+ * are none. `cwd` is what the paths are written relative to.
19
+ */
20
+ export declare function diagnosticsToProblemsString(cwd: string, diagnostics: readonly HostFileDiagnostics[], severities?: readonly DiagnosticSeverityName[]): Promise<string>;
21
+ /**
22
+ * One file's problems, or an empty string when the list is empty. `cwd` is
23
+ * what the path is written relative to.
24
+ */
25
+ export declare function singleFileDiagnosticsToProblemsString(cwd: string, filePath: string, diagnostics: readonly HostDiagnostic[], readText?: ReadText): Promise<string>;