@cerebriline/core 4.100.248 → 4.100.249

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.
@@ -5,7 +5,7 @@ import{execFile as Z2}from"node:child_process";import{basename as C4,resolve as
5
5
  ...and ${K.length-5} more`:"";throw new C("dirty_worktree",`Commit and push local changes before handing off to cloud. Uncommitted files are not transferred.
6
6
 
7
7
  ${_}${O}`)}let j;try{j=await J.symbolicBranch()}catch(K){let _=r(K)===1,O=t(K),B=_?"Cloud handoff requires a checked-out branch; detached HEAD is not supported.":"Could not inspect the current Git branch.";throw new C(_?"detached_head":"git_command_failed",O?`${B} (${O})`:B,{cause:K})}if(!j)throw new C("detached_head","Cloud handoff requires a checked-out branch; detached HEAD is not supported.");let[V,Y,W]=await Promise.all([y(()=>J.branchRemote(j),"missing_upstream",`Branch ${j} has no upstream. Push it with -u before handing off.`),y(()=>J.branchMergeRef(j),"missing_upstream",`Branch ${j} has no upstream. Push it with -u before handing off.`),y(J.headSha,"git_command_failed","Could not resolve the current commit.")]);if(!V||V==="."||!Y.startsWith("refs/heads/"))throw new C("missing_upstream",`Branch ${j} has no remote branch upstream. Push it with -u before handing off.`);let F=Y.slice(11),G=V;if(!o0(V))try{G=await J.remoteUrl(V)}catch{throw new C("missing_upstream","Could not resolve the upstream remote.")}let N=o0(G);if(!N)throw new C("unsupported_remote","Cloud handoff currently requires a github.com upstream remote.");let z;try{z=await J.remoteRefs(V,Y)}catch(K){let _=r(K)===2,O=_?`The upstream branch ${F} 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 C(_?"remote_branch_missing":"git_command_failed",O)}let L=Y2(z,F);if(!L)throw new C("remote_branch_missing",`The upstream branch ${F} was not found. Push it before handing off.`);if(L.toLowerCase()!==W.toLowerCase())throw new C("unpushed_commits",`Local HEAD does not match the upstream branch ${F}. Push the current commit before handing off.`);return{repoUrl:N,branch:F,headSha:W,...X?{workspaceRelativePath:X}:{}}}function L0($){return $&&typeof $==="object"&&!Array.isArray($)?$:void 0}function T($){if(typeof $!=="string")return;return $.trim()||void 0}function N2($){return typeof $==="string"&&$.length>0?$:void 0}function F2($){let J=T($.repoUrl),Z=T($.branch),X=T($.headSha),Q=T($.modelId);if(!J||!Z||!X||!Q)throw Error("Cloud handoff fingerprint fields cannot be empty.");let j=T($.organizationId),V=N2($.workspaceRelativePath),Y=$.mode;return{repoUrl:J,branch:Z,headSha:X,modelId:Q,...j?{organizationId:j}:{},...V?{workspaceRelativePath:V}:{},...Y?{mode:Y}:{}}}function y4($,J){return $!==void 0&&J!==void 0&&$.repoUrl===J.repoUrl&&$.branch===J.branch&&$.headSha.toLowerCase()===J.headSha.toLowerCase()&&$.modelId===J.modelId&&$.organizationId===J.organizationId&&$.workspaceRelativePath===J.workspaceRelativePath&&$.mode===J.mode}function K2($){let J=L0($);if(!J||typeof J.repoUrl!=="string"||typeof J.branch!=="string"||typeof J.headSha!=="string"||typeof J.modelId!=="string")return;try{return F2({repoUrl:J.repoUrl,branch:J.branch,headSha:J.headSha,modelId:J.modelId,...typeof J.organizationId==="string"?{organizationId:J.organizationId}:{},...typeof J.workspaceRelativePath==="string"?{workspaceRelativePath:J.workspaceRelativePath}:{},...J.mode==="plan"||J.mode==="yolo"||J.mode==="zen"?{mode:J.mode}:{}})}catch{return}}function g4($){let J=L0(L0($)?.handoff);if(!J)return;let Z=T(J.toCloudSessionId),X=T(J.handedOffAt),Q=J.status;if(!Z||!X||Q!=="pending"&&Q!=="complete")return;let j=T(J.innerSessionId),V=T(J.dashboardUrl),Y=K2(J.fingerprint);return{toCloudSessionId:Z,handedOffAt:X,status:Q,...j?{innerSessionId:j}:{},...V?{dashboardUrl:V}:{},...Y?{fingerprint:Y}:{}}}function h4($,J){return{...$??{},handoff:J}}function v4($){let{handoff:J,cloudHandoffIntent:Z,cloudHandoffSeedDispatched:X,...Q}=$??{};return Q}function S4($,J){let Z=J.trim();if(!Z)throw Error("Cloud session id cannot be empty.");let X=new URL("/agents",$);return X.searchParams.set("sessionId",Z),X.toString()}function e0($){return $.map((J)=>{let Z=J&&typeof J==="object"?J:{};return{role:Z.role,content:Z.content}})}function G0($,J){return $.length===J.length&&JSON.stringify(e0($))===JSON.stringify(e0(J))}class z0 extends Error{constructor($,J){super(`Cloud transcript verification failed (local ${$} messages, cloud ${J}).`);this.name="CloudHandoffTranscriptMismatchError"}}import{randomUUID as L2}from"node:crypto";import{decodeJwtPayload as G2}from"@cerebriline/shared";var z2=610000,_2=3000,m=15000,q2="CLOUD_SESSION_ERROR:",Z1="__cline_create_request__:";function X1($){return($.trim().split(`
8
- `)[0]??"").trim().slice(0,72)}class q extends Error{code;detail;connectUrl;status;constructor($,J,Z,X){super(`${q2}${JSON.stringify({code:$,message:J,connectUrl:Z})}`);this.code=$;this.detail=J;this.connectUrl=Z;this.status=X;this.name="CloudSessionError"}}class Q1 extends Error{constructor($){super($ instanceof Error?$.message:"Cloud handoff creation was rejected.",{cause:$});this.name="CloudHandoffCreationRejectedError"}}function O0($){let J=$.length;while(J>0&&$[J-1]==="/")J--;return $.slice(0,J)}function O2($){return`${Z1}${$}`.slice(0,255)}function $1($){return $?.startsWith(Z1)===!0}function A0($){switch($){case"provisioning":case"cloning_repo":case"agent_starting":case"ready":case"failed":return $;default:return}}function _0($){let J=G2($.replace(/^workos:/,""));return typeof J?.sub==="string"&&J.sub.trim()?J.sub.trim():void 0}function J1($){return new Promise((J,Z)=>{if($.aborted){Z($.reason);return}let X=()=>{clearTimeout(Q),Z($.reason)},Q=setTimeout(()=>{$.removeEventListener("abort",X),J()},_2);$.addEventListener("abort",X,{once:!0})})}function A2($,J){if($&&typeof $==="object"){let Z=$.error;if(typeof Z==="string"&&Z.trim())return Z.trim()}return J}function q0($,J,Z,X){let Q=A2(J,`Cloud session request failed (${$})`);if($===401)return new q("authentication_required",Q);if($===404)return new q("session_not_found",Q);if($===410)return new q("session_expired",Q);if($===412)return new q("github_not_connected",Q,X??`${O0(Z)}/dashboard/integrations`);if($===403&&Q.trim().toLowerCase()==="forbidden")return new q("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,$);return new q("request_failed",Q,void 0,$)}class B2{options;apiBaseUrl;appBaseUrl;fetchImpl;createTimeoutMs;unconfirmedHandoffCreates=new Set;completedHandoffCreates=new Map;constructor($){this.options=$;this.apiBaseUrl=O0($.apiBaseUrl),this.appBaseUrl=O0($.appBaseUrl),this.fetchImpl=$.fetch??fetch,this.createTimeoutMs=$.createTimeoutMs??z2}async request($,J={},Z,X,Q){let j=!1,V;while(!0){let Y;try{Y=typeof X==="string"?X:await this.options.getAuthToken()}catch(G){if(V)throw q0(401,void 0,this.appBaseUrl,Z);throw G}if(!Y?.trim())throw new q("authentication_required","Sign in to Cline before starting a cloud session.");if(Y.trim()===V)throw new q("authentication_required","The cloud session credential was rejected. Sign in again.");if(typeof X==="object"){if(X.subject?_0(Y.trim())!==X.subject:Y.trim()!==X.token)throw new q("authentication_required","The signed-in account changed during cloud session creation.");X.token=Y.trim()}Q?.();let W=await this.fetchImpl(`${this.apiBaseUrl}${$}`,{...J,signal:J.signal??AbortSignal.timeout(m),headers:{Accept:"application/json",Authorization:`Bearer ${Y.trim()}`,...J.body?{"Content-Type":"application/json"}:{},...J.headers}}),F=W.status===204?void 0:await W.json().catch(()=>{return});if(!W.ok){if(W.status===401&&typeof X==="object"&&!j&&X.subject){j=!0,V=Y.trim();continue}throw q0(W.status,F,this.appBaseUrl,Z)}return F?.data}}async list($){return await this.listWithToken($)}async listWithToken($,J,Z=!1){let X=$?.trim()?`?organizationId=${encodeURIComponent($.trim())}`:"";return(await this.request(`/api/v1/session${X}`,{},void 0,J)??[]).flatMap((j)=>{if(!j||typeof j!=="object"||typeof j.id!=="string")return[];return[{...j,title:!Z&&$1(j.title)?void 0:j.title,repoContext:j.repoContext&&typeof j.repoContext==="object"?j.repoContext:{},metadata:{...j.metadata&&typeof j.metadata==="object"?j.metadata:{},...!Z&&$1(j.title)?{createRequestTitle:j.title}:{}}}]})}async listRepositories($){let J=$?.trim(),Z=J?`${this.appBaseUrl}/dashboard/organization/integrations`:`${this.appBaseUrl}/dashboard/integrations`,X=J?`/api/v1/organizations/${encodeURIComponent(J)}/integrations/github/repositories`:"/api/v1/integrations/github/repositories";try{let Q=await this.request(X)??[];return{connected:!0,connectUrl:Z,repositories:Q.flatMap((j)=>{let V=Number(j.id),Y=String(j.html_url??j.clone_url??"").trim();if(!Number.isSafeInteger(V)||V<=0||!Y)return[];let W=String(j.name??"").trim();return[{id:V,name:W,fullName:String(j.full_name??(W||Y)).trim(),url:Y,defaultBranch:String(j.default_branch??"").trim()}]})}}catch(Q){if(Q instanceof q&&Q.code==="session_not_found")return{connected:!1,connectUrl:Z,repositories:[]};throw Q}}async listBranches($,J,Z={}){if(!Number.isSafeInteger($)||$<=0)throw new q("request_failed","Select a GitHub repository before loading branches.");let X=J?.trim(),Q=X?`/api/v1/organizations/${encodeURIComponent(X)}/integrations/github/repositories/${$}/branches`:`/api/v1/integrations/github/repositories/${$}/branches`,j=new URLSearchParams,V=Z.query?.trim(),Y=Z.cursor?.trim();if(V)j.set("query",V);if(Y)j.set("cursor",Y);let W=j.size>0?`${Q}?${j}`:Q;try{let F=await this.request(W),G=Array.isArray(F)?F:Array.isArray(F?.items)?F.items:[],N=V?.toLowerCase();return{available:!0,branches:G.flatMap((z)=>{let L=String(z.name??"").trim();return L&&(!Array.isArray(F)||!N||L.toLowerCase().includes(N))?[L]:[]}),nextToken:Array.isArray(F)?"":String(F?.nextToken??"").trim()}}catch(F){if(F instanceof q&&F.code==="session_not_found")return{available:!1,branches:[]};throw F}}async status($,J={}){return await this.request(`/api/v1/session/${encodeURIComponent($)}/status`,{signal:J.signal?AbortSignal.any([J.signal,AbortSignal.timeout(m)]):void 0},void 0,J.authToken)}async create($){if($.handoff&&typeof $.handoff.onCreating!=="function")throw new q("request_failed","Cloud handoff requires an onCreating callback to persist creation intent before dispatch.");let J=(await this.options.getAuthToken())?.trim();if(!J)throw new q("authentication_required","Sign in to Cline before starting a cloud session.");let Z={token:J,subject:_0(J)},X=O2($.requestId?.trim()||L2()),Q=$.handoff?`${Z.subject??J}/${$.organizationId??""}/${$.requestId?.trim()??""}`:void 0;if($.handoff&&!$.requestId?.trim())throw new q("request_failed","A stable request id is required for cloud handoff creation.");let j=async()=>(await this.listWithToken($.organizationId??void 0,Z,!0)).filter((N)=>N.title===X&&N.repoContext.repoUrl===$.repoUrl&&N.metadata.modelId===$.modelId&&(!$.branch?.trim()||N.repoContext.branch===$.branch.trim())),V=async(N)=>{if(N.status==="failed"||N.expiredAt&&Date.parse(N.expiredAt)<=Date.now()){let L=new q(N.status==="failed"?"session_failed":"session_expired","The recovered cloud handoff workspace is no longer usable.");try{await this.deleteWithAuth(N.id,Z)}catch(K){if(!(K instanceof q&&(K.code==="session_not_found"||K.code==="session_expired")))throw AggregateError([L,K],"The unusable recovered cloud handoff workspace could not be removed.")}if(Q)this.unconfirmedHandoffCreates.delete(Q),this.completedHandoffCreates.delete(Q);throw await $.handoff?.onOuterSessionRemoved?.(N.id),L}await $.handoff?.onOuterSessionCreated(N.id,{created:!1});let z={sessionId:N.id,status:N.status,sandboxUrl:N.sandboxUrl,cleanupAuthToken:Z.token};if(Q)this.unconfirmedHandoffCreates.delete(Q),this.completedHandoffCreates.set(Q,z);return z};if(Q){let N=await j();if(N.length>1)throw new q("request_failed","Cloud handoff creation is ambiguous; inspect your cloud session list before continuing.");if(N[0])return await V(N[0]);let z=this.completedHandoffCreates.get(Q);if(z){try{await this.request(`/api/v1/session/${encodeURIComponent(z.sessionId)}/status`,{},void 0,Z)}catch(L){if(L instanceof q&&(L.code==="session_not_found"||L.code==="session_expired"))await $.handoff?.onOuterSessionRemoved?.(z.sessionId),this.completedHandoffCreates.delete(Q),this.unconfirmedHandoffCreates.delete(Q);throw L}return await $.handoff?.onOuterSessionCreated(z.sessionId,{created:!1}),{...z,cleanupAuthToken:Z.token}}if(this.unconfirmedHandoffCreates.has(Q))throw new q("request_failed","Cloud handoff creation is still unconfirmed. Recover the original request before creating another workspace.");this.unconfirmedHandoffCreates.add(Q)}try{await $.handoff?.onCreating()}catch(N){if(Q)this.unconfirmedHandoffCreates.delete(Q);throw N}let Y=new AbortController,W=setTimeout(()=>Y.abort(),this.createTimeoutMs),F,G=!1;try{let N=await this.request("/api/v1/session",{method:"POST",body:JSON.stringify({modelId:$.modelId,repoUrl:$.repoUrl,...$.sandboxType?{sandboxType:$.sandboxType}:{},title:X,...$.branch?.trim()?{branch:$.branch.trim()}:{},...$.organizationId?.trim()?{organizationId:$.organizationId.trim()}:{}}),signal:Y.signal},$.organizationId?.trim()?`${this.appBaseUrl}/dashboard/organization/integrations`:void 0,Z,()=>{G=!0}),z=N?.sessionId?.trim();if(!z)throw new q("request_failed","The cloud session service returned no session id.");F=z,await this.persistHandoffOuterSession($,z,Z,Q);let L={sessionId:z,status:N.status?.trim()||"provisioning",sandboxUrl:N.sandboxUrl?.trim()??"",cleanupAuthToken:Z.token};if(Q)this.unconfirmedHandoffCreates.delete(Q),this.completedHandoffCreates.set(Q,L);return L}catch(N){if(F)throw N;let z=!G||N instanceof q&&(N.status!==void 0&&N.status>=400&&N.status<500&&N.status!==408&&N.status!==409||["authentication_required","github_not_connected","session_not_found","session_expired"].includes(N.code));if(Q&&z)throw this.unconfirmedHandoffCreates.delete(Q),new Q1(N);if(Y.signal.aborted||!(N instanceof q)||N instanceof q&&N.code==="request_failed"&&(N.status===void 0||N.status>=500||N.status===408||N.status===409)){let K=[];try{K=await j()}catch(O){if($.handoff)throw AggregateError([N,O],"Cloud handoff creation is unconfirmed and its session list could not be checked.")}if(K.length>1)throw new q("request_failed","Cloud session creation had an ambiguous result. Check your cloud session list before trying again.");let _=K[0];if(_){if($.handoff)return await V(_);return{sessionId:_.id,status:_.status,sandboxUrl:_.sandboxUrl,cleanupAuthToken:Z.token}}}else if(Q)this.unconfirmedHandoffCreates.delete(Q);throw N}finally{clearTimeout(W)}}async persistHandoffOuterSession($,J,Z,X){if(!$.handoff)return;try{await $.handoff.onOuterSessionCreated(J,{created:!0})}catch(Q){try{await this.deleteWithAuth(J,Z.token)}catch(j){if(!(j instanceof q&&(j.code==="session_not_found"||j.code==="session_expired")))throw AggregateError([Q,j],`Cloud session ${J} was created but its recovery record could not be saved or its sandbox removed.`)}if(X)this.unconfirmedHandoffCreates.delete(X);throw await $.handoff.onOuterSessionRemoved?.(J),Q}}async waitUntilReady($,J,Z){J=AbortSignal.any([J,AbortSignal.timeout(this.createTimeoutMs)]);let X=await this.options.getAuthToken(),Q=X?{token:X,subject:_0(X)}:void 0;while(!J.aborted){let j;try{j=await this.request(`/api/v1/session/${encodeURIComponent($)}/status`,{signal:AbortSignal.any([J,AbortSignal.timeout(m)])},void 0,Q)}catch(Y){if(J.aborted)throw Y;if(Y instanceof q&&Y.code!=="request_failed")throw Y;await J1(J);continue}let V=j?.status?.trim().toLowerCase();if(Z?.({phase:A0(j?.phase)}),V==="ready"||V==="active")return;if(V==="failed")throw new q("session_failed",j?.statusReason?.trim()||"The cloud sandbox could not be prepared.");if(V!=="provisioning")throw new q("request_failed","The cloud session service returned an unexpected provisioning status.");await J1(J)}throw J.reason}async resume($,J){return await this.request(`/api/v1/session/${encodeURIComponent($)}/resume`,{method:"POST",signal:J?AbortSignal.any([J,AbortSignal.timeout(m)]):void 0})}async delete($,J){await this.deleteWithAuth($,J)}async deleteWithAuth($,J){let Z;try{await this.request(`/api/v1/session/${encodeURIComponent($)}`,{method:"DELETE"},void 0,J)}catch(X){if(!(X instanceof q)||X.code!=="session_not_found"&&X.code!=="session_expired")throw X;Z=X}for(let[X,Q]of this.completedHandoffCreates)if(Q.sessionId===$)this.completedHandoffCreates.delete(X),this.unconfirmedHandoffCreates.delete(X);if(Z)throw Z}async updateTitle($,J){return await this.request(`/api/v1/session/${encodeURIComponent($)}`,{method:"PATCH",body:JSON.stringify({title:J})})}async history($){let J=await this.options.getAuthToken();if(!J?.trim())throw new q("authentication_required","Sign in to Cline to load this session's history.");let Z=await this.fetchImpl(`${this.apiBaseUrl}/api/v1/session/${encodeURIComponent($)}/history`,{headers:{Accept:"application/json",Authorization:`Bearer ${J.trim()}`},signal:AbortSignal.timeout(m)});if(Z.status===404)return null;let X=await Z.json().catch(()=>{return});if(!Z.ok)throw q0(Z.status,X,this.appBaseUrl);if(!X||typeof X!=="object"||!("version"in X)||X.version!==1||!("messages"in X)||!Array.isArray(X.messages))throw new q("request_failed","Invalid archived session history");return X.messages}}import{randomUUID as z4}from"node:crypto";import{posix as F0}from"node:path";import{createSessionId as v6,ensureLoopbackProxyBypass as S1,isHubProtocolCompatible as S6,resolveClineBuildEnv as m6,resolveHubCommandTimeoutMs as I6}from"@cerebriline/shared";import p6 from"ws";var g={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 j1="session_not_found";class s extends Error{sessionId;code="session_not_found";constructor($,J){super(J??($?`session not found: ${$}`:"session not found"));this.sessionId=$;this.name="SessionNotFoundError"}}function B0($){return $ instanceof s||typeof $==="object"&&$!==null&&"code"in $&&$.code==="session_not_found"}import{spawn as Z6}from"node:child_process";import{closeSync as X6,mkdirSync as Q6,openSync as j6,readFileSync as V6,unlinkSync as Y6}from"node:fs";import{basename as W6,dirname as N6,join as F6}from"node:path";import{fileURLToPath as K6}from"node:url";import{CLINE_RUN_AS_HUB_DAEMON_ENV as L6,isBunEmbeddedModulePath as G6,isHubDaemonProcess as z6,resolveClineBuildEnv as T1,withResolvedClineBuildEnv as _6}from"@cerebriline/shared";import{createHash as U2,randomBytes as M2}from"node:crypto";import{mkdir as U0,open as V1,readFile as K1,rename as R2,rm as M0,writeFile as P2}from"node:fs/promises";import{dirname as L1,join as R0}from"node:path";import{ensureLoopbackProxyBypass as C2,isHubProtocolCompatible as H2}from"@cerebriline/shared";import{resolveClineDataDir as I,resolveClineDir as Z8}from"@cerebriline/shared/storage";var x2="CLINE_HUB_DISCOVERY_PATH",E2="CLINE_HUB_BUILD_ID",T2="CLINE_HUB_BUILD_EPOCH_MS",w2=30000,f2=15000,Y1=100;function b2($){return $.replace(/[^a-zA-Z0-9_.-]+/g,"_")}function k2($){return U2("sha256").update($).digest("hex").slice(0,12)}function y2($){if(!Number.isInteger($)||!$||$<=0)return!1;try{return process.kill($,0),!0}catch(J){return J instanceof Error&&"code"in J?String(J.code)==="EPERM":!1}}function W1($){return new Promise((J)=>setTimeout(J,$))}function g2($){return`${$}.lock`}async function h2($){try{let J=JSON.parse(await K1(R0($,"owner.json"),"utf8"));if(typeof J.pid!=="number"||typeof J.acquiredAt!=="string")return;return{pid:J.pid,acquiredAt:J.acquiredAt}}catch{return}}async function D0($){await M0($,{recursive:!0,force:!0}).catch(()=>{return})}function h(){let $=process.env[E2]?.trim();if($)return $;return"sdk-v1-eaad04bfc2e2d0b95d022771b7b2a4b75fff12a8aa960cab44ab6eaeee6fc5fe".trim()||`source-${String(g.version)}`}function v2(){let $=Number(process.env[T2]);if(Number.isFinite($)&&$>0)return $;return Number.isFinite(1791822817314)?1791822817314:void 0}function n($,J=h()){let Z=H2($);if(!Z.compatible)return Z;let X=$.buildId?.trim();if(!X)return{compatible:!1,reason:"missing_build"};if(X!==J)return{compatible:!1,reason:"build_mismatch"};return{compatible:!0}}function N1($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:void 0}function F1($){let J=$?.trim().split(/[-+]/,1)[0];if(!J)return;let Z=J.split(".").map((X)=>Number(X));if(Z.length===0||Z.some((X)=>!Number.isInteger(X)||X<0))return;return Z}function S2($,J){for(let Z=0;Z<Math.max($.length,J.length);Z++){let X=$[Z]??0,Q=J[Z]??0;if(X!==Q)return X<Q?-1:1}return 0}function G1($,J){let Z=$.buildId?.trim(),X=J.buildId?.trim();if(Z&&X&&Z===X)return 0;let Q=N1($.buildEpochMs),j=N1(J.buildEpochMs);if(Q!==void 0&&j!==void 0&&Q!==j)return Q<j?-1:1;let V=F1($.coreVersion),Y=F1(J.coreVersion);if(V&&Y){let W=S2(V,Y);if(W!==0)return W}if(Z&&X&&Z!==X)return Z<X?-1:1;return 0}function z1(){return{buildId:h(),buildEpochMs:v2(),coreVersion:String(g.version)}}function o($,J){let Z=J?.self??z1(),X=n($,Z.buildId??"");if(X.compatible)return!0;if(X.reason!=="build_mismatch"&&X.reason!=="missing_build")return!1;return G1(Z,$)<=0}function _1($=process.argv[1]?.trim()||process.cwd()){let J=`hub-${k2($)}`,Z=process.env[x2]?.trim()||R0(I(),"locks","hub","owners",`${b2(J)}.json`);return{ownerId:J,discoveryPath:Z}}async function b($){try{let J=JSON.parse(await K1($,"utf8"));if(typeof J.hubId!=="string"||typeof J.protocolVersion!=="string"||typeof J.authToken!=="string"||typeof J.host!=="string"||typeof J.port!=="number"||typeof J.url!=="string"||typeof J.startedAt!=="string"||typeof J.updatedAt!=="string")return;return{hubId:J.hubId,protocolVersion:J.protocolVersion,minClientProtocolVersion:typeof J.minClientProtocolVersion==="string"?J.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof J.maxClientProtocolVersion==="string"?J.maxClientProtocolVersion:void 0,capabilities:Array.isArray(J.capabilities)?J.capabilities.filter((Z)=>typeof Z==="string"):void 0,coreVersion:typeof J.coreVersion==="string"?J.coreVersion:void 0,buildId:typeof J.buildId==="string"?J.buildId:void 0,buildEpochMs:typeof J.buildEpochMs==="number"?J.buildEpochMs:void 0,authToken:J.authToken,host:J.host,port:J.port,url:J.url,pid:typeof J.pid==="number"?J.pid:void 0,startedAt:J.startedAt,updatedAt:J.updatedAt}}catch{return}}async function q1($,J,Z){await A1($,async()=>{let X=L1($);await U0(X,{recursive:!0});let Q=`${$}.${process.pid}.${M2(6).toString("hex")}.tmp`,j;try{j=await V1(Q,"wx",384),await j.writeFile(`${JSON.stringify(J,null,2)}
8
+ `)[0]??"").trim().slice(0,72)}class q extends Error{code;detail;connectUrl;status;constructor($,J,Z,X){super(`${q2}${JSON.stringify({code:$,message:J,connectUrl:Z})}`);this.code=$;this.detail=J;this.connectUrl=Z;this.status=X;this.name="CloudSessionError"}}class Q1 extends Error{constructor($){super($ instanceof Error?$.message:"Cloud handoff creation was rejected.",{cause:$});this.name="CloudHandoffCreationRejectedError"}}function O0($){let J=$.length;while(J>0&&$[J-1]==="/")J--;return $.slice(0,J)}function O2($){return`${Z1}${$}`.slice(0,255)}function $1($){return $?.startsWith(Z1)===!0}function A0($){switch($){case"provisioning":case"cloning_repo":case"agent_starting":case"ready":case"failed":return $;default:return}}function _0($){let J=G2($.replace(/^workos:/,""));return typeof J?.sub==="string"&&J.sub.trim()?J.sub.trim():void 0}function J1($){return new Promise((J,Z)=>{if($.aborted){Z($.reason);return}let X=()=>{clearTimeout(Q),Z($.reason)},Q=setTimeout(()=>{$.removeEventListener("abort",X),J()},_2);$.addEventListener("abort",X,{once:!0})})}function A2($,J){if($&&typeof $==="object"){let Z=$.error;if(typeof Z==="string"&&Z.trim())return Z.trim()}return J}function q0($,J,Z,X){let Q=A2(J,`Cloud session request failed (${$})`);if($===401)return new q("authentication_required",Q);if($===404)return new q("session_not_found",Q);if($===410)return new q("session_expired",Q);if($===412)return new q("github_not_connected",Q,X??`${O0(Z)}/dashboard/integrations`);if($===403&&Q.trim().toLowerCase()==="forbidden")return new q("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,$);return new q("request_failed",Q,void 0,$)}class B2{options;apiBaseUrl;appBaseUrl;fetchImpl;createTimeoutMs;unconfirmedHandoffCreates=new Set;completedHandoffCreates=new Map;constructor($){this.options=$;this.apiBaseUrl=O0($.apiBaseUrl),this.appBaseUrl=O0($.appBaseUrl),this.fetchImpl=$.fetch??fetch,this.createTimeoutMs=$.createTimeoutMs??z2}async request($,J={},Z,X,Q){let j=!1,V;while(!0){let Y;try{Y=typeof X==="string"?X:await this.options.getAuthToken()}catch(G){if(V)throw q0(401,void 0,this.appBaseUrl,Z);throw G}if(!Y?.trim())throw new q("authentication_required","Sign in to Cline before starting a cloud session.");if(Y.trim()===V)throw new q("authentication_required","The cloud session credential was rejected. Sign in again.");if(typeof X==="object"){if(X.subject?_0(Y.trim())!==X.subject:Y.trim()!==X.token)throw new q("authentication_required","The signed-in account changed during cloud session creation.");X.token=Y.trim()}Q?.();let W=await this.fetchImpl(`${this.apiBaseUrl}${$}`,{...J,signal:J.signal??AbortSignal.timeout(m),headers:{Accept:"application/json",Authorization:`Bearer ${Y.trim()}`,...J.body?{"Content-Type":"application/json"}:{},...J.headers}}),F=W.status===204?void 0:await W.json().catch(()=>{return});if(!W.ok){if(W.status===401&&typeof X==="object"&&!j&&X.subject){j=!0,V=Y.trim();continue}throw q0(W.status,F,this.appBaseUrl,Z)}return F?.data}}async list($){return await this.listWithToken($)}async listWithToken($,J,Z=!1){let X=$?.trim()?`?organizationId=${encodeURIComponent($.trim())}`:"";return(await this.request(`/api/v1/session${X}`,{},void 0,J)??[]).flatMap((j)=>{if(!j||typeof j!=="object"||typeof j.id!=="string")return[];return[{...j,title:!Z&&$1(j.title)?void 0:j.title,repoContext:j.repoContext&&typeof j.repoContext==="object"?j.repoContext:{},metadata:{...j.metadata&&typeof j.metadata==="object"?j.metadata:{},...!Z&&$1(j.title)?{createRequestTitle:j.title}:{}}}]})}async listRepositories($){let J=$?.trim(),Z=J?`${this.appBaseUrl}/dashboard/organization/integrations`:`${this.appBaseUrl}/dashboard/integrations`,X=J?`/api/v1/organizations/${encodeURIComponent(J)}/integrations/github/repositories`:"/api/v1/integrations/github/repositories";try{let Q=await this.request(X)??[];return{connected:!0,connectUrl:Z,repositories:Q.flatMap((j)=>{let V=Number(j.id),Y=String(j.html_url??j.clone_url??"").trim();if(!Number.isSafeInteger(V)||V<=0||!Y)return[];let W=String(j.name??"").trim();return[{id:V,name:W,fullName:String(j.full_name??(W||Y)).trim(),url:Y,defaultBranch:String(j.default_branch??"").trim()}]})}}catch(Q){if(Q instanceof q&&Q.code==="session_not_found")return{connected:!1,connectUrl:Z,repositories:[]};throw Q}}async listBranches($,J,Z={}){if(!Number.isSafeInteger($)||$<=0)throw new q("request_failed","Select a GitHub repository before loading branches.");let X=J?.trim(),Q=X?`/api/v1/organizations/${encodeURIComponent(X)}/integrations/github/repositories/${$}/branches`:`/api/v1/integrations/github/repositories/${$}/branches`,j=new URLSearchParams,V=Z.query?.trim(),Y=Z.cursor?.trim();if(V)j.set("query",V);if(Y)j.set("cursor",Y);let W=j.size>0?`${Q}?${j}`:Q;try{let F=await this.request(W),G=Array.isArray(F)?F:Array.isArray(F?.items)?F.items:[],N=V?.toLowerCase();return{available:!0,branches:G.flatMap((z)=>{let L=String(z.name??"").trim();return L&&(!Array.isArray(F)||!N||L.toLowerCase().includes(N))?[L]:[]}),nextToken:Array.isArray(F)?"":String(F?.nextToken??"").trim()}}catch(F){if(F instanceof q&&F.code==="session_not_found")return{available:!1,branches:[]};throw F}}async status($,J={}){return await this.request(`/api/v1/session/${encodeURIComponent($)}/status`,{signal:J.signal?AbortSignal.any([J.signal,AbortSignal.timeout(m)]):void 0},void 0,J.authToken)}async create($){if($.handoff&&typeof $.handoff.onCreating!=="function")throw new q("request_failed","Cloud handoff requires an onCreating callback to persist creation intent before dispatch.");let J=(await this.options.getAuthToken())?.trim();if(!J)throw new q("authentication_required","Sign in to Cline before starting a cloud session.");let Z={token:J,subject:_0(J)},X=O2($.requestId?.trim()||L2()),Q=$.handoff?`${Z.subject??J}/${$.organizationId??""}/${$.requestId?.trim()??""}`:void 0;if($.handoff&&!$.requestId?.trim())throw new q("request_failed","A stable request id is required for cloud handoff creation.");let j=async()=>(await this.listWithToken($.organizationId??void 0,Z,!0)).filter((N)=>N.title===X&&N.repoContext.repoUrl===$.repoUrl&&N.metadata.modelId===$.modelId&&(!$.branch?.trim()||N.repoContext.branch===$.branch.trim())),V=async(N)=>{if(N.status==="failed"||N.expiredAt&&Date.parse(N.expiredAt)<=Date.now()){let L=new q(N.status==="failed"?"session_failed":"session_expired","The recovered cloud handoff workspace is no longer usable.");try{await this.deleteWithAuth(N.id,Z)}catch(K){if(!(K instanceof q&&(K.code==="session_not_found"||K.code==="session_expired")))throw AggregateError([L,K],"The unusable recovered cloud handoff workspace could not be removed.")}if(Q)this.unconfirmedHandoffCreates.delete(Q),this.completedHandoffCreates.delete(Q);throw await $.handoff?.onOuterSessionRemoved?.(N.id),L}await $.handoff?.onOuterSessionCreated(N.id,{created:!1});let z={sessionId:N.id,status:N.status,sandboxUrl:N.sandboxUrl,cleanupAuthToken:Z.token};if(Q)this.unconfirmedHandoffCreates.delete(Q),this.completedHandoffCreates.set(Q,z);return z};if(Q){let N=await j();if(N.length>1)throw new q("request_failed","Cloud handoff creation is ambiguous; inspect your cloud session list before continuing.");if(N[0])return await V(N[0]);let z=this.completedHandoffCreates.get(Q);if(z){try{await this.request(`/api/v1/session/${encodeURIComponent(z.sessionId)}/status`,{},void 0,Z)}catch(L){if(L instanceof q&&(L.code==="session_not_found"||L.code==="session_expired"))await $.handoff?.onOuterSessionRemoved?.(z.sessionId),this.completedHandoffCreates.delete(Q),this.unconfirmedHandoffCreates.delete(Q);throw L}return await $.handoff?.onOuterSessionCreated(z.sessionId,{created:!1}),{...z,cleanupAuthToken:Z.token}}if(this.unconfirmedHandoffCreates.has(Q))throw new q("request_failed","Cloud handoff creation is still unconfirmed. Recover the original request before creating another workspace.");this.unconfirmedHandoffCreates.add(Q)}try{await $.handoff?.onCreating()}catch(N){if(Q)this.unconfirmedHandoffCreates.delete(Q);throw N}let Y=new AbortController,W=setTimeout(()=>Y.abort(),this.createTimeoutMs),F,G=!1;try{let N=await this.request("/api/v1/session",{method:"POST",body:JSON.stringify({modelId:$.modelId,repoUrl:$.repoUrl,...$.sandboxType?{sandboxType:$.sandboxType}:{},title:X,...$.branch?.trim()?{branch:$.branch.trim()}:{},...$.organizationId?.trim()?{organizationId:$.organizationId.trim()}:{}}),signal:Y.signal},$.organizationId?.trim()?`${this.appBaseUrl}/dashboard/organization/integrations`:void 0,Z,()=>{G=!0}),z=N?.sessionId?.trim();if(!z)throw new q("request_failed","The cloud session service returned no session id.");F=z,await this.persistHandoffOuterSession($,z,Z,Q);let L={sessionId:z,status:N.status?.trim()||"provisioning",sandboxUrl:N.sandboxUrl?.trim()??"",cleanupAuthToken:Z.token};if(Q)this.unconfirmedHandoffCreates.delete(Q),this.completedHandoffCreates.set(Q,L);return L}catch(N){if(F)throw N;let z=!G||N instanceof q&&(N.status!==void 0&&N.status>=400&&N.status<500&&N.status!==408&&N.status!==409||["authentication_required","github_not_connected","session_not_found","session_expired"].includes(N.code));if(Q&&z)throw this.unconfirmedHandoffCreates.delete(Q),new Q1(N);if(Y.signal.aborted||!(N instanceof q)||N instanceof q&&N.code==="request_failed"&&(N.status===void 0||N.status>=500||N.status===408||N.status===409)){let K=[];try{K=await j()}catch(O){if($.handoff)throw AggregateError([N,O],"Cloud handoff creation is unconfirmed and its session list could not be checked.")}if(K.length>1)throw new q("request_failed","Cloud session creation had an ambiguous result. Check your cloud session list before trying again.");let _=K[0];if(_){if($.handoff)return await V(_);return{sessionId:_.id,status:_.status,sandboxUrl:_.sandboxUrl,cleanupAuthToken:Z.token}}}else if(Q)this.unconfirmedHandoffCreates.delete(Q);throw N}finally{clearTimeout(W)}}async persistHandoffOuterSession($,J,Z,X){if(!$.handoff)return;try{await $.handoff.onOuterSessionCreated(J,{created:!0})}catch(Q){try{await this.deleteWithAuth(J,Z.token)}catch(j){if(!(j instanceof q&&(j.code==="session_not_found"||j.code==="session_expired")))throw AggregateError([Q,j],`Cloud session ${J} was created but its recovery record could not be saved or its sandbox removed.`)}if(X)this.unconfirmedHandoffCreates.delete(X);throw await $.handoff.onOuterSessionRemoved?.(J),Q}}async waitUntilReady($,J,Z){J=AbortSignal.any([J,AbortSignal.timeout(this.createTimeoutMs)]);let X=await this.options.getAuthToken(),Q=X?{token:X,subject:_0(X)}:void 0;while(!J.aborted){let j;try{j=await this.request(`/api/v1/session/${encodeURIComponent($)}/status`,{signal:AbortSignal.any([J,AbortSignal.timeout(m)])},void 0,Q)}catch(Y){if(J.aborted)throw Y;if(Y instanceof q&&Y.code!=="request_failed")throw Y;await J1(J);continue}let V=j?.status?.trim().toLowerCase();if(Z?.({phase:A0(j?.phase)}),V==="ready"||V==="active")return;if(V==="failed")throw new q("session_failed",j?.statusReason?.trim()||"The cloud sandbox could not be prepared.");if(V!=="provisioning")throw new q("request_failed","The cloud session service returned an unexpected provisioning status.");await J1(J)}throw J.reason}async resume($,J){return await this.request(`/api/v1/session/${encodeURIComponent($)}/resume`,{method:"POST",signal:J?AbortSignal.any([J,AbortSignal.timeout(m)]):void 0})}async delete($,J){await this.deleteWithAuth($,J)}async deleteWithAuth($,J){let Z;try{await this.request(`/api/v1/session/${encodeURIComponent($)}`,{method:"DELETE"},void 0,J)}catch(X){if(!(X instanceof q)||X.code!=="session_not_found"&&X.code!=="session_expired")throw X;Z=X}for(let[X,Q]of this.completedHandoffCreates)if(Q.sessionId===$)this.completedHandoffCreates.delete(X),this.unconfirmedHandoffCreates.delete(X);if(Z)throw Z}async updateTitle($,J){return await this.request(`/api/v1/session/${encodeURIComponent($)}`,{method:"PATCH",body:JSON.stringify({title:J})})}async history($){let J=await this.options.getAuthToken();if(!J?.trim())throw new q("authentication_required","Sign in to Cline to load this session's history.");let Z=await this.fetchImpl(`${this.apiBaseUrl}/api/v1/session/${encodeURIComponent($)}/history`,{headers:{Accept:"application/json",Authorization:`Bearer ${J.trim()}`},signal:AbortSignal.timeout(m)});if(Z.status===404)return null;let X=await Z.json().catch(()=>{return});if(!Z.ok)throw q0(Z.status,X,this.appBaseUrl);if(!X||typeof X!=="object"||!("version"in X)||X.version!==1||!("messages"in X)||!Array.isArray(X.messages))throw new q("request_failed","Invalid archived session history");return X.messages}}import{randomUUID as z4}from"node:crypto";import{posix as F0}from"node:path";import{createSessionId as v6,ensureLoopbackProxyBypass as S1,isHubProtocolCompatible as S6,resolveClineBuildEnv as m6,resolveHubCommandTimeoutMs as I6}from"@cerebriline/shared";import p6 from"ws";var g={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 j1="session_not_found";class s extends Error{sessionId;code="session_not_found";constructor($,J){super(J??($?`session not found: ${$}`:"session not found"));this.sessionId=$;this.name="SessionNotFoundError"}}function B0($){return $ instanceof s||typeof $==="object"&&$!==null&&"code"in $&&$.code==="session_not_found"}import{spawn as Z6}from"node:child_process";import{closeSync as X6,mkdirSync as Q6,openSync as j6,readFileSync as V6,unlinkSync as Y6}from"node:fs";import{basename as W6,dirname as N6,join as F6}from"node:path";import{fileURLToPath as K6}from"node:url";import{CLINE_RUN_AS_HUB_DAEMON_ENV as L6,isBunEmbeddedModulePath as G6,isHubDaemonProcess as z6,resolveClineBuildEnv as T1,withResolvedClineBuildEnv as _6}from"@cerebriline/shared";import{createHash as U2,randomBytes as M2}from"node:crypto";import{mkdir as U0,open as V1,readFile as K1,rename as R2,rm as M0,writeFile as P2}from"node:fs/promises";import{dirname as L1,join as R0}from"node:path";import{ensureLoopbackProxyBypass as C2,isHubProtocolCompatible as H2}from"@cerebriline/shared";import{resolveClineDataDir as I,resolveClineDir as Z8}from"@cerebriline/shared/storage";var x2="CLINE_HUB_DISCOVERY_PATH",E2="CLINE_HUB_BUILD_ID",T2="CLINE_HUB_BUILD_EPOCH_MS",w2=30000,f2=15000,Y1=100;function b2($){return $.replace(/[^a-zA-Z0-9_.-]+/g,"_")}function k2($){return U2("sha256").update($).digest("hex").slice(0,12)}function y2($){if(!Number.isInteger($)||!$||$<=0)return!1;try{return process.kill($,0),!0}catch(J){return J instanceof Error&&"code"in J?String(J.code)==="EPERM":!1}}function W1($){return new Promise((J)=>setTimeout(J,$))}function g2($){return`${$}.lock`}async function h2($){try{let J=JSON.parse(await K1(R0($,"owner.json"),"utf8"));if(typeof J.pid!=="number"||typeof J.acquiredAt!=="string")return;return{pid:J.pid,acquiredAt:J.acquiredAt}}catch{return}}async function D0($){await M0($,{recursive:!0,force:!0}).catch(()=>{return})}function h(){let $=process.env[E2]?.trim();if($)return $;return"sdk-v1-5e5cbbd449b2ed4fe502fdfcac849230ad16119851bcdf43d5731fc082612031".trim()||`source-${String(g.version)}`}function v2(){let $=Number(process.env[T2]);if(Number.isFinite($)&&$>0)return $;return Number.isFinite(1791835710163)?1791835710163:void 0}function n($,J=h()){let Z=H2($);if(!Z.compatible)return Z;let X=$.buildId?.trim();if(!X)return{compatible:!1,reason:"missing_build"};if(X!==J)return{compatible:!1,reason:"build_mismatch"};return{compatible:!0}}function N1($){return typeof $==="number"&&Number.isFinite($)&&$>0?$:void 0}function F1($){let J=$?.trim().split(/[-+]/,1)[0];if(!J)return;let Z=J.split(".").map((X)=>Number(X));if(Z.length===0||Z.some((X)=>!Number.isInteger(X)||X<0))return;return Z}function S2($,J){for(let Z=0;Z<Math.max($.length,J.length);Z++){let X=$[Z]??0,Q=J[Z]??0;if(X!==Q)return X<Q?-1:1}return 0}function G1($,J){let Z=$.buildId?.trim(),X=J.buildId?.trim();if(Z&&X&&Z===X)return 0;let Q=N1($.buildEpochMs),j=N1(J.buildEpochMs);if(Q!==void 0&&j!==void 0&&Q!==j)return Q<j?-1:1;let V=F1($.coreVersion),Y=F1(J.coreVersion);if(V&&Y){let W=S2(V,Y);if(W!==0)return W}if(Z&&X&&Z!==X)return Z<X?-1:1;return 0}function z1(){return{buildId:h(),buildEpochMs:v2(),coreVersion:String(g.version)}}function o($,J){let Z=J?.self??z1(),X=n($,Z.buildId??"");if(X.compatible)return!0;if(X.reason!=="build_mismatch"&&X.reason!=="missing_build")return!1;return G1(Z,$)<=0}function _1($=process.argv[1]?.trim()||process.cwd()){let J=`hub-${k2($)}`,Z=process.env[x2]?.trim()||R0(I(),"locks","hub","owners",`${b2(J)}.json`);return{ownerId:J,discoveryPath:Z}}async function b($){try{let J=JSON.parse(await K1($,"utf8"));if(typeof J.hubId!=="string"||typeof J.protocolVersion!=="string"||typeof J.authToken!=="string"||typeof J.host!=="string"||typeof J.port!=="number"||typeof J.url!=="string"||typeof J.startedAt!=="string"||typeof J.updatedAt!=="string")return;return{hubId:J.hubId,protocolVersion:J.protocolVersion,minClientProtocolVersion:typeof J.minClientProtocolVersion==="string"?J.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof J.maxClientProtocolVersion==="string"?J.maxClientProtocolVersion:void 0,capabilities:Array.isArray(J.capabilities)?J.capabilities.filter((Z)=>typeof Z==="string"):void 0,coreVersion:typeof J.coreVersion==="string"?J.coreVersion:void 0,buildId:typeof J.buildId==="string"?J.buildId:void 0,buildEpochMs:typeof J.buildEpochMs==="number"?J.buildEpochMs:void 0,authToken:J.authToken,host:J.host,port:J.port,url:J.url,pid:typeof J.pid==="number"?J.pid:void 0,startedAt:J.startedAt,updatedAt:J.updatedAt}}catch{return}}async function q1($,J,Z){await A1($,async()=>{let X=L1($);await U0(X,{recursive:!0});let Q=`${$}.${process.pid}.${M2(6).toString("hex")}.tmp`,j;try{j=await V1(Q,"wx",384),await j.writeFile(`${JSON.stringify(J,null,2)}
9
9
  `,{encoding:"utf8"}),await j.sync(),await j.close(),j=void 0,Z?.beforePublish?.(),await R2(Q,$);let V;try{V=await V1(X,"r"),await V.sync()}catch{}finally{await V?.close().catch(()=>{return})}}catch(V){throw await j?.close().catch(()=>{return}),await M0(Q,{force:!0}).catch(()=>{return}),V}})}async function v($){await A1($,async()=>{await M0($,{force:!0}).catch(()=>{return})})}async function O1($,J,Z){let X=g2($);await U0(L1(X),{recursive:!0});let Q=Date.now()+f2;while(!0){try{await U0(X,{recursive:!1})}catch(j){if((j instanceof Error&&"code"in j?String(j.code):"")!=="EEXIST")throw j;let Y=await h2(X);if(!Y){if(Date.now()>=Q){await D0(X);continue}await W1(Y1);continue}let W=Date.now()-Date.parse(Y.acquiredAt);if(!y2(Y.pid)||W>w2){await D0(X);continue}if(Date.now()>=Q)throw Error(`Timed out waiting for hub ${J} lock ${X}`);await W1(Y1);continue}try{return await P2(R0(X,"owner.json"),`${JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()},null,2)}
