ccpet
Version:
A Claude Code status line script that displays a virtual pet
7 lines (6 loc) • 34.4 kB
JavaScript
;var pe=Object.create;var O=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var me=Object.getOwnPropertyNames;var fe=Object.getPrototypeOf,he=Object.prototype.hasOwnProperty;var ye=(o,e)=>{for(var t in e)O(o,t,{get:e[t],enumerable:!0})},ee=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of me(e))!he.call(o,n)&&n!==t&&O(o,n,{get:()=>e[n],enumerable:!(s=ge(e,n))||s.enumerable});return o};var y=(o,e,t)=>(t=o!=null?pe(fe(o)):{},ee(e||!o||!o.__esModule?O(t,"default",{value:o,enumerable:!0}):t,o)),Te=o=>ee(O({},"__esModule",{value:!0}),o);var Le={};ye(Le,{ClaudeCodeStatusLine:()=>N,StatusBarFormatter:()=>D,activate:()=>ke,deactivate:()=>we,main:()=>De});module.exports=Te(Le);function Se(){let o=process.env.COLORTERM,e=process.env.TERM;return!!(o==="truecolor"||o==="24bit"||e&&(["iterm","iterm2","alacritty","kitty","wezterm"].some(s=>e.toLowerCase().includes(s))||e.includes("256color"))||process.env.WT_SESSION)}function Ee(o){let e=o.replace("#",""),t=parseInt(e.substring(0,2),16),s=parseInt(e.substring(2,4),16),n=parseInt(e.substring(4,6),16);return{r:t,g:s,b:n}}function be(o,e,t){let s=[{r:0,g:0,b:0},{r:128,g:0,b:0},{r:0,g:128,b:0},{r:128,g:128,b:0},{r:0,g:0,b:128},{r:128,g:0,b:128},{r:0,g:128,b:128},{r:192,g:192,b:192},{r:128,g:128,b:128},{r:255,g:0,b:0},{r:0,g:255,b:0},{r:255,g:255,b:0},{r:0,g:0,b:255},{r:255,g:0,b:255},{r:0,g:255,b:255},{r:255,g:255,b:255}],n=0,r=1/0;for(let i=0;i<s.length;i++){let c=s[i],a=Math.sqrt(Math.pow(o-c.r,2)+Math.pow(e-c.g,2)+Math.pow(t-c.b,2));a<r&&(r=a,n=i)}for(let i=0;i<216;i++){let c=16+i,a=Math.floor(i/36)*51,d=Math.floor(i%36/6)*51,m=i%6*51,P=Math.sqrt(Math.pow(o-a,2)+Math.pow(e-d,2)+Math.pow(t-m,2));P<r&&(r=P,n=c)}for(let i=0;i<24;i++){let c=232+i,a=8+i*10,d=Math.sqrt(Math.pow(o-a,2)+Math.pow(e-a,2)+Math.pow(t-a,2));d<r&&(r=d,n=c)}return n}function Ce(o,e,t){return`\x1B[38;2;${o};${e};${t}m`}function ve(o,e=!1,t=!1){if(o==="RESET")return"\x1B[0m";let{r:s,g:n,b:r}=Ee(o);if(Se()){let a=Ce(s,n,r);return t?`\x1B[1m${a}`:a}let i=be(s,n,r);if(e&&i<8)return`\x1B[1;3${i}m`;let c=`\x1B[38;5;${i}m`;return t?`\x1B[1m${c}`:c}function J(o){let e={};for(let[t,s]of Object.entries(o))if(t==="RESET")e[t]="\x1B[0m";else{let n=s.split(":"),r=n[0],i=n.includes("bright"),c=n.includes("bold");e[t]=ve(r,i,c)}return e}var v=y(require("fs")),M=y(require("path")),te=y(require("os"));var E={colors:{petExpression:"#FFFF00:bright:bold",petName:"#00FFFF:bright",energyBar:"#00FF00",energyValue:"#00FFFF",accumulatedTokens:"#778899",lifetimeTokens:"#FF00FF",sessionInput:"#00FF00",sessionOutput:"#FFFF00",sessionCached:"#F4A460",sessionTotal:"#FFFFFF",contextLength:"#00DDFF",contextPercentage:"#0099DD",contextPercentageUsable:"#90EE90",cost:"#FFD700"},pet:{animationEnabled:!0,decayRate:.0231,emojiEnabled:!0},display:{maxLines:3,line1:{enabled:!0,items:["expression","energy-bar","energy-value","accumulated-tokens","lifetime-tokens"]},line2:{enabled:!0,items:["input","output","cached","total"]},line3:{enabled:!0,items:["context-length","context-percentage","context-percentage-usable","cost"]}},supabase:{url:"https://rzsupavqzxhyrgcexrpx.supabase.co",apiKey:"sbp_88f3151cc0a24a37dd71617c562e62a79727ef6f",autoSync:!1,syncInterval:1440}},b=class{configDir;configFile;cachedConfig=null;constructor(e){if(e)this.configDir=e,this.configFile=M.join(e,"config.json");else{let s=process.env.NODE_ENV==="test"||process.env.VITEST==="true"?".claude-pet-test":".claude-pet";this.configDir=M.join(te.homedir(),s),this.configFile=M.join(this.configDir,"config.json")}}ensureConfigDir(){v.existsSync(this.configDir)||v.mkdirSync(this.configDir,{recursive:!0})}loadConfig(){if(this.cachedConfig)return this.cachedConfig;if(this.ensureConfigDir(),!v.existsSync(this.configFile)){let e=JSON.parse(JSON.stringify(E));return this.saveConfig(e),this.cachedConfig=e,e}try{let e=v.readFileSync(this.configFile,"utf8"),t=JSON.parse(e);return this.cachedConfig=this.mergeWithDefaults(t),this.cachedConfig}catch(e){let t=e instanceof Error?e.message:"Unknown error";console.warn("Failed to load config, using defaults:",t);let s=JSON.parse(JSON.stringify(E));return this.cachedConfig=s,s}}mergeWithDefaults(e){return{colors:{...E.colors,...e.colors},pet:{...E.pet,...e.pet},display:{...E.display,...e.display,line1:{...E.display.line1,...e.display?.line1},line2:{...E.display.line2,...e.display?.line2},line3:{...E.display.line3,...e.display?.line3}},supabase:{...E.supabase,...e.supabase}}}saveConfig(e){this.ensureConfigDir(),v.writeFileSync(this.configFile,JSON.stringify(e,null,2),"utf8"),this.cachedConfig=JSON.parse(JSON.stringify(e))}getConfig(){return this.loadConfig()}setColorConfig(e,t){let s=this.loadConfig();s.colors[e]=t,this.saveConfig(s)}setPetConfig(e,t){let s=this.loadConfig();s.pet[e]=t,this.saveConfig(s)}setDisplayConfig(e,t){let s=this.loadConfig();if(e==="maxLines")s.display.maxLines=Math.min(3,Math.max(1,Number(t)));else if(e==="line1.enabled")s.display.line1.enabled=!!t;else if(e==="line1.items"){let n=Array.isArray(t)?t:t.split(",").map(c=>c.trim()),r=U(n),i=n.filter(c=>!r.includes(c));i.length>0&&console.warn(`Invalid line1 items ignored: ${i.join(", ")}`),s.display.line1.items=r.length>0?r:["expression","energy-bar","energy-value","accumulated-tokens","lifetime-tokens"]}else e==="line2.enabled"?s.display.line2.enabled=!!t:e==="line2.items"?s.display.line2.items=Array.isArray(t)?t:t.split(",").map(n=>n.trim()):e==="line3.enabled"?s.display.line3.enabled=!!t:e==="line3.items"&&(s.display.line3.items=Array.isArray(t)?t:t.split(",").map(n=>n.trim()));this.saveConfig(s)}setSupabaseConfig(e,t){let s=this.getConfig();if(s.supabase||(s.supabase={}),e==="url")s.supabase.url=t;else if(e==="apiKey")s.supabase.apiKey=t;else if(e==="autoSync")s.supabase.autoSync=t;else if(e==="syncInterval"){let n=Number(t);if(!isNaN(n)&&n>0)s.supabase.syncInterval=n;else throw new Error(`Invalid syncInterval value: ${t}. Must be a positive number.`)}else throw new Error(`Unknown Supabase configuration key: ${e}`);this.saveConfig(s)}resetConfig(){this.saveConfig(E)}listConfig(){let e=this.getConfig();return JSON.stringify(e,null,2)}getConfigPath(){return this.configFile}};var k=(r=>(r.CAT="cat",r.DOG="dog",r.RABBIT="rabbit",r.PANDA="panda",r.FOX="fox",r))(k||{}),_e=["expression","energy-bar","energy-value","accumulated-tokens","lifetime-tokens","pet-name"];function Fe(o){try{let t=(o||new b).getConfig();return{PET_EXPRESSION:t.colors.petExpression||"#FFFF00:bright:bold",PET_NAME:t.colors.petName||"#00FFFF:bright",ENERGY_BAR:t.colors.energyBar||"#00FF00",ENERGY_VALUE:t.colors.energyValue||"#00FFFF",ACCUMULATED_TOKENS:t.colors.accumulatedTokens||"#778899",LIFETIME_TOKENS:t.colors.lifetimeTokens||"#FF00FF",SESSION_INPUT:t.colors.sessionInput||"#00FF00",SESSION_OUTPUT:t.colors.sessionOutput||"#FFFF00",SESSION_CACHED:t.colors.sessionCached||"#F4A460",SESSION_TOTAL:t.colors.sessionTotal||"#FFFFFF",CONTEXT_LENGTH:t.colors.contextLength||"#00DDFF",CONTEXT_PERCENTAGE:t.colors.contextPercentage||"#0099DD",CONTEXT_PERCENTAGE_USABLE:t.colors.contextPercentageUsable||"#90EE90",COST:t.colors.cost||"#FFD700",RESET:"RESET"}}catch{return{PET_EXPRESSION:"#FFFF00:bright:bold",PET_NAME:"#00FFFF:bright",ENERGY_BAR:"#00FF00",ENERGY_VALUE:"#00FFFF",ACCUMULATED_TOKENS:"#778899",LIFETIME_TOKENS:"#FF00FF",SESSION_INPUT:"#00FF00",SESSION_OUTPUT:"#FFFF00",SESSION_CACHED:"#F4A460",SESSION_TOTAL:"#FFFFFF",CONTEXT_LENGTH:"#00DDFF",CONTEXT_PERCENTAGE:"#0099DD",CONTEXT_PERCENTAGE_USABLE:"#90EE90",COST:"#FFD700",RESET:"RESET"}}}function Ne(){return{PET_EXPRESSION:"#FFFF00:bright:bold",PET_NAME:"#00FFFF:bright",ENERGY_BAR:"#00FF00",ENERGY_VALUE:"#00FFFF",ACCUMULATED_TOKENS:"#778899",LIFETIME_TOKENS:"#FF00FF",SESSION_INPUT:"#00FF00",SESSION_OUTPUT:"#FFFF00",SESSION_CACHED:"#F4A460",SESSION_TOTAL:"#FFFFFF",CONTEXT_LENGTH:"#00DDFF",CONTEXT_PERCENTAGE:"#0099DD",CONTEXT_PERCENTAGE_USABLE:"#90EE90",COST:"#FFD700",RESET:"RESET"}}var V=["Fluffy","Whiskers","Shadow","Luna","Max","Bella","Charlie","Lucy","Cooper","Ruby","Milo","Lily","Buddy","Chloe","Rocky","\u5C0F\u767D","\u6BDB\u6BDB","\u7403\u7403","\u8C46\u8C46","\u82B1\u82B1","\u54AA\u54AA","\u65FA\u8D22","\u5C0F\u9ED1","\u96EA\u513F","\u7CD6\u7CD6"];function F(){if(V.length===0)return"Pet";let o=Math.floor(Math.random()*V.length);return V[o]}var I={cat:{id:"cat",name:"\u732B",emoji:"\u{1F431}"},dog:{id:"dog",name:"\u72D7",emoji:"\u{1F436}"},rabbit:{id:"rabbit",name:"\u5154\u5B50",emoji:"\u{1F430}"},panda:{id:"panda",name:"\u718A\u732B",emoji:"\u{1F43C}"},fox:{id:"fox",name:"\u72D0\u72F8",emoji:"\u{1F98A}"}},h={INITIAL_ENERGY:100,HAPPY_EXPRESSION_THRESHOLD:80,HAPPY_EXPRESSION:"(^_^)",ENERGY_BAR_LENGTH:10,STATUS_BAR_PRIORITY:100,FILLED_BAR_CHAR:"\u25CF",EMPTY_BAR_CHAR:"\u25CB",STATE_THRESHOLDS:{HAPPY:80,HUNGRY:40,SICK:10,DEAD:0},STATE_EXPRESSIONS:{HAPPY:"(^_^)",HUNGRY:"(o_o)",SICK:"(u_u)",DEAD:"(x_x)"},ANIMATED_EXPRESSIONS:{HAPPY:["(^_^)","(^o^)","(^_^)","(^v^)"],HUNGRY:["(o_o)","(O_O)","(o_o)","(-_-)"],SICK:["(u_u)","(T_T)","(u_u)","(>_<)"],DEAD:["(x_x)","(X_X)","(x_x)","(+_+)"]},TIME_DECAY:{DECAY_CHECK_INTERVAL:6e4,DECAY_RATE:.0231,MINIMUM_DECAY_INTERVAL:6e4},FEEDING:{TOKENS_PER_ENERGY:1e6},ANIMAL:{DEFAULT_TYPE:"cat"},COLORS:J(Ne())};function se(o){return J(Fe(o))}function U(o){return o.filter(e=>_e.includes(e))}var je={DEFAULT_URL:process.env.SUPABASE_URL||"",DEFAULT_API_KEY:process.env.SUPABASE_ANON_KEY||"",BATCH_SIZE:100,DEFAULT_SYNC_INTERVAL:24*60*60*1e3,MAX_RETRY_ATTEMPTS:3,RETRY_DELAY_MS:1e3};var g=[];for(let o=0;o<256;++o)g.push((o+256).toString(16).slice(1));function ne(o,e=0){return(g[o[e+0]]+g[o[e+1]]+g[o[e+2]]+g[o[e+3]]+"-"+g[o[e+4]]+g[o[e+5]]+"-"+g[o[e+6]]+g[o[e+7]]+"-"+g[o[e+8]]+g[o[e+9]]+"-"+g[o[e+10]]+g[o[e+11]]+g[o[e+12]]+g[o[e+13]]+g[o[e+14]]+g[o[e+15]]).toLowerCase()}var oe=require("crypto"),$=new Uint8Array(256),G=$.length;function q(){return G>$.length-16&&((0,oe.randomFillSync)($),G=0),$.slice(G,G+=16)}var re=require("crypto"),z={randomUUID:re.randomUUID};function Pe(o,e,t){if(z.randomUUID&&!e&&!o)return z.randomUUID();o=o||{};let s=o.random??o.rng?.()??q();if(s.length<16)throw new Error("Random bytes length must be >= 16");if(s[6]=s[6]&15|64,s[8]=s[8]&63|128,e){if(t=t||0,t<0||t+16>e.length)throw new RangeError(`UUID byte range ${t}:${t+15} is out of buffer bounds`);for(let n=0;n<16;++n)e[t+n]=s[n];return e}return ne(s)}var _=Pe;var w=class o{state;deps;observers=[];constructor(e,t){this.state={...e,uuid:e.uuid||_(),petName:e.petName||F(),emoji:e.emoji||I[e.animalType]?.emoji||I.cat.emoji},this.deps=t,this._updateExpression()}getState(){return{...this.state}}subscribe(e){return this.observers.push(e),()=>{let t=this.observers.indexOf(e);t>-1&&this.observers.splice(t,1)}}feed(e){try{let t=this.state.accumulatedTokens+e,{TOKENS_PER_ENERGY:s}=this.deps.config.FEEDING,n=Math.floor(t/s),r=t%s;this.state={...this.state,accumulatedTokens:r,lastFeedTime:new Date,totalTokensConsumed:this.state.totalTokensConsumed+e,totalLifetimeTokens:this.state.totalLifetimeTokens+e},n>0&&this.addEnergy(n)}catch(t){console.error("Pet feeding failed:",t)}}applyTimeDecay(){try{let e=new Date,{TIME_DECAY:t}=this.deps.config,s=this.state.lastDecayTime||this.state.lastFeedTime,n=(e.getTime()-s.getTime())/(1e3*60);if(n>0){let r=t?t.DECAY_RATE/(t.DECAY_CHECK_INTERVAL/6e4):.023148148148148147,i=n*r,c=t?t.MINIMUM_DECAY_INTERVAL/(1e3*60):0;i>0&&n>=c&&(this.decreaseEnergy(i),this.state={...this.state,lastDecayTime:e})}}catch(e){console.error("Pet time decay failed:",e)}}addEnergy(e){try{if(typeof e!="number"||e<0||isNaN(e))throw new Error(`Invalid energy amount: ${e}. Must be a non-negative number.`);let t=new Date;this.state={...this.state,energy:Math.min(100,this.state.energy+e),lastFeedTime:t,lastDecayTime:t},this._updateExpression(),this._notify()}catch(t){throw console.error("Pet addEnergy failed:",t),t}}decreaseEnergy(e){try{if(typeof e!="number"||e<0||isNaN(e))throw new Error(`Invalid energy amount: ${e}. Must be a non-negative number.`);this.state={...this.state,energy:Math.max(0,this.state.energy-e)},this._updateExpression(),this._notify()}catch(t){throw console.error("Pet decreaseEnergy failed:",t),t}}getCurrentEnergy(){return this.state.energy}getCurrentAnimalType(){return this.state.animalType}static getRandomAnimalType(){let e=Object.values(k),t=Math.floor(Math.random()*e.length);return e[t]}getAnimalEmoji(){return this.state.emoji||I[this.state.animalType]?.emoji||I.cat.emoji}isDead(){return this.state.energy===0}resetToInitialState(e){try{if(e&&this.isDead())try{e({...this.state})}catch(n){console.error("Graveyard callback failed, but continuing with reset:",n)}let t=new Date,s=o.getRandomAnimalType();this.state={uuid:_(),energy:this.deps.config.INITIAL_ENERGY,expression:this.deps.config.STATE_EXPRESSIONS.HAPPY,animalType:s,emoji:I[s]?.emoji||I.cat.emoji,birthTime:t,lastFeedTime:t,totalTokensConsumed:0,accumulatedTokens:0,totalLifetimeTokens:0,lastDecayTime:t,sessionTotalInputTokens:0,sessionTotalOutputTokens:0,sessionTotalCachedTokens:0,petName:F()},console.log(`Pet reborn as ${s} type with name: ${this.state.petName}`),this._updateExpression(),this._notify()}catch(t){throw console.error("Pet resetToInitialState failed:",t),t}}_updateExpression(){if(!this.deps?.config)return;let{STATE_THRESHOLDS:e,STATE_EXPRESSIONS:t}=this.deps.config;this.state.energy>=e.HAPPY?this.state.expression=t.HAPPY:this.state.energy>=e.HUNGRY?this.state.expression=t.HUNGRY:this.state.energy>=e.SICK?this.state.expression=t.SICK:this.state.expression=t.DEAD}getAnimatedExpression(e=!1,t=0,s=!0){let{STATE_THRESHOLDS:n,ANIMATED_EXPRESSIONS:r}=this.deps.config,i;if(!e||!r)i=this.state.expression;else{let c;this.state.energy>=n.HAPPY?c=r.HAPPY:this.state.energy>=n.HUNGRY?c=r.HUNGRY:this.state.energy>=n.SICK?c=r.SICK:c=r.DEAD;let a=t%c.length;i=c[a]}return s?`${this.getAnimalEmoji()}${i}`:i}updateSessionMetrics(e){try{this.state={...this.state,...e}}catch(t){console.error("Pet updateSessionMetrics failed:",t)}}_notify(){this.observers.forEach(e=>{try{e(this.getState())}catch(t){console.error("Observer notification failed:",t)}})}};var D=class{testMode;configService;constructor(e=!1,t){this.testMode=e,this.configService=t||new b}getColors(){return this.testMode?h.COLORS:se(this.configService)}formatPetDisplay(e,t){try{let s=this.configService.getConfig(),n=[];if(s.display.line1?.enabled!==!1&&(s.display.maxLines||3)>=1){let i=s.display.line1?.items?this.formatConfigurablePetLine(s.display.line1.items,e,t):this.formatPetLine(e,t);n.push(i)}let r=this.getSessionData(e);if(s.display.line2?.enabled&&(s.display.maxLines||3)>=2){let i=this.formatConfigurableLine(s.display.line2.items||[],r);i&&n.push(i)}if(s.display.line3?.enabled&&(s.display.maxLines||3)>=3){let i=this.formatConfigurableLine(s.display.line3.items||[],r);i&&n.push(i)}return n.join((this.testMode,`
`))}catch(s){return console.error("Failed to format pet display:",s),console.error("Error stack:",s instanceof Error?s.stack:"No stack trace"),"(?) ERROR"}}formatPetLine(e,t){let s=this.generateEnergyBar(e.energy),n=e.energy.toFixed(2),r=this.formatTokenCount(e.accumulatedTokens),i=this.formatTokenCount(e.totalLifetimeTokens),c=t||e.expression;if(this.testMode)return`${c} ${s} ${n} (${r}) \u{1F496}${i}`;{let a=this.getColors();return`${a.PET_EXPRESSION}${c}${a.RESET} ${a.ENERGY_BAR}${s}${a.RESET} ${a.ENERGY_VALUE}${n}${a.RESET} ${a.ACCUMULATED_TOKENS}(${r})${a.RESET} ${a.LIFETIME_TOKENS}\u{1F496}${i}${a.RESET}`}}formatConfigurablePetLine(e,t,s){try{let n=U(e);if(n.length===0)return console.warn("No valid line1 items found, falling back to default format"),this.formatPetLine(t,s);let r=this.getLine1Data(t,s),i=[];for(let c of n)if(r[c]){let a=r[c];if(this.testMode)i.push(a.value);else{let d=this.getColors();i.push(`${a.color}${a.value}${d.RESET}`)}}else console.warn(`Line1 data not available for item: ${c}`);return i.length>0?i.join(" "):this.formatPetLine(t,s)}catch(n){return console.error("Error in formatConfigurablePetLine:",n),this.formatPetLine(t,s)}}getLine1Data(e,t){let s=t||e.expression,n=this.generateEnergyBar(e.energy),r=e.energy.toFixed(2),i=this.formatTokenCount(e.accumulatedTokens),c=this.formatTokenCount(e.totalLifetimeTokens),a=this.getColors();return{expression:{value:s,color:a.PET_EXPRESSION},"energy-bar":{value:n,color:a.ENERGY_BAR},"energy-value":{value:r,color:a.ENERGY_VALUE},"accumulated-tokens":{value:`(${i})`,color:a.ACCUMULATED_TOKENS},"lifetime-tokens":{value:`\u{1F496}${c}`,color:a.LIFETIME_TOKENS},"pet-name":{value:e.petName||"Pet",color:a.PET_NAME}}}getSessionData(e){let t={},s=this.getColors();if(e.sessionTotalInputTokens!==void 0&&(t.input={value:this.formatTokenCount(e.sessionTotalInputTokens),color:s.SESSION_INPUT}),e.sessionTotalOutputTokens!==void 0&&(t.output={value:this.formatTokenCount(e.sessionTotalOutputTokens),color:s.SESSION_OUTPUT}),e.sessionTotalCachedTokens!==void 0&&(t.cached={value:this.formatTokenCount(e.sessionTotalCachedTokens),color:s.SESSION_CACHED}),e.sessionTotalInputTokens!==void 0&&e.sessionTotalOutputTokens!==void 0&&e.sessionTotalCachedTokens!==void 0){let n=e.sessionTotalInputTokens+e.sessionTotalOutputTokens+e.sessionTotalCachedTokens;t.total={value:this.formatTokenCount(n),color:s.SESSION_TOTAL}}return e.sessionTotalCostUsd!==void 0&&(t.cost={value:`$${e.sessionTotalCostUsd.toFixed(2)}`,color:s.COST}),e.contextLength!==void 0&&(t["context-length"]={value:this.formatTokenCount(e.contextLength),color:s.CONTEXT_LENGTH}),e.contextPercentage!==void 0&&(t["context-percentage"]={value:isNaN(e.contextPercentage)?"0.0%":`${e.contextPercentage.toFixed(1)}%`,color:s.CONTEXT_PERCENTAGE}),e.contextPercentageUsable!==void 0&&(t["context-percentage-usable"]={value:isNaN(e.contextPercentageUsable)?"0.0%":`${e.contextPercentageUsable.toFixed(1)}%`,color:s.CONTEXT_PERCENTAGE_USABLE}),t}formatConfigurableLine(e,t){let s=[];for(let n of e)if(t[n]){let r=t[n],i;if(n==="context-length"||n==="context-percentage"?i="Ctx":n==="context-percentage-usable"?i="Ctx(u)":n==="cost"?i="Cost":i=n.charAt(0).toUpperCase()+n.slice(1),this.testMode)s.push(`${i}: ${r.value}`);else{let c=this.getColors();s.push(`${r.color}${i}: ${r.value}${c.RESET}`)}}return s.length>0?s.join(" "):""}generateEnergyBar(e){try{if(isNaN(e))return"??????????";let t=Math.max(0,Math.min(100,e)),s=Math.round(t/100*h.ENERGY_BAR_LENGTH),n=h.ENERGY_BAR_LENGTH-s;return h.FILLED_BAR_CHAR.repeat(s)+h.EMPTY_BAR_CHAR.repeat(n)}catch(t){return console.error("Failed to generate energy bar:",t),"??????????"}}formatTokenCount(e){try{return isNaN(e)?"?":e>=1e6?`${(e/1e6).toFixed(2)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toString()}catch(t){return console.error("Failed to format token count:",t),"?"}}};var l=y(require("fs")),C=y(require("path")),W=y(require("os")),j=class{stateFilePath;constructor(){let e=W.homedir(),t=C.join(e,".claude-pet");this.stateFilePath=C.join(t,"pet-state.json"),this.ensureDirectoryExists(t)}loadState(){try{if(!l.existsSync(this.stateFilePath))return null;let e=l.readFileSync(this.stateFilePath,"utf8"),t=JSON.parse(e);return t.lastFeedTime&&(t.lastFeedTime=new Date(t.lastFeedTime)),t.lastDecayTime&&(t.lastDecayTime=new Date(t.lastDecayTime)),t.birthTime&&(t.birthTime=new Date(t.birthTime)),t.totalLifetimeTokens===void 0&&(t.totalLifetimeTokens=t.totalTokensConsumed||0),t.animalType===void 0&&(t.animalType=h.ANIMAL.DEFAULT_TYPE,console.log(`Migrating existing pet to default animal type: ${t.animalType}`)),Object.values(k).includes(t.animalType)||(console.warn(`Invalid animal type found: ${t.animalType}, using default`),t.animalType=h.ANIMAL.DEFAULT_TYPE),t.birthTime===void 0&&(t.birthTime=t.lastFeedTime||new Date,console.log(`Adding birthTime for existing pet: ${t.birthTime.toISOString()}`)),(t.petName===void 0||t.petName==="")&&(t.petName=F(),console.log(`Adding petName for existing pet: ${t.petName}`)),t.uuid===void 0&&(t.uuid=_(),console.log(`Adding uuid for existing pet: ${t.uuid}`)),t}catch(e){return console.error("Failed to load pet state:",e),null}}saveState(e){try{let t=JSON.stringify(e,null,2);l.writeFileSync(this.stateFilePath,t,"utf8")}catch(t){console.error("Failed to save pet state:",t)}}moveToGraveyard(e){try{let t=this._getGraveyardDir();this.ensureDirectoryExists(t);let s=this._createPetGraveyardDir(e.petName,t),n=C.join(s,"pet-state.json");this._atomicMoveToGraveyard(e,n)}catch(t){throw console.error("Failed to move pet to graveyard:",t),new Error(`Graveyard operation failed: ${t instanceof Error?t.message:"Unknown error"}`)}}loadGraveyardStates(){try{let e=this._getGraveyardDir();if(!l.existsSync(e))return[];let t=[],s=l.readdirSync(e,{withFileTypes:!0}).filter(n=>n.isDirectory()).map(n=>n.name);for(let n of s)try{let r=C.join(e,n),i=C.join(r,"pet-state.json");if(l.existsSync(i)){let c=l.readFileSync(i,"utf8"),a=JSON.parse(c),d={...a,birthTime:new Date(a.birthTime),lastFeedTime:new Date(a.lastFeedTime),lastDecayTime:a.lastDecayTime?new Date(a.lastDecayTime):void 0,uuid:a.uuid||_(),petName:a.petName||F()};if(!a.uuid||!a.petName)try{let m=JSON.stringify(d,null,2);l.writeFileSync(i,m,"utf8"),console.log(`Updated graveyard state for ${d.petName} with missing UUID/name`)}catch(m){console.warn(`Failed to update graveyard file ${i}:`,m)}t.push(d)}}catch(r){console.warn(`Failed to load graveyard state from ${n}:`,r)}return t}catch(e){return console.error("Failed to load graveyard states:",e),[]}}loadUnsyncedGraveyardStates(e){return this.loadGraveyardStates().filter(s=>!e.has(s.uuid))}ensureDirectoryExists(e){try{l.existsSync(e)||l.mkdirSync(e,{recursive:!0})}catch(t){console.error("Failed to create pet storage directory:",t)}}_getGraveyardDir(){let e=W.homedir(),t=C.join(e,".claude-pet");return C.join(t,"graveyard")}_createPetGraveyardDir(e,t){let s=this._sanitizePetName(e),n=C.join(t,s),r=1;for(;l.existsSync(n)&&r<1e3;)r++,n=C.join(t,`${s}-${r}`);if(r>=1e3)throw new Error(`Too many pets with similar names. Cannot create unique graveyard directory for ${e}`);return this.ensureDirectoryExists(n),n}_sanitizePetName(e){return e.replace(/[\/\\:*?"<>|]/g,"_").replace(/\.\./g,"_").trim().substring(0,100)}_atomicMoveToGraveyard(e,t){let s=null;try{l.existsSync(this.stateFilePath)&&(s=`${this.stateFilePath}.backup.${Date.now()}`,l.copyFileSync(this.stateFilePath,s));let n=JSON.stringify(e,null,2);if(l.writeFileSync(t,n,"utf8"),!l.existsSync(t))throw new Error("Failed to verify graveyard file creation");l.existsSync(this.stateFilePath)&&l.unlinkSync(this.stateFilePath),s&&l.existsSync(s)&&l.unlinkSync(s)}catch(n){throw this._recoverFromStorageFailure(s,n),n}}_recoverFromStorageFailure(e,t){try{e&&l.existsSync(e)&&(l.copyFileSync(e,this.stateFilePath),l.unlinkSync(e),console.log("Successfully recovered pet state from backup after storage failure"))}catch(s){console.error("Failed to recover from storage failure:",s),console.error("Original error:",t)}}};var ie=require("child_process"),f=y(require("fs")),x=y(require("path")),ae=y(require("os")),Y=class{configService;lastSyncFile;syncLogFile;testMode;constructor(e,t=!1){this.configService=e||new b,this.testMode=t;let s=t?".claude-pet-test":".claude-pet",n=x.join(ae.homedir(),s);this.lastSyncFile=x.join(n,"last-sync.json"),this.syncLogFile=x.join(n,"sync.log")}writeSyncLog(e,t="info"){try{let n=`[${new Date().toISOString()}] ${t.toUpperCase()}: ${e}
`,r=x.dirname(this.syncLogFile);f.existsSync(r)||f.mkdirSync(r,{recursive:!0}),f.appendFileSync(this.syncLogFile,n)}catch{}}async checkAndTriggerAutoSync(){try{let e=this.configService.getConfig();if(!e.supabase?.autoSync)return;if(!e.supabase.url||!e.supabase.apiKey){console.warn("Auto sync enabled but Supabase configuration is incomplete");return}let s=(e.supabase.syncInterval||1440)*60*1e3,n=this.getLastSyncRecord(),r=Date.now();if(n.syncInProgress){let i=n.lastSyncTime,c=5*60*1e3;if(r-i>c)this.writeSyncLog(`Detected stale sync process (${Math.round((r-i)/1e3)}s), resetting sync status`,"warn"),this.updateSyncStatus(!1,r);else{this.writeSyncLog(`Sync already in progress (started ${Math.round((r-i)/1e3)}s ago)`,"info");return}}if(r-n.lastSyncTime<s)return;this.triggerBackgroundSync()}catch(e){this.writeSyncLog(`Auto sync check failed: ${e}`,"error")}}triggerBackgroundSync(){try{if(this.updateSyncStatus(!0,Date.now()),this.testMode){console.log("[TEST MODE] Would trigger background sync"),setTimeout(()=>{this.updateSyncStatus(!1,Date.now())},100);return}let e=this.getCCPetExecutablePath(),s=(0,ie.spawn)(e,["sync"],{detached:!0,stdio:["ignore","pipe","pipe"]});s.unref(),s.on("close",n=>{let r=Date.now();this.updateSyncStatus(!1,r),n===0?this.writeSyncLog("Background sync completed successfully","info"):this.writeSyncLog(`Background sync failed with code ${n}`,"error")}),s.on("error",n=>{this.writeSyncLog(`Background sync process error: ${n.message}`,"error"),this.updateSyncStatus(!1,Date.now())}),this.writeSyncLog("Background sync triggered","info")}catch(e){this.writeSyncLog(`Failed to trigger background sync: ${e}`,"error"),this.updateSyncStatus(!1,Date.now())}}getCCPetExecutablePath(){try{let{execSync:e}=require("child_process"),t=e("which ccpet",{encoding:"utf8"}).trim();if(t&&f.existsSync(t))return t}catch{}return"npx"}getLastSyncRecord(){try{if(f.existsSync(this.lastSyncFile)){let e=JSON.parse(f.readFileSync(this.lastSyncFile,"utf8"));return{lastSyncTime:e.lastSyncTime||0,syncInProgress:e.syncInProgress||!1}}}catch(e){this.writeSyncLog(`Failed to read last sync record: ${e}`,"error")}return{lastSyncTime:0,syncInProgress:!1}}resetSyncStatus(){try{let e=this.getLastSyncRecord(),t=Date.now();if(e.syncInProgress){let s=Math.round((t-e.lastSyncTime)/1e3);this.writeSyncLog(`Manually resetting stuck sync status (was stuck for ${s}s)`,"warn")}else this.writeSyncLog("Sync status manually reset (was already false)","info");this.updateSyncStatus(!1,t)}catch(e){this.writeSyncLog(`Failed to reset sync status: ${e}`,"error")}}updateSyncStatus(e,t){try{let s=x.dirname(this.lastSyncFile);f.existsSync(s)||f.mkdirSync(s,{recursive:!0});let n={lastSyncTime:t,syncInProgress:e};f.writeFileSync(this.lastSyncFile,JSON.stringify(n,null,2)),this.writeSyncLog(`Sync status updated: syncInProgress=${e}`,"info")}catch(s){this.writeSyncLog(`Failed to update sync status: ${s}`,"error")}}getLastSyncTime(){let e=this.getLastSyncRecord();return e.lastSyncTime>0?new Date(e.lastSyncTime):null}isSyncInProgress(){return this.getLastSyncRecord().syncInProgress}};var T=y(require("fs")),ce=y(require("readline")),H=y(require("path")),B=H.join(process.env.HOME||"",".claude-pet","global-tracker.json");function Ie(){try{if(!T.existsSync(B))return null;let o=T.readFileSync(B,"utf8");return JSON.parse(o)}catch{return null}}function xe(o){try{let e=H.dirname(B);T.existsSync(e)||T.mkdirSync(e,{recursive:!0}),T.writeFileSync(B,JSON.stringify(o,null,2))}catch(e){console.error("Failed to save global tracker:",e)}}async function le(o,e=!1){let t=0,s=0,n=0,r=0,i=0,c=0,a=0,d="";try{if(!T.existsSync(o))return{inputTokens:0,outputTokens:0,cachedTokens:0,totalTokens:0,sessionTotalInputTokens:0,sessionTotalOutputTokens:0,sessionTotalCachedTokens:0,contextLength:0};let m=Ie(),P=m?new Date(m.lastProcessedTimestamp).getTime():0,Q=!e,ue=T.createReadStream(o),de=ce.createInterface({input:ue,crlfDelay:1/0}),L=[];for await(let u of de)if(u.trim()!=="")try{let p=JSON.parse(u);L.push(p)}catch{continue}let A=null,X=0,K=-1;for(let u=0;u<L.length;u++){let p=L[u],S=p.usage||p.message&&p.message.usage;if(S&&(r+=S.input_tokens||0,i+=S.output_tokens||0,c+=(S.cache_creation_input_tokens||0)+(S.cache_read_input_tokens||0)),p.isSidechain!==!0&&S)if(p.timestamp){let R=new Date(p.timestamp).getTime();(!X||R>X)&&(X=R,A=p,K=u)}else u>K&&(A=p,K=u)}if(A){let u=A.usage||A.message&&A.message.usage;u&&(a=(u.input_tokens||0)+(u.cache_read_input_tokens||0)+(u.cache_creation_input_tokens||0))}for(let u of L){let p=u.usage||u.message&&u.message.usage;if(Q&&!(u.timestamp&&P>0&&new Date(u.timestamp).getTime()<=P)&&(p&&(t+=p.input_tokens||0,s+=p.output_tokens||0,n+=(p.cache_creation_input_tokens||0)+(p.cache_read_input_tokens||0)),u.timestamp)){let S=new Date(u.timestamp).getTime(),R=d?new Date(d).getTime():0;S>R&&(d=u.timestamp)}}if(d&&Q){let u=new Date(d).getTime(),p=m?new Date(m.lastProcessedTimestamp).getTime():0;if(u>p){let S={lastProcessedTimestamp:d,totalProcessedTokens:(m?.totalProcessedTokens||0)+t+s+n};xe(S)}}return{inputTokens:t,outputTokens:s,cachedTokens:n,totalTokens:t+s+n,sessionTotalInputTokens:r,sessionTotalOutputTokens:i,sessionTotalCachedTokens:c,contextLength:a}}catch(m){return console.error("Failed to process JSONL transcript:",m),{inputTokens:0,outputTokens:0,cachedTokens:0,totalTokens:0,sessionTotalInputTokens:0,sessionTotalOutputTokens:0,sessionTotalCachedTokens:0,contextLength:0}}}var Z=class{callCount=0;testMode;COUNTER_FILE=require("path").join(require("os").homedir(),".claude-pet","animation-counter.json");constructor(e=!1){this.testMode=e,e||this.loadCounter()}loadCounter(){try{let e=require("fs");if(e.existsSync(this.COUNTER_FILE)){let t=JSON.parse(e.readFileSync(this.COUNTER_FILE,"utf8"));this.callCount=t.callCount||0}}catch{this.callCount=0}}saveCounter(){try{let e=require("fs"),s=require("path").dirname(this.COUNTER_FILE);e.existsSync(s)||e.mkdirSync(s,{recursive:!0});let n={callCount:this.callCount,lastUpdate:Date.now()};e.writeFileSync(this.COUNTER_FILE,JSON.stringify(n))}catch{}}recordCall(){this.testMode||(this.callCount++,this.saveCounter())}shouldEnableAnimation(){return!this.testMode}getFrameIndex(){return this.callCount}},N=class{pet;formatter;storage;configService;animationCounter;autoSyncService;constructor(e=!1,t){this.animationCounter=new Z(e),this.storage=new j,this.configService=t||new b,this.autoSyncService=new Y(this.configService,e),this.formatter=new D(e,t);let s=this.storage.loadState(),n=new Date,r=s||{uuid:_(),energy:h.INITIAL_ENERGY,expression:h.HAPPY_EXPRESSION,animalType:w.getRandomAnimalType(),birthTime:n,lastFeedTime:n,totalTokensConsumed:0,accumulatedTokens:0,totalLifetimeTokens:0,petName:F()};this.pet=new w(r,{config:h}),s&&this.pet.applyTimeDecay()}async processTokensAndGetStatusDisplay(e){try{this.animationCounter.recordCall(),this.pet.applyTimeDecay();let t=e.cost.total_cost_usd===0,s=await le(e.transcript_path,t);s.totalTokens>0&&this.pet.feed(s.totalTokens);let n={sessionTotalInputTokens:s.sessionTotalInputTokens,sessionTotalOutputTokens:s.sessionTotalOutputTokens,sessionTotalCachedTokens:s.sessionTotalCachedTokens,sessionTotalCostUsd:e.cost.total_cost_usd,contextLength:s.contextLength};s.contextLength!==void 0&&(n.contextPercentage=Math.min(100,s.contextLength/2e5*100),n.contextPercentageUsable=Math.min(100,s.contextLength/16e4*100)),this.pet.updateSessionMetrics(n);let r=this.pet.getState();this.autoSyncService.checkAndTriggerAutoSync().catch(P=>{console.warn("Auto sync check failed:",P)});let i=this.animationCounter.shouldEnableAnimation(),c=this.animationCounter.getFrameIndex(),d=this.configService.getConfig().pet.emojiEnabled??!0,m=this.pet.getAnimatedExpression(i,c,d);return this.formatter.formatPetDisplay(r,m)}catch(t){console.error("Token processing failed:",t),this.pet.applyTimeDecay();let s=this.pet.getState();return this.formatter.formatPetDisplay(s)}}getStatusDisplay(){this.animationCounter.recordCall(),this.pet.applyTimeDecay();let e=this.pet.getState();this.autoSyncService.checkAndTriggerAutoSync().catch(c=>{console.warn("Auto sync check failed:",c)});let t=this.animationCounter.shouldEnableAnimation(),s=this.animationCounter.getFrameIndex(),r=this.configService.getConfig().pet.emojiEnabled??!0,i=this.pet.getAnimatedExpression(t,s,r);return this.formatter.formatPetDisplay(e,i)}saveState(){this.storage.saveState(this.pet.getState())}adoptNewPet(){if(this.pet.isDead()){this.pet.resetToInitialState(t=>{try{this.storage.moveToGraveyard(t),console.log(`Moved deceased pet "${t.petName}" to graveyard`),this.triggerDeathSync(t)}catch(s){console.error("Failed to move pet to graveyard:",s)}}),this.saveState();let e=this.pet.getState();console.log(`New pet "${e.petName}" adopted successfully`),typeof window<"u"&&window.vscode?.postMessage&&window.vscode.postMessage({command:"showInformationMessage",text:`Successfully adopted a new pet named "${e.petName}"! Your pet is now happy and full of energy.`})}}isPetDead(){return this.pet.isDead()}triggerDeathSync(e){try{let t=this.configService.getConfig();if(!t.supabase?.url||!t.supabase?.apiKey){console.log("Supabase sync not configured, skipping death sync");return}let{spawn:s}=require("child_process"),n=this.getCCPetExecutablePath();s(n,["sync"],{detached:!0,stdio:["ignore","ignore","ignore"]}).unref(),console.log(`Triggered death sync for pet "${e.petName}" (${e.uuid})`)}catch(t){console.warn("Failed to trigger death sync:",t)}}getCCPetExecutablePath(){try{let{execSync:e}=require("child_process"),t=e("which ccpet",{encoding:"utf8"}).trim();if(t&&require("fs").existsSync(t))return t}catch{}return"npx"}};function Ae(){return new Promise(o=>{let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t}),process.stdin.on("end",()=>{o(e.trim())})})}async function De(){try{let o=await Ae();if(!o){let n=process.env.CCPET_TRANSCRIPT_PATH;if(n){let c={hook_event_name:"test",session_id:"test",transcript_path:n,cwd:process.cwd(),model:{id:"test",display_name:"test"},workspace:{current_dir:process.cwd(),project_dir:process.cwd()},version:"1.0.0",output_style:{name:"default"},cost:{total_cost_usd:0,total_duration_ms:0,total_api_duration_ms:0,total_lines_added:0,total_lines_removed:0}},a=new N,d=await a.processTokensAndGetStatusDisplay(c);a.saveState(),process.stdout.write(d);return}let r=new N,i=r.getStatusDisplay();r.saveState(),process.stdout.write(i);return}let e;try{e=JSON.parse(o)}catch{let r=new N,i=r.getStatusDisplay();r.saveState(),process.stdout.write(i);return}let t=new N,s=await t.processTokensAndGetStatusDisplay(e);t.saveState(),process.stdout.write(s)}catch(o){process.stdout.write("(?) ERROR"),process.stderr.write(`Pet status error: ${o}
`),process.exit(1)}}function ke(o){let e=new N;o.subscriptions.push({command:"claude-pet.adoptNewPet",callback:()=>{e.adoptNewPet()}}),typeof window<"u"&&window.vscode?.commands&&window.vscode.commands.registerCommand("claude-pet.adoptNewPet",()=>{e.adoptNewPet()})}function we(){}0&&(module.exports={ClaudeCodeStatusLine,StatusBarFormatter,activate,deactivate,main});
//# sourceMappingURL=ccpet.js.map