@promptctl/cc-candybar 1.7.0 → 1.7.1
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/dist/index.mjs +2 -2
- package/package.json +5 -5
- package/src/utils/terminal-width.ts +13 -5
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import e from"node:process";import{json as t}from"node:stream/consumers";import n,{createReadStream as r,existsSync as i,watch as a}from"node:fs";import o,{basename as s,dirname as c,join as l}from"node:path";import u,{homedir as d}from"node:os";import{spawn as f,spawnSync as p}from"node:child_process";import m from"node:net";import{URL as h,URLSearchParams as g,fileURLToPath as _}from"node:url";import{parseArgs as v}from"node:util";import{get as y}from"node:https";import{createHash as b}from"node:crypto";import{setTimeout as x}from"node:timers/promises";import{open as S,readFile as C,readdir as ee,stat as te}from"node:fs/promises";import{createInterface as w}from"node:readline";import{clearInterval as ne,setInterval as re}from"node:timers";import ie from"node:v8";var T=Object.create,E=Object.defineProperty,ae=Object.getOwnPropertyDescriptor,oe=Object.getOwnPropertyNames,se=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty,D=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),le=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=oe(t),a=0,o=i.length,s;a<o;a++)s=i[a],!ce.call(e,s)&&s!==n&&E(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=ae(t,s))||r.enumerable});return e},ue=(e,t,n)=>(n=e==null?{}:T(se(e)),le(t||!e||!e.__esModule?E(n,`default`,{value:e,enumerable:!0}):n,e));function O(e,...t){process.env.CC_CANDYBAR_DEBUG&&console.error(`[DEBUG] ${e}`,...t)}const de={"click.pbcopy":1e3,"click.open":1e3},fe=new Map;function pe(e){let t=de[e];if(t===void 0)return{allowed:!0};let n=fe.get(e);if(n===void 0)return{allowed:!0};let r=Date.now()-n;return r>=t?{allowed:!0}:{allowed:!1,minIntervalMs:t,sinceLastMs:r}}function me(e){fe.set(e,Date.now())}function he(e,t,n){return{ok:!1,reason:`rate-limited`,stdout:``,stderr:``,exitCode:null,signal:null,error:`rate-limited: ${e} min interval ${t}ms, last start ${n}ms ago`}}let ge=null;function k(e){ge=e}async function _e(e){let t=pe(e.category);if(!t.allowed)return he(e.category,t.minIntervalMs,t.sinceLastMs);me(e.category);let n=Date.now();return ge?.onStart(e.category),new Promise(t=>{let r;try{r=f(e.bin,e.args??[],{cwd:e.cwd,env:e.env,stdio:[`pipe`,`pipe`,`pipe`]})}catch(r){ge?.onEnd(e.category,Date.now()-n),t({ok:!1,reason:`spawn-error`,stdout:``,stderr:``,exitCode:null,signal:null,error:r instanceof Error?r.message:String(r)});return}let i=``,a=``,o=!1,s=null,c=null,l=!1,u=r=>{o||(o=!0,s&&clearTimeout(s),c&&clearTimeout(c),ge?.onEnd(e.category,Date.now()-n),t(r))};r.stdout?.on(`data`,e=>{i+=e.toString(`utf8`)}),r.stderr?.on(`data`,e=>{a+=e.toString(`utf8`)}),r.on(`error`,e=>{u({ok:!1,reason:`spawn-error`,stdout:i,stderr:a,exitCode:null,signal:null,error:e.message})}),r.on(`close`,(e,t)=>{if(l){u({ok:!1,reason:`timeout`,stdout:i,stderr:a,exitCode:e,signal:t});return}if(e===0){u({ok:!0,stdout:i,stderr:a,exitCode:e});return}u({ok:!1,reason:t?`signal`:`non-zero`,stdout:i,stderr:a,exitCode:e,signal:t})}),e.timeoutMs&&e.timeoutMs>0&&(s=setTimeout(()=>{l=!0,r.pid!==void 0&&(r.kill(`SIGTERM`),c=setTimeout(()=>{r.kill(`SIGKILL`)},250))},e.timeoutMs)),e.stdinInput!==void 0&&r.stdin?r.stdin.end(e.stdinInput):r.stdin&&r.stdin.end()})}function ve(e){let t=pe(e.category);if(!t.allowed)return he(e.category,t.minIntervalMs,t.sinceLastMs);me(e.category);let n=Date.now();ge?.onStart(e.category);let r=[`pipe`,`pipe`,`pipe`];try{let t=p(e.bin,e.args??[],{cwd:e.cwd,env:e.env,input:e.stdinInput,timeout:e.timeoutMs&&e.timeoutMs>0?e.timeoutMs:void 0,stdio:r,encoding:`utf8`});ge?.onEnd(e.category,Date.now()-n);let i=typeof t.stdout==`string`?t.stdout:``,a=typeof t.stderr==`string`?t.stderr:``;if(t.error)return{ok:!1,reason:t.error.code===`ETIMEDOUT`?`timeout`:`spawn-error`,stdout:i,stderr:a,exitCode:null,signal:t.signal??null,error:t.error.message};if(t.status===0)return{ok:!0,stdout:i,stderr:a,exitCode:t.status};let o=e.timeoutMs!==void 0&&e.timeoutMs>0;return{ok:!1,reason:t.signal?o&&t.signal===`SIGTERM`?`timeout`:`signal`:`non-zero`,stdout:i,stderr:a,exitCode:t.status,signal:t.signal??null}}catch(t){return ge?.onEnd(e.category,Date.now()-n),{ok:!1,reason:`spawn-error`,stdout:``,stderr:``,exitCode:null,signal:null,error:t instanceof Error?t.message:String(t)}}}function ye(e){let t=pe(e.category);if(!t.allowed)return he(e.category,t.minIntervalMs,t.sinceLastMs);me(e.category);let n=Date.now();ge?.onStart(e.category);let r=be(e);return ge?.onEnd(e.category,Date.now()-n),r}function be(e){let t;try{t=f(e.bin,e.args??[],{cwd:e.cwd,env:e.env,detached:!0,stdio:`ignore`})}catch(e){return{ok:!1,reason:`spawn-error`,stdout:``,stderr:``,exitCode:null,signal:null,error:e instanceof Error?e.message:String(e)}}return t.once(`error`,()=>{}),t.pid===void 0?{ok:!1,reason:`spawn-error`,stdout:``,stderr:``,exitCode:null,signal:null,error:`spawn(${e.bin}): no pid (binary not found or unexecutable)`}:(t.unref(),{ok:!0,stdout:``,stderr:``,exitCode:null})}function xe(e){let t=process.env[e];return t&&t.length>0?t:void 0}function Se(){let e=xe(`XDG_STATE_HOME`)??o.join(u.homedir(),`.local`,`state`);return o.join(e,`cc-candybar`)}function Ce(){let e=xe(`XDG_CACHE_HOME`)??o.join(u.homedir(),`.cache`);return o.join(e,`cc-candybar`)}function we(){return Se()}function Te(){let e=process.env.CC_CANDYBAR_SOCKET;if(e)return e;let t=u.userInfo().uid;return o.join(`/tmp`,`cc-candybar-${t}`,`socket`)}function Ee(e){let t=o.dirname(e);n.mkdirSync(t,{recursive:!0,mode:448});let r=n.lstatSync(t);if(r.isSymbolicLink())throw Error(`socket parent is a symlink: ${t}`);if(!r.isDirectory())throw Error(`socket parent is not a directory: ${t}`);let i=u.userInfo().uid;if(typeof i==`number`&&r.uid!==i)throw Error(`socket parent is not owned by uid ${i}: ${t} (owner uid=${r.uid})`);if(r.mode&63)throw Error(`socket parent has unsafe permissions: ${t} (mode=${(r.mode&511).toString(8)}, expected 0700)`);try{if(n.lstatSync(e).isSymbolicLink())throw Error(`socket path is a symlink: ${e}`)}catch(e){if(e.code!==`ENOENT`)throw e}}function De(){return o.join(Se(),`pid`)}function Oe(){return o.join(Se(),`session-state.json`)}function ke(){return o.join(Se(),`spawn.lock`)}function A(){return o.join(Se(),`daemon.log`)}const Ae=1e4;function je(e){if(typeof e!=`number`||!Number.isFinite(e))return;let t=Math.floor(e);if(!(t<=0))return t>Ae?Ae:t}var Me=class extends Error{constructor(e){super(e),this.name=`ProtocolError`}};function Ne(e){let t=Buffer.from(JSON.stringify(e),`utf8`),n=Buffer.alloc(4);return n.writeUInt32BE(t.length,0),Buffer.concat([n,t])}function Pe(e,t){let n=Buffer.alloc(0);return function(r){for(n=Buffer.concat([n,r]);n.length>=4;){let r=n.readUInt32BE(0);if(r>16777216){t(new Me(`frame too large: ${r}`));return}if(n.length<4+r)return;let i=n.subarray(4,4+r);n=n.subarray(4+r);try{e(JSON.parse(i.toString(`utf8`)))}catch(e){let n=new Me(e instanceof Error?e.message:String(e));e instanceof Error&&(n.cause=e),t(n);return}}}}function Fe(e,t,n){return new Promise((r,i)=>{let a=!1,o=t=>{if(!a){a=!0,clearTimeout(s),e.removeAllListeners();try{t()}catch{}}},s=setTimeout(()=>{o(()=>{e.destroy(),i(Error(`TIMEOUT`))})},n),c=Pe(e=>o(()=>r(e)),e=>o(()=>i(e)));e.on(`data`,c),e.on(`error`,e=>o(()=>i(e))),e.on(`close`,()=>o(()=>i(Error(`socket closed before response`)))),e.write(Ne(t))})}async function Ie(e,t,n){let r=null;try{r=await Ve(Te(),t.connectMs);let i=await Fe(r,{v:3,...e},t.budgetMs);return ze(e.kind,i,n)}catch(e){return Be(e)}finally{r&&r.destroy()}}function Le(e,t){return typeof e==`string`?e:t}function Re(e){return typeof e==`number`&&Number.isInteger(e)&&e>=0?e:0}function ze(e,t,n){let r=t;if(r.ok===!0){let r=n(t);return r===void 0?{kind:`permanent`,cause:`malformed_response`,message:`ok response without payload for "${e}" request`}:{kind:`ok`,value:r}}let i=Le(r.error,`(no error message)`);switch(r.code){case`VERSION_MISMATCH`:return{kind:`permanent`,cause:`version_mismatch`,clientV:3,daemonV:Re(r.daemonV)};case`TIMEOUT`:return{kind:`transient`,cause:`timeout`,message:i};case`BAD_REQUEST`:return{kind:`permanent`,cause:`bad_request`,message:i};case`RENDER_FAILED`:return{kind:`permanent`,cause:`render_failed`,message:i};default:return{kind:`permanent`,cause:`malformed_response`,message:`unknown error code: ${String(r.code)}`}}}function Be(e){if(e instanceof Me||e instanceof SyntaxError)return{kind:`permanent`,cause:`malformed_response`,message:e instanceof Error?e.message:String(e)};let t=e instanceof Error?e.message:String(e);return t===`CONNECT_TIMEOUT`||t===`TIMEOUT`?{kind:`transient`,cause:`timeout`,message:t}:t.includes(`ECONNREFUSED`)||t.includes(`ENOENT`)||t.includes(`ENOTSOCK`)?{kind:`transient`,cause:`unreachable`,message:t}:{kind:`transient`,cause:`io_error`,message:t}}function Ve(e,t){return new Promise((n,r)=>{let i=m.createConnection({path:e}),a=setTimeout(()=>{i.destroy(),r(Error(`CONNECT_TIMEOUT`))},t);i.once(`connect`,()=>{clearTimeout(a),n(i)}),i.once(`error`,e=>{clearTimeout(a),r(e)})})}function He(e){if(e.kind===`transient`)return`daemon unavailable (${e.cause}: ${e.message})\nHint: daemon may not be running. Run \`cc-candybar\` once to spawn it.`;switch(e.cause){case`version_mismatch`:{let t=e.daemonV===0?`unknown`:`v${e.daemonV}`;return`daemon protocol mismatch (client v${e.clientV} ≠ daemon ${t})`}case`bad_request`:case`render_failed`:case`malformed_response`:return`daemon error (${e.cause}): ${e.message}`}}const Ue={connectMs:50,budgetMs:150},We={connectMs:50,budgetMs:200};function Ge(e){let t=e.output;return typeof t==`string`?t:void 0}function Ke(e,t,n,r){return Ie({kind:`render`,hookData:e,args:t,cwd:n,termCols:r},Ue,Ge)}function qe(e,t){return Ie({kind:`click`,verb:e,value:t},We,Ge)}function Je(t={}){if(tt()!==null)return;let n=t.spawn??nt,r=Qe();if(r.kind===`contended`){let t=Ye();t!==null&&t>2e3&&(e.stderr.write(`cc-candybar: spawn-lock held ${t}ms (likely crashed holder) — spawning unlocked\n`),Xe(n));return}if(r.kind===`error`){e.stderr.write(`cc-candybar: spawn-lock unavailable (${r.reason}) — spawning unlocked\n`),Xe(n);return}try{Xe(n)}finally{et()}}function Ye(){try{let e=n.statSync(ke());return Date.now()-e.mtimeMs}catch{return null}}function Xe(t){try{t()||e.stderr.write(`cc-candybar: daemon spawn returned false (unable to resolve script path?)
|
|
3
|
-
`)}catch(t){e.stderr.write(`cc-candybar: daemon spawn failed: ${t.message}\n`)}}let Ze=null;function Qe(){let t=ke();for(let r=0;r<2;r++){try{let r=n.openSync(t,`wx`,384);try{n.writeSync(r,JSON.stringify({pid:e.pid,ts:Date.now()}))}catch{}return Ze={fd:r,path:t},{kind:`held`}}catch(e){let n=e.code;if(n!==`EEXIST`)return{kind:`error`,reason:`openSync(${t}): ${n??e.message}`}}if(!$e(t))return{kind:`contended`};try{n.unlinkSync(t)}catch(e){if(e.code!==`ENOENT`)return{kind:`error`,reason:`unlink stale spawn.lock: ${e.message}`}}}return{kind:`contended`}}function $e(e){try{let t=n.statSync(e);return Date.now()-t.mtimeMs>1e4}catch{return!0}}function et(){if(!Ze)return;let{fd:e,path:t}=Ze;Ze=null;try{n.closeSync(e)}catch{}try{n.unlinkSync(t)}catch{}}function tt(){try{return n.mkdirSync(we(),{recursive:!0}),null}catch(e){return`mkdir ${we()}: ${e.message}`}}function nt(){let t=e.execPath,n=e.argv[1];return n?ye({bin:t,args:[`--max-old-space-size=400`,n,`daemon`],category:`daemon-spawn`}).ok:!1}const rt=`cc-candybar`,it=`dispatch`,at=`set-state`,ot=`step-state`,st=`copy`,ct=`open-vscode`,lt=`show-config-error`,ut=`show-config-warning`;function dt(e){return e.map(encodeURIComponent).join(`/`)}function ft(e){return e.length===0?[]:e.split(`/`).map(decodeURIComponent)}function pt(e){return`${rt}://${it}/${e.map(e=>`e=${encodeURIComponent(`${e.verb}/${dt(e.args)}`)}`).join(`&`)}`}function mt(e){return new g(e).getAll(`e`).map(ht)}function ht(e){let t=e.indexOf(`/`);return t===-1?{verb:e,value:``}:{verb:e.slice(0,t),value:e.slice(t+1)}}const gt=`@promptctl/cc-candybar`,_t=`CCCandybarURLHandler`,vt=[];function yt(e){return/^[A-Za-z0-9_./=,:-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function bt(e){return[`pnpm`,`dlx`,`${gt}@1.7.
|
|
3
|
+
`)}catch(t){e.stderr.write(`cc-candybar: daemon spawn failed: ${t.message}\n`)}}let Ze=null;function Qe(){let t=ke();for(let r=0;r<2;r++){try{let r=n.openSync(t,`wx`,384);try{n.writeSync(r,JSON.stringify({pid:e.pid,ts:Date.now()}))}catch{}return Ze={fd:r,path:t},{kind:`held`}}catch(e){let n=e.code;if(n!==`EEXIST`)return{kind:`error`,reason:`openSync(${t}): ${n??e.message}`}}if(!$e(t))return{kind:`contended`};try{n.unlinkSync(t)}catch(e){if(e.code!==`ENOENT`)return{kind:`error`,reason:`unlink stale spawn.lock: ${e.message}`}}}return{kind:`contended`}}function $e(e){try{let t=n.statSync(e);return Date.now()-t.mtimeMs>1e4}catch{return!0}}function et(){if(!Ze)return;let{fd:e,path:t}=Ze;Ze=null;try{n.closeSync(e)}catch{}try{n.unlinkSync(t)}catch{}}function tt(){try{return n.mkdirSync(we(),{recursive:!0}),null}catch(e){return`mkdir ${we()}: ${e.message}`}}function nt(){let t=e.execPath,n=e.argv[1];return n?ye({bin:t,args:[`--max-old-space-size=400`,n,`daemon`],category:`daemon-spawn`}).ok:!1}const rt=`cc-candybar`,it=`dispatch`,at=`set-state`,ot=`step-state`,st=`copy`,ct=`open-vscode`,lt=`show-config-error`,ut=`show-config-warning`;function dt(e){return e.map(encodeURIComponent).join(`/`)}function ft(e){return e.length===0?[]:e.split(`/`).map(decodeURIComponent)}function pt(e){return`${rt}://${it}/${e.map(e=>`e=${encodeURIComponent(`${e.verb}/${dt(e.args)}`)}`).join(`&`)}`}function mt(e){return new g(e).getAll(`e`).map(ht)}function ht(e){let t=e.indexOf(`/`);return t===-1?{verb:e,value:``}:{verb:e.slice(0,t),value:e.slice(t+1)}}const gt=`@promptctl/cc-candybar`,_t=`CCCandybarURLHandler`,vt=[];function yt(e){return/^[A-Za-z0-9_./=,:-]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}function bt(e){return[`pnpm`,`dlx`,`${gt}@1.7.1`,...e.map(yt)].join(` `)}function xt(){return o.join(u.homedir(),`Applications`,`${_t}.app`)}function St(){return o.join(u.homedir(),`.claude`,`settings.json`)}function Ct(){if(process.platform!==`darwin`)throw Error(`URL handler installation requires macOS (found platform: ${process.platform}).`)}function wt(){return o.join(u.homedir(),`Library`,`Application Support`,`CCCandybar`)}function Tt(){return o.join(wt(),`url-handler.mjs`)}function Et(e,t,n){let r=e.replace(/"/g,`\\"`),i=t.replace(/"/g,`\\"`);return[`on open location L`,`\tdo shell script "NODE_PATH='${n.replace(/"/g,`\\"`)}' '${r}' '${i}' url-handle " & quoted form of L`,`end open location`].join(`
|
|
4
4
|
`)}function Dt(e){if(!e)throw Error(`install-url-handler: process.argv[1] not set`);return e.endsWith(`.mjs`)||e.endsWith(`.js`)?e:o.resolve(o.dirname(e),`..`,`dist`,`index.mjs`)}function Ot(){let e=Dt(process.argv[1]);if(!n.existsSync(e))throw Error(`install-url-handler: bundled dist not found at ${e}. Reinstall the package.`);n.mkdirSync(wt(),{recursive:!0});let t=Tt();return n.copyFileSync(e,t),t}function kt(){return[{key:`CFBundleIdentifier`,xml:`<string>com.cccandybar.url-handler</string>`},{key:`CFBundleURLTypes`,xml:[`<array>`,` <dict>`,` <key>CFBundleURLName</key>`,` <string>Claude Powerline Click Action</string>`,` <key>CFBundleURLSchemes</key>`,` <array>`,` <string>${rt}</string>`,` </array>`,` </dict>`,`</array>`].join(`
|
|
5
5
|
`)}]}function At(){Ct();let e=Ot();process.stdout.write(`Copied dist to ${e}\n`);let t=Dt(process.argv[1]),r=o.join(o.dirname(t),`..`,`node_modules`);if(!n.existsSync(r))throw Error(`install-url-handler: node_modules not found at ${r}. Install deps first.`);let i=xt();n.mkdirSync(o.dirname(i),{recursive:!0}),n.existsSync(i)&&n.rmSync(i,{recursive:!0,force:!0}),process.stdout.write(`Building ${i}\n`);let a=ve({bin:`/usr/bin/osacompile`,args:[`-o`,i,`-e`,Et(process.execPath,e,r)],category:`install.osacompile`});if(!a.ok)throw process.stderr.write(a.stderr),Error(`osacompile failed (${a.reason})`);let s=o.join(i,`Contents`,`Info.plist`);for(let{key:e}of kt())ve({bin:`/usr/bin/plutil`,args:[`-remove`,e,s],category:`install.plutil`});for(let{key:e,xml:t}of kt()){let n=ve({bin:`/usr/bin/plutil`,args:[`-insert`,e,`-xml`,t,s],category:`install.plutil`});if(!n.ok)throw process.stderr.write(n.stderr),Error(`plutil -insert ${e} failed (${n.reason})`)}process.stdout.write(`Registering ${rt}:// with Launch Services\n`);let c=ve({bin:`/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister`,args:[`-f`,i],category:`install.lsregister`});if(!c.ok)throw process.stderr.write(c.stderr),Error(`lsregister failed (${c.reason})`);process.stdout.write(`✓ ${_t}.app installed and registered.\n`),process.stdout.write(` Test: open '${rt}://hello-world' && pbpaste\n`)}function jt(e,t=rt){let n=`${t}://`;if(!e.startsWith(n))throw Error(`expected ${n} scheme, got: ${e}`);let r=e.slice(n.length),i=r.indexOf(`/`);return i===-1?{verb:st,value:r}:{verb:decodeURIComponent(r.slice(0,i)),value:r.slice(i+1)}}async function Mt(e){e||(process.stderr.write(`url-handle: missing URL argument.
|
|
6
6
|
`),process.exit(1));let t;try{t=jt(e)}catch(e){process.stderr.write(`url-handle: ${e instanceof Error?e.message:String(e)}\n`),process.exit(1)}let n=await qe(t.verb,t.value);n.kind===`ok`&&process.exit(0),n.kind===`transient`&&(Je(),process.stderr.write(`url-handle: daemon unavailable (${n.cause}: ${n.message})\n`),process.exit(1)),process.stderr.write(Nt(n)+`
|
|
@@ -105,7 +105,7 @@ Use 'override' annotation for methods overridden by subclass.`)}}var $i=aa(0),ea
|
|
|
105
105
|
`)}const u_=ns(),d_=new Set(u_),f_=new Set(rs),p_=e=>e?d_.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown theme "${e}" (have: ${u_.join(`, `)})`}:{ok:!1,reason:`theme name is required`},m_=e=>e?f_.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown style "${e}" (have: ${rs.join(`, `)})`}:{ok:!1,reason:`style name is required`},h_=new Set([`1`,`true`]),g_=new Set([`0`,`false`]),__=new Map([[`style`,{validator:m_,permanent:!0}],[`theme`,{validator:p_,permanent:!0}],[`toolbar-expanded`,{validator:e=>h_.has(e)?{ok:!0,value:`1`}:g_.has(e)?{ok:!0,value:``}:{ok:!1,reason:`expected boolean-ish (1, 0, true, false), got "${e}"`},permanent:!0}]]);function v_(){return[...__.keys()]}function y_(e,t,n){if(t===`int`)return w_(`menu page "${e}"`);if(t===`range`){let t=n.flatMap(e=>e.kind===`range`?[e.min]:[]),r=n.flatMap(e=>e.kind===`range`?[e.max]:[]);return T_(Math.min(...t),Math.max(...r),`stepper "${e}"`)}return S_([...new Set(n.flatMap(e=>e.kind===`allow-list`?e.allowed:[]))],`state "${e}"`)}function b_(e,t){if(!e)throw Error(`registerStateValidator: key is required`);if(e.includes(`/`))throw Error(`registerStateValidator: key "${e}" contains "/" — the set-state wire shape splits on "/" so a slash-bearing key cannot be addressed. Use a slash-free key.`);let n=__.get(e);if(n){if(n.permanent)throw Error(`registerStateValidator: key "${e}" is a built-in state key and cannot be re-claimed (built-in keys: ${[...x_()].join(`, `)})`);if(n.kind!==t.kind)throw Error(`registerStateValidator: key "${e}" is already a ${n.kind} state key; cannot also register it as ${t.kind}. A state key has one key shape — a menu page index (int) and a button allow-list cannot share a key.`);n.specs.push(t),n.validator=y_(e,n.kind,n.specs)}else{let n=[t];__.set(e,{permanent:!1,kind:t.kind,validator:y_(e,t.kind,n),specs:n})}let r=!0;return()=>{if(!r)return;r=!1;let n=__.get(e);if(!n||n.permanent)return;let i=n.specs.indexOf(t);i>=0&&n.specs.splice(i,1),n.specs.length===0?__.delete(e):n.validator=y_(e,n.kind,n.specs)}}function x_(){let e=[];for(let[t,n]of __)n.permanent&&e.push(t);return e}function S_(e,t){let n=e.filter(e=>e.includes(`/`));if(n.length>0)throw Error(`makeAllowListValidator(${t}): values contain "/" — the set-state wire shape splits values on "/" so slash-bearing options cannot be addressed. Offending values: ${n.join(`, `)}`);if(e.includes(``))throw Error(`makeAllowListValidator(${t}): empty string is not a writable option — the validator rejects empty input before the allow-list check, so an "" in the allowed list could be rendered but never delivered. Remove "" from the allowed list.`);let r=new Set(e),i=[...e];return e=>e?r.has(e)?{ok:!0,value:e}:{ok:!1,reason:`unknown ${t} "${e}" (have: ${i.join(`, `)})`}:{ok:!1,reason:`${t} value is required`}}const C_=/^-?\d+$/;function w_(e){return t=>{if(!t)return{ok:!1,reason:`${e} value is required`};if(!C_.test(t))return{ok:!1,reason:`${e} must be an integer, got "${t}"`};let n=t[0]===`-`,r=(n?t.slice(1):t).replace(/^0+/,``);return r===``?{ok:!0,value:`0`}:{ok:!0,value:n?`-${r}`:r}}}function T_(e,t,n){return r=>r?C_.test(r)?{ok:!0,value:String(Math.max(e,Math.min(t,parseInt(r,10))))}:{ok:!1,reason:`${n} must be an integer, got "${r}"`}:{ok:!1,reason:`${n} value is required`}}function E_(e){return e===`themes`?u_:rs}function D_(e,t){let n=t.filter(e=>e.kind===`range`),r=t.some(e=>e.kind===`int`),i=t.flatMap(e=>e.kind===`allow-list`?e.allowed:[]);if(n.length===0&&!r)return{kind:`allow-list`,allowed:[...new Set(i)]};let a=i.filter(e=>!C_.test(e));if(a.length>0)throw Error(`deriveActionValidators: key "${e}" is an integer spec (a paged cursor or a bounded value) but a click writes non-integer value(s) to it (${a.join(`, `)}). A state key has one key shape — point that click at a distinct key, or write an integer.`);if(r&&n.length>0)throw Error(`deriveActionValidators: key "${e}" is declared as both a paged cursor (int) and a bounded value (range) — a state key has one key shape. Use distinct keys.`);if(n.length>0){let t=Math.min(...n.map(e=>e.min)),r=Math.max(...n.map(e=>e.max)),a=i.filter(e=>{let n=parseInt(e,10);return n<t||n>r});if(a.length>0)throw Error(`deriveActionValidators: key "${e}" is a bounded range [${t},${r}] but a click writes out-of-range value(s) to it (${a.join(`, `)}). The range gate would clamp them, storing a different value than the click renders — write an in-range integer, or point that click at a distinct key.`);return{kind:`range`,min:t,max:r,seed:j_(n[0].seed,t,r)}}return{kind:`int`}}function O_(e){let t=new Set(x_());return e.filter(e=>e.spec.kind!==`allow-list`||!t.has(e.key))}function k_(e){let t=new Map;for(let{key:n,spec:r}of e){let e=t.get(n);e?e.push(r):t.set(n,[r])}return[...t].map(([e,t])=>({key:e,spec:D_(e,t)}))}function A_(e,t){return`set`in e?`to`in e?[{key:e.set,spec:{kind:`allow-list`,allowed:[e.to]}}]:`from`in e?[{key:e.set,spec:{kind:`allow-list`,allowed:E_(e.from)}}]:`int`in e?[{key:e.set,spec:{kind:`int`}}]:`cycle`in e?[{key:e.set,spec:{kind:`allow-list`,allowed:e.cycle}}]:[{key:e.set,spec:{kind:`range`,min:e.min,max:e.max,seed:j_(t.get(e.set),e.min,e.max)}}]:[]}function j_(e,t,n){return e===void 0?t:Math.max(t,Math.min(n,e))}function M_(e){let t=new Map;for(let n of Object.values(e.variables)){if(n.kind!==`state`)continue;let e=n.default;e!==void 0&&C_.test(e)&&t.set(n.key,parseInt(e,10))}return t}function N_(e){let t=M_(e);return O_(Object.values(e.actions).flatMap(e=>A_(e,t)))}function P_(e){return k_(N_(e))}function F_(e,t){let n=__.get(e);return n?n.validator(t):{ok:!1,reason:`unknown state key "${e}" (have: ${v_().join(`, `)})`}}function I_(e){let t=__.get(e);if(!t||t.permanent||t.kind!==`range`)return null;let n=t.specs.flatMap(e=>e.kind===`range`?[e]:[]);if(n.length===0)return null;let r=Math.min(...n.map(e=>e.min)),i=Math.max(...n.map(e=>e.max));return{min:r,max:i,seed:j_(n[0].seed,r,i)}}var L_=class{kind=`box`;cell;lastSetAt;constructor(e,t,n){this.name=e,this.type=t,z_(e,t,n,`initial value`),this.cell=X.observable.box(n,{deep:!1}),this.lastSetAt=Date.now()}read(){return this.cell.get()}set(e){z_(this.name,this.type,e,`set value`),this.cell.set(e),this.lastSetAt=Date.now()}lastUpdatedMs(){return this.lastSetAt}},R_=class{kind=`computed`;cell;constructor(e,t,n){this.name=e,this.type=t,this.cell=(0,X.computed)(()=>{let e=n();return z_(this.name,this.type,e,`computed result`),e},{keepAlive:!0})}read(){return this.cell.get()}lastUpdatedMs(){return null}};function z_(e,t,n,r){let i=su(n);if(i!==t)throw TypeError(`Variable "${e}": ${r} type ${i} does not match declared type ${t}`)}var B_=class{nodes=new Map;defineBox(e,t,n){this.assertNotDefined(e),this.nodes.set(e,new L_(e,t,n))}defineComputed(e,t,n){this.assertNotDefined(e);let r=e=>this.read(e);this.nodes.set(e,new R_(e,t,()=>n(r)))}read(e){return this.requireNode(e).read()}setBox(e,t){let n=this.requireNode(e);if(n.kind!==`box`)throw TypeError(`Variable "${e}" is a ${n.kind}, not a box (use defineBox to create a settable variable)`);(0,X.runInAction)(()=>n.set(t))}runInAction(e){(0,X.runInAction)(e)}has(e){return this.nodes.has(e)}getType(e){return this.requireNode(e).type}getKind(e){return this.requireNode(e).kind}getNode(e){let t=this.requireNode(e);return{name:t.name,type:t.type,kind:t.kind,read:()=>t.read(),lastUpdatedMs:()=>t.lastUpdatedMs()}}names(){return[...this.nodes.keys()]}requireNode(e){let t=this.nodes.get(e);if(!t)throw ReferenceError(`Unknown variable "${e}"`);return t}assertNotDefined(e){if(this.nodes.has(e))throw Error(`Variable "${e}" is already declared`)}};function V_(e,t,n){return e+`\0`+t+`\0`+(n??``)}var H_=class{entries=new Map;deps;maxEntries;constructor(e,t={}){this.deps=e,this.maxEntries=t.maxEntries??256}getOrCreate(e,t,n){let r=V_(e,t,n),i=this.entries.get(r);if(i)return this.entries.delete(r),this.entries.set(r,i),i;let a={projectDir:e,cwd:t,configFile:n,configFilePath:null,lastError:null,lastWarning:null,state:null,watcher:null};if(this.reloadInto(a),this.entries.set(r,a),this.entries.size>this.maxEntries){let e=this.entries.keys().next().value;if(e!==void 0){let t=this.entries.get(e);t?.state?.registry.dispose(),t?.state?.validatorDisposers.forEach(e=>e()),t?.watcher?.release(),this.entries.delete(e)}}return a}reloadInto(e){let t=Pl(e.projectDir,e.cwd,e.configFile);e.lastWarning=Fl(e.projectDir,e.cwd);let n;try{n=this.buildState(e,t)}catch(n){e.lastError=n instanceof os||n instanceof Error?n.message:String(n),this.refreshWatcher(e,t);return}if(e.state?.registry.dispose(),e.state?.validatorDisposers.forEach(e=>e()),e.lastError=null,e.state=n,n.compiled.loadWarnings.length>0){let t=n.compiled.loadWarnings.join(`
|
|
106
106
|
`);e.lastWarning=e.lastWarning?e.lastWarning+`
|
|
107
107
|
`+t:t}this.refreshWatcher(e,t)}buildState(e,t){let{config:n,source:r}=Il(t),i=Ll(n,t??`<default>`,r),a=new B_,o=new bg(a,i.globals.default_empty_value??``,this.deps.gitService,this.deps.sessionState),s,c=[];try{s=c_(i,o,{cwd:e.cwd});for(let{key:e,spec:t}of P_(i))c.push(b_(e,t))}catch(e){for(let e of c)e();throw o.dispose(),e}return{config:i,store:a,registry:o,compiled:s,neededInputPaths:$l(i),lastRenderCellsBySegment:new Map,validatorDisposers:c}}refreshWatcher(e,t){(t!==e.configFilePath||e.watcher===null)&&(e.configFilePath=t,this.rebindWatcher(e,t))}rebindWatcher(e,t){e.watcher&&=(e.watcher.release(),null);let r=Nl(e.projectDir,e.cwd,e.configFile),i=new Map;for(let e of r){let t=o.dirname(e);if(!n.existsSync(t))continue;let r=o.basename(e);i.has(t)||i.set(t,new Set),i.get(t).add(r)}let a=[...i.entries()].map(([e,t])=>({path:e,filenames:[...t]})),s=`config:${e.projectDir}:${e.cwd}:${e.configFile??``}:${t??`<none>`}`;e.watcher=this.deps.watchers.acquire(s,{files:t===null?[]:[t],dirs:a},()=>this.onConfigChanged(e))}onConfigChanged(e){M(`info`,`config change detected for entry projectDir=${e.projectDir} cwd=${e.cwd}`),this.reloadInto(e)}get size(){return this.entries.size}firstPopulatedState(){for(let e of this.entries.values())if(e.state!==null)return e.state;return null}};const U_=16384;var W_=class{startedAt=new Date;requestsTotal=0;requestsErrored=0;requestsTimedOut=0;inFlight=0;watchersOpened=0;watchersClosed=0;watchersEvicted=0;subprocessTotal=0;subprocessInFlight=0;subprocessCount=new Map;subprocessHistogram=new Map;subprocessHistogramRotator=new Map;rollingTimestamps=[];rollingHead=0;launchStats={onStart:e=>{this.subprocessTotal++,this.subprocessInFlight++,this.subprocessCount.set(e,(this.subprocessCount.get(e)??0)+1),this.recordRollingNow()},onEnd:(e,t)=>{this.subprocessInFlight=Math.max(0,this.subprocessInFlight-1),this.recordDuration(e,t)}};recordRollingNow(){let e=Date.now();if(this.rollingTimestamps.length<U_){this.rollingTimestamps.push(e);return}this.rollingTimestamps[this.rollingHead]=e,this.rollingHead=(this.rollingHead+1)%U_}recordDuration(e,t){let n=this.subprocessHistogram.get(e);if(n||(n=[],this.subprocessHistogram.set(e,n)),n.length<16){n.push(t);return}let r=(this.subprocessHistogramRotator.get(e)??0)%16;n[r]=t,this.subprocessHistogramRotator.set(e,r+1)}snapshotSubprocesses(){let e=Date.now()-6e4,t=0;for(let n of this.rollingTimestamps)n>=e&&t++;let n={};for(let[e,t]of this.subprocessCount)t>0&&(n[e]=t);let r={},i={};for(let[e,t]of this.subprocessHistogram){if(t.length===0)continue;let n=[...t].sort((e,t)=>e-t),a=Math.floor(n.length*.5),o=Math.min(n.length-1,Math.floor(n.length*.99)),s=n[a],c=n[o];s!==void 0&&(r[e]=s),c!==void 0&&(i[e]=c)}return{total:this.subprocessTotal,inFlight:this.subprocessInFlight,lastMinute:t,byCategory:n,p50DurationMs:r,p99DurationMs:i}}snapshot(e){let t=process.memoryUsage();return{pid:process.pid,version:3,startedAt:this.startedAt.toISOString(),uptimeSec:Math.floor((Date.now()-this.startedAt.getTime())/1e3),rssBytes:t.rss,heapUsedBytes:t.heapUsed,heapTotalBytes:t.heapTotal,externalBytes:t.external,arrayBuffersBytes:t.arrayBuffers,requests:{total:this.requestsTotal,errored:this.requestsErrored,timedOut:this.requestsTimedOut,inFlight:this.inFlight},gitCache:e.gitCache,usageCache:e.usageCache,renderCache:{size:e.renderCacheSize},watchers:{active:e.watchersActive,opened:this.watchersOpened,closed:this.watchersClosed,evicted:this.watchersEvicted},subprocesses:this.snapshotSubprocesses(),nextRestartReason:e.nextRestartReason??null}}};const G_=(parseInt(process.env.CC_CANDYBAR_RSS_LIMIT_MB??``,10)||512)*1024*1024;function K_(e){let t=e.rssLimitBytes??G_,n=e.snapshotsKeep??3,r=!1;function i(){if(r)return!0;let i=e.rssBytes();if(i<=t)return!1;r=!0,e.log(`warn`,`RSS ${i} > limit ${t}; writing heap snapshot then shutting down`);try{let t=new Date(e.now()).toISOString().replace(/[:.]/g,`-`),r=o.join(e.snapshotDir,`heap-${t}-${e.pid}.heapsnapshot`),i=e.writeHeapSnapshot(r);e.log(`info`,`heap snapshot written: ${i}`),q_(e.listSnapshots(),n,e.removeFile)}catch(t){e.log(`warn`,`heap snapshot failed: ${t.message}`)}return e.shutdown(0),!0}function a(){let n=e.rssBytes();return n>t*.75?`rss ${n} approaching limit ${t}`:null}function s(e=6e4){let t=setInterval(()=>{i()},e);return t.unref(),{disarm:()=>clearInterval(t)}}return{checkRss:i,describeNextRestart:a,arm:s}}function q_(e,t,n){let r=[...e].sort((e,t)=>{let n=e.slice(e.lastIndexOf(`/`)+1);return t.slice(t.lastIndexOf(`/`)+1).localeCompare(n)});for(let e of r.slice(t))try{n(e)}catch{}}function J_(e,t,r={}){let i=we();return{now:()=>Date.now(),pid:process.pid,snapshotDir:i,log:M,rssBytes:()=>process.memoryUsage().rss,writeHeapSnapshot:e=>ie.writeHeapSnapshot(e),listSnapshots:()=>{try{return n.readdirSync(i).filter(e=>e.startsWith(`heap-`)&&e.endsWith(`.heapsnapshot`)).map(e=>o.join(i,e))}catch{return[]}},removeFile:e=>n.unlinkSync(e),shutdown:t,startedAtMs:e,...r}}const Y_=`CC_CANDYBAR_PARENT_PID`;function X_(e){let t=e[Y_];if(t===void 0)return{kind:`outlives-nobody`};let n=Number.parseInt(t,10);if(!Number.isInteger(n)||n<=0)throw Error(`${Y_} must be a positive integer pid, got ${JSON.stringify(t)}`);return{kind:`anchored`,pid:n}}function Z_(e){if(e.anchor.kind===`outlives-nobody`)return{disarm:()=>{}};let{pid:t}=e.anchor,n=setInterval(()=>{e.isAlive(t)||e.onOrphaned(`spawner pid ${t} gone`)},e.intervalMs??1e3);return n.unref(),{disarm:()=>clearInterval(n)}}function Q_(t){try{return e.kill(t,0),!0}catch(e){return e.code===`EPERM`}}const $_={load:()=>({}),save:()=>{},flush:()=>{}};function ev(e){let t=new Map;for(let[n,r]of Object.entries(e))t.set(n,new Map(Object.entries(r)));return t}var tv=class{sessions;storage;atom=(0,X.createAtom)(`SessionState`);constructor(e=$_,t=256){this.maxSessions=t,this.storage=e,this.sessions=new Map,this.hydrateFromStorage()}useStorage(e){this.storage=e,this.hydrateFromStorage()}hydrateFromStorage(){this.sessions=ev(this.storage.load()),this.evictOldest(),this.persist()}get(e,t){this.atom.reportObserved();let n=this.sessions.get(e);return n?(this.touch(e,n),n.get(t)??null):null}set(e,t,n){this.setBatch(e,[{key:t,value:n}])}setBatch(e,t){t.length!==0&&(0,X.runInAction)(()=>{let n=this.sessions.get(e)??new Map;for(let{key:e,value:r}of t)n.set(e,r);this.touch(e,n),this.evictOldest(),this.persist(),this.atom.reportChanged()})}clear(e,t){(0,X.runInAction)(()=>{let n=this.sessions.get(e);n&&(n.delete(t),n.size===0?this.sessions.delete(e):this.touch(e,n)),this.persist(),this.atom.reportChanged()})}prune(e){(0,X.runInAction)(()=>{for(let t of this.sessions.keys())e.has(t)||this.sessions.delete(t);this.persist(),this.atom.reportChanged()})}touch(e,t){this.sessions.delete(e),this.sessions.set(e,t)}evictOldest(){let e=this.sessions.size-this.maxSessions;if(!(e<=0)){for(let t of this.sessions.keys())if(this.sessions.delete(t),--e===0)break}}flush(){this.storage.flush()}persist(){this.storage.save(this.serialize())}serialize(){let e=Object.create(null);for(let[t,n]of this.sessions)e[t]=Object.fromEntries(n);return e}};const nv=(e,t)=>O(t);function rv(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;for(let t of Object.values(e)){if(typeof t!=`object`||!t||Array.isArray(t))return!1;for(let e of Object.values(t))if(typeof e!=`string`)return!1}return!0}var iv=class{timer=null;pending=null;constructor(e,t=500,n=nv){this.filePath=e,this.debounceMs=t,this.logger=n}load(){let e;try{e=n.readFileSync(this.filePath,`utf8`)}catch(e){let t=e.code;return t!==`ENOENT`&&this.logger(`warn`,`session-state read failed (${t}); starting empty`),{}}try{let t=JSON.parse(e);return rv(t)?t:(this.logger(`warn`,`session-state load: unexpected shape, starting empty`),{})}catch{return this.logger(`warn`,`session-state load: corrupt JSON, starting empty`),{}}}save(e){this.pending=e,!this.timer&&(this.timer=setTimeout(()=>this.flush(),this.debounceMs),this.timer.unref())}flush(){if(this.timer&&=(clearTimeout(this.timer),null),this.pending===null)return;let e=this.pending;try{n.mkdirSync(o.dirname(this.filePath),{recursive:!0});let t=`${this.filePath}.tmp`;n.writeFileSync(t,JSON.stringify(e),{mode:384}),n.chmodSync(t,384),n.renameSync(t,this.filePath),this.pending=null}catch(e){this.logger(`warn`,`session-state save failed: ${e.message}`)}}},av=class extends Error{constructor(e){super(e),this.name=`BadVerbArgs`}};function ov(e){if(!e)throw new av(`session id is required`);if(e.includes(`/`)||e.includes(`..`))throw new av(`invalid session id "${e}"`);return e}function sv(e){return cv(()=>decodeURIComponent(e))}function cv(e){try{return e()}catch(e){throw e instanceof URIError?new av(`malformed wire encoding: ${e.message}`):e}}function lv(e,t){let n=ve({bin:`/usr/bin/pbcopy`,stdinInput:e,category:`click.pbcopy`});if(!n.ok){if(n.reason===`rate-limited`){t.dlog(`warn`,`click.pbcopy rate-limited: ${n.error??``}`);return}throw Error(`pbcopy failed (${n.reason}, exit ${n.exitCode??`null`})`)}}const uv=(e,t)=>lv(sv(e),t),dv=(e,t)=>{let n=ve({bin:`/usr/bin/open`,args:[`-a`,`Visual Studio Code`,sv(e)],category:`click.open`});if(!n.ok){if(n.reason===`rate-limited`){t.dlog(`warn`,`click.open rate-limited: ${n.error??``}`);return}throw Error(`open -a "Visual Studio Code" failed (${n.reason}, exit ${n.exitCode??`null`})`)}},fv=(e,t)=>lv(sv(e),t),pv=(e,t)=>lv(sv(e),t),mv=(e,t)=>{let n=ov(sv(e));t.sessionState.get(n,`toolbar-expanded`)?t.sessionState.clear(n,`toolbar-expanded`):t.sessionState.set(n,`toolbar-expanded`,`1`)},hv=(e,t)=>{let[n=``,...r]=cv(()=>ft(e)),i=ov(n);if(r.length===0)throw new av(`set-state: <key>/<value> is required (have keys: ${v_().join(`, `)})`);if(r.length%2!=0)throw new av(`set-state: expected even-count <key>/<value> pairs, got ${r.length} segment(s) after session id (have keys: ${v_().join(`, `)})`);let a=[];for(let e=0;e<r.length;e+=2){let t=r[e],n=r[e+1];if(!t)throw new av(`set-state: empty key at pair ${e/2+1} (expected <sessionId>/<key>/<value>[/<key>/<value>...] segments)`);let i=F_(t,n);if(!i.ok)throw new av(`set-state: pair ${e/2+1}: ${i.reason}`);a.push({key:t,value:i.value})}t.sessionState.setBatch(i,a);let o=a.map(e=>`${e.key}=${e.value}`).join(` `);t.dlog(`info`,`set-state: ${o} (session=${i})`)},gv=/^-?\d+$/;function _v(e,t,n){return e>n?t:e<t?n:e}const vv=(e,t)=>{let[n=``,r=``,i=``]=cv(()=>ft(e)),a=ov(n);if(!r)throw new av(`step-state: <key> is required (shape: <sessionId>/<key>/<by>)`);if(!gv.test(i))throw new av(`step-state: delta must be an integer, got "${i}"`);let o=parseInt(i,10),s=I_(r);if(!s)throw new av(`step-state: key "${r}" is not a bounded (range) state key (have keys: ${v_().join(`, `)})`);let c=t.sessionState.get(a,r),l=c&&gv.test(c)?Math.max(s.min,Math.min(s.max,parseInt(c,10))):s.seed,u=_v(l+o,s.min,s.max),d=F_(r,String(u));if(!d.ok)throw new av(`step-state: ${d.reason}`);t.sessionState.set(a,r,d.value),t.dlog(`info`,`step-state: ${r} ${l}→${d.value} (by ${o}, session=${a})`)},yv=`config-override`,bv=new Map([[st,uv],[`load-config`,(e,t)=>{let n=e.indexOf(`/`);if(n===-1)throw new av(`load-config: expected <sessionId>/<path> (missing separator)`);let r=ov(cv(()=>decodeURIComponent(e.slice(0,n)))),i=cv(()=>decodeURIComponent(e.slice(n+1))).trim();if(i!==``){if(!i.startsWith(`/`))throw new av(`load-config: path must be absolute, got "${i}"`);if(!/\.(json5?|json)$/.test(i))throw new av(`load-config: path must end with .json5 or .json, got "${i}"`)}i===``?(t.sessionState.clear(r,yv),t.dlog(`info`,`load-config: override cleared (session=${r})`)):(t.sessionState.set(r,yv,i),t.dlog(`info`,`load-config: ${i} (session=${r})`))}],[ct,dv],[at,hv],[ot,vv],[lt,fv],[ut,pv],[`toolbar-toggle`,mv]]),xv=(e,t)=>{let n=[],r=!1,i=null;for(let{verb:a,value:o}of mt(e)){if(!i&&(a===`set-state`||a===`step-state`||a===`toolbar-toggle`)){let e=ft(o);e.length>0&&e[0]&&(i=e[0])}let e=bv.get(a);if(!e){n.push(`unknown effect verb "${a}"`);continue}try{e(o,t)}catch(e){e instanceof av||(r=!0),n.push(`${a}: ${e instanceof Error?e.message:String(e)}`)}}if(n.length>0){i&&t.sessionState.set(i,`click.error`,n.join(`
|
|
108
|
-
`));let e=`dispatch: ${n.join(`; `)}`;throw r?Error(e):new av(e)}},Sv=new Map([...bv,[it,xv]]);Object.freeze([...Sv.keys()]);const Cv=new Set([`hook_event_name`,`session_id`,`session_name`,`transcript_path`,`cwd`,`model`,`workspace`,`version`,`output_style`,`cost`,`context_window`,`exceeds_200k_tokens`,`effort`,`thinking`,`rate_limits`,`vim`,`agent`,`worktree`]),wv=[[`session_id`,`string`],[`transcript_path`,`string`],[`cwd`,`string`],[`model`,`object`],[`model.id`,`string`],[`model.display_name`,`string`],[`workspace`,`object`],[`workspace.current_dir`,`string`],[`workspace.project_dir`,`string`]];function Tv(e){let t={missingRequired:[],typeMismatches:[],unknownTopLevelFields:[]},n=typeof e==`object`&&e&&!Array.isArray(e)?e:{};for(let[e,r]of wv){let i=Ev(n,e);if(i==null)t.missingRequired.push(e);else{let n=Array.isArray(i)?`array`:typeof i;(r===`object`?n!==`object`:n!==r)&&t.typeMismatches.push({path:e,expected:r,got:n})}}for(let e of Object.keys(n))Cv.has(e)||t.unknownTopLevelFields.push(e);return{data:e,report:t}}function Ev(e,t){let n=e;for(let e of t.split(`.`)){if(typeof n!=`object`||!n||Array.isArray(n))return;n=n[e]}return n}function Dv(e,t){switch(e){case`vars`:return{what:e,vars:Ov(t)};case`segments`:return{what:e,segments:Mv(t)};case`config`:return{what:e,config:Fv(t)}}}function Ov(e){if(e===null)return[];let{store:t,registry:n,config:r}=e,i=Av(r),a=t.names().sort(),o=[];for(let e of a){let r=t.getNode(e),a=n.getLastError(e);o.push({name:e,source:i.get(e)??null,type:r.type,value:r.read(),lastError:a===void 0?null:{timestampMs:a.timestamp,message:a.message},ageMs:kv(r.lastUpdatedMs())})}return o}function kv(e){return e===null?null:Math.max(0,Date.now()-e)}function Av(e){let t=new Map;for(let[n,r]of Object.entries(e.variables))t.set(n,jv(r));for(let[n,r]of Object.entries(e.segments))if(r.vars)for(let[e,i]of Object.entries(r.vars))t.set(`${n}.${e}`,jv(i));return t}function jv(e){return e.kind}function Mv(e){if(e===null)return[];let{store:t,config:n,lastRenderBySegment:r}=e,i=new Set(t.names()),a=Nv(n),o=[];for(let e of a){let t=n.segments[e];t&&o.push({name:e,template:t.template,referencedVars:Pv(t.template,i),lastRender:r.get(e)??null})}return o}function Nv(e){let t=[],n=new Set;for(let r of Fn(e.root))r.kind===`segment`&&e.segments[r.name]&&!n.has(r.name)&&(t.push(r.name),n.add(r.name));for(let r of Object.keys(e.segments))n.has(r)||(t.push(r),n.add(r));return t}function Pv(e,t){let n=new Set;for(let r of gl(e)){if(t.has(r)){n.add(r);continue}let e=r.split(`.`);for(;e.length>1;){e.pop();let r=e.join(`.`);if(t.has(r)){n.add(r);break}}}return Array.from(n).sort()}function Fv(e){return e===null?null:e.config}const Iv=[`vars`,`segments`,`config`];function Lv(e){return typeof e==`string`&&Iv.includes(e)}function Rv(e){return Math.max(1,e-45)}var zv=class{thresholds={LOW:50,MEDIUM:80};getContextUsageThresholds(){return this.thresholds}ratioPercentages(e,t){let n=Math.min(100,Math.max(0,Math.round(e/t*100)));return{percentage:n,contextLeftPercentage:Math.max(0,100-n)}}calculateContextFromHookData(e){let t=e.context_window;if(!t?.current_usage)return O(`No current_usage in hook data, falling back to transcript parsing`),null;let n=t.current_usage,r=t.context_window_size,i=(n.input_tokens||0)+(n.cache_creation_input_tokens||0)+(n.cache_read_input_tokens||0);O(`Native current_usage: input=${n.input_tokens}, cache_create=${n.cache_creation_input_tokens}, cache_read=${n.cache_read_input_tokens}, total=${i} (limit: ${r})`);let a=this.ratioPercentages(i,r);return{totalTokens:i,maxTokens:r,percentage:t.used_percentage==null?a.percentage:Math.round(t.used_percentage),contextLeftPercentage:t.remaining_percentage==null?a.contextLeftPercentage:Math.round(t.remaining_percentage)}}async calculateContextTokensFromTranscript(e,t){try{O(`Calculating context tokens from transcript: ${e}`);let n=await yn(e);if(n.length===0)return O(`No entries in transcript`),Bt;let r=null;for(let e=n.length-1;e>=0;e--){let t=n[e];if(t&&t.message?.usage?.input_tokens&&t.isSidechain!==!0){r=t,O(`Context segment: Found most recent entry at ${t.timestamp.toISOString()}, stopping search`);break}}if(r?.message?.usage){let e=r.message.usage,n=(e.input_tokens||0)+(e.cache_read_input_tokens||0)+(e.cache_creation_input_tokens||0);return O(`Most recent main chain context: ${n} tokens (limit: ${t})`),N({totalTokens:n,maxTokens:t,...this.ratioPercentages(n,t)})}return O(`No main chain entries with usage data found`),Bt}catch(e){return P(`context transcript: ${e instanceof Error?e.message:String(e)}`)}}async getContextInfo(e){let t=this.calculateContextFromHookData(e);if(t)return N(t);let n=e.context_window?.context_window_size??2e5;return this.calculateContextTokensFromTranscript(e.transcript_path,n)}};function Bv(e){let t=e.type||e.message?.role||e.message?.type,n=e.type===`user`&&e.message?.firstContentType===`tool_result`;return t===`user`&&!n}var Vv=class{calculateMessageCount(e){return e.filter(Bv).length}calculateLastResponseTime(e){if(e.length===0)return null;let t=e.slice(-20),n=null,r=null;for(let e of t){let t=e.type||e.message?.role||e.message?.type;if(Bv(e))n=e.timestamp;else if(t===`assistant`&&n){let t=(e.timestamp.getTime()-n.getTime())/1e3;t>.1&&t<300&&(r=t)}}return r}async getMetricsInfo(e,t){try{if(O(`Getting metrics from hook data for session: ${e}`),!t.cost)return Bt;let n=(await yn(t.transcript_path)).filter(e=>!e.isSidechain),r=this.calculateMessageCount(n),i=this.calculateLastResponseTime(n);return N({responseTime:t.cost.total_api_duration_ms/1e3,lastResponseTime:i,sessionDuration:t.cost.total_duration_ms/1e3,messageCount:r,linesAdded:t.cost.total_lines_added,linesRemoved:t.cost.total_lines_removed})}catch(t){return P(`metrics (${e}): ${t instanceof Error?t.message:String(t)}`)}}};const Hv=new Map;function Uv(e){if(!e)return``;let t=e.indexOf(`,`);return t<0?e:e.slice(0,t)}var Wv=class{async getSessionId(){if(!process.env.TMUX_PANE)return Bt;let e=Uv(process.env.TMUX),t=Hv.get(e);if(t!==void 0)return t;O(`Getting tmux session ID, TMUX_PANE: ${process.env.TMUX_PANE}`);let n=await _e({bin:`tmux`,args:[`display-message`,`-p`,`#S`],timeoutMs:1e3,category:`tmux`}),r=n.ok?n.stdout.trim()?N(n.stdout.trim()):Bt:P(`tmux display-message: ${n.reason}`);return Hv.set(e,r),r}isInTmux(){return!!process.env.TMUX_PANE}};function Gv(e){return e<32||e===127||e>=128&&e<=159}function Kv(e,t){let n=``;for(let t of e)n+=Gv(t.codePointAt(0)??0)?` `:t;n=n.replace(/\s+/g,` `).trim();let r=``,i=0;for(let e of n){if(i===t)return r.replace(/.$/u,`…`);r+=e,i++}return r}const qv=`\x1B[38;2;255;255;255m`,Jv=`\x1B[48;2;200;40;40m`,Yv=`\x1B[0m`,Xv=new W_;k(Xv.launchStats);const Zv=new $t({counters:Xv,logger:M}),Qv=new on({watchers:Zv,logger:M}),$v=new Nn,ey=new tv,ty=new zv,ny=new Vv,ry=new Wv,iy=new H_({gitService:Qv,sessionState:ey,watchers:Zv});function ay(){n.mkdirSync(we(),{recursive:!0}),Ee(Te()),ey.useStorage(new iv(Oe(),500,M)),e.on(`uncaughtException`,e=>{M(`error`,`uncaughtException: ${e.stack||e.message}`),vy(1)}),e.on(`unhandledRejection`,e=>{M(`error`,`unhandledRejection: ${String(e)}`),vy(1)});for(let t of[`SIGINT`,`SIGTERM`,`SIGHUP`])e.on(t,()=>{M(`info`,`received ${t}, shutting down`),vy(0)});Z_({anchor:X_(e.env),isAlive:Q_,onOrphaned:e=>{M(`info`,`parent watchdog: ${e}; shutting down`),vy(0)}}),oy(m.createServer({allowHalfOpen:!1},e=>{yy(e)}),Te(),!1)}function oy(t,n,r){t.removeAllListeners(`error`),t.once(`error`,i=>{if(i.code!==`EADDRINUSE`){M(`error`,`server error: ${i.message}`),vy(1);return}if(r){M(`info`,`lost rebind race; another daemon is alive — exiting`),e.exit(0);return}sy(t,n)}),t.listen(n,()=>uy(n))}async function sy(t,r){await ly(r)&&(M(`info`,`another daemon is listening on socket — exiting`),e.exit(0)),await ly(r)&&(M(`info`,`race: another daemon claimed the socket during recovery — exiting`),e.exit(0)),M(`warn`,`stale socket from crashed daemon — unlinking and rebinding`);try{n.unlinkSync(r)}catch(e){if(e.code!==`ENOENT`){M(`error`,`cannot unlink stale socket ${r}: ${e.message}`),vy(1);return}}oy(t,r,!0)}function cy(e){return new Promise(t=>{let n=m.connect(e),r=!1,i=null,a=e=>{r||(r=!0,i&&clearTimeout(i),n.removeAllListeners(),n.destroy(),t(e))};n.once(`connect`,()=>a(`alive`)),n.once(`error`,e=>{let t=e.code;a(t===`ECONNREFUSED`||t===`ENOENT`||t===`ENOTSOCK`?`dead`:`unknown`)}),i=setTimeout(()=>a(`unknown`),50),i.unref()})}async function ly(e){return await cy(e)!==`dead`}function uy(t){try{n.chmodSync(t,384)}catch(e){M(`warn`,`chmod socket failed: ${e.message}`)}my(),M(`info`,`daemon up: pid=${e.pid} v=3 sock=${t}`),dy(),py()}function dy(){let t=import.meta.url,r=[];t.startsWith(`file://`)&&r.push(_(t)),e.argv[1]&&r.push(e.argv[1]);let i=new Map;for(let e of r)try{i.set(e,n.statSync(e).mtimeMs)}catch{}if(i.size===0)return;let a=setInterval(()=>{for(let[e,t]of i)try{if(n.statSync(e).mtimeMs!==t){M(`info`,`binary mtime changed (${e}); shutting down`),clearInterval(a),vy(0);return}}catch(e){M(`warn`,`bin stat failed: ${e.message}`)}},6e4);a.unref()}let fy=null;function py(){fy=K_(J_(Xv.startedAt.getTime(),e=>vy(e))),fy.arm()}function my(){let t=JSON.stringify({pid:e.pid,version:3,binPath:e.argv[1],startedAt:new Date().toISOString()});try{n.writeFileSync(De(),t,{mode:384}),n.chmodSync(De(),384)}catch(e){M(`warn`,`pidfile write failed: ${e.message}`)}}function hy(){try{n.unlinkSync(De())}catch{}}let gy=0,_y=!1;function vy(t){if(!_y){_y=!0,setTimeout(()=>e.kill(e.pid,`SIGKILL`),500);try{Qv.close()}catch(e){M(`warn`,`gitService close failed: ${e.message}`)}try{$v.close()}catch(e){M(`warn`,`usageStore close failed: ${e.message}`)}try{Zv.closeAll()}catch(e){M(`warn`,`watcherRegistry close failed: ${e.message}`)}try{ey.flush()}catch(e){M(`warn`,`sessionState flush failed: ${e.message}`)}hy(),zt(),e.exit(t)}}function yy(e){gy++,Xv.inFlight=gy;let t=!1,n=(n,r)=>{if(t){r!==null&&M(`warn`,`exit-after-flush dropped: an earlier responder settled this socket`);return}t=!0;let i=r===null?void 0:()=>vy(r);try{e.end(Ne(n),i)}catch(e){M(`warn`,`response write failed: ${e.message}`),i?.()}},r=setTimeout(()=>{Xv.requestsTimedOut++,n({ok:!1,error:`request exceeded 200ms`,code:`TIMEOUT`,daemonV:3},null)},200),i=Pe(e=>{xy(e).then(e=>n(e.resp,e.exitAfterFlush)).catch(e=>{M(`error`,`handler threw: ${e?.stack||e}`),n({ok:!1,error:String(e?.message||e),code:`RENDER_FAILED`,daemonV:3},null)})},e=>{M(`warn`,`frame parse failed: ${e.message}`),n({ok:!1,error:e.message,code:`BAD_REQUEST`,daemonV:3},null)});e.on(`data`,i),e.on(`error`,e=>{M(`warn`,`socket error: ${e.message}`)}),e.on(`close`,()=>{clearTimeout(r),gy=Math.max(0,gy-1),Xv.inFlight=gy})}const by=e=>({resp:e,exitAfterFlush:null});async function xy(e){if(!e||typeof e!=`object`||typeof e.v!=`number`)return by({ok:!1,error:`malformed request`,code:`BAD_REQUEST`,daemonV:3});if(e.v!==3)return e.v>3?M(`info`,`version mismatch: client=${e.v} > daemon=3; binary likely upgraded — exiting after the response flushes`):M(`info`,`version mismatch: client=${e.v} < daemon=3; client is stale — staying up`),{resp:{ok:!1,error:`protocol v${e.v} not supported (daemon at v3)`,code:`VERSION_MISMATCH`,daemonV:3},exitAfterFlush:e.v>3?0:null};if(e.kind===`shutdown`)return{resp:{ok:!0,output:``},exitAfterFlush:0};if(e.kind===`stats`)return by({ok:!0,stats:Xv.snapshot({gitCache:Qv.getStats(),usageCache:$v.getStats(),renderCacheSize:iy.size,watchersActive:Zv.size(),nextRestartReason:fy?.describeNextRestart()??null})});if(e.kind===`render`){Xv.requestsTotal++;let t=Date.now();try{let{report:n}=Tv(e.hookData);for(let e of n.unknownTopLevelFields)M(`info`,`schema: unknown field '${e}' — Anthropic may have added it`);let r=[];for(let e of n.missingRequired)r.push(`missing required field '${e}'`);for(let{path:e,expected:t,got:i}of n.typeMismatches)r.push(`field '${e}' expected ${t}, got ${i}`);if(e.cwd===``&&r.push(`request 'cwd' is empty`),r.length>0)return Xv.requestsErrored++,M(`warn`,`BAD_REQUEST: ${r.join(`; `)}`),by({ok:!1,error:`malformed hookData: ${r.join(`; `)}`,code:`BAD_REQUEST`,daemonV:3});let i=e.hookData.workspace.project_dir,{configFile:a,unknownFlagsError:o}=wy(e.args),s=e.hookData.session_id,c=ey.get(s,`config-override`)??a,l=iy.getOrCreate(i,e.cwd,c),u=je(e.termCols),d=Rv(u??120),f={...Oy,width:d},p=``;if(l.state!==null){let t=await ru(e.hookData,My,e.cwd,l.state.neededInputPaths),n=Tg(es(ey.get(e.hookData.session_id,`theme`),l.state.config.globals.palette));f.style=as(ey.get(e.hookData.session_id,`style`),l.state.config.globals.style),p=l_(l.state.config,l.state.compiled,l.state.store,l.state.registry,t,n,f,l.state.lastRenderCellsBySegment)}let m=ey.get(e.hookData.session_id,`click.error`);m&&ey.clear(e.hookData.session_id,`click.error`);let h=[o,l.lastError,m].filter(Boolean).join(`
|
|
108
|
+
`));let e=`dispatch: ${n.join(`; `)}`;throw r?Error(e):new av(e)}},Sv=new Map([...bv,[it,xv]]);Object.freeze([...Sv.keys()]);const Cv=new Set([`hook_event_name`,`session_id`,`session_name`,`transcript_path`,`cwd`,`model`,`workspace`,`version`,`output_style`,`cost`,`context_window`,`exceeds_200k_tokens`,`effort`,`thinking`,`rate_limits`,`vim`,`agent`,`worktree`]),wv=[[`session_id`,`string`],[`transcript_path`,`string`],[`cwd`,`string`],[`model`,`object`],[`model.id`,`string`],[`model.display_name`,`string`],[`workspace`,`object`],[`workspace.current_dir`,`string`],[`workspace.project_dir`,`string`]];function Tv(e){let t={missingRequired:[],typeMismatches:[],unknownTopLevelFields:[]},n=typeof e==`object`&&e&&!Array.isArray(e)?e:{};for(let[e,r]of wv){let i=Ev(n,e);if(i==null)t.missingRequired.push(e);else{let n=Array.isArray(i)?`array`:typeof i;(r===`object`?n!==`object`:n!==r)&&t.typeMismatches.push({path:e,expected:r,got:n})}}for(let e of Object.keys(n))Cv.has(e)||t.unknownTopLevelFields.push(e);return{data:e,report:t}}function Ev(e,t){let n=e;for(let e of t.split(`.`)){if(typeof n!=`object`||!n||Array.isArray(n))return;n=n[e]}return n}function Dv(e,t){switch(e){case`vars`:return{what:e,vars:Ov(t)};case`segments`:return{what:e,segments:Mv(t)};case`config`:return{what:e,config:Fv(t)}}}function Ov(e){if(e===null)return[];let{store:t,registry:n,config:r}=e,i=Av(r),a=t.names().sort(),o=[];for(let e of a){let r=t.getNode(e),a=n.getLastError(e);o.push({name:e,source:i.get(e)??null,type:r.type,value:r.read(),lastError:a===void 0?null:{timestampMs:a.timestamp,message:a.message},ageMs:kv(r.lastUpdatedMs())})}return o}function kv(e){return e===null?null:Math.max(0,Date.now()-e)}function Av(e){let t=new Map;for(let[n,r]of Object.entries(e.variables))t.set(n,jv(r));for(let[n,r]of Object.entries(e.segments))if(r.vars)for(let[e,i]of Object.entries(r.vars))t.set(`${n}.${e}`,jv(i));return t}function jv(e){return e.kind}function Mv(e){if(e===null)return[];let{store:t,config:n,lastRenderBySegment:r}=e,i=new Set(t.names()),a=Nv(n),o=[];for(let e of a){let t=n.segments[e];t&&o.push({name:e,template:t.template,referencedVars:Pv(t.template,i),lastRender:r.get(e)??null})}return o}function Nv(e){let t=[],n=new Set;for(let r of Fn(e.root))r.kind===`segment`&&e.segments[r.name]&&!n.has(r.name)&&(t.push(r.name),n.add(r.name));for(let r of Object.keys(e.segments))n.has(r)||(t.push(r),n.add(r));return t}function Pv(e,t){let n=new Set;for(let r of gl(e)){if(t.has(r)){n.add(r);continue}let e=r.split(`.`);for(;e.length>1;){e.pop();let r=e.join(`.`);if(t.has(r)){n.add(r);break}}}return Array.from(n).sort()}function Fv(e){return e===null?null:e.config}const Iv=[`vars`,`segments`,`config`];function Lv(e){return typeof e==`string`&&Iv.includes(e)}function Rv(e){return Math.max(1,e-2)}var zv=class{thresholds={LOW:50,MEDIUM:80};getContextUsageThresholds(){return this.thresholds}ratioPercentages(e,t){let n=Math.min(100,Math.max(0,Math.round(e/t*100)));return{percentage:n,contextLeftPercentage:Math.max(0,100-n)}}calculateContextFromHookData(e){let t=e.context_window;if(!t?.current_usage)return O(`No current_usage in hook data, falling back to transcript parsing`),null;let n=t.current_usage,r=t.context_window_size,i=(n.input_tokens||0)+(n.cache_creation_input_tokens||0)+(n.cache_read_input_tokens||0);O(`Native current_usage: input=${n.input_tokens}, cache_create=${n.cache_creation_input_tokens}, cache_read=${n.cache_read_input_tokens}, total=${i} (limit: ${r})`);let a=this.ratioPercentages(i,r);return{totalTokens:i,maxTokens:r,percentage:t.used_percentage==null?a.percentage:Math.round(t.used_percentage),contextLeftPercentage:t.remaining_percentage==null?a.contextLeftPercentage:Math.round(t.remaining_percentage)}}async calculateContextTokensFromTranscript(e,t){try{O(`Calculating context tokens from transcript: ${e}`);let n=await yn(e);if(n.length===0)return O(`No entries in transcript`),Bt;let r=null;for(let e=n.length-1;e>=0;e--){let t=n[e];if(t&&t.message?.usage?.input_tokens&&t.isSidechain!==!0){r=t,O(`Context segment: Found most recent entry at ${t.timestamp.toISOString()}, stopping search`);break}}if(r?.message?.usage){let e=r.message.usage,n=(e.input_tokens||0)+(e.cache_read_input_tokens||0)+(e.cache_creation_input_tokens||0);return O(`Most recent main chain context: ${n} tokens (limit: ${t})`),N({totalTokens:n,maxTokens:t,...this.ratioPercentages(n,t)})}return O(`No main chain entries with usage data found`),Bt}catch(e){return P(`context transcript: ${e instanceof Error?e.message:String(e)}`)}}async getContextInfo(e){let t=this.calculateContextFromHookData(e);if(t)return N(t);let n=e.context_window?.context_window_size??2e5;return this.calculateContextTokensFromTranscript(e.transcript_path,n)}};function Bv(e){let t=e.type||e.message?.role||e.message?.type,n=e.type===`user`&&e.message?.firstContentType===`tool_result`;return t===`user`&&!n}var Vv=class{calculateMessageCount(e){return e.filter(Bv).length}calculateLastResponseTime(e){if(e.length===0)return null;let t=e.slice(-20),n=null,r=null;for(let e of t){let t=e.type||e.message?.role||e.message?.type;if(Bv(e))n=e.timestamp;else if(t===`assistant`&&n){let t=(e.timestamp.getTime()-n.getTime())/1e3;t>.1&&t<300&&(r=t)}}return r}async getMetricsInfo(e,t){try{if(O(`Getting metrics from hook data for session: ${e}`),!t.cost)return Bt;let n=(await yn(t.transcript_path)).filter(e=>!e.isSidechain),r=this.calculateMessageCount(n),i=this.calculateLastResponseTime(n);return N({responseTime:t.cost.total_api_duration_ms/1e3,lastResponseTime:i,sessionDuration:t.cost.total_duration_ms/1e3,messageCount:r,linesAdded:t.cost.total_lines_added,linesRemoved:t.cost.total_lines_removed})}catch(t){return P(`metrics (${e}): ${t instanceof Error?t.message:String(t)}`)}}};const Hv=new Map;function Uv(e){if(!e)return``;let t=e.indexOf(`,`);return t<0?e:e.slice(0,t)}var Wv=class{async getSessionId(){if(!process.env.TMUX_PANE)return Bt;let e=Uv(process.env.TMUX),t=Hv.get(e);if(t!==void 0)return t;O(`Getting tmux session ID, TMUX_PANE: ${process.env.TMUX_PANE}`);let n=await _e({bin:`tmux`,args:[`display-message`,`-p`,`#S`],timeoutMs:1e3,category:`tmux`}),r=n.ok?n.stdout.trim()?N(n.stdout.trim()):Bt:P(`tmux display-message: ${n.reason}`);return Hv.set(e,r),r}isInTmux(){return!!process.env.TMUX_PANE}};function Gv(e){return e<32||e===127||e>=128&&e<=159}function Kv(e,t){let n=``;for(let t of e)n+=Gv(t.codePointAt(0)??0)?` `:t;n=n.replace(/\s+/g,` `).trim();let r=``,i=0;for(let e of n){if(i===t)return r.replace(/.$/u,`…`);r+=e,i++}return r}const qv=`\x1B[38;2;255;255;255m`,Jv=`\x1B[48;2;200;40;40m`,Yv=`\x1B[0m`,Xv=new W_;k(Xv.launchStats);const Zv=new $t({counters:Xv,logger:M}),Qv=new on({watchers:Zv,logger:M}),$v=new Nn,ey=new tv,ty=new zv,ny=new Vv,ry=new Wv,iy=new H_({gitService:Qv,sessionState:ey,watchers:Zv});function ay(){n.mkdirSync(we(),{recursive:!0}),Ee(Te()),ey.useStorage(new iv(Oe(),500,M)),e.on(`uncaughtException`,e=>{M(`error`,`uncaughtException: ${e.stack||e.message}`),vy(1)}),e.on(`unhandledRejection`,e=>{M(`error`,`unhandledRejection: ${String(e)}`),vy(1)});for(let t of[`SIGINT`,`SIGTERM`,`SIGHUP`])e.on(t,()=>{M(`info`,`received ${t}, shutting down`),vy(0)});Z_({anchor:X_(e.env),isAlive:Q_,onOrphaned:e=>{M(`info`,`parent watchdog: ${e}; shutting down`),vy(0)}}),oy(m.createServer({allowHalfOpen:!1},e=>{yy(e)}),Te(),!1)}function oy(t,n,r){t.removeAllListeners(`error`),t.once(`error`,i=>{if(i.code!==`EADDRINUSE`){M(`error`,`server error: ${i.message}`),vy(1);return}if(r){M(`info`,`lost rebind race; another daemon is alive — exiting`),e.exit(0);return}sy(t,n)}),t.listen(n,()=>uy(n))}async function sy(t,r){await ly(r)&&(M(`info`,`another daemon is listening on socket — exiting`),e.exit(0)),await ly(r)&&(M(`info`,`race: another daemon claimed the socket during recovery — exiting`),e.exit(0)),M(`warn`,`stale socket from crashed daemon — unlinking and rebinding`);try{n.unlinkSync(r)}catch(e){if(e.code!==`ENOENT`){M(`error`,`cannot unlink stale socket ${r}: ${e.message}`),vy(1);return}}oy(t,r,!0)}function cy(e){return new Promise(t=>{let n=m.connect(e),r=!1,i=null,a=e=>{r||(r=!0,i&&clearTimeout(i),n.removeAllListeners(),n.destroy(),t(e))};n.once(`connect`,()=>a(`alive`)),n.once(`error`,e=>{let t=e.code;a(t===`ECONNREFUSED`||t===`ENOENT`||t===`ENOTSOCK`?`dead`:`unknown`)}),i=setTimeout(()=>a(`unknown`),50),i.unref()})}async function ly(e){return await cy(e)!==`dead`}function uy(t){try{n.chmodSync(t,384)}catch(e){M(`warn`,`chmod socket failed: ${e.message}`)}my(),M(`info`,`daemon up: pid=${e.pid} v=3 sock=${t}`),dy(),py()}function dy(){let t=import.meta.url,r=[];t.startsWith(`file://`)&&r.push(_(t)),e.argv[1]&&r.push(e.argv[1]);let i=new Map;for(let e of r)try{i.set(e,n.statSync(e).mtimeMs)}catch{}if(i.size===0)return;let a=setInterval(()=>{for(let[e,t]of i)try{if(n.statSync(e).mtimeMs!==t){M(`info`,`binary mtime changed (${e}); shutting down`),clearInterval(a),vy(0);return}}catch(e){M(`warn`,`bin stat failed: ${e.message}`)}},6e4);a.unref()}let fy=null;function py(){fy=K_(J_(Xv.startedAt.getTime(),e=>vy(e))),fy.arm()}function my(){let t=JSON.stringify({pid:e.pid,version:3,binPath:e.argv[1],startedAt:new Date().toISOString()});try{n.writeFileSync(De(),t,{mode:384}),n.chmodSync(De(),384)}catch(e){M(`warn`,`pidfile write failed: ${e.message}`)}}function hy(){try{n.unlinkSync(De())}catch{}}let gy=0,_y=!1;function vy(t){if(!_y){_y=!0,setTimeout(()=>e.kill(e.pid,`SIGKILL`),500);try{Qv.close()}catch(e){M(`warn`,`gitService close failed: ${e.message}`)}try{$v.close()}catch(e){M(`warn`,`usageStore close failed: ${e.message}`)}try{Zv.closeAll()}catch(e){M(`warn`,`watcherRegistry close failed: ${e.message}`)}try{ey.flush()}catch(e){M(`warn`,`sessionState flush failed: ${e.message}`)}hy(),zt(),e.exit(t)}}function yy(e){gy++,Xv.inFlight=gy;let t=!1,n=(n,r)=>{if(t){r!==null&&M(`warn`,`exit-after-flush dropped: an earlier responder settled this socket`);return}t=!0;let i=r===null?void 0:()=>vy(r);try{e.end(Ne(n),i)}catch(e){M(`warn`,`response write failed: ${e.message}`),i?.()}},r=setTimeout(()=>{Xv.requestsTimedOut++,n({ok:!1,error:`request exceeded 200ms`,code:`TIMEOUT`,daemonV:3},null)},200),i=Pe(e=>{xy(e).then(e=>n(e.resp,e.exitAfterFlush)).catch(e=>{M(`error`,`handler threw: ${e?.stack||e}`),n({ok:!1,error:String(e?.message||e),code:`RENDER_FAILED`,daemonV:3},null)})},e=>{M(`warn`,`frame parse failed: ${e.message}`),n({ok:!1,error:e.message,code:`BAD_REQUEST`,daemonV:3},null)});e.on(`data`,i),e.on(`error`,e=>{M(`warn`,`socket error: ${e.message}`)}),e.on(`close`,()=>{clearTimeout(r),gy=Math.max(0,gy-1),Xv.inFlight=gy})}const by=e=>({resp:e,exitAfterFlush:null});async function xy(e){if(!e||typeof e!=`object`||typeof e.v!=`number`)return by({ok:!1,error:`malformed request`,code:`BAD_REQUEST`,daemonV:3});if(e.v!==3)return e.v>3?M(`info`,`version mismatch: client=${e.v} > daemon=3; binary likely upgraded — exiting after the response flushes`):M(`info`,`version mismatch: client=${e.v} < daemon=3; client is stale — staying up`),{resp:{ok:!1,error:`protocol v${e.v} not supported (daemon at v3)`,code:`VERSION_MISMATCH`,daemonV:3},exitAfterFlush:e.v>3?0:null};if(e.kind===`shutdown`)return{resp:{ok:!0,output:``},exitAfterFlush:0};if(e.kind===`stats`)return by({ok:!0,stats:Xv.snapshot({gitCache:Qv.getStats(),usageCache:$v.getStats(),renderCacheSize:iy.size,watchersActive:Zv.size(),nextRestartReason:fy?.describeNextRestart()??null})});if(e.kind===`render`){Xv.requestsTotal++;let t=Date.now();try{let{report:n}=Tv(e.hookData);for(let e of n.unknownTopLevelFields)M(`info`,`schema: unknown field '${e}' — Anthropic may have added it`);let r=[];for(let e of n.missingRequired)r.push(`missing required field '${e}'`);for(let{path:e,expected:t,got:i}of n.typeMismatches)r.push(`field '${e}' expected ${t}, got ${i}`);if(e.cwd===``&&r.push(`request 'cwd' is empty`),r.length>0)return Xv.requestsErrored++,M(`warn`,`BAD_REQUEST: ${r.join(`; `)}`),by({ok:!1,error:`malformed hookData: ${r.join(`; `)}`,code:`BAD_REQUEST`,daemonV:3});let i=e.hookData.workspace.project_dir,{configFile:a,unknownFlagsError:o}=wy(e.args),s=e.hookData.session_id,c=ey.get(s,`config-override`)??a,l=iy.getOrCreate(i,e.cwd,c),u=je(e.termCols),d=Rv(u??120),f={...Oy,width:d},p=``;if(l.state!==null){let t=await ru(e.hookData,My,e.cwd,l.state.neededInputPaths),n=Tg(es(ey.get(e.hookData.session_id,`theme`),l.state.config.globals.palette));f.style=as(ey.get(e.hookData.session_id,`style`),l.state.config.globals.style),p=l_(l.state.config,l.state.compiled,l.state.store,l.state.registry,t,n,f,l.state.lastRenderCellsBySegment)}let m=ey.get(e.hookData.session_id,`click.error`);m&&ey.clear(e.hookData.session_id,`click.error`);let h=[o,l.lastError,m].filter(Boolean).join(`
|
|
109
109
|
`)||null,g=Ey(p,h,l.lastWarning),_=Date.now()-t,v=Qv.getStats(),y=$v.getStats();return M(`info`,`render sid=${e.hookData.session_id??`?`} took=${_}ms termCols=${u??`?`} width=${d} git=${v.size}/${v.hits}h/${v.misses}m usage=${y.size}/${y.hits}h/${y.misses}m err=${l.lastError?`Y`:`N`} warn=${l.lastWarning?`Y`:`N`}`),by({ok:!0,output:g+`
|
|
110
110
|
`})}catch(e){throw Xv.requestsErrored++,e}}if(e.kind===`click`)return by(await Ny(e.verb,e.value));if(e.kind===`debug`){if(!Lv(e.what))return by({ok:!1,error:`unknown debug 'what': ${String(e.what)} (have: ${Iv.join(`, `)})`,code:`BAD_REQUEST`,daemonV:3});let t=iy.firstPopulatedState(),n=t===null?null:{store:t.store,registry:t.registry,config:t.config,compiled:t.compiled,lastRenderBySegment:e.what===`segments`?jy(t.lastRenderCellsBySegment):Ay};return by({ok:!0,debug:Dv(e.what,n)})}return by({ok:!1,error:`unknown kind`,code:`BAD_REQUEST`,daemonV:3})}const Sy=`\x1B]8;;`,Cy=`\x1B]8;;\x1B\\`;function wy(e){let{values:t,tokens:n}=v({args:e.slice(1),options:{config:{type:`string`}},strict:!1,tokens:!0,allowPositionals:!0}),r=[...new Set((n??[]).filter(e=>e.kind===`option`&&e.name!==`config`).map(e=>`--${e.name}`))],i=t.config;return{configFile:i===void 0?void 0:Ml(i),unknownFlagsError:r.length>0?`Unknown flags: ${r.join(`, `)}`:null}}function Ty(e,t,n,r){let i=pt([{verb:e,args:[t]}]),a=t.split(/\r\n|\r|\n/).map(e=>Kv(e,120)).filter(Boolean).slice(0,8);return a.length===0?``:[`${Sy}${i}\\${n}${r} ⚠ ${a[0]} ${Yv}${Cy}`,...a.slice(1).map(e=>`${Sy}${i}\\${n}${r} ${e} ${Yv}${Cy}`)].join(`
|
|
111
111
|
`)}function Ey(e,t,n){let r=[];if(t&&r.push(Ty(lt,t,Jv,qv)),n&&r.push(Ty(ut,n,`\x1B[48;2;220;160;40m`,`\x1B[38;2;0;0;0m`)),r.length===0)return e;let i=r.join(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptctl/cc-candybar",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Statusline renderer for Claude Code — a JSON5-configurable DSL with daemon-cached data sources, byte-clean palette-aware composition, and OSC8 click verbs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -91,10 +91,10 @@
|
|
|
91
91
|
"mobx": "^6.15.0"
|
|
92
92
|
},
|
|
93
93
|
"optionalDependencies": {
|
|
94
|
-
"@promptctl/cc-candybar-darwin-arm64": "1.7.
|
|
95
|
-
"@promptctl/cc-candybar-darwin-x64": "1.7.
|
|
96
|
-
"@promptctl/cc-candybar-linux-x64": "1.7.
|
|
97
|
-
"@promptctl/cc-candybar-linux-arm64": "1.7.
|
|
94
|
+
"@promptctl/cc-candybar-darwin-arm64": "1.7.1",
|
|
95
|
+
"@promptctl/cc-candybar-darwin-x64": "1.7.1",
|
|
96
|
+
"@promptctl/cc-candybar-linux-x64": "1.7.1",
|
|
97
|
+
"@promptctl/cc-candybar-linux-arm64": "1.7.1"
|
|
98
98
|
},
|
|
99
99
|
"pnpm": {
|
|
100
100
|
"supportedArchitectures": {
|
|
@@ -11,13 +11,21 @@
|
|
|
11
11
|
// Variability lives in the inputs (hint set or not, env set or not, stderr a
|
|
12
12
|
// TTY or not), never in whether work runs.
|
|
13
13
|
|
|
14
|
-
// @info Reserves
|
|
15
|
-
//
|
|
16
|
-
|
|
14
|
+
// @info Reserves columns for Claude Code's statusline left gutter. Claude Code
|
|
15
|
+
// prints each statusline row inset by a fixed left margin, so a row rendered at
|
|
16
|
+
// the full raw column count would be shifted right past the terminal edge and
|
|
17
|
+
// soft-wrap its trailing cells. The reserve is exactly that left margin — NOT a
|
|
18
|
+
// right-side overlay budget. The version/autoupdate/"Remote Control" hints render
|
|
19
|
+
// on their own right-aligned lines below the bar and never overlap a statusline
|
|
20
|
+
// row, so they cost zero usable width here. Verified empirically against a live
|
|
21
|
+
// Claude Code statusline (the older value of 45 was a guess for a right-side
|
|
22
|
+
// overlay that does not sit on the statusline row); re-measure if Claude Code's
|
|
23
|
+
// statusline gutter changes.
|
|
24
|
+
const RESERVED_CHARS = 2;
|
|
17
25
|
|
|
18
26
|
// [LAW:single-enforcer] The canonical raw-cols → usable-cols transform.
|
|
19
|
-
// Every consumer that needs to honor Claude Code's
|
|
20
|
-
// here; there is no parallel `cols -
|
|
27
|
+
// Every consumer that needs to honor Claude Code's statusline gutter routes
|
|
28
|
+
// through here; there is no parallel `cols - N` math anywhere. Exposed so callers
|
|
21
29
|
// that already have a raw width (e.g. the daemon's wire-fallback path,
|
|
22
30
|
// the demo reading process.stdout.columns) can apply the reserve without
|
|
23
31
|
// re-entering the env/stderr resolution chain in getTerminalWidth.
|