10
10
  `,"utf8"),await Z()}finally{await D0(X)}}}function A1($,J){return O1(`${$}.mutation`,"discovery mutation",J)}function B1($,J){return O1($,"startup",J)}async function e($,J){C2();try{let Z=await fetch(J?.authToken?m2($):U1($),{headers:J?.authToken?{authorization:`Bearer ${J.authToken}`}:void 0,signal:J?.signal});if(!Z.ok)return;let X=await Z.json();if(typeof X.protocolVersion!=="string"||typeof X.host!=="string"||typeof X.port!=="number"||typeof X.url!=="string")return;return{protocolVersion:X.protocolVersion,minClientProtocolVersion:typeof X.minClientProtocolVersion==="string"?X.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof X.maxClientProtocolVersion==="string"?X.maxClientProtocolVersion:void 0,capabilities:Array.isArray(X.capabilities)?X.capabilities.filter((Q)=>typeof Q==="string"):void 0,coreVersion:typeof X.coreVersion==="string"?X.coreVersion:void 0,buildId:typeof X.buildId==="string"?X.buildId:void 0,buildEpochMs:typeof X.buildEpochMs==="number"?X.buildEpochMs:void 0,host:X.host,port:X.port,url:X.url,hubId:typeof X.hubId==="string"?X.hubId:void 0,authToken:typeof X.authToken==="string"?X.authToken:void 0,pid:typeof X.pid==="number"?X.pid:void 0,startedAt:typeof X.startedAt==="string"?X.startedAt:void 0,updatedAt:typeof X.updatedAt==="string"?X.updatedAt:void 0}}catch{return}}function D1($,J,Z="/hub"){return new URL(`ws://${$}:${J}${Z}`).toString()}function U1($){let J=new URL($);return J.protocol=J.protocol==="wss:"?"https:":"http:",J.pathname="/health",J.search="",J.toString()}function m2($){let J=new URL(U1($));return J.pathname="/status",J.toString()}import{CLINE_HUB_DEV_PORT as I2,CLINE_HUB_PORT as p2,resolveClineBuildEnv as l2}from"@cerebriline/shared";var u2="CLINE_HUB_HOST",c2="CLINE_HUB_PORT",a2="CLINE_HUB_PATHNAME",d2="127.0.0.1",i2=p2,t2="/hub";function M1($){return l2($)==="development"?I2:i2}function r2($={}){return($.env??process.env)[u2]?.trim()||d2}function s2($={}){let Z=($.env??process.env)[c2]?.trim();if(!Z)return M1($);let X=Number.parseInt(Z,10);if(!Number.isInteger(X)||X<1||X>65535)return M1($);return X}function n2($={}){return($.env??process.env)[a2]?.trim()||t2}function R1($={},J={}){return{host:$.host??r2(J),port:$.port??s2(J),pathname:$.pathname??n2(J)}}import{join as o2}from"node:path";var e2="shared:cline",$6="CLINE_HUB_DISCOVERY_PATH",J6="hub-production";function p($=e2){return _1(`${$}@${h()}`)}function $0(){return{ownerId:J6,discoveryPath:process.env[$6]?.trim()||o2(I(),"locks","hub","production.json")}}var P1=15000,q6=200,C1=3000,O6=100,A6=[100,250,500,1000,2000],B6="--cline-hub-daemon",D6=3,U6=60000,H1=new Map;function M6($,J=Date.now()){let Z=H1.get($);if(!Z||J-Z.windowStartedAt>U6)return H1.set($,{count:1,windowStartedAt:J}),!0;return Z.count+=1,Z.count<=D6}function R6($){return[...$.host?["--host",$.host]:[],...typeof $.port==="number"?["--port",String($.port)]:[],...$.pathname?["--pathname",$.pathname]:[]]}function P6(){try{let $=F6(I(),"logs","hub-daemon.log");return Q6(N6($),{recursive:!0}),{fd:j6($,"a"),logPath:$}}catch{return}}function C6(){return T1()==="production"?$0():p()}function l($){return o($)}function H6($){try{let J=JSON.parse(V6(`${$}.superseded`,"utf8"));return{url:typeof J.url==="string"?J.url:void 0,authToken:typeof J.authToken==="string"?J.authToken:void 0,pid:typeof J.pid==="number"?J.pid:void 0}}catch{return}}function P0($){try{Y6(`${$}.superseded`)}catch{}}function x1($,J,Z){if(!J||J.url!==Z)return $;return{...$,authToken:$.authToken??J.authToken,pid:$.pid??J.pid}}async function u($,J){try{return await e($,{authToken:J})}catch{return}}async function E1($,J){let Z=Date.now()+J;while(Date.now()<Z){if(!(await u($))?.url)return!0;await new Promise((Q)=>setTimeout(Q,O6))}return!1}async function H0($,J){if(!M6($.url))return!1;await c($.url,$.authToken,"retired by newer install").catch(()=>!1),await b1($.url,$.authToken).catch(()=>!1);let Z=await E1($.url,C1);if(!Z&&$.pid&&x6($.pid)){try{process.kill($.pid,"SIGTERM")}catch{}Z=await E1($.url,C1)}if(Z)await v(J).catch(()=>{return});return Z}function x6($){try{return process.kill($,0),!0}catch(J){return J?.code==="EPERM"}}async function E6($){try{return(await x0($.url,$.authToken)).activeSessionCount>0}catch{return!1}}async function C0($,J){if(l($))return"reusable";let Z=await c($.url,$.authToken,"retired by newer install").catch(()=>!1);if(await E6($)){if(Z)await c($.url,$.authToken,"hub retirement deferred",{off:!0}).catch(()=>!1);return"deferred_busy"}let X=await H0($,J);if(!X&&Z)await c($.url,$.authToken,"hub retirement failed",{off:!0}).catch(()=>!1);return X?"retired":"failed"}async function T6($){if(T1()!=="production")return;let J=p();if(J.discoveryPath===$.discoveryPath)return;let Z=await b(J.discoveryPath);if(Z?.url)await H0(Z,J.discoveryPath);else await v(J.discoveryPath).catch(()=>{return})}function w6(){let $=import.meta.url.endsWith(".ts")?"ts":"js";return K6(new URL(`./entry.${$}`,import.meta.url))}function f6($,J){if(G6($))return[B6];return[...J&&$.toLowerCase().endsWith(".ts")?["--conditions=development"]:[],$]}function b6($,J){let Z=w6(),X=process.execPath?.trim();if(!X)throw Error("unable to resolve runtime executable for hub daemon");let Q=W6(X).toLowerCase().includes("bun"),j=f6(Z,Q);return{launcher:X,args:[...j,"--cwd",$,...R6(J),...J.manageConnectors===!1?["--no-connectors"]:[]],cwd:$,env:{..._6(process.env),CLINE_NO_INTERACTIVE:"1",[L6]:"1"}}}function k6($){if(!$||typeof $!=="object")return!1;if(("code"in $?$.code:void 0)==="ETXTBSY")return!0;let Z="message"in $?$.message:void 0;return typeof Z==="string"&&Z.includes("ETXTBSY")}function y6($,J={}){if(z6())return;let Z=b6($,J),X=P6();try{Z6(Z.launcher,Z.args,{detached:!0,stdio:X?["ignore",X.fd,X.fd]:"ignore",env:Z.env,cwd:Z.cwd,windowsHide:!0}).unref()}finally{if(X)X6(X.fd)}}async function g6($,J={}){for(let Z=0;;Z++)try{y6($,J);return}catch(X){let Q=A6[Z];if(!k6(X)||Q===void 0)throw X;await new Promise((j)=>setTimeout(j,Q))}}async function h6($,J,Z={}){let X=Z.host!==void 0||Z.port!==void 0||Z.pathname!==void 0||!!process.env.CLINE_HUB_PORT?.trim(),Q=R1(Z),j=D1(Q.host,Q.port,Q.pathname),V=(K)=>{if(!X)J0(K.url,K.authToken);else f1(K.url,K.authToken);return K};await T6($).catch(()=>{return});let Y=await b($.discoveryPath),W=Y?.url?void 0:H6($.discoveryPath),F=!1;if(Y?.url){let K=Y.authToken;if(!K)F=!0,await H0(Y,$.discoveryPath);else{let _=await u(Y.url,K);if(_?.url&&l(_)&&await w(_.url,{authToken:K}))return P0($.discoveryPath),V({url:_.url,authToken:K});if(_?.url){if(await C0({..._,authToken:K},$.discoveryPath)==="deferred_busy"&&await w(_.url,{authToken:K}))return V({url:_.url,authToken:K})}else await v($.discoveryPath).catch(()=>{return})}}let G=await u(j);if(G?.url){let K=x1(G,Y??W,j);if(l(G)){let O=[G.authToken,Y?.authToken,W?.authToken].filter((D)=>typeof D==="string"&&D.trim().length>0);for(let D of O){if(!await w(G.url,{authToken:D}))continue;let H={hubId:G.hubId??`repaired-${G.port}`,protocolVersion:G.protocolVersion,minClientProtocolVersion:G.minClientProtocolVersion,maxClientProtocolVersion:G.maxClientProtocolVersion,capabilities:G.capabilities,coreVersion:G.coreVersion,buildId:G.buildId,authToken:D,host:G.host,port:G.port,url:G.url,pid:G.pid??Y?.pid??W?.pid,startedAt:G.startedAt??new Date().toISOString(),updatedAt:new Date().toISOString()};try{await q1($.discoveryPath,H)}catch{}return P0($.discoveryPath),V({url:G.url,authToken:D})}throw Error(`A compatible Cline Hub is already running at ${j}, but its discovery record is missing or unreadable and no usable auth token is available. Run 'cline doctor fix' to repair local hub discovery.${F?" 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 _=await C0(K,$.discoveryPath);if(_==="deferred_busy"){for(let O of[K.authToken,Y?.authToken].filter((B)=>typeof B==="string"&&B.trim().length>0))if(await w(G.url,{authToken:O}))return V({url:G.url,authToken:O});if(Z.allowPortFallback!==!0&&Q.port!==0)throw Error(`An older Cline Hub is running at ${j} 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(_==="failed"&&Z.allowPortFallback!==!0&&Q.port!==0)throw Error(`An incompatible Cline Hub is already running at ${j} and could not be retired automatically. Run 'cline doctor fix' to stop stale hub daemons before starting a new hub.`)}let z=Z.allowPortFallback===!0&&Q.port!==0?{...Q,port:0}:Q;await g6(J,{...z,manageConnectors:Z.manageConnectors});let L=Date.now()+P1;while(Date.now()<L){let K=await b($.discoveryPath);if(K?.url&&K.authToken){let O=await u(K.url,K.authToken);if(O?.url&&l(O)&&await w(O.url,{authToken:K.authToken}))return P0($.discoveryPath),V({url:O.url,authToken:K.authToken})}let _=await u(j);if(_?.url&&!l(_)){let O=x1(_,K??W,j),B=await C0(O,$.discoveryPath);if(B==="deferred_busy"&&K?.authToken&&await w(_.url,{authToken:K.authToken}))return V({url:_.url,authToken:K.authToken});if(B==="failed"&&Z.allowPortFallback!==!0&&Q.port!==0)throw Error(`An incompatible Cline Hub is still running at ${j} and could not be retired automatically. Run 'cline doctor fix' to stop stale hub daemons before starting a new hub.`)}await new Promise((O)=>setTimeout(O,q6))}throw Error(`Timed out after ${P1}ms waiting for detached hub startup.`)}async function w1($,J={}){let Z=C6();return await B1(Z.discoveryPath,async()=>h6(Z,$,J))}function l6(){return m6()==="production"?$0():p()}function u6(){let $=globalThis.WebSocket;if(!$)throw Error("Global WebSocket is not available in this runtime. Node 22+ is required for hub mode.");return $}function m1($){if(typeof $==="string")return $;if($ instanceof Uint8Array)return Buffer.from($).toString();if($ instanceof ArrayBuffer)return Buffer.from($).toString();if(Array.isArray($))return Buffer.concat($.map((J)=>Buffer.from(J))).toString();if($&&typeof $==="object"&&"data"in $&&typeof $.data<"u")return m1($.data);return String($)}function c6($){if(typeof $==="string")return $;if($ instanceof Uint8Array)return Buffer.from($).toString("utf8");if($ instanceof ArrayBuffer)return Buffer.from($).toString("utf8");return""}function k1($){let J=$,Z=c6(J.reason);return new R("hub_connection_closed",J.code||Z?`Hub connection closed (code=${J.code??0}${Z?`, reason=${Z}`:""})`:T0,{closeCode:J.code,closeReason:Z||void 0})}function y1($,J){if($ instanceof R)return $;if($ instanceof Error)return new R("hub_connect_failed",$.message);if($&&typeof $==="object"&&"error"in $&&$.error instanceof Error)return new R("hub_connect_failed",$.error.message);let Z=$&&typeof $==="object"&&"message"in $&&typeof $.message==="string"?$.message.trim():"";if(Z)return new R("hub_connect_failed",Z);let X=$&&typeof $==="object"&&"type"in $&&typeof $.type==="string"?$.type.trim():"";return new R("hub_connect_failed",X?`Failed to connect to hub at ${J.toString()} (${X} event before socket open).`:`Failed to connect to hub at ${J.toString()}.`)}var E0="*",Z0=8000,a6="cline-hub-auth.",b0=new Map,I1=new Set,d6=3000;var T0="Hub connection closed",i6=250,t6=5000,g1=0.5;class R extends Error{code;details;constructor($,J,Z){super(J);this.code=$;this.details=Z;this.name="HubTransportError"}}function r6($){return $ instanceof R}class w0 extends Error{command;code;constructor($,J,Z){super(Z);this.command=$;this.code=J;this.name="HubCommandError"}}function k0($,J={}){let Z=$.searchParams.get("authToken")?.trim();if($.searchParams.delete("authToken"),Z)return Z;if(J.skipRegistry)return;let X=X0($.toString());return X?b0.get(X):void 0}function s6($){try{let Z=new URL($).hostname.toLowerCase().replace(/^\[|\]$/g,"");return Z==="localhost"||Z==="127.0.0.1"||Z==="::1"}catch{return!1}}function X0($){if(!s6($))return;let J=new URL(p1($));return J.search="",J.hash="",J.toString()}function h1($){let J=X0($);return!!J&&I1.has(J)}function J0($,J){let Z=X0($);if(Z){if(I1.add(Z),J?.trim())b0.set(Z,J)}return $}function f1($,J){let Z=X0($);if(Z&&J?.trim())b0.set(Z,J)}class a{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 R("hub_connection_closed",T0);sawSocketClose=!1;registered=!1;capabilities;constructor($){this.options=$;if($.authToken?.trim()&&$.resolveConnectionHeaders)throw Error("Hub connection headers cannot be combined with authToken authentication.");this.clientId=$.clientId??`core-${Math.random().toString(36).slice(2,10)}-${Date.now().toString(36)}`,this.currentUrl=$.url,this.capabilities=[...$.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($){if(this.capabilities=$.map((J)=>({...J})),!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 $=new URL(this.currentUrl),J=this.options.authToken?.trim()||k0($,{skipRegistry:Boolean(this.options.resolveConnectionHeaders)});if($.hash="",J&&this.options.resolveConnectionHeaders)throw Error("Hub connection headers cannot be combined with authToken authentication.");let Z=++this.connectGeneration,X=this.openSocket($,J,Z),Q;this.connectPromise=X.then(async(V)=>{if(Q=V,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(g.version),pid:process.pid},workspaceContext:{workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd}},void 0,void 0,!1),Z!==this.connectGeneration||this.closedByClient){try{V.close()}catch{}throw this.lastCloseError}this.registered=!0;for(let Y of this.subscriptionCounts.keys())this.sendSubscriptionFrame("stream.subscribe",this.subscriptionSessionIdFromKey(Y));this.reconnectAttempt=0});let j=this.connectPromise;try{await j}catch(V){if(this.connectPromise===j)this.connectPromise=void 0;if(Q&&this.socket===Q){this.lastCloseError=y1(V,$),this.registered=!1,this.sawSocketClose=!1,this.socket=void 0;try{Q.close()}catch{}}if(!this.closedByClient&&this.hasActiveSubscriptions())this.scheduleReconnect();throw V}}async openSocket($,J,Z){let X=this.options.resolveConnectionHeaders,Q;if(X){let W;try{Q=await Promise.race([Promise.resolve().then(()=>X()),new Promise((F,G)=>{W=setTimeout(()=>{G(new R("hub_connect_timeout",`Timed out resolving hub connection headers after ${Z0}ms`))},Z0)})])}catch(F){let G=F instanceof R?F:new R("hub_connect_failed",F instanceof Error?F.message:String(F));if(Z===this.connectGeneration)this.lastCloseError=G;throw G}finally{clearTimeout(W)}}if(Z!==this.connectGeneration||this.closedByClient)throw this.lastCloseError;if(Q&&Object.keys(Q).some((W)=>W.toLowerCase()==="sec-websocket-protocol")){let W=new R("hub_connect_failed","Hub connection headers cannot set Sec-WebSocket-Protocol.");if(Z===this.connectGeneration)this.lastCloseError=W;throw W}let j=Q?new p6($.toString(),{headers:{...Q}}):new(u6())($.toString(),J?[`${a6}${J}`]:void 0);this.socket=j;let V=!1,Y=new Promise((W,F)=>{let G=!1,N=setTimeout(()=>{if(G)return;G=!0,V=!0;let z=new R("hub_connect_timeout",`Timed out connecting to hub after ${Z0}ms`);if(this.socket===j)this.lastCloseError=z,this.sawSocketClose=!1,this.connectPromise=void 0,this.socket=void 0;try{j.close()}catch{}F(z)},Z0);j.addEventListener("open",()=>{if(G)return;G=!0,clearTimeout(N),W()}),j.addEventListener("error",(z)=>{if(G)return;G=!0,clearTimeout(N);let L=y1(z,$);if(this.socket===j)this.lastCloseError=L,this.sawSocketClose=!1,this.connectPromise=void 0,this.socket=void 0;F(L)}),j.addEventListener("close",(z)=>{if(G)return;G=!0,clearTimeout(N);let L=V?this.lastCloseError:k1(z);if(this.socket===j){if(!V)this.lastCloseError=L,this.sawSocketClose=!0;this.connectPromise=void 0,this.socket=void 0}F(L)})});return j.addEventListener("message",(W)=>{this.handleFrame(JSON.parse(m1(W)))}),j.addEventListener("close",(W)=>{if(this.socket!==j)return;if(!V)this.lastCloseError=k1(W),this.sawSocketClose=!0;this.registered=!1;for(let F of this.pendingReplies.values())F.reject(this.lastCloseError);if(this.pendingReplies.clear(),this.connectPromise=void 0,this.socket=void 0,!this.closedByClient&&this.hasActiveSubscriptions())this.scheduleReconnect()}),await Y,j}subscribe($,J){let Z=J?.sessionId?.trim()||void 0,X={listener:$,sessionId:Z};return this.listeners.add(X),this.adjustSubscriptionCount(Z,1),()=>{if(!this.listeners.delete(X))return;this.adjustSubscriptionCount(Z,-1)}}async command($,J,Z,X){let Q=0,j=$!=="client.register"&&$!=="client.unregister";while(!0)try{return await this.commandOnce($,J,Z,X)}catch(V){if(!j||Q>=1||!await this.recoverLocalHubTransport(V))throw V;Q+=1}}async commandOnce($,J,Z,X,Q=!0){if(Q)await this.connect();X?.beforeDispatch?.();let j=v6("hubreq_");X?.onDispatch?.(j);let V=I6($,X?.timeoutMs),Y=new Promise((F,G)=>{let N=V===null?void 0:setTimeout(()=>{if(!this.pendingReplies.delete(j))return;G(new w0($,"hub_command_timeout",`Hub command ${$} timed out after ${V}ms (hub=${this.currentUrl}, requestId=${j}, clientId=${this.clientId}). Check hub-daemon.log for matching command.start/command.slow entries, or run 'cline doctor fix' to restart the hub.`))},V);this.pendingReplies.set(j,{resolve:(z)=>{if(N)clearTimeout(N);F(z)},reject:(z)=>{if(N)clearTimeout(N);G(z)}})});try{this.sendFrame({kind:"command",envelope:{version:"v1",command:$,requestId:j,clientId:this.clientId,sessionId:Z,timeoutMs:V,payload:J}})}catch(F){throw this.pendingReplies.delete(j),F}let W=await Y;if(!W.ok){if(W.error?.code===j1){let F=Z??(typeof J?.sessionId==="string"?J.sessionId:void 0);throw new s(F,W.error.message)}throw new w0($,W.error?.code,W.error?.message??`Hub command ${$} failed`)}return W}async recoverLocalHubTransport($){if(!h1(this.currentUrl)||!r6($))return!1;if(this.recoveryPromise)return await this.recoveryPromise;return this.recoveryPromise=(async()=>{let J=await v1({workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd}).catch(()=>{return});if(!J)return!1;return this.currentUrl=J,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 $=Math.min(i6*2**this.reconnectAttempt,t6),J=Math.round($*(1-g1)+Math.random()*$*g1);this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=void 0,this.reconnectSubscribedTransport()},J)}async reconnectSubscribedTransport(){if(this.closedByClient||!this.hasActiveSubscriptions())return;try{await this.connect(),this.reconnectAttempt=0}catch{if(!h1(this.currentUrl)){this.reconnectAttempt+=1,this.scheduleReconnect();return}try{let $=await v1({workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd});if($){this.currentUrl=$,await this.connect(),this.reconnectAttempt=0;return}}catch{}this.reconnectAttempt+=1,this.scheduleReconnect()}}close(){let $=this.socket;if(this.closedByClient=!0,this.connectGeneration+=1,this.clearReconnectTimer(),this.registered=!1,$)this.lastCloseError=new R("hub_connection_closed",T0);for(let J of this.pendingReplies.values())J.reject(this.lastCloseError);if(this.pendingReplies.clear(),this.connectPromise=void 0,!$)return;this.sawSocketClose=!1,this.socket=void 0;try{$.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($){if(!this.socket||this.socket.readyState!==1){if(this.lastCloseError.code==="hub_connection_closed"&&!this.sawSocketClose)throw new R("hub_connection_not_open","Hub connection is not open.");throw this.lastCloseError}this.socket.send(JSON.stringify($))}sendSubscriptionFrame($,J){let Z=$==="stream.subscribe"?this.lastEventSequenceByKey.get(this.subscriptionKeyForSessionId(J)):void 0;this.sendFrame({kind:$,clientId:this.clientId,...J?{sessionId:J}:{},...Z!==void 0?{sinceSequence:Z}:{}})}adjustSubscriptionCount($,J){let Z=this.subscriptionKeyForSessionId($),X=(this.subscriptionCounts.get(Z)??0)+J;if(X<=0){if(this.subscriptionCounts.delete(Z),!this.hasActiveSubscriptions())this.clearReconnectTimer();if(J<0&&this.socket?.readyState===1)this.sendSubscriptionFrame("stream.unsubscribe",$);return}if(this.subscriptionCounts.set(Z,X),J>0&&X===1&&this.socket?.readyState===1)this.sendSubscriptionFrame("stream.subscribe",$)}subscriptionKeyForSessionId($){return $??E0}subscriptionSessionIdFromKey($){return $===E0?void 0:$}handleFrame($){switch($.kind){case"reply":{let J=$.envelope.requestId;if(!J)return;let Z=this.pendingReplies.get(J);if(!Z)return;this.pendingReplies.delete(J),Z.resolve($.envelope);return}case"event":{let J=$.envelope.sequence;if(typeof J==="number"){let Z=$.envelope.sessionId?.trim();for(let X of[E0,Z]){if(!X||!this.subscriptionCounts.has(X))continue;let Q=this.lastEventSequenceByKey.get(X)??0;if(J>Q)this.lastEventSequenceByKey.set(X,J)}}for(let Z of this.listeners){if(Z.sessionId&&Z.sessionId!==$.envelope.sessionId?.trim())continue;Z.listener($.envelope)}return}case"command":case"stream.subscribe":case"stream.unsubscribe":return}}}function p1($){let J=new URL($);if(J.protocol==="http:")J.protocol="ws:";else if(J.protocol==="https:")J.protocol="wss:";return J.toString()}async function w($,J){let Z=new a({url:$,authToken:J?.authToken,clientType:"hub-healthcheck",displayName:"hub healthcheck",workspaceRoot:J?.workspaceRoot,cwd:J?.cwd});try{return await Z.connect(),!0}catch{return!1}finally{Z.close()}}async function f0($,J){let Z=p1($),X=await e(Z,{authToken:J?.authToken});if(!X)return{status:"unreachable",url:Z};if(J?.requireCurrentBuild){let Q=h(),j=n(X,Q);if(!j.compatible&&!o(X))return{status:j.reason==="unsupported_protocol"?"protocol_mismatch":"build_mismatch",url:Z}}else if(!S6(X).compatible)return{status:"protocol_mismatch",url:Z};if(J?.verifyConnection===!0&&!await w(Z,{workspaceRoot:J.workspaceRoot,cwd:J.cwd,authToken:J.authToken}))return{status:"unreachable",url:Z};return{status:"compatible",url:Z}}function n6($){let J=$&&typeof $==="object"&&Array.isArray($.sessions)?$.sessions:[],Z=0,X=new Set;for(let Q of J){if(!Q||typeof Q!=="object")continue;let j=Q.participants;if(!Array.isArray(j)||j.length===0)continue;Z+=1;for(let V of j){let Y=V&&typeof V==="object"?V.clientId:void 0;if(typeof Y==="string"&&Y.trim())X.add(Y)}}return{activeSessionCount:Z,participantClientCount:X.size}}async function x0($,J,Z){let X=new a({url:$,authToken:J,clientType:"hub-recovery-check",displayName:"hub recovery check",workspaceRoot:Z?.workspaceRoot,cwd:Z?.cwd});try{let Q=await X.command("session.list",{limit:500},void 0,{timeoutMs:d6});return n6(Q.payload)}finally{await X.dispose().catch(()=>{return})}}async function o6($,J,Z){try{return(await x0($,J,Z)).activeSessionCount===0}catch{return!1}}async function e6($,J){let Z=`${$.discoveryPath}.superseded`,X=await b(Z);if(!X?.url||!X.authToken)return;let Q=await f0(X.url,{authToken:X.authToken});if(Q.status!=="compatible")return;if(await o6(Q.url,X.authToken,J))return;return J0(Q.url,X.authToken)}async function $4($={}){if($.endpoint?.trim()){let Q=await f0($.endpoint);return Q.status==="compatible"?Q.url:void 0}let J=l6(),Z=await b(J.discoveryPath);if(!Z?.url)return await e6(J,$);let X=await f0(Z.url,{authToken:Z.authToken,requireCurrentBuild:!0});if(X.status==="compatible")return J0(X.url,Z.authToken);if(X.status==="protocol_mismatch")await v(J.discoveryPath).catch(()=>{return});return}async function v1($={}){let J=await $4($);if(J&&await w(J,{workspaceRoot:$.workspaceRoot,cwd:$.cwd}))return J;if($.endpoint?.trim())return;try{return(await w1($.workspaceRoot??process.cwd())).url}catch(Z){$.onStartupError?.(Z);return}}async function c($,J,Z,X){S1();let Q=new URL($),j=J?.trim()||k0(Q);if(Q.protocol==="ws:")Q.protocol="http:";else if(Q.protocol==="wss:")Q.protocol="https:";if(Q.pathname="/drain",Q.hash="",Z)Q.searchParams.set("reason",Z);if(X?.off)Q.searchParams.set("off","1");return(await fetch(Q,{method:"POST",headers:j?{authorization:`Bearer ${j}`}:void 0})).ok}async function b1($,J){S1();let Z=new URL($),X=J?.trim()||k0(Z);if(Z.protocol==="ws:")Z.protocol="http:";else if(Z.protocol==="wss:")Z.protocol="https:";return Z.pathname="/shutdown",Z.hash="",(await fetch(Z,{method:"POST",headers:X?{authorization:`Bearer ${X}`}:void 0})).ok}function J4($,J){if(!$||typeof $!=="object")return;let Z=$,X=typeof Z.id==="string"?Z.id.trim():"";if(!X)return;let Q=typeof Z.display_name==="string"?Z.display_name.trim():typeof Z.displayName==="string"?Z.displayName.trim():"",j=typeof Z.name==="string"?Z.name.trim():"";return{id:X,name:Q||j||X,catalogId:J}}function y0($,J){return Array.isArray($)?$.flatMap((Z)=>{let X=J4(Z,J);return X?[X]:[]}):[]}async function l1($,J={}){let Z=$.trim(),X=Z.length;while(X>0&&Z[X-1]==="/")X--;let Q=Z.slice(0,X),j=async(_)=>{let O=await(J.fetchImpl??fetch)(`${Q}${_}`,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!O.ok)throw Error(`HTTP ${O.status}`);return await O.json()},V,Y;try{[V,Y]=await Promise.all([j("/api/v1/ai/cline/models"),j("/api/v1/ai/cline/recommended-models")])}catch(_){throw Error("Could not load the cloud model catalog.",{cause:_})}let W=V&&typeof V==="object"?V:void 0,F=y0(Array.isArray(V)?V:W?.data,"cline"),G=Y&&typeof Y==="object"?Y:void 0,N=G?.data&&typeof G.data==="object"?G.data:G,z=y0(N?.clinePass,"cline-pass"),L=y0(N?.clineCloud,"cline-cloud"),K=new Set;return[...J.isOrganizationSession?[]:z,...L,...F].filter((_)=>{if(K.has(_.id))return!1;return K.add(_.id),!0})}import{formatDisplayUserInput as u1}from"@cerebriline/shared";var Z4=new Set(["auto_compaction","compaction_budget_emergency","completion_reminder","loop_detection_notice","manual_compaction","mistake_stop_notice","recovery_notice"]);function X4($){switch($){case"user":case"assistant":case"tool":case"system":case"status":case"error":return $;default:return"assistant"}}function Q4($){return $.metadata&&typeof $.metadata==="object"&&!Array.isArray($.metadata)?$.metadata:void 0}function j4($){let J=$?.userRunSpan;return typeof J==="number"&&Number.isInteger(J)&&J>=0?J:void 0}function V4($){if(typeof $.content==="string")return{hasAttachment:!1,text:$.content};if(!Array.isArray($.content))return{hasAttachment:!1,text:"unknown"};let J=!1,Z=!1,X=[];for(let Q of $.content){if(!Q||typeof Q!=="object"||Array.isArray(Q))continue;let j=Q;if(j.type==="text"&&typeof j.text==="string")X.push(j.text);else if(j.type==="tool_result"||j.type==="tool-result")Z=!0;else if(j.type==="file"||j.type==="image")J=!0}return{hasAttachment:J&&!Z,text:X.join(`
