@cerebriline/core 4.100.271 → 4.100.272
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.
- package/assets/prompt-templates/claude.md +3 -0
- package/assets/prompt-templates/deepseek.md +3 -0
- package/assets/prompt-templates/default.md +13 -0
- package/assets/prompt-templates/gemma.md +3 -0
- package/assets/prompt-templates/glm.md +3 -0
- package/assets/prompt-templates/kimi-k3.md +3 -0
- package/assets/prompt-templates/kimi.md +3 -0
- package/assets/prompt-templates/minimax-m3.1-flash.md +3 -0
- package/assets/prompt-templates/minimax.md +3 -0
- package/assets/prompt-templates/nemotron.md +3 -0
- package/assets/prompt-templates/qwen.md +3 -0
- package/assets/skills/media-audio/SKILL.md +22 -7
- package/dist/cloud/index.js +1 -1
- package/dist/extensions/tools/audio-tools.d.ts +54 -7
- package/dist/extensions/tools/image-edit.d.ts +1 -1
- package/dist/extensions/tools/image-generation.d.ts +1 -1
- package/dist/extensions/tools/media-endpoint.d.ts +14 -5
- package/dist/extensions/tools/media-tools.d.ts +10 -4
- package/dist/hub/daemon/entry.js +495 -495
- package/dist/hub/index.js +465 -465
- package/dist/index.d.ts +1 -1
- package/dist/index.js +749 -729
- package/dist/remote/remote-helper-entry.js +1 -1
- package/dist/remote/remote-helper.js +1 -1
- package/package.json +4 -4
|
@@ -310,6 +310,19 @@ Arguments:
|
|
|
310
310
|
|
|
311
311
|
Output: the saved path, the audio format and its length. You do not hear the result, so say what you asked for when reporting it. A long text takes a while.
|
|
312
312
|
|
|
313
|
+
# tool: generate_sound_effect
|
|
314
|
+
Generate a short sound effect from a description and save it as a file in the workspace. Use it for the sound of a button, a notification, a game event or an ambience. It makes sounds, not speech: use `synthesize_speech` for words.
|
|
315
|
+
|
|
316
|
+
Arguments:
|
|
317
|
+
- `prompt` — the sound, described plainly, e.g. "a short wooden click". Say what makes it and how it ends.
|
|
318
|
+
- `negative_prompt` — what the sound must not have, e.g. "reverb, music". Optional.
|
|
319
|
+
- `seconds` — how long the clip is. Optional; 4 by default, and the model sets the most it allows. A UI sound is usually under 1 second.
|
|
320
|
+
- `seed` — repeats an earlier clip on the same machine. Optional; the result reports the seed that was used.
|
|
321
|
+
- `path` — where to save it, relative to the workspace. Optional; defaults to a file under `.cline/generated-audio/`.
|
|
322
|
+
- `format` — `wav` (the default), `mp3` or `pcm`. Optional, and a backend that cannot encode it returns what it can.
|
|
323
|
+
|
|
324
|
+
Output: the saved path, the audio format, its length and the seed. You do not hear the result, so say what you asked for and let the user listen. The first clip also loads the model and can take minutes.
|
|
325
|
+
|
|
313
326
|
# tool: generate_video
|
|
314
327
|
Generate a short video clip from a text description and save it as a file in the workspace. Use it for a few seconds of footage you would otherwise have to ask the user to make elsewhere: a background loop, a product shot, a placeholder for a scene, an animated version of an image you already have.
|
|
315
328
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: media-audio
|
|
3
3
|
description: >-
|
|
4
|
-
Reads and makes audio: turns a recording into text or subtitles,
|
|
5
|
-
|
|
6
|
-
meeting, a voice note or the sound of a video, to
|
|
7
|
-
translate speech,
|
|
8
|
-
version of a text
|
|
4
|
+
Reads and makes audio: turns a recording into text or subtitles, turns text
|
|
5
|
+
into spoken audio, and makes sound effects. Use when the user asks to
|
|
6
|
+
transcribe a recording, a meeting, a voice note or the sound of a video, to
|
|
7
|
+
make subtitles, to translate speech, to make a voice-over, a spoken prompt or
|
|
8
|
+
an audio version of a text, or to make a sound for a button, a notification
|
|
9
|
+
or a game.
|
|
9
10
|
---
|
|
10
11
|
|
|
11
12
|
# Audio
|
|
@@ -21,11 +22,12 @@ recording you could transcribe, or to record something you could synthesize.
|
|
|
21
22
|
| Subtitles for a recording or a clip | `transcribe_audio` with `format: srt` or `vtt` |
|
|
22
23
|
| The English of speech in another language | `transcribe_audio` with `translate: true` |
|
|
23
24
|
| A voice-over, a spoken prompt, an audio version of a text | `synthesize_speech` |
|
|
25
|
+
| A button click, a notification, a game event, an ambience | `generate_sound_effect` |
|
|
24
26
|
|
|
25
27
|
When you do not have the tool you need, it is not set up. Say that the user
|
|
26
28
|
turns it on in **Settings > API Configuration > Audio** (the speech-to-text
|
|
27
|
-
endpoint for transcription, the text-to-speech endpoint for speech
|
|
28
|
-
there.
|
|
29
|
+
endpoint for transcription, the text-to-speech endpoint for speech, sound
|
|
30
|
+
effects for sounds), and stop there.
|
|
29
31
|
|
|
30
32
|
## Transcribing
|
|
31
33
|
|
|
@@ -53,3 +55,16 @@ there.
|
|
|
53
55
|
how long it is, and let the user listen.
|
|
54
56
|
- For a long text, make one file per section. A section that came out wrong
|
|
55
57
|
can then be made again alone.
|
|
58
|
+
|
|
59
|
+
## Sound effects
|
|
60
|
+
|
|
61
|
+
- Describe the sound plainly: what makes it, what it is like and how it ends.
|
|
62
|
+
"a short wooden click, dry, no echo" works better than "a nice button sound".
|
|
63
|
+
- Keep UI sounds short: give `seconds` under 1 for a click and leave them as
|
|
64
|
+
`wav`, which starts on time. Length barely changes how long a clip takes.
|
|
65
|
+
- Use `negative_prompt` for what keeps coming out wrong, such as music or
|
|
66
|
+
reverb.
|
|
67
|
+
- The result reports a `seed`. Keep it: the same prompt and seed remake the
|
|
68
|
+
clip on the same machine.
|
|
69
|
+
- For a set of sounds, make one file each with names that say what they are for.
|
|
70
|
+
- You do not hear the result. Say what you asked for and let the user listen.
|
package/dist/cloud/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import{execFile as sn}from"node:child_process";import{basename as To,resolve as
|
|
|
5
5
|
...and ${l.length-5} more`:"";throw new _("dirty_worktree",`Commit and push local changes before handing off to cloud. Uncommitted files are not transferred.
|
|
6
6
|
|
|
7
7
|
${m}${y}`)}let i;try{i=await t.symbolicBranch()}catch(l){let m=Q(l)===1,y=K(l),w=m?"Cloud handoff requires a checked-out branch; detached HEAD is not supported.":"Could not inspect the current Git branch.";throw new _(m?"detached_head":"git_command_failed",y?`${w} (${y})`:w,{cause:l})}if(!i)throw new _("detached_head","Cloud handoff requires a checked-out branch; detached HEAD is not supported.");let[r,a,d]=await Promise.all([O(()=>t.branchRemote(i),"missing_upstream",`Branch ${i} has no upstream. Push it with -u before handing off.`),O(()=>t.branchMergeRef(i),"missing_upstream",`Branch ${i} has no upstream. Push it with -u before handing off.`),O(t.headSha,"git_command_failed","Could not resolve the current commit.")]);if(!r||r==="."||!a.startsWith("refs/heads/"))throw new _("missing_upstream",`Branch ${i} has no remote branch upstream. Push it with -u before handing off.`);let u=a.slice(11),f=r;if(!Ze(r))try{f=await t.remoteUrl(r)}catch{throw new _("missing_upstream","Could not resolve the upstream remote.")}let c=Ze(f);if(!c)throw new _("unsupported_remote","Cloud handoff currently requires a github.com upstream remote.");let h;try{h=await t.remoteRefs(r,a)}catch(l){let m=Q(l)===2,y=m?`The upstream branch ${u} was not found. Push it before handing off.`:"Could not verify the remote branch. Check your network and GitHub authentication, then try again.";throw new _(m?"remote_branch_missing":"git_command_failed",y)}let p=cn(h,u);if(!p)throw new _("remote_branch_missing",`The upstream branch ${u} was not found. Push it before handing off.`);if(p.toLowerCase()!==d.toLowerCase())throw new _("unpushed_commits",`Local HEAD does not match the upstream branch ${u}. Push the current commit before handing off.`);return{repoUrl:c,branch:u,headSha:d,...s?{workspaceRelativePath:s}:{}}}function fe(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function x(e){if(typeof e!=="string")return;return e.trim()||void 0}function ln(e){return typeof e==="string"&&e.length>0?e:void 0}function pn(e){let t=x(e.repoUrl),n=x(e.branch),s=x(e.headSha),o=x(e.modelId);if(!t||!n||!s||!o)throw Error("Cloud handoff fingerprint fields cannot be empty.");let i=x(e.organizationId),r=ln(e.workspaceRelativePath),a=e.mode;return{repoUrl:t,branch:n,headSha:s,modelId:o,...i?{organizationId:i}:{},...r?{workspaceRelativePath:r}:{},...a?{mode:a}:{}}}function Do(e,t){return e!==void 0&&t!==void 0&&e.repoUrl===t.repoUrl&&e.branch===t.branch&&e.headSha.toLowerCase()===t.headSha.toLowerCase()&&e.modelId===t.modelId&&e.organizationId===t.organizationId&&e.workspaceRelativePath===t.workspaceRelativePath&&e.mode===t.mode}function fn(e){let t=fe(e);if(!t||typeof t.repoUrl!=="string"||typeof t.branch!=="string"||typeof t.headSha!=="string"||typeof t.modelId!=="string")return;try{return pn({repoUrl:t.repoUrl,branch:t.branch,headSha:t.headSha,modelId:t.modelId,...typeof t.organizationId==="string"?{organizationId:t.organizationId}:{},...typeof t.workspaceRelativePath==="string"?{workspaceRelativePath:t.workspaceRelativePath}:{},...t.mode==="plan"||t.mode==="yolo"||t.mode==="zen"?{mode:t.mode}:{}})}catch{return}}function Bo(e){let t=fe(fe(e)?.handoff);if(!t)return;let n=x(t.toCloudSessionId),s=x(t.handedOffAt),o=t.status;if(!n||!s||o!=="pending"&&o!=="complete")return;let i=x(t.innerSessionId),r=x(t.dashboardUrl),a=fn(t.fingerprint);return{toCloudSessionId:n,handedOffAt:s,status:o,...i?{innerSessionId:i}:{},...r?{dashboardUrl:r}:{},...a?{fingerprint:a}:{}}}function qo(e,t){return{...e??{},handoff:t}}function No(e){let{handoff:t,cloudHandoffIntent:n,cloudHandoffSeedDispatched:s,...o}=e??{};return o}function $o(e,t){let n=t.trim();if(!n)throw Error("Cloud session id cannot be empty.");let s=new URL("/agents",e);return s.searchParams.set("sessionId",n),s.toString()}function et(e){return e.map((t)=>{let n=t&&typeof t==="object"?t:{};return{role:n.role,content:n.content}})}function he(e,t){return e.length===t.length&&JSON.stringify(et(e))===JSON.stringify(et(t))}class me extends Error{constructor(e,t){super(`Cloud transcript verification failed (local ${e} messages, cloud ${t}).`);this.name="CloudHandoffTranscriptMismatchError"}}import{randomUUID as hn}from"node:crypto";import{decodeJwtPayload as mn}from"@cerebriline/shared";var gn=610000,yn=3000,B=15000,bn="CLOUD_SESSION_ERROR:",st="__cline_create_request__:";function ot(e){return(e.trim().split(`
|
|
8
|
-
`)[0]??"").trim().slice(0,72)}class g extends Error{code;detail;connectUrl;status;constructor(e,t,n,s){super(`${bn}${JSON.stringify({code:e,message:t,connectUrl:n})}`);this.code=e;this.detail=t;this.connectUrl=n;this.status=s;this.name="CloudSessionError"}}class it extends Error{constructor(e){super(e instanceof Error?e.message:"Cloud handoff creation was rejected.",{cause:e});this.name="CloudHandoffCreationRejectedError"}}function be(e){let t=e.length;while(t>0&&e[t-1]==="/")t--;return e.slice(0,t)}function wn(e){return`${st}${e}`.slice(0,255)}function tt(e){return e?.startsWith(st)===!0}function we(e){switch(e){case"provisioning":case"cloning_repo":case"agent_starting":case"ready":case"failed":return e;default:return}}function ge(e){let t=mn(e.replace(/^workos:/,""));return typeof t?.sub==="string"&&t.sub.trim()?t.sub.trim():void 0}function nt(e){return new Promise((t,n)=>{if(e.aborted){n(e.reason);return}let s=()=>{clearTimeout(o),n(e.reason)},o=setTimeout(()=>{e.removeEventListener("abort",s),t()},yn);e.addEventListener("abort",s,{once:!0})})}function vn(e,t){if(e&&typeof e==="object"){let n=e.error;if(typeof n==="string"&&n.trim())return n.trim()}return t}function ye(e,t,n,s){let o=vn(t,`Cloud session request failed (${e})`);if(e===401)return new g("authentication_required",o);if(e===404)return new g("session_not_found",o);if(e===410)return new g("session_expired",o);if(e===412)return new g("github_not_connected",o,s??`${be(n)}/dashboard/integrations`);if(e===403&&o.trim().toLowerCase()==="forbidden")return new g("request_failed","Your active account or organization cannot create cloud sessions. Switch to Personal or another organization in Settings → Account, then try again.",void 0,e);return new g("request_failed",o,void 0,e)}class Cn{options;apiBaseUrl;appBaseUrl;fetchImpl;createTimeoutMs;unconfirmedHandoffCreates=new Set;completedHandoffCreates=new Map;constructor(e){this.options=e;this.apiBaseUrl=be(e.apiBaseUrl),this.appBaseUrl=be(e.appBaseUrl),this.fetchImpl=e.fetch??fetch,this.createTimeoutMs=e.createTimeoutMs??gn}async request(e,t={},n,s,o){let i=!1,r;while(!0){let a;try{a=typeof s==="string"?s:await this.options.getAuthToken()}catch(f){if(r)throw ye(401,void 0,this.appBaseUrl,n);throw f}if(!a?.trim())throw new g("authentication_required","Sign in to Cline before starting a cloud session.");if(a.trim()===r)throw new g("authentication_required","The cloud session credential was rejected. Sign in again.");if(typeof s==="object"){if(s.subject?ge(a.trim())!==s.subject:a.trim()!==s.token)throw new g("authentication_required","The signed-in account changed during cloud session creation.");s.token=a.trim()}o?.();let d=await this.fetchImpl(`${this.apiBaseUrl}${e}`,{...t,signal:t.signal??AbortSignal.timeout(B),headers:{Accept:"application/json",Authorization:`Bearer ${a.trim()}`,...t.body?{"Content-Type":"application/json"}:{},...t.headers}}),u=d.status===204?void 0:await d.json().catch(()=>{return});if(!d.ok){if(d.status===401&&typeof s==="object"&&!i&&s.subject){i=!0,r=a.trim();continue}throw ye(d.status,u,this.appBaseUrl,n)}return u?.data}}async list(e){return await this.listWithToken(e)}async listWithToken(e,t,n=!1){let s=e?.trim()?`?organizationId=${encodeURIComponent(e.trim())}`:"";return(await this.request(`/api/v1/session${s}`,{},void 0,t)??[]).flatMap((i)=>{if(!i||typeof i!=="object"||typeof i.id!=="string")return[];return[{...i,title:!n&&tt(i.title)?void 0:i.title,repoContext:i.repoContext&&typeof i.repoContext==="object"?i.repoContext:{},metadata:{...i.metadata&&typeof i.metadata==="object"?i.metadata:{},...!n&&tt(i.title)?{createRequestTitle:i.title}:{}}}]})}async listRepositories(e){let t=e?.trim(),n=t?`${this.appBaseUrl}/dashboard/organization/integrations`:`${this.appBaseUrl}/dashboard/integrations`,s=t?`/api/v1/organizations/${encodeURIComponent(t)}/integrations/github/repositories`:"/api/v1/integrations/github/repositories";try{let o=await this.request(s)??[];return{connected:!0,connectUrl:n,repositories:o.flatMap((i)=>{let r=Number(i.id),a=String(i.html_url??i.clone_url??"").trim();if(!Number.isSafeInteger(r)||r<=0||!a)return[];let d=String(i.name??"").trim();return[{id:r,name:d,fullName:String(i.full_name??(d||a)).trim(),url:a,defaultBranch:String(i.default_branch??"").trim()}]})}}catch(o){if(o instanceof g&&o.code==="session_not_found")return{connected:!1,connectUrl:n,repositories:[]};throw o}}async listBranches(e,t,n={}){if(!Number.isSafeInteger(e)||e<=0)throw new g("request_failed","Select a GitHub repository before loading branches.");let s=t?.trim(),o=s?`/api/v1/organizations/${encodeURIComponent(s)}/integrations/github/repositories/${e}/branches`:`/api/v1/integrations/github/repositories/${e}/branches`,i=new URLSearchParams,r=n.query?.trim(),a=n.cursor?.trim();if(r)i.set("query",r);if(a)i.set("cursor",a);let d=i.size>0?`${o}?${i}`:o;try{let u=await this.request(d),f=Array.isArray(u)?u:Array.isArray(u?.items)?u.items:[],c=r?.toLowerCase();return{available:!0,branches:f.flatMap((h)=>{let p=String(h.name??"").trim();return p&&(!Array.isArray(u)||!c||p.toLowerCase().includes(c))?[p]:[]}),nextToken:Array.isArray(u)?"":String(u?.nextToken??"").trim()}}catch(u){if(u instanceof g&&u.code==="session_not_found")return{available:!1,branches:[]};throw u}}async status(e,t={}){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:t.signal?AbortSignal.any([t.signal,AbortSignal.timeout(B)]):void 0},void 0,t.authToken)}async create(e){if(e.handoff&&typeof e.handoff.onCreating!=="function")throw new g("request_failed","Cloud handoff requires an onCreating callback to persist creation intent before dispatch.");let t=(await this.options.getAuthToken())?.trim();if(!t)throw new g("authentication_required","Sign in to Cline before starting a cloud session.");let n={token:t,subject:ge(t)},s=wn(e.requestId?.trim()||hn()),o=e.handoff?`${n.subject??t}/${e.organizationId??""}/${e.requestId?.trim()??""}`:void 0;if(e.handoff&&!e.requestId?.trim())throw new g("request_failed","A stable request id is required for cloud handoff creation.");let i=async()=>(await this.listWithToken(e.organizationId??void 0,n,!0)).filter((c)=>c.title===s&&c.repoContext.repoUrl===e.repoUrl&&c.metadata.modelId===e.modelId&&(!e.branch?.trim()||c.repoContext.branch===e.branch.trim())),r=async(c)=>{if(c.status==="failed"||c.expiredAt&&Date.parse(c.expiredAt)<=Date.now()){let p=new g(c.status==="failed"?"session_failed":"session_expired","The recovered cloud handoff workspace is no longer usable.");try{await this.deleteWithAuth(c.id,n)}catch(l){if(!(l instanceof g&&(l.code==="session_not_found"||l.code==="session_expired")))throw AggregateError([p,l],"The unusable recovered cloud handoff workspace could not be removed.")}if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.delete(o);throw await e.handoff?.onOuterSessionRemoved?.(c.id),p}await e.handoff?.onOuterSessionCreated(c.id,{created:!1});let h={sessionId:c.id,status:c.status,sandboxUrl:c.sandboxUrl,cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,h);return h};if(o){let c=await i();if(c.length>1)throw new g("request_failed","Cloud handoff creation is ambiguous; inspect your cloud session list before continuing.");if(c[0])return await r(c[0]);let h=this.completedHandoffCreates.get(o);if(h){try{await this.request(`/api/v1/session/${encodeURIComponent(h.sessionId)}/status`,{},void 0,n)}catch(p){if(p instanceof g&&(p.code==="session_not_found"||p.code==="session_expired"))await e.handoff?.onOuterSessionRemoved?.(h.sessionId),this.completedHandoffCreates.delete(o),this.unconfirmedHandoffCreates.delete(o);throw p}return await e.handoff?.onOuterSessionCreated(h.sessionId,{created:!1}),{...h,cleanupAuthToken:n.token}}if(this.unconfirmedHandoffCreates.has(o))throw new g("request_failed","Cloud handoff creation is still unconfirmed. Recover the original request before creating another workspace.");this.unconfirmedHandoffCreates.add(o)}try{await e.handoff?.onCreating()}catch(c){if(o)this.unconfirmedHandoffCreates.delete(o);throw c}let a=new AbortController,d=setTimeout(()=>a.abort(),this.createTimeoutMs),u,f=!1;try{let c=await this.request("/api/v1/session",{method:"POST",body:JSON.stringify({modelId:e.modelId,repoUrl:e.repoUrl,...e.sandboxType?{sandboxType:e.sandboxType}:{},title:s,...e.branch?.trim()?{branch:e.branch.trim()}:{},...e.organizationId?.trim()?{organizationId:e.organizationId.trim()}:{}}),signal:a.signal},e.organizationId?.trim()?`${this.appBaseUrl}/dashboard/organization/integrations`:void 0,n,()=>{f=!0}),h=c?.sessionId?.trim();if(!h)throw new g("request_failed","The cloud session service returned no session id.");u=h,await this.persistHandoffOuterSession(e,h,n,o);let p={sessionId:h,status:c.status?.trim()||"provisioning",sandboxUrl:c.sandboxUrl?.trim()??"",cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,p);return p}catch(c){if(u)throw c;let h=!f||c instanceof g&&(c.status!==void 0&&c.status>=400&&c.status<500&&c.status!==408&&c.status!==409||["authentication_required","github_not_connected","session_not_found","session_expired"].includes(c.code));if(o&&h)throw this.unconfirmedHandoffCreates.delete(o),new it(c);if(a.signal.aborted||!(c instanceof g)||c instanceof g&&c.code==="request_failed"&&(c.status===void 0||c.status>=500||c.status===408||c.status===409)){let l=[];try{l=await i()}catch(y){if(e.handoff)throw AggregateError([c,y],"Cloud handoff creation is unconfirmed and its session list could not be checked.")}if(l.length>1)throw new g("request_failed","Cloud session creation had an ambiguous result. Check your cloud session list before trying again.");let m=l[0];if(m){if(e.handoff)return await r(m);return{sessionId:m.id,status:m.status,sandboxUrl:m.sandboxUrl,cleanupAuthToken:n.token}}}else if(o)this.unconfirmedHandoffCreates.delete(o);throw c}finally{clearTimeout(d)}}async persistHandoffOuterSession(e,t,n,s){if(!e.handoff)return;try{await e.handoff.onOuterSessionCreated(t,{created:!0})}catch(o){try{await this.deleteWithAuth(t,n.token)}catch(i){if(!(i instanceof g&&(i.code==="session_not_found"||i.code==="session_expired")))throw AggregateError([o,i],`Cloud session ${t} was created but its recovery record could not be saved or its sandbox removed.`)}if(s)this.unconfirmedHandoffCreates.delete(s);throw await e.handoff.onOuterSessionRemoved?.(t),o}}async waitUntilReady(e,t,n){t=AbortSignal.any([t,AbortSignal.timeout(this.createTimeoutMs)]);let s=await this.options.getAuthToken(),o=s?{token:s,subject:ge(s)}:void 0;while(!t.aborted){let i;try{i=await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:AbortSignal.any([t,AbortSignal.timeout(B)])},void 0,o)}catch(a){if(t.aborted)throw a;if(a instanceof g&&a.code!=="request_failed")throw a;await nt(t);continue}let r=i?.status?.trim().toLowerCase();if(n?.({phase:we(i?.phase)}),r==="ready"||r==="active")return;if(r==="failed")throw new g("session_failed",i?.statusReason?.trim()||"The cloud sandbox could not be prepared.");if(r!=="provisioning")throw new g("request_failed","The cloud session service returned an unexpected provisioning status.");await nt(t)}throw t.reason}async resume(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/resume`,{method:"POST",signal:t?AbortSignal.any([t,AbortSignal.timeout(B)]):void 0})}async delete(e,t){await this.deleteWithAuth(e,t)}async deleteWithAuth(e,t){let n;try{await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"DELETE"},void 0,t)}catch(s){if(!(s instanceof g)||s.code!=="session_not_found"&&s.code!=="session_expired")throw s;n=s}for(let[s,o]of this.completedHandoffCreates)if(o.sessionId===e)this.completedHandoffCreates.delete(s),this.unconfirmedHandoffCreates.delete(s);if(n)throw n}async updateTitle(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({title:t})})}async history(e){let t=await this.options.getAuthToken();if(!t?.trim())throw new g("authentication_required","Sign in to Cline to load this session's history.");let n=await this.fetchImpl(`${this.apiBaseUrl}/api/v1/session/${encodeURIComponent(e)}/history`,{headers:{Accept:"application/json",Authorization:`Bearer ${t.trim()}`},signal:AbortSignal.timeout(B)});if(n.status===404)return null;let s=await n.json().catch(()=>{return});if(!n.ok)throw ye(n.status,s,this.appBaseUrl);if(!s||typeof s!=="object"||!("version"in s)||s.version!==1||!("messages"in s)||!Array.isArray(s.messages))throw new g("request_failed","Invalid archived session history");return s.messages}}import{randomUUID as yo}from"node:crypto";import{posix as le}from"node:path";import{createSessionId as qs,ensureLoopbackProxyBypass as qt,isHubProtocolCompatible as Ns,resolveClineBuildEnv as $s,resolveHubCommandTimeoutMs as Ws}from"@cerebriline/shared";import js from"ws";var q={name:"@cerebriline/core",description:"Cline Core SDK for Node Runtime",version:"0.0.92",repository:{type:"git",url:"https://github.com/cline/cline",directory:"sdk/packages/core"},type:"module",types:"./dist/index.d.ts",main:"./dist/index.js",private:!1,publishConfig:{access:"public"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./hub":{types:"./dist/hub/index.d.ts",import:"./dist/hub/index.js"},"./hub/daemon-entry":{types:"./dist/hub/daemon/entry.d.ts",import:"./dist/hub/daemon/entry.js"},"./telemetry":{types:"./dist/services/telemetry/index.d.ts",import:"./dist/services/telemetry/index.js"},"./services/feature-flags/posthog":{types:"./dist/services/feature-flags/posthog.d.ts",import:"./dist/services/feature-flags/posthog.js"},"./remote/helper-entry":{types:"./dist/remote/remote-helper-entry.d.ts",import:"./dist/remote/remote-helper-entry.js"},"./cloud":{types:"./dist/cloud/index.d.ts",import:"./dist/cloud/index.js"},"./remote/helper":{types:"./dist/remote/remote-helper.d.ts",import:"./dist/remote/remote-helper.js"}},scripts:{build:"bun run ./bun.mts && bun tsc -p tsconfig.build.json && bun run ./scripts/verify-runtime-build-id.ts",typecheck:"bun tsc -p tsconfig.dev.json --noEmit && bun run typecheck:smoke","typecheck:smoke":"bun tsc -p tsconfig.smoke.json --noEmit",test:"bun run test:unit && bun run test:e2e","test:live":"vitest run --config vitest.config.ts src/extensions/context/compaction.live.test.ts","test:compaction":"bun --conditions=development run scripts/compact-session.ts","test:unit":"vitest run --config vitest.config.ts","test:e2e":"vitest run --config vitest.e2e.config.ts","verify:routines":"zsh -lc 'bunx vitest run src/cron/schedule-service.test.ts --config vitest.config.ts'","test:watch":"vitest --config vitest.config.ts"},dependencies:{"@cerebriline/agents":"workspace:*","@cerebriline/llms":"workspace:*","@cerebriline/shared":"workspace:*","@joplin/turndown-plugin-gfm":"1.0.68","@lingo-reader/epub-parser":"0.4.6","@lingo-reader/fb2-parser":"0.4.6","@lingo-reader/mobi-parser":"0.4.6","@modelcontextprotocol/sdk":"^1.29.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.214.0","@opentelemetry/exporter-logs-otlp-http":"^0.214.0","@opentelemetry/exporter-metrics-otlp-http":"^0.214.0","@opentelemetry/exporter-trace-otlp-http":"^0.214.0","@opentelemetry/resources":"^2.6.1","@opentelemetry/sdk-logs":"^0.214.0","@opentelemetry/sdk-metrics":"^2.6.1","@opentelemetry/sdk-trace-base":"^2.6.1","@opentelemetry/sdk-trace-node":"^2.6.1","@opentelemetry/semantic-conventions":"^1.40.0","@tesseract.js-data/eng":"1.0.0",cfb:"1.2.2","fast-png":"8.0.0",jiti:"^2.7.0",nanoid:"^5.1.7","node-machine-id":"^1.1.12",officeparser:"8.0.0","pdfjs-dist":"6.2.108","simple-git":"3.36.0","tesseract.js":"7.0.0","tree-sitter-wasms":"^0.1.12",turndown:"7.2.0","web-tree-sitter":"^0.25.0",ws:"^8.20.0",yaml:"^2.8.2",zod:"^4.3.6"},peerDependencies:{"posthog-node":"^5.8.0"},peerDependenciesMeta:{"posthog-node":{optional:!0}},devDependencies:{"@types/turndown":"^5.0.6","@types/ws":"^8.18.1","posthog-node":"^5.8.0"},engines:{node:">=22"},files:["assets","dist","scripts/document-reader-assets.mjs","!dist/**/*.d.ts.map"]};var rt="session_not_found";class Y extends Error{sessionId;code="session_not_found";constructor(e,t){super(t??(e?`session not found: ${e}`:"session not found"));this.sessionId=e;this.name="SessionNotFoundError"}}function ve(e){return e instanceof Y||typeof e==="object"&&e!==null&&"code"in e&&e.code==="session_not_found"}import{spawn as os}from"node:child_process";import{closeSync as is,mkdirSync as rs,openSync as as,readFileSync as ds,unlinkSync as cs}from"node:fs";import{basename as us,dirname as ls,join as ps}from"node:path";import{fileURLToPath as fs}from"node:url";import{CLINE_RUN_AS_HUB_DAEMON_ENV as hs,isBunEmbeddedModulePath as ms,isHubDaemonProcess as gs,resolveClineBuildEnv as Et,withResolvedClineBuildEnv as ys}from"@cerebriline/shared";import{createHash as kn,randomBytes as Rn}from"node:crypto";import{mkdir as Se,open as at,readFile as pt,rename as _n,rm as ke,writeFile as Pn}from"node:fs/promises";import{dirname as ft,join as Re}from"node:path";import{ensureLoopbackProxyBypass as An,isHubProtocolCompatible as Tn}from"@cerebriline/shared";import{resolveClineDataDir as N,resolveClineDir as ii}from"@cerebriline/shared/storage";var xn="CLINE_HUB_DISCOVERY_PATH",En="CLINE_HUB_BUILD_ID",Hn="CLINE_HUB_BUILD_EPOCH_MS",In=30000,Mn=15000,dt=100;function On(e){return e.replace(/[^a-zA-Z0-9_.-]+/g,"_")}function Un(e){return kn("sha256").update(e).digest("hex").slice(0,12)}function Ln(e){if(!Number.isInteger(e)||!e||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t instanceof Error&&"code"in t?String(t.code)==="EPERM":!1}}function ct(e){return new Promise((t)=>setTimeout(t,e))}function Dn(e){return`${e}.lock`}async function Bn(e){try{let t=JSON.parse(await pt(Re(e,"owner.json"),"utf8"));if(typeof t.pid!=="number"||typeof t.acquiredAt!=="string")return;return{pid:t.pid,acquiredAt:t.acquiredAt}}catch{return}}async function Ce(e){await ke(e,{recursive:!0,force:!0}).catch(()=>{return})}function U(){let e=process.env[En]?.trim();if(e)return e;return"sdk-v1-ae0398ec8aafc784b621c159c759e7880762e2aea04c797ef2d90837a45894e8".trim()||`source-${String(q.version)}`}function qn(){let e=Number(process.env[Hn]);if(Number.isFinite(e)&&e>0)return e;return Number.isFinite(1793518707834)?1793518707834:void 0}function X(e,t=U()){let n=Tn(e);if(!n.compatible)return n;let s=e.buildId?.trim();if(!s)return{compatible:!1,reason:"missing_build"};if(s!==t)return{compatible:!1,reason:"build_mismatch"};return{compatible:!0}}function ut(e){return typeof e==="number"&&Number.isFinite(e)&&e>0?e:void 0}function lt(e){let t=e?.trim().split(/[-+]/,1)[0];if(!t)return;let n=t.split(".").map((s)=>Number(s));if(n.length===0||n.some((s)=>!Number.isInteger(s)||s<0))return;return n}function Nn(e,t){for(let n=0;n<Math.max(e.length,t.length);n++){let s=e[n]??0,o=t[n]??0;if(s!==o)return s<o?-1:1}return 0}function ht(e,t){let n=e.buildId?.trim(),s=t.buildId?.trim();if(n&&s&&n===s)return 0;let o=ut(e.buildEpochMs),i=ut(t.buildEpochMs);if(o!==void 0&&i!==void 0&&o!==i)return o<i?-1:1;let r=lt(e.coreVersion),a=lt(t.coreVersion);if(r&&a){let d=Nn(r,a);if(d!==0)return d}if(n&&s&&n!==s)return n<s?-1:1;return 0}function mt(){return{buildId:U(),buildEpochMs:qn(),coreVersion:String(q.version)}}function Z(e,t){let n=t?.self??mt(),s=X(e,n.buildId??"");if(s.compatible)return!0;if(s.reason!=="build_mismatch"&&s.reason!=="missing_build")return!1;return ht(n,e)<=0}function gt(e=process.argv[1]?.trim()||process.cwd()){let t=`hub-${Un(e)}`,n=process.env[xn]?.trim()||Re(N(),"locks","hub","owners",`${On(t)}.json`);return{ownerId:t,discoveryPath:n}}async function I(e){try{let t=JSON.parse(await pt(e,"utf8"));if(typeof t.hubId!=="string"||typeof t.protocolVersion!=="string"||typeof t.authToken!=="string"||typeof t.host!=="string"||typeof t.port!=="number"||typeof t.url!=="string"||typeof t.startedAt!=="string"||typeof t.updatedAt!=="string")return;return{hubId:t.hubId,protocolVersion:t.protocolVersion,minClientProtocolVersion:typeof t.minClientProtocolVersion==="string"?t.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof t.maxClientProtocolVersion==="string"?t.maxClientProtocolVersion:void 0,capabilities:Array.isArray(t.capabilities)?t.capabilities.filter((n)=>typeof n==="string"):void 0,coreVersion:typeof t.coreVersion==="string"?t.coreVersion:void 0,buildId:typeof t.buildId==="string"?t.buildId:void 0,buildEpochMs:typeof t.buildEpochMs==="number"?t.buildEpochMs:void 0,authToken:t.authToken,host:t.host,port:t.port,url:t.url,pid:typeof t.pid==="number"?t.pid:void 0,startedAt:t.startedAt,updatedAt:t.updatedAt}}catch{return}}async function yt(e,t,n){await wt(e,async()=>{let s=ft(e);await Se(s,{recursive:!0});let o=`${e}.${process.pid}.${Rn(6).toString("hex")}.tmp`,i;try{i=await at(o,"wx",384),await i.writeFile(`${JSON.stringify(t,null,2)}
|
|
8
|
+
`)[0]??"").trim().slice(0,72)}class g extends Error{code;detail;connectUrl;status;constructor(e,t,n,s){super(`${bn}${JSON.stringify({code:e,message:t,connectUrl:n})}`);this.code=e;this.detail=t;this.connectUrl=n;this.status=s;this.name="CloudSessionError"}}class it extends Error{constructor(e){super(e instanceof Error?e.message:"Cloud handoff creation was rejected.",{cause:e});this.name="CloudHandoffCreationRejectedError"}}function be(e){let t=e.length;while(t>0&&e[t-1]==="/")t--;return e.slice(0,t)}function wn(e){return`${st}${e}`.slice(0,255)}function tt(e){return e?.startsWith(st)===!0}function we(e){switch(e){case"provisioning":case"cloning_repo":case"agent_starting":case"ready":case"failed":return e;default:return}}function ge(e){let t=mn(e.replace(/^workos:/,""));return typeof t?.sub==="string"&&t.sub.trim()?t.sub.trim():void 0}function nt(e){return new Promise((t,n)=>{if(e.aborted){n(e.reason);return}let s=()=>{clearTimeout(o),n(e.reason)},o=setTimeout(()=>{e.removeEventListener("abort",s),t()},yn);e.addEventListener("abort",s,{once:!0})})}function vn(e,t){if(e&&typeof e==="object"){let n=e.error;if(typeof n==="string"&&n.trim())return n.trim()}return t}function ye(e,t,n,s){let o=vn(t,`Cloud session request failed (${e})`);if(e===401)return new g("authentication_required",o);if(e===404)return new g("session_not_found",o);if(e===410)return new g("session_expired",o);if(e===412)return new g("github_not_connected",o,s??`${be(n)}/dashboard/integrations`);if(e===403&&o.trim().toLowerCase()==="forbidden")return new g("request_failed","Your active account or organization cannot create cloud sessions. Switch to Personal or another organization in Settings → Account, then try again.",void 0,e);return new g("request_failed",o,void 0,e)}class Cn{options;apiBaseUrl;appBaseUrl;fetchImpl;createTimeoutMs;unconfirmedHandoffCreates=new Set;completedHandoffCreates=new Map;constructor(e){this.options=e;this.apiBaseUrl=be(e.apiBaseUrl),this.appBaseUrl=be(e.appBaseUrl),this.fetchImpl=e.fetch??fetch,this.createTimeoutMs=e.createTimeoutMs??gn}async request(e,t={},n,s,o){let i=!1,r;while(!0){let a;try{a=typeof s==="string"?s:await this.options.getAuthToken()}catch(f){if(r)throw ye(401,void 0,this.appBaseUrl,n);throw f}if(!a?.trim())throw new g("authentication_required","Sign in to Cline before starting a cloud session.");if(a.trim()===r)throw new g("authentication_required","The cloud session credential was rejected. Sign in again.");if(typeof s==="object"){if(s.subject?ge(a.trim())!==s.subject:a.trim()!==s.token)throw new g("authentication_required","The signed-in account changed during cloud session creation.");s.token=a.trim()}o?.();let d=await this.fetchImpl(`${this.apiBaseUrl}${e}`,{...t,signal:t.signal??AbortSignal.timeout(B),headers:{Accept:"application/json",Authorization:`Bearer ${a.trim()}`,...t.body?{"Content-Type":"application/json"}:{},...t.headers}}),u=d.status===204?void 0:await d.json().catch(()=>{return});if(!d.ok){if(d.status===401&&typeof s==="object"&&!i&&s.subject){i=!0,r=a.trim();continue}throw ye(d.status,u,this.appBaseUrl,n)}return u?.data}}async list(e){return await this.listWithToken(e)}async listWithToken(e,t,n=!1){let s=e?.trim()?`?organizationId=${encodeURIComponent(e.trim())}`:"";return(await this.request(`/api/v1/session${s}`,{},void 0,t)??[]).flatMap((i)=>{if(!i||typeof i!=="object"||typeof i.id!=="string")return[];return[{...i,title:!n&&tt(i.title)?void 0:i.title,repoContext:i.repoContext&&typeof i.repoContext==="object"?i.repoContext:{},metadata:{...i.metadata&&typeof i.metadata==="object"?i.metadata:{},...!n&&tt(i.title)?{createRequestTitle:i.title}:{}}}]})}async listRepositories(e){let t=e?.trim(),n=t?`${this.appBaseUrl}/dashboard/organization/integrations`:`${this.appBaseUrl}/dashboard/integrations`,s=t?`/api/v1/organizations/${encodeURIComponent(t)}/integrations/github/repositories`:"/api/v1/integrations/github/repositories";try{let o=await this.request(s)??[];return{connected:!0,connectUrl:n,repositories:o.flatMap((i)=>{let r=Number(i.id),a=String(i.html_url??i.clone_url??"").trim();if(!Number.isSafeInteger(r)||r<=0||!a)return[];let d=String(i.name??"").trim();return[{id:r,name:d,fullName:String(i.full_name??(d||a)).trim(),url:a,defaultBranch:String(i.default_branch??"").trim()}]})}}catch(o){if(o instanceof g&&o.code==="session_not_found")return{connected:!1,connectUrl:n,repositories:[]};throw o}}async listBranches(e,t,n={}){if(!Number.isSafeInteger(e)||e<=0)throw new g("request_failed","Select a GitHub repository before loading branches.");let s=t?.trim(),o=s?`/api/v1/organizations/${encodeURIComponent(s)}/integrations/github/repositories/${e}/branches`:`/api/v1/integrations/github/repositories/${e}/branches`,i=new URLSearchParams,r=n.query?.trim(),a=n.cursor?.trim();if(r)i.set("query",r);if(a)i.set("cursor",a);let d=i.size>0?`${o}?${i}`:o;try{let u=await this.request(d),f=Array.isArray(u)?u:Array.isArray(u?.items)?u.items:[],c=r?.toLowerCase();return{available:!0,branches:f.flatMap((h)=>{let p=String(h.name??"").trim();return p&&(!Array.isArray(u)||!c||p.toLowerCase().includes(c))?[p]:[]}),nextToken:Array.isArray(u)?"":String(u?.nextToken??"").trim()}}catch(u){if(u instanceof g&&u.code==="session_not_found")return{available:!1,branches:[]};throw u}}async status(e,t={}){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:t.signal?AbortSignal.any([t.signal,AbortSignal.timeout(B)]):void 0},void 0,t.authToken)}async create(e){if(e.handoff&&typeof e.handoff.onCreating!=="function")throw new g("request_failed","Cloud handoff requires an onCreating callback to persist creation intent before dispatch.");let t=(await this.options.getAuthToken())?.trim();if(!t)throw new g("authentication_required","Sign in to Cline before starting a cloud session.");let n={token:t,subject:ge(t)},s=wn(e.requestId?.trim()||hn()),o=e.handoff?`${n.subject??t}/${e.organizationId??""}/${e.requestId?.trim()??""}`:void 0;if(e.handoff&&!e.requestId?.trim())throw new g("request_failed","A stable request id is required for cloud handoff creation.");let i=async()=>(await this.listWithToken(e.organizationId??void 0,n,!0)).filter((c)=>c.title===s&&c.repoContext.repoUrl===e.repoUrl&&c.metadata.modelId===e.modelId&&(!e.branch?.trim()||c.repoContext.branch===e.branch.trim())),r=async(c)=>{if(c.status==="failed"||c.expiredAt&&Date.parse(c.expiredAt)<=Date.now()){let p=new g(c.status==="failed"?"session_failed":"session_expired","The recovered cloud handoff workspace is no longer usable.");try{await this.deleteWithAuth(c.id,n)}catch(l){if(!(l instanceof g&&(l.code==="session_not_found"||l.code==="session_expired")))throw AggregateError([p,l],"The unusable recovered cloud handoff workspace could not be removed.")}if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.delete(o);throw await e.handoff?.onOuterSessionRemoved?.(c.id),p}await e.handoff?.onOuterSessionCreated(c.id,{created:!1});let h={sessionId:c.id,status:c.status,sandboxUrl:c.sandboxUrl,cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,h);return h};if(o){let c=await i();if(c.length>1)throw new g("request_failed","Cloud handoff creation is ambiguous; inspect your cloud session list before continuing.");if(c[0])return await r(c[0]);let h=this.completedHandoffCreates.get(o);if(h){try{await this.request(`/api/v1/session/${encodeURIComponent(h.sessionId)}/status`,{},void 0,n)}catch(p){if(p instanceof g&&(p.code==="session_not_found"||p.code==="session_expired"))await e.handoff?.onOuterSessionRemoved?.(h.sessionId),this.completedHandoffCreates.delete(o),this.unconfirmedHandoffCreates.delete(o);throw p}return await e.handoff?.onOuterSessionCreated(h.sessionId,{created:!1}),{...h,cleanupAuthToken:n.token}}if(this.unconfirmedHandoffCreates.has(o))throw new g("request_failed","Cloud handoff creation is still unconfirmed. Recover the original request before creating another workspace.");this.unconfirmedHandoffCreates.add(o)}try{await e.handoff?.onCreating()}catch(c){if(o)this.unconfirmedHandoffCreates.delete(o);throw c}let a=new AbortController,d=setTimeout(()=>a.abort(),this.createTimeoutMs),u,f=!1;try{let c=await this.request("/api/v1/session",{method:"POST",body:JSON.stringify({modelId:e.modelId,repoUrl:e.repoUrl,...e.sandboxType?{sandboxType:e.sandboxType}:{},title:s,...e.branch?.trim()?{branch:e.branch.trim()}:{},...e.organizationId?.trim()?{organizationId:e.organizationId.trim()}:{}}),signal:a.signal},e.organizationId?.trim()?`${this.appBaseUrl}/dashboard/organization/integrations`:void 0,n,()=>{f=!0}),h=c?.sessionId?.trim();if(!h)throw new g("request_failed","The cloud session service returned no session id.");u=h,await this.persistHandoffOuterSession(e,h,n,o);let p={sessionId:h,status:c.status?.trim()||"provisioning",sandboxUrl:c.sandboxUrl?.trim()??"",cleanupAuthToken:n.token};if(o)this.unconfirmedHandoffCreates.delete(o),this.completedHandoffCreates.set(o,p);return p}catch(c){if(u)throw c;let h=!f||c instanceof g&&(c.status!==void 0&&c.status>=400&&c.status<500&&c.status!==408&&c.status!==409||["authentication_required","github_not_connected","session_not_found","session_expired"].includes(c.code));if(o&&h)throw this.unconfirmedHandoffCreates.delete(o),new it(c);if(a.signal.aborted||!(c instanceof g)||c instanceof g&&c.code==="request_failed"&&(c.status===void 0||c.status>=500||c.status===408||c.status===409)){let l=[];try{l=await i()}catch(y){if(e.handoff)throw AggregateError([c,y],"Cloud handoff creation is unconfirmed and its session list could not be checked.")}if(l.length>1)throw new g("request_failed","Cloud session creation had an ambiguous result. Check your cloud session list before trying again.");let m=l[0];if(m){if(e.handoff)return await r(m);return{sessionId:m.id,status:m.status,sandboxUrl:m.sandboxUrl,cleanupAuthToken:n.token}}}else if(o)this.unconfirmedHandoffCreates.delete(o);throw c}finally{clearTimeout(d)}}async persistHandoffOuterSession(e,t,n,s){if(!e.handoff)return;try{await e.handoff.onOuterSessionCreated(t,{created:!0})}catch(o){try{await this.deleteWithAuth(t,n.token)}catch(i){if(!(i instanceof g&&(i.code==="session_not_found"||i.code==="session_expired")))throw AggregateError([o,i],`Cloud session ${t} was created but its recovery record could not be saved or its sandbox removed.`)}if(s)this.unconfirmedHandoffCreates.delete(s);throw await e.handoff.onOuterSessionRemoved?.(t),o}}async waitUntilReady(e,t,n){t=AbortSignal.any([t,AbortSignal.timeout(this.createTimeoutMs)]);let s=await this.options.getAuthToken(),o=s?{token:s,subject:ge(s)}:void 0;while(!t.aborted){let i;try{i=await this.request(`/api/v1/session/${encodeURIComponent(e)}/status`,{signal:AbortSignal.any([t,AbortSignal.timeout(B)])},void 0,o)}catch(a){if(t.aborted)throw a;if(a instanceof g&&a.code!=="request_failed")throw a;await nt(t);continue}let r=i?.status?.trim().toLowerCase();if(n?.({phase:we(i?.phase)}),r==="ready"||r==="active")return;if(r==="failed")throw new g("session_failed",i?.statusReason?.trim()||"The cloud sandbox could not be prepared.");if(r!=="provisioning")throw new g("request_failed","The cloud session service returned an unexpected provisioning status.");await nt(t)}throw t.reason}async resume(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}/resume`,{method:"POST",signal:t?AbortSignal.any([t,AbortSignal.timeout(B)]):void 0})}async delete(e,t){await this.deleteWithAuth(e,t)}async deleteWithAuth(e,t){let n;try{await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"DELETE"},void 0,t)}catch(s){if(!(s instanceof g)||s.code!=="session_not_found"&&s.code!=="session_expired")throw s;n=s}for(let[s,o]of this.completedHandoffCreates)if(o.sessionId===e)this.completedHandoffCreates.delete(s),this.unconfirmedHandoffCreates.delete(s);if(n)throw n}async updateTitle(e,t){return await this.request(`/api/v1/session/${encodeURIComponent(e)}`,{method:"PATCH",body:JSON.stringify({title:t})})}async history(e){let t=await this.options.getAuthToken();if(!t?.trim())throw new g("authentication_required","Sign in to Cline to load this session's history.");let n=await this.fetchImpl(`${this.apiBaseUrl}/api/v1/session/${encodeURIComponent(e)}/history`,{headers:{Accept:"application/json",Authorization:`Bearer ${t.trim()}`},signal:AbortSignal.timeout(B)});if(n.status===404)return null;let s=await n.json().catch(()=>{return});if(!n.ok)throw ye(n.status,s,this.appBaseUrl);if(!s||typeof s!=="object"||!("version"in s)||s.version!==1||!("messages"in s)||!Array.isArray(s.messages))throw new g("request_failed","Invalid archived session history");return s.messages}}import{randomUUID as yo}from"node:crypto";import{posix as le}from"node:path";import{createSessionId as qs,ensureLoopbackProxyBypass as qt,isHubProtocolCompatible as Ns,resolveClineBuildEnv as $s,resolveHubCommandTimeoutMs as Ws}from"@cerebriline/shared";import js from"ws";var q={name:"@cerebriline/core",description:"Cline Core SDK for Node Runtime",version:"0.0.92",repository:{type:"git",url:"https://github.com/cline/cline",directory:"sdk/packages/core"},type:"module",types:"./dist/index.d.ts",main:"./dist/index.js",private:!1,publishConfig:{access:"public"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./hub":{types:"./dist/hub/index.d.ts",import:"./dist/hub/index.js"},"./hub/daemon-entry":{types:"./dist/hub/daemon/entry.d.ts",import:"./dist/hub/daemon/entry.js"},"./telemetry":{types:"./dist/services/telemetry/index.d.ts",import:"./dist/services/telemetry/index.js"},"./services/feature-flags/posthog":{types:"./dist/services/feature-flags/posthog.d.ts",import:"./dist/services/feature-flags/posthog.js"},"./remote/helper-entry":{types:"./dist/remote/remote-helper-entry.d.ts",import:"./dist/remote/remote-helper-entry.js"},"./cloud":{types:"./dist/cloud/index.d.ts",import:"./dist/cloud/index.js"},"./remote/helper":{types:"./dist/remote/remote-helper.d.ts",import:"./dist/remote/remote-helper.js"}},scripts:{build:"bun run ./bun.mts && bun tsc -p tsconfig.build.json && bun run ./scripts/verify-runtime-build-id.ts",typecheck:"bun tsc -p tsconfig.dev.json --noEmit && bun run typecheck:smoke","typecheck:smoke":"bun tsc -p tsconfig.smoke.json --noEmit",test:"bun run test:unit && bun run test:e2e","test:live":"vitest run --config vitest.config.ts src/extensions/context/compaction.live.test.ts","test:compaction":"bun --conditions=development run scripts/compact-session.ts","test:unit":"vitest run --config vitest.config.ts","test:e2e":"vitest run --config vitest.e2e.config.ts","verify:routines":"zsh -lc 'bunx vitest run src/cron/schedule-service.test.ts --config vitest.config.ts'","test:watch":"vitest --config vitest.config.ts"},dependencies:{"@cerebriline/agents":"workspace:*","@cerebriline/llms":"workspace:*","@cerebriline/shared":"workspace:*","@joplin/turndown-plugin-gfm":"1.0.68","@lingo-reader/epub-parser":"0.4.6","@lingo-reader/fb2-parser":"0.4.6","@lingo-reader/mobi-parser":"0.4.6","@modelcontextprotocol/sdk":"^1.29.0","@opentelemetry/api":"^1.9.0","@opentelemetry/api-logs":"^0.214.0","@opentelemetry/exporter-logs-otlp-http":"^0.214.0","@opentelemetry/exporter-metrics-otlp-http":"^0.214.0","@opentelemetry/exporter-trace-otlp-http":"^0.214.0","@opentelemetry/resources":"^2.6.1","@opentelemetry/sdk-logs":"^0.214.0","@opentelemetry/sdk-metrics":"^2.6.1","@opentelemetry/sdk-trace-base":"^2.6.1","@opentelemetry/sdk-trace-node":"^2.6.1","@opentelemetry/semantic-conventions":"^1.40.0","@tesseract.js-data/eng":"1.0.0",cfb:"1.2.2","fast-png":"8.0.0",jiti:"^2.7.0",nanoid:"^5.1.7","node-machine-id":"^1.1.12",officeparser:"8.0.0","pdfjs-dist":"6.2.108","simple-git":"3.36.0","tesseract.js":"7.0.0","tree-sitter-wasms":"^0.1.12",turndown:"7.2.0","web-tree-sitter":"^0.25.0",ws:"^8.20.0",yaml:"^2.8.2",zod:"^4.3.6"},peerDependencies:{"posthog-node":"^5.8.0"},peerDependenciesMeta:{"posthog-node":{optional:!0}},devDependencies:{"@types/turndown":"^5.0.6","@types/ws":"^8.18.1","posthog-node":"^5.8.0"},engines:{node:">=22"},files:["assets","dist","scripts/document-reader-assets.mjs","!dist/**/*.d.ts.map"]};var rt="session_not_found";class Y extends Error{sessionId;code="session_not_found";constructor(e,t){super(t??(e?`session not found: ${e}`:"session not found"));this.sessionId=e;this.name="SessionNotFoundError"}}function ve(e){return e instanceof Y||typeof e==="object"&&e!==null&&"code"in e&&e.code==="session_not_found"}import{spawn as os}from"node:child_process";import{closeSync as is,mkdirSync as rs,openSync as as,readFileSync as ds,unlinkSync as cs}from"node:fs";import{basename as us,dirname as ls,join as ps}from"node:path";import{fileURLToPath as fs}from"node:url";import{CLINE_RUN_AS_HUB_DAEMON_ENV as hs,isBunEmbeddedModulePath as ms,isHubDaemonProcess as gs,resolveClineBuildEnv as Et,withResolvedClineBuildEnv as ys}from"@cerebriline/shared";import{createHash as kn,randomBytes as Rn}from"node:crypto";import{mkdir as Se,open as at,readFile as pt,rename as _n,rm as ke,writeFile as Pn}from"node:fs/promises";import{dirname as ft,join as Re}from"node:path";import{ensureLoopbackProxyBypass as An,isHubProtocolCompatible as Tn}from"@cerebriline/shared";import{resolveClineDataDir as N,resolveClineDir as ii}from"@cerebriline/shared/storage";var xn="CLINE_HUB_DISCOVERY_PATH",En="CLINE_HUB_BUILD_ID",Hn="CLINE_HUB_BUILD_EPOCH_MS",In=30000,Mn=15000,dt=100;function On(e){return e.replace(/[^a-zA-Z0-9_.-]+/g,"_")}function Un(e){return kn("sha256").update(e).digest("hex").slice(0,12)}function Ln(e){if(!Number.isInteger(e)||!e||e<=0)return!1;try{return process.kill(e,0),!0}catch(t){return t instanceof Error&&"code"in t?String(t.code)==="EPERM":!1}}function ct(e){return new Promise((t)=>setTimeout(t,e))}function Dn(e){return`${e}.lock`}async function Bn(e){try{let t=JSON.parse(await pt(Re(e,"owner.json"),"utf8"));if(typeof t.pid!=="number"||typeof t.acquiredAt!=="string")return;return{pid:t.pid,acquiredAt:t.acquiredAt}}catch{return}}async function Ce(e){await ke(e,{recursive:!0,force:!0}).catch(()=>{return})}function U(){let e=process.env[En]?.trim();if(e)return e;return"sdk-v1-53775de0d2fd28896f283d6a0b352b1849403c4306c8f9e8a4a256efd67e5186".trim()||`source-${String(q.version)}`}function qn(){let e=Number(process.env[Hn]);if(Number.isFinite(e)&&e>0)return e;return Number.isFinite(1793571532443)?1793571532443:void 0}function X(e,t=U()){let n=Tn(e);if(!n.compatible)return n;let s=e.buildId?.trim();if(!s)return{compatible:!1,reason:"missing_build"};if(s!==t)return{compatible:!1,reason:"build_mismatch"};return{compatible:!0}}function ut(e){return typeof e==="number"&&Number.isFinite(e)&&e>0?e:void 0}function lt(e){let t=e?.trim().split(/[-+]/,1)[0];if(!t)return;let n=t.split(".").map((s)=>Number(s));if(n.length===0||n.some((s)=>!Number.isInteger(s)||s<0))return;return n}function Nn(e,t){for(let n=0;n<Math.max(e.length,t.length);n++){let s=e[n]??0,o=t[n]??0;if(s!==o)return s<o?-1:1}return 0}function ht(e,t){let n=e.buildId?.trim(),s=t.buildId?.trim();if(n&&s&&n===s)return 0;let o=ut(e.buildEpochMs),i=ut(t.buildEpochMs);if(o!==void 0&&i!==void 0&&o!==i)return o<i?-1:1;let r=lt(e.coreVersion),a=lt(t.coreVersion);if(r&&a){let d=Nn(r,a);if(d!==0)return d}if(n&&s&&n!==s)return n<s?-1:1;return 0}function mt(){return{buildId:U(),buildEpochMs:qn(),coreVersion:String(q.version)}}function Z(e,t){let n=t?.self??mt(),s=X(e,n.buildId??"");if(s.compatible)return!0;if(s.reason!=="build_mismatch"&&s.reason!=="missing_build")return!1;return ht(n,e)<=0}function gt(e=process.argv[1]?.trim()||process.cwd()){let t=`hub-${Un(e)}`,n=process.env[xn]?.trim()||Re(N(),"locks","hub","owners",`${On(t)}.json`);return{ownerId:t,discoveryPath:n}}async function I(e){try{let t=JSON.parse(await pt(e,"utf8"));if(typeof t.hubId!=="string"||typeof t.protocolVersion!=="string"||typeof t.authToken!=="string"||typeof t.host!=="string"||typeof t.port!=="number"||typeof t.url!=="string"||typeof t.startedAt!=="string"||typeof t.updatedAt!=="string")return;return{hubId:t.hubId,protocolVersion:t.protocolVersion,minClientProtocolVersion:typeof t.minClientProtocolVersion==="string"?t.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof t.maxClientProtocolVersion==="string"?t.maxClientProtocolVersion:void 0,capabilities:Array.isArray(t.capabilities)?t.capabilities.filter((n)=>typeof n==="string"):void 0,coreVersion:typeof t.coreVersion==="string"?t.coreVersion:void 0,buildId:typeof t.buildId==="string"?t.buildId:void 0,buildEpochMs:typeof t.buildEpochMs==="number"?t.buildEpochMs:void 0,authToken:t.authToken,host:t.host,port:t.port,url:t.url,pid:typeof t.pid==="number"?t.pid:void 0,startedAt:t.startedAt,updatedAt:t.updatedAt}}catch{return}}async function yt(e,t,n){await wt(e,async()=>{let s=ft(e);await Se(s,{recursive:!0});let o=`${e}.${process.pid}.${Rn(6).toString("hex")}.tmp`,i;try{i=await at(o,"wx",384),await i.writeFile(`${JSON.stringify(t,null,2)}
|
|
9
9
|
`,{encoding:"utf8"}),await i.sync(),await i.close(),i=void 0,n?.beforePublish?.(),await _n(o,e);let r;try{r=await at(s,"r"),await r.sync()}catch{}finally{await r?.close().catch(()=>{return})}}catch(r){throw await i?.close().catch(()=>{return}),await ke(o,{force:!0}).catch(()=>{return}),r}})}async function L(e){await wt(e,async()=>{await ke(e,{force:!0}).catch(()=>{return})})}async function bt(e,t,n){let s=Dn(e);await Se(ft(s),{recursive:!0});let o=Date.now()+Mn;while(!0){try{await Se(s,{recursive:!1})}catch(i){if((i instanceof Error&&"code"in i?String(i.code):"")!=="EEXIST")throw i;let a=await Bn(s);if(!a){if(Date.now()>=o){await Ce(s);continue}await ct(dt);continue}let d=Date.now()-Date.parse(a.acquiredAt);if(!Ln(a.pid)||d>In){await Ce(s);continue}if(Date.now()>=o)throw Error(`Timed out waiting for hub ${t} lock ${s}`);await ct(dt);continue}try{return await Pn(Re(s,"owner.json"),`${JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()},null,2)}
|
|
10
10
|
`,"utf8"),await n()}finally{await Ce(s)}}}function wt(e,t){return bt(`${e}.mutation`,"discovery mutation",t)}function vt(e,t){return bt(e,"startup",t)}async function ee(e,t){An();try{let n=await fetch(t?.authToken?$n(e):St(e),{headers:t?.authToken?{authorization:`Bearer ${t.authToken}`}:void 0,signal:t?.signal});if(!n.ok)return;let s=await n.json();if(typeof s.protocolVersion!=="string"||typeof s.host!=="string"||typeof s.port!=="number"||typeof s.url!=="string")return;return{protocolVersion:s.protocolVersion,minClientProtocolVersion:typeof s.minClientProtocolVersion==="string"?s.minClientProtocolVersion:void 0,maxClientProtocolVersion:typeof s.maxClientProtocolVersion==="string"?s.maxClientProtocolVersion:void 0,capabilities:Array.isArray(s.capabilities)?s.capabilities.filter((o)=>typeof o==="string"):void 0,coreVersion:typeof s.coreVersion==="string"?s.coreVersion:void 0,buildId:typeof s.buildId==="string"?s.buildId:void 0,buildEpochMs:typeof s.buildEpochMs==="number"?s.buildEpochMs:void 0,host:s.host,port:s.port,url:s.url,hubId:typeof s.hubId==="string"?s.hubId:void 0,authToken:typeof s.authToken==="string"?s.authToken:void 0,pid:typeof s.pid==="number"?s.pid:void 0,startedAt:typeof s.startedAt==="string"?s.startedAt:void 0,updatedAt:typeof s.updatedAt==="string"?s.updatedAt:void 0}}catch{return}}function Ct(e,t,n="/hub"){return new URL(`ws://${e}:${t}${n}`).toString()}function St(e){let t=new URL(e);return t.protocol=t.protocol==="wss:"?"https:":"http:",t.pathname="/health",t.search="",t.toString()}function $n(e){let t=new URL(St(e));return t.pathname="/status",t.toString()}import{CLINE_HUB_DEV_PORT as Wn,CLINE_HUB_PORT as jn,resolveClineBuildEnv as Fn}from"@cerebriline/shared";var zn="CLINE_HUB_HOST",Vn="CLINE_HUB_PORT",Gn="CLINE_HUB_PATHNAME",Jn="127.0.0.1",Kn=jn,Qn="/hub";function kt(e){return Fn(e)==="development"?Wn:Kn}function Yn(e={}){return(e.env??process.env)[zn]?.trim()||Jn}function Xn(e={}){let n=(e.env??process.env)[Vn]?.trim();if(!n)return kt(e);let s=Number.parseInt(n,10);if(!Number.isInteger(s)||s<1||s>65535)return kt(e);return s}function Zn(e={}){return(e.env??process.env)[Gn]?.trim()||Qn}function Rt(e={},t={}){return{host:e.host??Yn(t),port:e.port??Xn(t),pathname:e.pathname??Zn(t)}}import{join as es}from"node:path";var ts="shared:cline",ns="CLINE_HUB_DISCOVERY_PATH",ss="hub-production";function W(e=ts){return gt(`${e}@${U()}`)}function te(){return{ownerId:ss,discoveryPath:process.env[ns]?.trim()||es(N(),"locks","hub","production.json")}}var _t=15000,bs=200,Pt=3000,ws=100,vs=[100,250,500,1000,2000],Cs="--cline-hub-daemon",Ss=3,ks=60000,At=new Map;function Rs(e,t=Date.now()){let n=At.get(e);if(!n||t-n.windowStartedAt>ks)return At.set(e,{count:1,windowStartedAt:t}),!0;return n.count+=1,n.count<=Ss}function _s(e){return[...e.host?["--host",e.host]:[],...typeof e.port==="number"?["--port",String(e.port)]:[],...e.pathname?["--pathname",e.pathname]:[]]}function Ps(){try{let e=ps(N(),"logs","hub-daemon.log");return rs(ls(e),{recursive:!0}),{fd:as(e,"a"),logPath:e}}catch{return}}function As(){return Et()==="production"?te():W()}function j(e){return Z(e)}function Ts(e){try{let t=JSON.parse(ds(`${e}.superseded`,"utf8"));return{url:typeof t.url==="string"?t.url:void 0,authToken:typeof t.authToken==="string"?t.authToken:void 0,pid:typeof t.pid==="number"?t.pid:void 0}}catch{return}}function _e(e){try{cs(`${e}.superseded`)}catch{}}function Tt(e,t,n){if(!t||t.url!==n)return e;return{...e,authToken:e.authToken??t.authToken,pid:e.pid??t.pid}}async function F(e,t){try{return await ee(e,{authToken:t})}catch{return}}async function xt(e,t){let n=Date.now()+t;while(Date.now()<n){if(!(await F(e))?.url)return!0;await new Promise((o)=>setTimeout(o,ws))}return!1}async function Ae(e,t){if(!Rs(e.url))return!1;await z(e.url,e.authToken,"retired by newer install").catch(()=>!1),await Mt(e.url,e.authToken).catch(()=>!1);let n=await xt(e.url,Pt);if(!n&&e.pid&&xs(e.pid)){try{process.kill(e.pid,"SIGTERM")}catch{}n=await xt(e.url,Pt)}if(n)await L(t).catch(()=>{return});return n}function xs(e){try{return process.kill(e,0),!0}catch(t){return t?.code==="EPERM"}}async function Es(e){try{return(await Te(e.url,e.authToken)).activeSessionCount>0}catch{return!1}}async function Pe(e,t){if(j(e))return"reusable";let n=await z(e.url,e.authToken,"retired by newer install").catch(()=>!1);if(await Es(e)){if(n)await z(e.url,e.authToken,"hub retirement deferred",{off:!0}).catch(()=>!1);return"deferred_busy"}let s=await Ae(e,t);if(!s&&n)await z(e.url,e.authToken,"hub retirement failed",{off:!0}).catch(()=>!1);return s?"retired":"failed"}async function Hs(e){if(Et()!=="production")return;let t=W();if(t.discoveryPath===e.discoveryPath)return;let n=await I(t.discoveryPath);if(n?.url)await Ae(n,t.discoveryPath);else await L(t.discoveryPath).catch(()=>{return})}function Is(){let e=import.meta.url.endsWith(".ts")?"ts":"js";return fs(new URL(`./entry.${e}`,import.meta.url))}function Ms(e,t){if(ms(e))return[Cs];return[...t&&e.toLowerCase().endsWith(".ts")?["--conditions=development"]:[],e]}function Os(e,t){let n=Is(),s=process.execPath?.trim();if(!s)throw Error("unable to resolve runtime executable for hub daemon");let o=us(s).toLowerCase().includes("bun"),i=Ms(n,o);return{launcher:s,args:[...i,"--cwd",e,..._s(t),...t.manageConnectors===!1?["--no-connectors"]:[]],cwd:e,env:{...ys(process.env),CLINE_NO_INTERACTIVE:"1",[hs]:"1"}}}function Us(e){if(!e||typeof e!=="object")return!1;if(("code"in e?e.code:void 0)==="ETXTBSY")return!0;let n="message"in e?e.message:void 0;return typeof n==="string"&&n.includes("ETXTBSY")}function Ls(e,t={}){if(gs())return;let n=Os(e,t),s=Ps();try{os(n.launcher,n.args,{detached:!0,stdio:s?["ignore",s.fd,s.fd]:"ignore",env:n.env,cwd:n.cwd,windowsHide:!0}).unref()}finally{if(s)is(s.fd)}}async function Ds(e,t={}){for(let n=0;;n++)try{Ls(e,t);return}catch(s){let o=vs[n];if(!Us(s)||o===void 0)throw s;await new Promise((i)=>setTimeout(i,o))}}async function Bs(e,t,n={}){let s=n.host!==void 0||n.port!==void 0||n.pathname!==void 0||!!process.env.CLINE_HUB_PORT?.trim(),o=Rt(n),i=Ct(o.host,o.port,o.pathname),r=(l)=>{if(!s)ne(l.url,l.authToken);else It(l.url,l.authToken);return l};await Hs(e).catch(()=>{return});let a=await I(e.discoveryPath),d=a?.url?void 0:Ts(e.discoveryPath),u=!1;if(a?.url){let l=a.authToken;if(!l)u=!0,await Ae(a,e.discoveryPath);else{let m=await F(a.url,l);if(m?.url&&j(m)&&await E(m.url,{authToken:l}))return _e(e.discoveryPath),r({url:m.url,authToken:l});if(m?.url){if(await Pe({...m,authToken:l},e.discoveryPath)==="deferred_busy"&&await E(m.url,{authToken:l}))return r({url:m.url,authToken:l})}else await L(e.discoveryPath).catch(()=>{return})}}let f=await F(i);if(f?.url){let l=Tt(f,a??d,i);if(j(f)){let y=[f.authToken,a?.authToken,d?.authToken].filter((v)=>typeof v==="string"&&v.trim().length>0);for(let v of y){if(!await E(f.url,{authToken:v}))continue;let P={hubId:f.hubId??`repaired-${f.port}`,protocolVersion:f.protocolVersion,minClientProtocolVersion:f.minClientProtocolVersion,maxClientProtocolVersion:f.maxClientProtocolVersion,capabilities:f.capabilities,coreVersion:f.coreVersion,buildId:f.buildId,authToken:v,host:f.host,port:f.port,url:f.url,pid:f.pid??a?.pid??d?.pid,startedAt:f.startedAt??new Date().toISOString(),updatedAt:new Date().toISOString()};try{await yt(e.discoveryPath,P)}catch{}return _e(e.discoveryPath),r({url:f.url,authToken:v})}throw Error(`A compatible Cline Hub is already running at ${i}, but its discovery record is missing or unreadable and no usable auth token is available. Run 'cline doctor fix' to repair local hub discovery.${u?" This can happen immediately after upgrading from a build that wrote an empty hub auth token; run 'cline doctor fix' to stop the old daemon and repair local hub discovery.":""}`)}let m=await Pe(l,e.discoveryPath);if(m==="deferred_busy"){for(let y of[l.authToken,a?.authToken].filter((w)=>typeof w==="string"&&w.trim().length>0))if(await E(f.url,{authToken:y}))return r({url:f.url,authToken:y});if(n.allowPortFallback!==!0&&o.port!==0)throw Error(`An older Cline Hub is running at ${i} and is still serving active sessions, so it was not replaced, but no usable auth token is available to attach to it. Finish those sessions, or run 'cline doctor fix' to stop the hub.`)}if(m==="failed"&&n.allowPortFallback!==!0&&o.port!==0)throw Error(`An incompatible Cline Hub is already running at ${i} and could not be retired automatically. Run 'cline doctor fix' to stop stale hub daemons before starting a new hub.`)}let h=n.allowPortFallback===!0&&o.port!==0?{...o,port:0}:o;await Ds(t,{...h,manageConnectors:n.manageConnectors});let p=Date.now()+_t;while(Date.now()<p){let l=await I(e.discoveryPath);if(l?.url&&l.authToken){let y=await F(l.url,l.authToken);if(y?.url&&j(y)&&await E(y.url,{authToken:l.authToken}))return _e(e.discoveryPath),r({url:y.url,authToken:l.authToken})}let m=await F(i);if(m?.url&&!j(m)){let y=Tt(m,l??d,i),w=await Pe(y,e.discoveryPath);if(w==="deferred_busy"&&l?.authToken&&await E(m.url,{authToken:l.authToken}))return r({url:m.url,authToken:l.authToken});if(w==="failed"&&n.allowPortFallback!==!0&&o.port!==0)throw Error(`An incompatible Cline Hub is still running at ${i} and could not be retired automatically. Run 'cline doctor fix' to stop stale hub daemons before starting a new hub.`)}await new Promise((y)=>setTimeout(y,bs))}throw Error(`Timed out after ${_t}ms waiting for detached hub startup.`)}async function Ht(e,t={}){let n=As();return await vt(n.discoveryPath,async()=>Bs(n,e,t))}function Fs(){return $s()==="production"?te():W()}function zs(){let e=globalThis.WebSocket;if(!e)throw Error("Global WebSocket is not available in this runtime. Node 22+ is required for hub mode.");return e}function Nt(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return Buffer.from(e).toString();if(e instanceof ArrayBuffer)return Buffer.from(e).toString();if(Array.isArray(e))return Buffer.concat(e.map((t)=>Buffer.from(t))).toString();if(e&&typeof e==="object"&&"data"in e&&typeof e.data<"u")return Nt(e.data);return String(e)}function Vs(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return Buffer.from(e).toString("utf8");if(e instanceof ArrayBuffer)return Buffer.from(e).toString("utf8");return""}function Ot(e){let t=e,n=Vs(t.reason);return new k("hub_connection_closed",t.code||n?`Hub connection closed (code=${t.code??0}${n?`, reason=${n}`:""})`:Ee,{closeCode:t.code,closeReason:n||void 0})}function Ut(e,t){if(e instanceof k)return e;if(e instanceof Error)return new k("hub_connect_failed",e.message);if(e&&typeof e==="object"&&"error"in e&&e.error instanceof Error)return new k("hub_connect_failed",e.error.message);let n=e&&typeof e==="object"&&"message"in e&&typeof e.message==="string"?e.message.trim():"";if(n)return new k("hub_connect_failed",n);let s=e&&typeof e==="object"&&"type"in e&&typeof e.type==="string"?e.type.trim():"";return new k("hub_connect_failed",s?`Failed to connect to hub at ${t.toString()} (${s} event before socket open).`:`Failed to connect to hub at ${t.toString()}.`)}var xe="*",se=8000,Gs="cline-hub-auth.",Me=new Map,$t=new Set,Js=3000;var Ee="Hub connection closed",Ks=250,Qs=5000,Lt=0.5;class k extends Error{code;details;constructor(e,t,n){super(t);this.code=e;this.details=n;this.name="HubTransportError"}}function Ys(e){return e instanceof k}class He extends Error{command;code;constructor(e,t,n){super(n);this.command=e;this.code=t;this.name="HubCommandError"}}function Oe(e,t={}){let n=e.searchParams.get("authToken")?.trim();if(e.searchParams.delete("authToken"),n)return n;if(t.skipRegistry)return;let s=oe(e.toString());return s?Me.get(s):void 0}function Xs(e){try{let n=new URL(e).hostname.toLowerCase().replace(/^\[|\]$/g,"");return n==="localhost"||n==="127.0.0.1"||n==="::1"}catch{return!1}}function oe(e){if(!Xs(e))return;let t=new URL(Wt(e));return t.search="",t.hash="",t.toString()}function Dt(e){let t=oe(e);return!!t&&$t.has(t)}function ne(e,t){let n=oe(e);if(n){if($t.add(n),t?.trim())Me.set(n,t)}return e}function It(e,t){let n=oe(e);if(n&&t?.trim())Me.set(n,t)}class V{options;socket;connectPromise;clientId;currentUrl;recoveryPromise;pendingReplies=new Map;listeners=new Set;subscriptionCounts=new Map;lastEventSequenceByKey=new Map;reconnectTimer;reconnectAttempt=0;closedByClient=!1;connectGeneration=0;lastCloseError=new k("hub_connection_closed",Ee);sawSocketClose=!1;registered=!1;capabilities;constructor(e){this.options=e;if(e.authToken?.trim()&&e.resolveConnectionHeaders)throw Error("Hub connection headers cannot be combined with authToken authentication.");this.clientId=e.clientId??`core-${Math.random().toString(36).slice(2,10)}-${Date.now().toString(36)}`,this.currentUrl=e.url,this.capabilities=[...e.capabilities??[]]}getClientId(){return this.clientId}getUrl(){return this.currentUrl}isConnected(){return this.socket?.readyState===1&&this.registered}getConnectionError(){return this.isConnected()?null:this.lastCloseError}async updateCapabilities(e){if(this.capabilities=e.map((t)=>({...t})),!this.registered)return;await this.command("client.update",{capabilities:this.capabilities})}async connect(){if(this.connectPromise)return this.connectPromise;if(this.socket&&(this.socket.readyState===1||this.socket.readyState===0))return this.connectPromise??Promise.resolve();this.closedByClient=!1,this.clearReconnectTimer();let e=new URL(this.currentUrl),t=this.options.authToken?.trim()||Oe(e,{skipRegistry:Boolean(this.options.resolveConnectionHeaders)});if(e.hash="",t&&this.options.resolveConnectionHeaders)throw Error("Hub connection headers cannot be combined with authToken authentication.");let n=++this.connectGeneration,s=this.openSocket(e,t,n),o;this.connectPromise=s.then(async(r)=>{if(o=r,await this.commandOnce("client.register",{clientId:this.clientId,clientType:this.options.clientType??"core",displayName:this.options.displayName??"core",transport:"native",actorKind:"client",capabilities:this.capabilities,metadata:{...this.options.metadata,version:this.options.clientVersion??String(q.version),pid:process.pid},workspaceContext:{workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd}},void 0,void 0,!1),n!==this.connectGeneration||this.closedByClient){try{r.close()}catch{}throw this.lastCloseError}this.registered=!0;for(let a of this.subscriptionCounts.keys())this.sendSubscriptionFrame("stream.subscribe",this.subscriptionSessionIdFromKey(a));this.reconnectAttempt=0});let i=this.connectPromise;try{await i}catch(r){if(this.connectPromise===i)this.connectPromise=void 0;if(o&&this.socket===o){this.lastCloseError=Ut(r,e),this.registered=!1,this.sawSocketClose=!1,this.socket=void 0;try{o.close()}catch{}}if(!this.closedByClient&&this.hasActiveSubscriptions())this.scheduleReconnect();throw r}}async openSocket(e,t,n){let s=this.options.resolveConnectionHeaders,o;if(s){let d;try{o=await Promise.race([Promise.resolve().then(()=>s()),new Promise((u,f)=>{d=setTimeout(()=>{f(new k("hub_connect_timeout",`Timed out resolving hub connection headers after ${se}ms`))},se)})])}catch(u){let f=u instanceof k?u:new k("hub_connect_failed",u instanceof Error?u.message:String(u));if(n===this.connectGeneration)this.lastCloseError=f;throw f}finally{clearTimeout(d)}}if(n!==this.connectGeneration||this.closedByClient)throw this.lastCloseError;if(o&&Object.keys(o).some((d)=>d.toLowerCase()==="sec-websocket-protocol")){let d=new k("hub_connect_failed","Hub connection headers cannot set Sec-WebSocket-Protocol.");if(n===this.connectGeneration)this.lastCloseError=d;throw d}let i=o?new js(e.toString(),{headers:{...o}}):new(zs())(e.toString(),t?[`${Gs}${t}`]:void 0);this.socket=i;let r=!1,a=new Promise((d,u)=>{let f=!1,c=setTimeout(()=>{if(f)return;f=!0,r=!0;let h=new k("hub_connect_timeout",`Timed out connecting to hub after ${se}ms`);if(this.socket===i)this.lastCloseError=h,this.sawSocketClose=!1,this.connectPromise=void 0,this.socket=void 0;try{i.close()}catch{}u(h)},se);i.addEventListener("open",()=>{if(f)return;f=!0,clearTimeout(c),d()}),i.addEventListener("error",(h)=>{if(f)return;f=!0,clearTimeout(c);let p=Ut(h,e);if(this.socket===i)this.lastCloseError=p,this.sawSocketClose=!1,this.connectPromise=void 0,this.socket=void 0;u(p)}),i.addEventListener("close",(h)=>{if(f)return;f=!0,clearTimeout(c);let p=r?this.lastCloseError:Ot(h);if(this.socket===i){if(!r)this.lastCloseError=p,this.sawSocketClose=!0;this.connectPromise=void 0,this.socket=void 0}u(p)})});return i.addEventListener("message",(d)=>{this.handleFrame(JSON.parse(Nt(d)))}),i.addEventListener("close",(d)=>{if(this.socket!==i)return;if(!r)this.lastCloseError=Ot(d),this.sawSocketClose=!0;this.registered=!1;for(let u of this.pendingReplies.values())u.reject(this.lastCloseError);if(this.pendingReplies.clear(),this.connectPromise=void 0,this.socket=void 0,!this.closedByClient&&this.hasActiveSubscriptions())this.scheduleReconnect()}),await a,i}subscribe(e,t){let n=t?.sessionId?.trim()||void 0,s={listener:e,sessionId:n};return this.listeners.add(s),this.adjustSubscriptionCount(n,1),()=>{if(!this.listeners.delete(s))return;this.adjustSubscriptionCount(n,-1)}}async command(e,t,n,s){let o=0,i=e!=="client.register"&&e!=="client.unregister";while(!0)try{return await this.commandOnce(e,t,n,s)}catch(r){if(!i||o>=1||!await this.recoverLocalHubTransport(r))throw r;o+=1}}async commandOnce(e,t,n,s,o=!0){if(o)await this.connect();s?.beforeDispatch?.();let i=qs("hubreq_");s?.onDispatch?.(i);let r=Ws(e,s?.timeoutMs),a=new Promise((u,f)=>{let c=r===null?void 0:setTimeout(()=>{if(!this.pendingReplies.delete(i))return;f(new He(e,"hub_command_timeout",`Hub command ${e} timed out after ${r}ms (hub=${this.currentUrl}, requestId=${i}, clientId=${this.clientId}). Check hub-daemon.log for matching command.start/command.slow entries, or run 'cline doctor fix' to restart the hub.`))},r);this.pendingReplies.set(i,{resolve:(h)=>{if(c)clearTimeout(c);u(h)},reject:(h)=>{if(c)clearTimeout(c);f(h)}})});try{this.sendFrame({kind:"command",envelope:{version:"v1",command:e,requestId:i,clientId:this.clientId,sessionId:n,timeoutMs:r,payload:t}})}catch(u){throw this.pendingReplies.delete(i),u}let d=await a;if(!d.ok){if(d.error?.code===rt){let u=n??(typeof t?.sessionId==="string"?t.sessionId:void 0);throw new Y(u,d.error.message)}throw new He(e,d.error?.code,d.error?.message??`Hub command ${e} failed`)}return d}async recoverLocalHubTransport(e){if(!Dt(this.currentUrl)||!Ys(e))return!1;if(this.recoveryPromise)return await this.recoveryPromise;return this.recoveryPromise=(async()=>{let t=await Bt({workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd}).catch(()=>{return});if(!t)return!1;return this.currentUrl=t,this.close(),!0})().finally(()=>{this.recoveryPromise=void 0}),await this.recoveryPromise}hasActiveSubscriptions(){return this.subscriptionCounts.size>0}clearReconnectTimer(){if(!this.reconnectTimer)return;clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0}scheduleReconnect(){if(this.reconnectTimer||this.closedByClient||!this.hasActiveSubscriptions())return;let e=Math.min(Ks*2**this.reconnectAttempt,Qs),t=Math.round(e*(1-Lt)+Math.random()*e*Lt);this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=void 0,this.reconnectSubscribedTransport()},t)}async reconnectSubscribedTransport(){if(this.closedByClient||!this.hasActiveSubscriptions())return;try{await this.connect(),this.reconnectAttempt=0}catch{if(!Dt(this.currentUrl)){this.reconnectAttempt+=1,this.scheduleReconnect();return}try{let e=await Bt({workspaceRoot:this.options.workspaceRoot,cwd:this.options.cwd});if(e){this.currentUrl=e,await this.connect(),this.reconnectAttempt=0;return}}catch{}this.reconnectAttempt+=1,this.scheduleReconnect()}}close(){let e=this.socket;if(this.closedByClient=!0,this.connectGeneration+=1,this.clearReconnectTimer(),this.registered=!1,e)this.lastCloseError=new k("hub_connection_closed",Ee);for(let t of this.pendingReplies.values())t.reject(this.lastCloseError);if(this.pendingReplies.clear(),this.connectPromise=void 0,!e)return;this.sawSocketClose=!1,this.socket=void 0;try{e.close()}catch{}}async dispose(){if(this.socket?.readyState===1&&this.registered)try{await this.command("client.unregister",void 0,void 0,{timeoutMs:2000})}catch{}this.close()}sendFrame(e){if(!this.socket||this.socket.readyState!==1){if(this.lastCloseError.code==="hub_connection_closed"&&!this.sawSocketClose)throw new k("hub_connection_not_open","Hub connection is not open.");throw this.lastCloseError}this.socket.send(JSON.stringify(e))}sendSubscriptionFrame(e,t){let n=e==="stream.subscribe"?this.lastEventSequenceByKey.get(this.subscriptionKeyForSessionId(t)):void 0;this.sendFrame({kind:e,clientId:this.clientId,...t?{sessionId:t}:{},...n!==void 0?{sinceSequence:n}:{}})}adjustSubscriptionCount(e,t){let n=this.subscriptionKeyForSessionId(e),s=(this.subscriptionCounts.get(n)??0)+t;if(s<=0){if(this.subscriptionCounts.delete(n),!this.hasActiveSubscriptions())this.clearReconnectTimer();if(t<0&&this.socket?.readyState===1)this.sendSubscriptionFrame("stream.unsubscribe",e);return}if(this.subscriptionCounts.set(n,s),t>0&&s===1&&this.socket?.readyState===1)this.sendSubscriptionFrame("stream.subscribe",e)}subscriptionKeyForSessionId(e){return e??xe}subscriptionSessionIdFromKey(e){return e===xe?void 0:e}handleFrame(e){switch(e.kind){case"reply":{let t=e.envelope.requestId;if(!t)return;let n=this.pendingReplies.get(t);if(!n)return;this.pendingReplies.delete(t),n.resolve(e.envelope);return}case"event":{let t=e.envelope.sequence;if(typeof t==="number"){let n=e.envelope.sessionId?.trim();for(let s of[xe,n]){if(!s||!this.subscriptionCounts.has(s))continue;let o=this.lastEventSequenceByKey.get(s)??0;if(t>o)this.lastEventSequenceByKey.set(s,t)}}for(let n of this.listeners){if(n.sessionId&&n.sessionId!==e.envelope.sessionId?.trim())continue;n.listener(e.envelope)}return}case"command":case"stream.subscribe":case"stream.unsubscribe":return}}}function Wt(e){let t=new URL(e);if(t.protocol==="http:")t.protocol="ws:";else if(t.protocol==="https:")t.protocol="wss:";return t.toString()}async function E(e,t){let n=new V({url:e,authToken:t?.authToken,clientType:"hub-healthcheck",displayName:"hub healthcheck",workspaceRoot:t?.workspaceRoot,cwd:t?.cwd});try{return await n.connect(),!0}catch{return!1}finally{n.close()}}async function Ie(e,t){let n=Wt(e),s=await ee(n,{authToken:t?.authToken});if(!s)return{status:"unreachable",url:n};if(t?.requireCurrentBuild){let o=U(),i=X(s,o);if(!i.compatible&&!Z(s))return{status:i.reason==="unsupported_protocol"?"protocol_mismatch":"build_mismatch",url:n}}else if(!Ns(s).compatible)return{status:"protocol_mismatch",url:n};if(t?.verifyConnection===!0&&!await E(n,{workspaceRoot:t.workspaceRoot,cwd:t.cwd,authToken:t.authToken}))return{status:"unreachable",url:n};return{status:"compatible",url:n}}function Zs(e){let t=e&&typeof e==="object"&&Array.isArray(e.sessions)?e.sessions:[],n=0,s=new Set;for(let o of t){if(!o||typeof o!=="object")continue;let i=o.participants;if(!Array.isArray(i)||i.length===0)continue;n+=1;for(let r of i){let a=r&&typeof r==="object"?r.clientId:void 0;if(typeof a==="string"&&a.trim())s.add(a)}}return{activeSessionCount:n,participantClientCount:s.size}}async function Te(e,t,n){let s=new V({url:e,authToken:t,clientType:"hub-recovery-check",displayName:"hub recovery check",workspaceRoot:n?.workspaceRoot,cwd:n?.cwd});try{let o=await s.command("session.list",{limit:500},void 0,{timeoutMs:Js});return Zs(o.payload)}finally{await s.dispose().catch(()=>{return})}}async function eo(e,t,n){try{return(await Te(e,t,n)).activeSessionCount===0}catch{return!1}}async function to(e,t){let n=`${e.discoveryPath}.superseded`,s=await I(n);if(!s?.url||!s.authToken)return;let o=await Ie(s.url,{authToken:s.authToken});if(o.status!=="compatible")return;if(await eo(o.url,s.authToken,t))return;return ne(o.url,s.authToken)}async function no(e={}){if(e.endpoint?.trim()){let o=await Ie(e.endpoint);return o.status==="compatible"?o.url:void 0}let t=Fs(),n=await I(t.discoveryPath);if(!n?.url)return await to(t,e);let s=await Ie(n.url,{authToken:n.authToken,requireCurrentBuild:!0});if(s.status==="compatible")return ne(s.url,n.authToken);if(s.status==="protocol_mismatch")await L(t.discoveryPath).catch(()=>{return});return}async function Bt(e={}){let t=await no(e);if(t&&await E(t,{workspaceRoot:e.workspaceRoot,cwd:e.cwd}))return t;if(e.endpoint?.trim())return;try{return(await Ht(e.workspaceRoot??process.cwd())).url}catch(n){e.onStartupError?.(n);return}}async function z(e,t,n,s){qt();let o=new URL(e),i=t?.trim()||Oe(o);if(o.protocol==="ws:")o.protocol="http:";else if(o.protocol==="wss:")o.protocol="https:";if(o.pathname="/drain",o.hash="",n)o.searchParams.set("reason",n);if(s?.off)o.searchParams.set("off","1");return(await fetch(o,{method:"POST",headers:i?{authorization:`Bearer ${i}`}:void 0})).ok}async function Mt(e,t){qt();let n=new URL(e),s=t?.trim()||Oe(n);if(n.protocol==="ws:")n.protocol="http:";else if(n.protocol==="wss:")n.protocol="https:";return n.pathname="/shutdown",n.hash="",(await fetch(n,{method:"POST",headers:s?{authorization:`Bearer ${s}`}:void 0})).ok}function so(e,t){if(!e||typeof e!=="object")return;let n=e,s=typeof n.id==="string"?n.id.trim():"";if(!s)return;let o=typeof n.display_name==="string"?n.display_name.trim():typeof n.displayName==="string"?n.displayName.trim():"",i=typeof n.name==="string"?n.name.trim():"";return{id:s,name:o||i||s,catalogId:t}}function Ue(e,t){return Array.isArray(e)?e.flatMap((n)=>{let s=so(n,t);return s?[s]:[]}):[]}async function jt(e,t={}){let n=e.trim(),s=n.length;while(s>0&&n[s-1]==="/")s--;let o=n.slice(0,s),i=async(m)=>{let y=await(t.fetchImpl??fetch)(`${o}${m}`,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!y.ok)throw Error(`HTTP ${y.status}`);return await y.json()},r,a;try{[r,a]=await Promise.all([i("/api/v1/ai/cline/models"),i("/api/v1/ai/cline/recommended-models")])}catch(m){throw Error("Could not load the cloud model catalog.",{cause:m})}let d=r&&typeof r==="object"?r:void 0,u=Ue(Array.isArray(r)?r:d?.data,"cline"),f=a&&typeof a==="object"?a:void 0,c=f?.data&&typeof f.data==="object"?f.data:f,h=Ue(c?.clinePass,"cline-pass"),p=Ue(c?.clineCloud,"cline-cloud"),l=new Set;return[...t.isOrganizationSession?[]:h,...p,...u].filter((m)=>{if(l.has(m.id))return!1;return l.add(m.id),!0})}import{formatDisplayUserInput as Ft}from"@cerebriline/shared";var oo=new Set(["auto_compaction","compaction_budget_emergency","completion_reminder","loop_detection_notice","manual_compaction","mistake_stop_notice","recovery_notice"]);function io(e){switch(e){case"user":case"assistant":case"tool":case"system":case"status":case"error":return e;default:return"assistant"}}function ro(e){return e.metadata&&typeof e.metadata==="object"&&!Array.isArray(e.metadata)?e.metadata:void 0}function ao(e){let t=e?.userRunSpan;return typeof t==="number"&&Number.isInteger(t)&&t>=0?t:void 0}function co(e){if(typeof e.content==="string")return{hasAttachment:!1,text:e.content};if(!Array.isArray(e.content))return{hasAttachment:!1,text:"unknown"};let t=!1,n=!1,s=[];for(let o of e.content){if(!o||typeof o!=="object"||Array.isArray(o))continue;let i=o;if(i.type==="text"&&typeof i.text==="string")s.push(i.text);else if(i.type==="tool_result"||i.type==="tool-result")n=!0;else if(i.type==="file"||i.type==="image")t=!0}return{hasAttachment:t&&!n,text:s.join(`
|
|
11
11
|
`)}}function uo(e){let t=Ft(e);return t.startsWith("[TASK RESUMPTION]")||t==="The user approved switching to act mode. Continue with the approved plan now."}function lo(e){if(io(e.role)!=="user")return 0;let t=ro(e),n=typeof t?.kind==="string"?t.kind:void 0,s=ao(t);if(n==="compaction"||n==="compaction_summary")return s??1;if(s!==void 0)return s;if(n&&oo.has(n))return 0;let o=co(e);if(!o.hasAttachment&&!Ft(o.text))return 0;if(!o.hasAttachment&&uo(o.text))return 0;return 1}function zt(e){return lo(e)>0}function ae(e){return Array.isArray(e?.sessions)?e.sessions.filter((t)=>Boolean(t)&&typeof t==="object"&&!Array.isArray(t)):[]}function Le(e){let t=e.updatedAt;return typeof t==="number"?t:Date.parse(String(t??""))||0}function De(e){let t=e?.metadata&&typeof e.metadata==="object"?e.metadata:void 0;return String(t?.model??e?.model??"").trim()}function de(e){let t=e.metadata&&typeof e.metadata==="object"?e.metadata:void 0;return!String(t?.parentSessionId??e.parentSessionId??"").trim()}function Kt(e,t="text"){if(!e||typeof e!=="object"||Array.isArray(e))return"";let n=e.content;if(typeof n==="string")return t==="text"?n.trim():"";if(!Array.isArray(n))return"";return n.map((s)=>s&&typeof s==="object"&&!Array.isArray(s)?t==="thinking"&&s.type==="redacted_thinking"?"[redacted]":String(s[t]??""):"").join("").trim()}function ie(e){let t=e.trim(),n=t.match(/^<user_input\b[^>]*>([\s\S]*)<\/user_input>$/);return(n?n[1]:t).trim()}function G(e,t,n){let s=ie(n);return e.filter((o)=>Boolean(o)&&typeof o==="object"&&!Array.isArray(o)&&String(o.role??"").toLowerCase()==="user"&&(s!==""||zt(o))&&ie(Kt(o))===s).length+t.filter((o)=>ie(o.prompt)===s).length}function Be(e){return e.flatMap((t)=>{if(t.event!=="session.pending_prompt_submitted")return[];let n=t.payload?.prompt&&typeof t.payload.prompt==="object"&&!Array.isArray(t.payload.prompt)?t.payload.prompt:void 0,s=String(n?.id??"").trim();if(!s)return[];return[{id:s,prompt:String(n?.prompt??""),steer:n?.delivery==="steer",attachmentCount:typeof n?.attachmentCount==="number"?n.attachmentCount:0,userImages:Array.isArray(n?.userImages)?n.userImages.filter((o)=>typeof o==="string"):void 0}]})}var po=new Set(["run.completed","run.aborted","run.failed"]),fo=new Set(["assistant.delta","assistant.finished","reasoning.delta","reasoning.finished"]);function Vt(e,t){return e.filter((n)=>Boolean(n)&&typeof n==="object"&&!Array.isArray(n)&&String(n.role??"").toLowerCase()==="assistant").map((n)=>Kt(n,t)).filter(Boolean)}function Gt(e,t,n="text"){let s=new Map;for(let o of Vt(t,n))s.set(o,(s.get(o)??0)+1);return Vt(e,n).filter((o)=>{let i=s.get(o)??0;if(i===0)return!0;if(i===1)s.delete(o);else s.set(o,i-1);return!1})}function re(e,t,n=new Set){if(!e||typeof e!=="object")return n;if(Array.isArray(e)){for(let i of e)re(i,t,n);return n}let s=e,o=t==="tool_use"?s.id:s.tool_use_id;if(s.type===t&&typeof o==="string")n.add(o);for(let i of Object.values(s))re(i,t,n);return n}function Jt(e,t="assistant"){let n="",s="";for(let o of e)if(o.event===`${t}.delta`)s+=t==="reasoning"&&o.payload?.redacted&&!o.payload?.text?"[redacted]":typeof o.payload?.text==="string"?o.payload.text:"";else if(o.event===`${t}.finished`){let i=o.payload?.[t==="assistant"?"text":"reasoning"],r=typeof i==="string"&&i?i:s;if(r)n=r;s=""}return(n||s).trim()}function Qt(e,t,n={}){let s=n.queueSnapshotApplied!==!1,o=Gt(t,n.baselineMessages??[]),i=Gt(t,n.baselineMessages??[],"thinking"),r=re(t,"tool_use"),a=re(t,"tool_result"),d=new Set(e.slice(0,n.messagesSnapshotEventCutoff??e.length)),u=new Set,f=new Map;for(let y of e.slice(0,n.messagesSnapshotEventCutoff??e.length)){let w=Be([y])[0];if(!w)continue;let v=ie(w.prompt),P=f.get(v)??Math.max(0,G(t,[],v)-G(n.baselineMessages??[],[],v));if(f.set(v,Math.max(0,P-1)),P>0)u.add(y)}let h=[...s?e.slice(n.queueSnapshotEventCutoff??e.length):e].reverse().find((y)=>y.event==="session.pending_prompts"),p=[],l=[],m=(y)=>{if(l.length===0)return;let w=l.filter((A)=>d.has(A)),v=(A)=>{if(!y)return-1;let S=[...w].reverse().findIndex((nn)=>nn.event===`${A}.finished`),D=S<0?-1:w.length-1-S;return D>=0||l.at(-1)?.event==="run.aborted"?D:w.length-1},P=v("assistant"),H=v("reasoning"),b=Jt(w.slice(0,P+1)),R=b?o.findIndex((A)=>A.endsWith(b)):-1,M=R>=0;if(M)o.splice(R,1);let J=Jt(w.slice(0,H+1),"reasoning"),pe=J?i.findIndex((A)=>A.endsWith(J)):-1;if(pe>=0)i.splice(pe,1);for(let[A,S]of l.entries()){if(u.has(S)){p.push({...S,payload:{...S.payload,transcriptReflected:!0}});continue}if(d.has(S)&&fo.has(S.event)&&(S.event.startsWith("reasoning.")?pe>=0&&A<=H:M&&A<=P))continue;if(S.event==="session.pending_prompts"&&S!==h)continue;if(d.has(S)&&S.event.startsWith("tool.")){let D=String(S.payload?.toolCallId??"").trim();if(a.has(D)||S.event==="tool.started"&&r.has(D))continue}p.push(S)}l=[]};for(let y of e)if(l.push(y),po.has(y.event))m(!0);return m(!1),p}import{formatDisplayUserInput as ho}from"@cerebriline/shared";function ce(e){let t=structuredClone(e),n=(s)=>{if(!s||typeof s!=="object"||Object.isFrozen(s))return;for(let o of Object.values(s))n(o);Object.freeze(s)};return n(t),t}function ue(e){let t=e?.trim();return t?ho(t).slice(0,120):void 0}function qe(e){if(typeof e==="string")return e;if(Array.isArray(e)){let t=[];for(let n of e){if(typeof n==="string"){if(n.trim())t.push(n);continue}if(!n||typeof n!=="object")continue;let s=n,o=typeof s.type==="string"?s.type:"",i=o==="text"?String(s.text??""):o==="thinking"?String(s.thinking??""):o==="tool_use"?`[tool] ${String(s.name??"tool_call")}`:o==="tool_result"?`[tool_result]
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Three tools that cross between text and sound.
|
|
3
3
|
*
|
|
4
|
-
* `transcribe_audio` turns a recording in the workspace into text,
|
|
5
|
-
* `synthesize_speech` turns text into an audio file there
|
|
6
|
-
*
|
|
4
|
+
* `transcribe_audio` turns a recording in the workspace into text,
|
|
5
|
+
* `synthesize_speech` turns text into an audio file there, and
|
|
6
|
+
* `generate_sound_effect` turns a description into one. A meeting recording
|
|
7
|
+
* that has to become notes, a voice-over for a demo, a click for a button:
|
|
7
8
|
* each one used to leave the session, like an image did before
|
|
8
9
|
* `generate_image`.
|
|
9
10
|
*
|
|
@@ -11,7 +12,9 @@
|
|
|
11
12
|
* transcriptions` (multipart) and `POST {endpoint}/audio/speech` (JSON, bytes
|
|
12
13
|
* back) -- which opencoti and xOllama serve beside chat and which the hosted
|
|
13
14
|
* services serve too. The two are separate endpoints because they are often
|
|
14
|
-
* separate servers: a Whisper box and a TTS box.
|
|
15
|
+
* separate servers: a Whisper box and a TTS box. Sound effects have no OpenAI
|
|
16
|
+
* route: `POST {endpoint}/audio/generations` is opencoti's, and xOllama's after
|
|
17
|
+
* it.
|
|
15
18
|
*
|
|
16
19
|
* Audio is never re-encoded here. What the engine returns is what is written,
|
|
17
20
|
* and the file is named from what came back: opencoti b97 answers WAV whatever
|
|
@@ -21,6 +24,7 @@ import { type AgentTool } from "@cerebriline/shared";
|
|
|
21
24
|
import { type MediaServer } from "./media-endpoint";
|
|
22
25
|
export declare const TRANSCRIBE_AUDIO_TOOL_NAME = "transcribe_audio";
|
|
23
26
|
export declare const SYNTHESIZE_SPEECH_TOOL_NAME = "synthesize_speech";
|
|
27
|
+
export declare const GENERATE_SOUND_EFFECT_TOOL_NAME = "generate_sound_effect";
|
|
24
28
|
export declare const TRANSCRIBE_AUDIO_TOOL_DESCRIPTION = "Transcribe an audio file in the workspace to text. Use it to read a recording you would otherwise have to ask the user to describe: a meeting, a voice note, the audio of a demo.\n\nArguments:\n- `path` \u2014 the audio file, relative to the workspace (wav, mp3, flac, ogg, m4a, webm).\n- `format` \u2014 `text` (the default), `srt` or `vtt` for subtitles with timestamps, or `verbose_json` for segments with start and end times.\n- `language` \u2014 the spoken language as a two-letter code, e.g. `en`. Optional; the model detects it when omitted.\n- `translate` \u2014 true to get the text in English whatever language is spoken. Optional.\n- `prompt` \u2014 names and terms the recording uses, to help spelling. Optional.\n- `output` \u2014 a workspace path to write the transcript to. Optional. Give one for a long recording or for subtitles: the transcript is saved there and only its beginning is returned to you.\n\nOutput: the transcript as plain text. Without `output`, a very long transcript is cut and the cut is stated. A long recording takes minutes.";
|
|
25
29
|
export declare const TRANSCRIBE_AUDIO_TOOL_INPUT_SCHEMA: {
|
|
26
30
|
readonly type: "object";
|
|
@@ -54,6 +58,38 @@ export declare const TRANSCRIBE_AUDIO_TOOL_INPUT_SCHEMA: {
|
|
|
54
58
|
readonly required: readonly ["path"];
|
|
55
59
|
};
|
|
56
60
|
export declare const SYNTHESIZE_SPEECH_TOOL_DESCRIPTION = "Turn text into spoken audio and save it as a file in the workspace. Use it for a voice-over, a spoken prompt, or an audio version of something you wrote.\n\nArguments:\n- `text` \u2014 what to say. Write it as it should be spoken: spell out abbreviations and numbers that must be read a particular way.\n- `path` \u2014 where to save it, relative to the workspace. Optional; defaults to a file under `.cline/generated-audio/`. The extension is corrected to match the audio the backend returns.\n- `voice` \u2014 the voice to use. Optional; the configured default is used when omitted. Backends name their own voices, and most accept the OpenAI names (alloy, echo, fable, onyx, nova, shimmer).\n- `speed` \u2014 speaking rate, 1 is normal, e.g. 1.25. Optional.\n- `format` \u2014 `wav`, `mp3`, `flac`, `opus` or `pcm`. Optional, and a backend that cannot encode it returns what it can; the reply says which.\n\nOutput: the saved path, the audio format and its length. You do not hear the result, so say what you asked for when reporting it. A long text takes a while.";
|
|
61
|
+
export declare const GENERATE_SOUND_EFFECT_TOOL_DESCRIPTION = "Generate a short sound effect from a description and save it as a file in the workspace. Use it for the sound of a button, a notification, a game event or an ambience. It makes sounds, not speech: use `synthesize_speech` for words.\n\nArguments:\n- `prompt` \u2014 the sound, described plainly, e.g. \"a short wooden click\". Say what makes it and how it ends.\n- `negative_prompt` \u2014 what the sound must not have, e.g. \"reverb, music\". Optional.\n- `seconds` \u2014 how long the clip is. Optional; 4 by default, and the model sets the most it allows. A UI sound is usually under 1 second.\n- `seed` \u2014 repeats an earlier clip on the same machine. Optional; the result reports the seed that was used.\n- `path` \u2014 where to save it, relative to the workspace. Optional; defaults to a file under `.cline/generated-audio/`.\n- `format` \u2014 `wav` (the default), `mp3` or `pcm`. Optional, and a backend that cannot encode it returns what it can.\n\nOutput: the saved path, the audio format, its length and the seed. You do not hear the result, so say what you asked for and let the user listen. The first clip also loads the model and can take minutes.";
|
|
62
|
+
export declare const GENERATE_SOUND_EFFECT_TOOL_INPUT_SCHEMA: {
|
|
63
|
+
readonly type: "object";
|
|
64
|
+
readonly properties: {
|
|
65
|
+
readonly prompt: {
|
|
66
|
+
readonly type: "string";
|
|
67
|
+
readonly description: "The sound, described plainly.";
|
|
68
|
+
};
|
|
69
|
+
readonly negative_prompt: {
|
|
70
|
+
readonly type: "string";
|
|
71
|
+
readonly description: "What the sound must not have. Optional.";
|
|
72
|
+
};
|
|
73
|
+
readonly seconds: {
|
|
74
|
+
readonly type: "number";
|
|
75
|
+
readonly description: "How long the clip is. Optional.";
|
|
76
|
+
};
|
|
77
|
+
readonly seed: {
|
|
78
|
+
readonly type: "integer";
|
|
79
|
+
readonly description: "Repeats an earlier clip on the same machine. Optional.";
|
|
80
|
+
};
|
|
81
|
+
readonly path: {
|
|
82
|
+
readonly type: "string";
|
|
83
|
+
readonly description: "Where to save it, relative to the workspace. Optional; defaults to a file under .cline/generated-audio/.";
|
|
84
|
+
};
|
|
85
|
+
readonly format: {
|
|
86
|
+
readonly type: "string";
|
|
87
|
+
readonly enum: readonly ["wav", "mp3", "pcm"];
|
|
88
|
+
readonly description: "The audio format to ask for; wav by default. Optional.";
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
readonly required: readonly ["prompt"];
|
|
92
|
+
};
|
|
57
93
|
export declare const SYNTHESIZE_SPEECH_TOOL_INPUT_SCHEMA: {
|
|
58
94
|
readonly type: "object";
|
|
59
95
|
readonly properties: {
|
|
@@ -93,6 +129,10 @@ export interface SpeechEndpoint extends TranscriptionEndpoint {
|
|
|
93
129
|
/** Default for calls that name no format. */
|
|
94
130
|
format?: string;
|
|
95
131
|
}
|
|
132
|
+
export interface SoundEffectEndpoint extends TranscriptionEndpoint {
|
|
133
|
+
/** Default for calls that name no format. */
|
|
134
|
+
format?: string;
|
|
135
|
+
}
|
|
96
136
|
type MaybePromise<T> = T | Promise<T>;
|
|
97
137
|
interface AudioToolBase {
|
|
98
138
|
cwd: string;
|
|
@@ -103,7 +143,7 @@ export interface TranscribeAudioToolOptions extends AudioToolBase {
|
|
|
103
143
|
getEndpoint: () => MaybePromise<TranscriptionEndpoint | undefined>;
|
|
104
144
|
readFile: (absolutePath: string) => Promise<Buffer>;
|
|
105
145
|
writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
|
|
106
|
-
/** Milliseconds one transcription may take. Defaults to
|
|
146
|
+
/** Milliseconds one transcription may take. Defaults to 25 minutes. */
|
|
107
147
|
timeoutMs?: number;
|
|
108
148
|
/** Characters of transcript returned to the model. Defaults to 24,000. */
|
|
109
149
|
maxReturnedChars?: number;
|
|
@@ -111,7 +151,13 @@ export interface TranscribeAudioToolOptions extends AudioToolBase {
|
|
|
111
151
|
export interface SynthesizeSpeechToolOptions extends AudioToolBase {
|
|
112
152
|
getEndpoint: () => MaybePromise<SpeechEndpoint | undefined>;
|
|
113
153
|
writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
|
|
114
|
-
/** Milliseconds one synthesis may take. Defaults to
|
|
154
|
+
/** Milliseconds one synthesis may take. Defaults to 15 minutes. */
|
|
155
|
+
timeoutMs?: number;
|
|
156
|
+
}
|
|
157
|
+
export interface GenerateSoundEffectToolOptions extends AudioToolBase {
|
|
158
|
+
getEndpoint: () => MaybePromise<SoundEffectEndpoint | undefined>;
|
|
159
|
+
writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
|
|
160
|
+
/** Milliseconds one clip may take. Defaults to 15 minutes. */
|
|
115
161
|
timeoutMs?: number;
|
|
116
162
|
}
|
|
117
163
|
/**
|
|
@@ -129,6 +175,7 @@ export declare function wavSeconds(data: Buffer): number | undefined;
|
|
|
129
175
|
export declare function defaultSpeechPath(text: string, now: number): string;
|
|
130
176
|
export declare function createTranscribeAudioTool(options: TranscribeAudioToolOptions): AgentTool;
|
|
131
177
|
export declare function createSynthesizeSpeechTool(options: SynthesizeSpeechToolOptions): AgentTool;
|
|
178
|
+
export declare function createGenerateSoundEffectTool(options: GenerateSoundEffectToolOptions): AgentTool;
|
|
132
179
|
/** What a speech engine says it can do, for a settings picker. */
|
|
133
180
|
export interface SpeechVoices {
|
|
134
181
|
/** The engine's own voices first, then the OpenAI names it also answers to. */
|
|
@@ -61,7 +61,7 @@ export interface EditImageToolOptions {
|
|
|
61
61
|
readFile: (absolutePath: string) => Promise<Buffer>;
|
|
62
62
|
writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
|
|
63
63
|
fetchImpl?: typeof fetch;
|
|
64
|
-
/** Milliseconds one edit may take. Defaults to
|
|
64
|
+
/** Milliseconds one edit may take. Defaults to 13 minutes. */
|
|
65
65
|
timeoutMs?: number;
|
|
66
66
|
onError?: (message: string, error: unknown) => void;
|
|
67
67
|
}
|
|
@@ -97,7 +97,7 @@ export interface GenerateImageToolOptions {
|
|
|
97
97
|
getEndpoint: () => ImageGenerationEndpoint | undefined | Promise<ImageGenerationEndpoint | undefined>;
|
|
98
98
|
writeFile: (absolutePath: string, data: Buffer) => Promise<void>;
|
|
99
99
|
fetchImpl?: typeof fetch;
|
|
100
|
-
/** Milliseconds before a generation is abandoned. Defaults to
|
|
100
|
+
/** Milliseconds before a generation is abandoned. Defaults to 13 minutes. */
|
|
101
101
|
timeoutMs?: number;
|
|
102
102
|
onError?: (message: string, error: unknown) => void;
|
|
103
103
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Three kinds of server answer these routes, and they say different amounts:
|
|
10
10
|
* - **opencoti** names what is loaded in `features` on `/props`
|
|
11
11
|
* (`images_generate_v1`, `images_edit_v1`, `audio_transcriptions_v1`,
|
|
12
|
-
* `audio_speech_v1`, `videos_generate_v1`), and its `/v1/models` rows carry
|
|
12
|
+
* `audio_speech_v1`, `videos_generate_v1`, `audio_generations_v1`), and its `/v1/models` rows carry
|
|
13
13
|
* `capabilities`. One process can serve the LLM and every media kind.
|
|
14
14
|
* - **xOllama** answers `/api/xollama`, and its `/v1/models` rows carry
|
|
15
15
|
* `input_modalities` / `output_modalities` for models with media.
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* audio/speech`, so the whole route gets pasted. Nothing is lost by taking it
|
|
34
34
|
* back off: a route under a route is never what anyone meant.
|
|
35
35
|
*/
|
|
36
|
-
export type MediaKind = "image_generation" | "image_edit" | "transcription" | "speech" | "video";
|
|
36
|
+
export type MediaKind = "image_generation" | "image_edit" | "transcription" | "speech" | "video" | "sound_effects";
|
|
37
37
|
export declare const MEDIA_KINDS: readonly MediaKind[];
|
|
38
38
|
export type MediaServer = "opencoti" | "xollama" | "openai";
|
|
39
39
|
export interface MediaEndpoint {
|
|
@@ -79,7 +79,8 @@ export declare function mediaServerOrigin(baseUrl: string): string;
|
|
|
79
79
|
*
|
|
80
80
|
* Capabilities are exact and win. Modalities are xOllama's listing and need
|
|
81
81
|
* reading: an edit model takes an image and returns one, a transcription model
|
|
82
|
-
* takes audio and returns text.
|
|
82
|
+
* takes audio and returns text. Sound effects are never read from them: speech
|
|
83
|
+
* returns audio too, and only the capability tells the two apart.
|
|
83
84
|
*/
|
|
84
85
|
export declare function mediaKindsOfModelRow(row: unknown): MediaKind[] | undefined;
|
|
85
86
|
export interface MediaProbeOptions {
|
|
@@ -137,13 +138,21 @@ export type ResolvedMediaEndpoint = {
|
|
|
137
138
|
export declare function resolveMediaEndpoint(input: ResolveMediaEndpointInput): Promise<ResolvedMediaEndpoint>;
|
|
138
139
|
/** `Retry-After` in milliseconds: seconds or a date, bounded, 5 s by default. */
|
|
139
140
|
export declare function retryAfterMs(header: string | null, now?: number): number;
|
|
141
|
+
/**
|
|
142
|
+
* How long xOllama may hold a request before it starts or answers `503`: its
|
|
143
|
+
* `mediaQueueWait`. The wait happens inside one attempt, so a tool's limit is
|
|
144
|
+
* this plus the time the work itself may take. Without it a queued request is
|
|
145
|
+
* abandoned, and reported as stopped, before the server has answered at all.
|
|
146
|
+
*/
|
|
147
|
+
export declare const MEDIA_QUEUE_WAIT_MS: number;
|
|
140
148
|
export interface MediaRequestOptions {
|
|
141
149
|
fetchImpl?: typeof fetch;
|
|
142
150
|
/** The caller's cancellation. The only thing that ends the waiting. */
|
|
143
151
|
signal?: AbortSignal;
|
|
144
152
|
/**
|
|
145
|
-
* Milliseconds one attempt may take. Waiting on a busy
|
|
146
|
-
*
|
|
153
|
+
* Milliseconds one attempt may take. Waiting between attempts on a busy
|
|
154
|
+
* engine is not counted, but a server's own queue is: see
|
|
155
|
+
* `MEDIA_QUEUE_WAIT_MS`.
|
|
147
156
|
*/
|
|
148
157
|
attemptTimeoutMs?: number;
|
|
149
158
|
/**
|