11
11
  `)}}function Y4($){let J=u1($);return J.startsWith("[TASK RESUMPTION]")||J==="The user approved switching to act mode. Continue with the approved plan now."}function W4($){if(X4($.role)!=="user")return 0;let J=Q4($),Z=typeof J?.kind==="string"?J.kind:void 0,X=j4(J);if(Z==="compaction"||Z==="compaction_summary")return X??1;if(X!==void 0)return X;if(Z&&Z4.has(Z))return 0;let Q=V4($);if(!Q.hasAttachment&&!u1(Q.text))return 0;if(!Q.hasAttachment&&Y4(Q.text))return 0;return 1}function c1($){return W4($)>0}function V0($){return Array.isArray($?.sessions)?$.sessions.filter((J)=>Boolean(J)&&typeof J==="object"&&!Array.isArray(J)):[]}function g0($){let J=$.updatedAt;return typeof J==="number"?J:Date.parse(String(J??""))||0}function h0($){let J=$?.metadata&&typeof $.metadata==="object"?$.metadata:void 0;return String(J?.model??$?.model??"").trim()}function Y0($){let J=$.metadata&&typeof $.metadata==="object"?$.metadata:void 0;return!String(J?.parentSessionId??$.parentSessionId??"").trim()}function t1($,J="text"){if(!$||typeof $!=="object"||Array.isArray($))return"";let Z=$.content;if(typeof Z==="string")return J==="text"?Z.trim():"";if(!Array.isArray(Z))return"";return Z.map((X)=>X&&typeof X==="object"&&!Array.isArray(X)?J==="thinking"&&X.type==="redacted_thinking"?"[redacted]":String(X[J]??""):"").join("").trim()}function Q0($){let J=$.trim(),Z=J.match(/^<user_input\b[^>]*>([\s\S]*)<\/user_input>$/);return(Z?Z[1]:J).trim()}function d($,J,Z){let X=Q0(Z);return $.filter((Q)=>Boolean(Q)&&typeof Q==="object"&&!Array.isArray(Q)&&String(Q.role??"").toLowerCase()==="user"&&(X!==""||c1(Q))&&Q0(t1(Q))===X).length+J.filter((Q)=>Q0(Q.prompt)===X).length}function v0($){return $.flatMap((J)=>{if(J.event!=="session.pending_prompt_submitted")return[];let Z=J.payload?.prompt&&typeof J.payload.prompt==="object"&&!Array.isArray(J.payload.prompt)?J.payload.prompt:void 0,X=String(Z?.id??"").trim();if(!X)return[];return[{id:X,prompt:String(Z?.prompt??""),steer:Z?.delivery==="steer",attachmentCount:typeof Z?.attachmentCount==="number"?Z.attachmentCount:0,userImages:Array.isArray(Z?.userImages)?Z.userImages.filter((Q)=>typeof Q==="string"):void 0}]})}var N4=new Set(["run.completed","run.aborted","run.failed"]),F4=new Set(["assistant.delta","assistant.finished","reasoning.delta","reasoning.finished"]);function a1($,J){return $.filter((Z)=>Boolean(Z)&&typeof Z==="object"&&!Array.isArray(Z)&&String(Z.role??"").toLowerCase()==="assistant").map((Z)=>t1(Z,J)).filter(Boolean)}function d1($,J,Z="text"){let X=new Map;for(let Q of a1(J,Z))X.set(Q,(X.get(Q)??0)+1);return a1($,Z).filter((Q)=>{let j=X.get(Q)??0;if(j===0)return!0;if(j===1)X.delete(Q);else X.set(Q,j-1);return!1})}function j0($,J,Z=new Set){if(!$||typeof $!=="object")return Z;if(Array.isArray($)){for(let j of $)j0(j,J,Z);return Z}let X=$,Q=J==="tool_use"?X.id:X.tool_use_id;if(X.type===J&&typeof Q==="string")Z.add(Q);for(let j of Object.values(X))j0(j,J,Z);return Z}function i1($,J="assistant"){let Z="",X="";for(let Q of $)if(Q.event===`${J}.delta`)X+=J==="reasoning"&&Q.payload?.redacted&&!Q.payload?.text?"[redacted]":typeof Q.payload?.text==="string"?Q.payload.text:"";else if(Q.event===`${J}.finished`){let j=Q.payload?.[J==="assistant"?"text":"reasoning"],V=typeof j==="string"&&j?j:X;if(V)Z=V;X=""}return(Z||X).trim()}function r1($,J,Z={}){let X=Z.queueSnapshotApplied!==!1,Q=d1(J,Z.baselineMessages??[]),j=d1(J,Z.baselineMessages??[],"thinking"),V=j0(J,"tool_use"),Y=j0(J,"tool_result"),W=new Set($.slice(0,Z.messagesSnapshotEventCutoff??$.length)),F=new Set,G=new Map;for(let O of $.slice(0,Z.messagesSnapshotEventCutoff??$.length)){let B=v0([O])[0];if(!B)continue;let D=Q0(B.prompt),H=G.get(D)??Math.max(0,d(J,[],D)-d(Z.baselineMessages??[],[],D));if(G.set(D,Math.max(0,H-1)),H>0)F.add(O)}let z=[...X?$.slice(Z.queueSnapshotEventCutoff??$.length):$].reverse().find((O)=>O.event==="session.pending_prompts"),L=[],K=[],_=(O)=>{if(K.length===0)return;let B=K.filter((x)=>W.has(x)),D=(x)=>{if(!O)return-1;let M=[...B].reverse().findIndex((J2)=>J2.event===`${x}.finished`),S=M<0?-1:B.length-1-M;return S>=0||K.at(-1)?.event==="run.aborted"?S:B.length-1},H=D("assistant"),f=D("reasoning"),A=i1(B.slice(0,H+1)),P=A?Q.findIndex((x)=>x.endsWith(A)):-1,k=P>=0;if(k)Q.splice(P,1);let i=i1(B.slice(0,f+1),"reasoning"),K0=i?j.findIndex((x)=>x.endsWith(i)):-1;if(K0>=0)j.splice(K0,1);for(let[x,M]of K.entries()){if(F.has(M)){L.push({...M,payload:{...M.payload,transcriptReflected:!0}});continue}if(W.has(M)&&F4.has(M.event)&&(M.event.startsWith("reasoning.")?K0>=0&&x<=f:k&&x<=H))continue;if(M.event==="session.pending_prompts"&&M!==z)continue;if(W.has(M)&&M.event.startsWith("tool.")){let S=String(M.payload?.toolCallId??"").trim();if(Y.has(S)||M.event==="tool.started"&&V.has(S))continue}L.push(M)}K=[]};for(let O of $)if(K.push(O),N4.has(O.event))_(!0);return _(!1),L}import{formatDisplayUserInput as K4}from"@cerebriline/shared";function W0($){let J=structuredClone($),Z=(X)=>{if(!X||typeof X!=="object"||Object.isFrozen(X))return;for(let Q of Object.values(X))Z(Q);Object.freeze(X)};return Z(J),J}function N0($){let J=$?.trim();return J?K4(J).slice(0,120):void 0}function S0($){if(typeof $==="string")return $;if(Array.isArray($)){let J=[];for(let Z of $){if(typeof Z==="string"){if(Z.trim())J.push(Z);continue}if(!Z||typeof Z!=="object")continue;let X=Z,Q=typeof X.type==="string"?X.type:"",j=Q==="text"?String(X.text??""):Q==="thinking"?String(X.thinking??""):Q==="tool_use"?`[tool] ${String(X.name??"tool_call")}`:Q==="tool_result"?`[tool_result]
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Icons: several proposals to choose from, then every file an icon is.
3
+ *
4
+ * `generate_image` can draw an icon, and the first person to use it for one
5
+ * was pleased that it could. What it left him with was one PNG at the size the
6
+ * model draws, when an icon is a choice between candidates and then a dozen
7
+ * files: an `.ico` holding seven sizes, an `.icns`, and the PNGs a web page and
8
+ * a phone ask for by size.
9
+ *
10
+ * So this is two steps under one name. With a `prompt` it draws several
11
+ * proposals and shows them on one numbered sheet, for the user to pick from.
12
+ * With `pick` it writes the chosen one out in every format. The model asks the
13
+ * question in between: choosing is the user's part.
14
+ */
15
+ import { type AgentTool } from "@cerebriline/shared";
16
+ import { type ImageGenerationEndpoint } from "./image-generation";
17
+ import { type RenderDriver } from "./render-image";
18
+ export declare const GENERATE_ICON_TOOL_NAME = "generate_icon";
19
+ export declare const GENERATE_ICON_TOOL_DESCRIPTION = "Make an icon for an application, a site or a file type: several proposals for the user to choose from, then the chosen one saved in every format an icon needs. Two steps, one call each.\n\n1. Proposals. Give `prompt`: what the icon shows and the feeling it should have (\"a paper plane, friendly, blue on white\"). Several candidates are drawn and returned on one numbered sheet, each saved as its own file. Show the user the sheet and ask which one they want (`ask_question`, with the numbers as the options); do not choose for them. If none is right, call again with a changed prompt.\n2. Files. Give `pick`: the path of the chosen proposal (or of any square image in the workspace), and `path`: where the icon belongs, without an extension, e.g. `assets/icon`. That writes `assets/icon.ico`, `assets/icon.icns`, `assets/icon.png` and `assets/icon-<size>.png` for the usual sizes.\n\nArguments:\n- `prompt` \u2014 step 1: the subject and the mood. The rules of an icon (one centred subject, bold shapes, no text) are added for you.\n- `count` \u2014 step 1: how many proposals, 1 to 6. Optional, default 4.\n- `style` \u2014 step 1: e.g. `flat vector`, `glossy 3D`, `line art`, `pixel art`. Optional, default flat vector.\n- `pick` \u2014 step 2: workspace path of the image to make the icon from.\n- `path` \u2014 step 2: where to save, without an extension.\n- `formats` \u2014 step 2: which of `ico`, `icns`, `png`, `webp` to write. Optional, default `ico,icns,png`.\n- `sizes` \u2014 step 2: the PNG sizes to write beside the main one. Optional, default `16,32,48,64,128,180,192,256,512`.\n- `background` \u2014 step 2: a CSS colour to put behind the icon. Optional; left as the proposal has it.\n\nEach proposal costs what an image costs: seconds to a minute, and money on a hosted backend.";
20
+ export declare const GENERATE_ICON_TOOL_INPUT_SCHEMA: {
21
+ readonly type: "object";
22
+ readonly properties: {
23
+ readonly prompt: {
24
+ readonly type: "string";
25
+ readonly description: "Step 1: what the icon shows, and its mood.";
26
+ };
27
+ readonly count: {
28
+ readonly type: "number";
29
+ readonly description: "Step 1: how many proposals, 1 to 6. Default 4.";
30
+ };
31
+ readonly style: {
32
+ readonly type: "string";
33
+ readonly description: "Step 1: the drawing style. Default flat vector.";
34
+ };
35
+ readonly pick: {
36
+ readonly type: "string";
37
+ readonly description: "Step 2: workspace path of the chosen image.";
38
+ };
39
+ readonly path: {
40
+ readonly type: "string";
41
+ readonly description: "Step 2: where the icon is saved, without an extension, e.g. assets/icon.";
42
+ };
43
+ readonly formats: {
44
+ readonly type: "string";
45
+ readonly description: "Step 2: any of ico, icns, png, webp. Default ico,icns,png.";
46
+ };
47
+ readonly sizes: {
48
+ readonly type: "string";
49
+ readonly description: "Step 2: PNG sizes to write beside the main one.";
50
+ };
51
+ readonly background: {
52
+ readonly type: "string";
53
+ readonly description: "Step 2: a CSS colour behind the icon. Optional.";
54
+ };
55
+ };
56
+ readonly required: readonly [];
57
+ };
58
+ export interface GenerateIconToolOptions {
59
+ cwd: string;
60
+ getEndpoint: () => ImageGenerationEndpoint | undefined | Promise<ImageGenerationEndpoint | undefined>;
61
+ createDriver: () => RenderDriver | Promise<RenderDriver>;
62
+ fileExists: (absolutePath: string) => Promise<boolean>;
63
+ writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
64
+ fetchImpl?: typeof fetch;
65
+ timeoutMs?: number;
66
+ now?: () => number;
67
+ onError?: (message: string, error: unknown) => void;
68
+ }
69
+ /** The prompt an icon is drawn from: the subject, then what makes it an icon. */
70
+ export declare function buildIconPrompt(subject: string, style: string, index: number): string;
71
+ /** The proposals on one sheet, each under its number. */
72
+ export declare function buildProposalSheet(fileUrls: string[]): string;
73
+ /** Create the `generate_icon` tool. */
74
+ export declare function createGenerateIconTool(options: GenerateIconToolOptions): AgentTool;
@@ -38,7 +38,7 @@ export type ToolOutput = string | Array<{
38
38
  mediaType: string;
39
39
  }>;
40
40
  export declare const GENERATE_IMAGE_TOOL_NAME = "generate_image";
41
- export declare const GENERATE_IMAGE_TOOL_DESCRIPTION = "Generate an image from a text description and save it into the workspace. Use it for visual work you would otherwise have to ask the user to do elsewhere: an app icon, a placeholder texture or sprite, a logo, a background, or a mockup of a layout or theme you are about to build.\n\nThe image is written to a file and, if you can see images, returned to you as well \u2014 so you can look at what you made and generate again with a changed prompt if it is wrong.\n\nArguments:\n- `prompt` \u2014 what to draw. Describe the subject, the style and the background. Say \"flat vector icon, solid background, no text\" rather than \"an icon\": these models render text badly, so ask for lettering only when you must.\n- `path` \u2014 where to save it, relative to the workspace. Optional; defaults to a file under `.cline/generated-images/`. Give a real path when the image is an asset the project will use.\n- `size` \u2014 `WxH` in pixels, e.g. `1024x1024`. Optional, and the backend may round it.\n\nThis costs real time \u2014 seconds to a minute per image \u2014 and on a hosted backend it costs money. Generate one image and look at it before generating variations.";
41
+ export declare const GENERATE_IMAGE_TOOL_DESCRIPTION = "Generate an image from a text description and save it into the workspace. Use it for visual work you would otherwise have to ask the user to do elsewhere: an app icon, a placeholder texture or sprite, a logo, a background, an illustration or a photograph.\n\nIt paints pixels: it cannot write legible text, and a picture of an interface or a diagram made this way has garbled labels. For a screen, a mockup, a workflow diagram, a chart or anything else with words in it, write it as HTML, SVG or Mermaid and use `render_image` when you have it.\n\nThe image is written to a file and, if you can see images, returned to you as well \u2014 so you can look at what you made and generate again with a changed prompt if it is wrong.\n\nArguments:\n- `prompt` \u2014 what to draw. Describe the subject, the style and the background. Say \"flat vector icon, solid background, no text\" rather than \"an icon\": these models render text badly, so ask for lettering only when you must.\n- `path` \u2014 where to save it, relative to the workspace. Optional; defaults to a file under `.cline/generated-images/`. Give a real path when the image is an asset the project will use.\n- `size` \u2014 `WxH` in pixels, e.g. `1024x1024`. Optional, and the backend may round it.\n\nThis costs real time \u2014 seconds to a minute per image \u2014 and on a hosted backend it costs money. Generate one image and look at it before generating variations.";
42
42
  export declare const GENERATE_IMAGE_TOOL_INPUT_SCHEMA: {
43
43
  readonly type: "object";
44
44
  readonly properties: {
@@ -172,6 +172,30 @@ export declare function saveAndReportImage(input: {
172
172
  emitUpdate?: (update: unknown) => void;
173
173
  } | undefined;
174
174
  }): Promise<ToolOutput>;
175
+ /**
176
+ * One image from the endpoint, or why not, in words for the model.
177
+ *
178
+ * Shared by every tool that asks for a picture: the wire format, the busy
179
+ * retry and the reading of the answer are the same whatever it is for.
180
+ * A timeout and an unreachable server are thrown, as the request throws them.
181
+ */
182
+ export declare function requestGeneratedImage(input: {
183
+ endpoint: ImageGenerationEndpoint;
184
+ prompt: string;
185
+ size?: string;
186
+ fetchImpl: typeof fetch;
187
+ timeoutMs: number;
188
+ signal?: AbortSignal;
189
+ onBusy?: (waitMs: number) => void;
190
+ }): Promise<{
191
+ image: {
192
+ data: Buffer;
193
+ mediaType: string;
194
+ };
195
+ revisedPrompt?: string;
196
+ } | {
197
+ error: string;
198
+ }>;
175
199
  /**
176
200
  * Create the `generate_image` tool.
177
201
  *
@@ -17,6 +17,7 @@ import type { AgentTool } from "@cerebriline/shared";
17
17
  import { type SpeechEndpoint, type TranscriptionEndpoint } from "./audio-tools";
18
18
  import { type ImageGenerationEndpoint } from "./image-generation";
19
19
  import { type MediaEndpointProbe, type MediaSessionProvider, type ResolvedMediaEndpoint } from "./media-endpoint";
20
+ import type { RenderDriver } from "./render-image";
20
21
  import { type VideoGenerationEndpoint } from "./video-generation";
21
22
  /** What every media section holds. */
22
23
  export interface MediaSectionSettings {
@@ -100,6 +101,13 @@ export interface CreateMediaToolsOptions {
100
101
  readFile: (absolutePath: string) => Promise<Buffer>;
101
102
  /** Must create the directory: the default paths are under `.cline/`. */
102
103
  writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
104
+ /**
105
+ * The host's browser, where it has one. With it and `fileExists`,
106
+ * `generate_icon` is offered beside `generate_image`: drawing the proposals
107
+ * is the endpoint's work, and writing an `.ico` from one is the browser's.
108
+ */
109
+ createRenderDriver?: () => RenderDriver | Promise<RenderDriver>;
110
+ fileExists?: (absolutePath: string) => Promise<boolean>;
103
111
  fetchImpl?: typeof fetch;
104
112
  onError?: (message: string, error: unknown) => void;
105
113
  /** One line per tool: where it goes, or why it was left out. */
@@ -0,0 +1,139 @@
1
+ /**
2
+ * A tool that draws what the model writes.
3
+ *
4
+ * `generate_image` paints pixels, and pixels that look like an interface are
5
+ * not one: asked for "rendered images showing the workflow of the
6
+ * application", a model on xOllama produced two dashboards whose tabs read
7
+ * "Dasihorad" and "Documets" (2026-10-12). No prompt mends that. The models
8
+ * that cannot draw a word can write one, and they write HTML, CSS, SVG and
9
+ * diagram notation well. So this tool takes the source and a real browser
10
+ * renders it: every label is the text that was typed, and a screen can be
11
+ * built from the application's own markup and stylesheet.
12
+ *
13
+ * The picture is as large as what was drawn unless a size is asked for. The
14
+ * first diagram rendered the other way was 1180 by 370 pixels in a fixed 1280
15
+ * by 800 capture, a third of it empty.
16
+ */
17
+ import { type AgentTool } from "@cerebriline/shared";
18
+ export declare const RENDER_IMAGE_TOOL_NAME = "render_image";
19
+ export declare const RENDER_IMAGE_TOOL_DESCRIPTION = "Render HTML, SVG or a Mermaid diagram that you write into an image file in the workspace. Use it for anything with text or structure in it: application screens and mockups, workflow and architecture diagrams, charts, annotated figures. An image model cannot write legible text or draw a real interface; this draws exactly what you write.\n\nThe image is saved and, if you can see images, returned to you, so you can check the layout and render again.\n\n- `source` \u2014 what to draw: HTML with its CSS (a fragment or a whole document), an SVG document, or Mermaid notation (`flowchart LR`, `sequenceDiagram`, ...). Relative URLs resolve against the workspace root, so a screen of the application can link the project's own stylesheet and images: reuse its markup and class names with sample data and the picture is the real interface.\n- `kind` \u2014 `html`, `svg` or `mermaid`. Optional; read from the source.\n- `path` \u2014 where to save, relative to the workspace: `.png`, or `.svg` to keep an SVG or Mermaid drawing as vectors. Optional; defaults to a PNG under `.cline/rendered-images/`.\n- `width`, `height` \u2014 page size in CSS pixels. Optional. Leave both out and the image is exactly as large as what was drawn; `width` alone fixes where the layout wraps.\n- `scale` \u2014 pixel density, 1 to 4, default 2.\n- `crop` \u2014 `\"x,y,width,height\"` in CSS pixels, to keep one region of the page.\n- `background` \u2014 a CSS colour, or `transparent`.\n- `theme` \u2014 Mermaid only: `default`, `dark`, `neutral` or `forest`.\n\nA README on GitHub renders a ```mermaid block as it is; render a diagram to a file when it must show somewhere that does not. Remote fonts, scripts and images load only if the machine reaches them quickly: inline what matters.";
20
+ export declare const RENDER_IMAGE_TOOL_INPUT_SCHEMA: {
21
+ readonly type: "object";
22
+ readonly properties: {
23
+ readonly source: {
24
+ readonly type: "string";
25
+ readonly description: "HTML (with its CSS), an SVG document, or Mermaid notation, written out in full.";
26
+ };
27
+ readonly kind: {
28
+ readonly type: "string";
29
+ readonly enum: readonly ["html", "svg", "mermaid"];
30
+ readonly description: "Optional; read from the source when left out.";
31
+ };
32
+ readonly path: {
33
+ readonly type: "string";
34
+ readonly description: "Where to save, relative to the workspace (.png, or .svg for an SVG or Mermaid drawing). Optional.";
35
+ };
36
+ readonly width: {
37
+ readonly type: "number";
38
+ readonly description: "Page width in CSS pixels. Optional.";
39
+ };
40
+ readonly height: {
41
+ readonly type: "number";
42
+ readonly description: "Page height in CSS pixels. Optional; without it the height is what was drawn.";
43
+ };
44
+ readonly scale: {
45
+ readonly type: "number";
46
+ readonly description: "Pixel density, 1 to 4. Optional, default 2.";
47
+ };
48
+ readonly crop: {
49
+ readonly type: "string";
50
+ readonly description: "\"x,y,width,height\" in CSS pixels. Optional.";
51
+ };
52
+ readonly background: {
53
+ readonly type: "string";
54
+ readonly description: "A CSS colour, or \"transparent\". Optional.";
55
+ };
56
+ readonly theme: {
57
+ readonly type: "string";
58
+ readonly description: "Mermaid only: default, dark, neutral or forest.";
59
+ };
60
+ };
61
+ readonly required: readonly ["source"];
62
+ };
63
+ export type RenderKind = "html" | "svg" | "mermaid";
64
+ export interface RenderRegion {
65
+ x: number;
66
+ y: number;
67
+ width: number;
68
+ height: number;
69
+ }
70
+ /** One render, as the host's browser is asked for it. */
71
+ export interface RenderRequest {
72
+ /** A whole HTML document. */
73
+ html: string;
74
+ /** The folder relative URLs in it resolve against. */
75
+ baseDir: string;
76
+ /** Present for a diagram: the browser draws it before the capture. */
77
+ mermaid?: {
78
+ theme: string;
79
+ };
80
+ /** The page's width; what a layout wraps at. */
81
+ width: number;
82
+ /** The page's height. Absent: as tall as what was drawn. */
83
+ height?: number;
84
+ /** No size was asked for: capture what was drawn and nothing around it. */
85
+ fitContent: boolean;
86
+ scale: number;
87
+ crop?: RenderRegion;
88
+ transparent: boolean;
89
+ /** Also hand back the drawing as SVG text, where the page holds one. */
90
+ wantSvg: boolean;
91
+ /** What the capture is encoded as. Absent: PNG. */
92
+ format?: "png" | "jpeg" | "webp";
93
+ /** 1 to 100, for the two formats that have one. */
94
+ quality?: number;
95
+ signal?: AbortSignal;
96
+ }
97
+ export interface RenderResult {
98
+ /** The capture, in the format asked for. */
99
+ data: Buffer;
100
+ /** The captured region, in CSS pixels. */
101
+ width: number;
102
+ height: number;
103
+ svg?: string;
104
+ }
105
+ /** The host's browser. Structural, as the browser tool's driver is. */
106
+ export interface RenderDriver {
107
+ render(request: RenderRequest): Promise<RenderResult>;
108
+ }
109
+ export interface RenderImageToolOptions {
110
+ cwd: string;
111
+ /** Built on first use: a session that never renders never starts a browser. */
112
+ createDriver: () => RenderDriver | Promise<RenderDriver>;
113
+ writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
114
+ onError?: (message: string, error: unknown) => void;
115
+ }
116
+ /** The id of the element a fragment is measured by. */
117
+ export declare const RENDER_ROOT_ID = "cerebriline-render-root";
118
+ /** What a source is, when the call does not say. */
119
+ export declare function detectRenderKind(source: string): RenderKind;
120
+ /** A fenced block's contents, when the source arrives wrapped in one. */
121
+ export declare function unfence(source: string): string;
122
+ /** `"x,y,width,height"`, or the same four as a list. */
123
+ export declare function parseCrop(value: unknown): RenderRegion | undefined;
124
+ /**
125
+ * The page a source is rendered as.
126
+ *
127
+ * A whole document goes in as it is. Anything else is set in a page with no
128
+ * margin, inside one inline block the capture is measured by: a block-level
129
+ * wrapper would be as wide as the page whatever it held.
130
+ */
131
+ export declare function buildRenderDocument(input: {
132
+ kind: RenderKind;
133
+ source: string;
134
+ background?: string;
135
+ /** The folder relative URLs resolve against: the workspace. */
136
+ baseDir?: string;
137
+ }): string;
138
+ /** Create the `render_image` tool. */
139
+ export declare function createRenderImageTool(options: RenderImageToolOptions): AgentTool;