a24z 1.0.29 → 1.0.30
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.js +4 -4
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -159,14 +159,14 @@ ${QFD}
|
|
|
159
159
|
Try running with %s or get access `,P.cyan("sudo"))+`
|
|
160
160
|
to the local update config store via
|
|
161
161
|
`+P.cyan(m$(" sudo chown -R $USER:$(id -gn $USER) %s ",T4));G6.on("exit",()=>{console.error(O7(F,{textAlignment:"center"}))})}}check(){if(!this.config||this.config.get("optOut")||this.#Z)return;if(this.update=this.config.get("update"),this.update)this.update.current=this.#J,this.config.delete("update");if(Date.now()-this.config.get("lastUpdateCheck")<this.#Y)return;V2D(G6.execPath,[Mk.join(C2D,"check.js"),JSON.stringify(this.#D)],{detached:!0,stdio:"ignore"}).unref()}async fetchInfo(){let{distTag:D}=this.#D,F=await I$(this._packageName,{version:D});return{latest:F,current:this.#J,type:Nk.default(this.#J,F)??D,name:this._packageName}}notify(D){let F=!this._shouldNotifyInNpmScript&&SS;if(!G6.stdout.isTTY||F||!this.update||!Ak.default(this.update.latest,this.update.current))return this;D={isGlobal:bS,...D};let Z=D.isGlobal?`npm i -g ${this._packageName}`:`npm i ${this._packageName}`,J="Update available "+P.dim("{currentVersion}")+P.reset(" → ")+P.green("{latestVersion}")+`
|
|
162
|
-
Run `+P.cyan("{updateCommand}")+" to update",Y=D.message||J;D.boxenOptions??={padding:1,margin:1,textAlignment:"center",borderColor:"yellow",borderStyle:"round"};let X=O7(g$(Y,{packageName:this._packageName,currentVersion:this.update.current,latestVersion:this.update.latest,updateCommand:Z}),D.boxenOptions);if(D.defer===!1)console.error(X);else G6.on("exit",()=>{console.error(X)});return this}}function b$(D){let F=new P7(D);return F.check(),F}var P3=d(Lx(),1);var Rx={name:"a24z",version:"1.0.
|
|
162
|
+
Run `+P.cyan("{updateCommand}")+" to update",Y=D.message||J;D.boxenOptions??={padding:1,margin:1,textAlignment:"center",borderColor:"yellow",borderStyle:"round"};let X=O7(g$(Y,{packageName:this._packageName,currentVersion:this.update.current,latestVersion:this.update.latest,updateCommand:Z}),D.boxenOptions);if(D.defer===!1)console.error(X);else G6.on("exit",()=>{console.error(X)});return this}}function b$(D){let F=new P7(D);return F.check(),F}var P3=d(Lx(),1);var Rx={name:"a24z",version:"1.0.30",description:"AI Agent Observability CLI - Monitor and analyze your AI tool performance",main:"dist/index.js",bin:{a24z:"bin/a24z.js"},type:"module",files:["bin/","dist/","README.md"],scripts:{build:"NODE_ENV=production rm -rf dist && bun run build.ts","build:dev":"NODE_ENV=development rm -rf dist && bun run build.ts",prepublishOnly:"bun run build","perf:test":"node scripts/perf-test.js"},keywords:["claude","ai","observability","monitoring","cli","tools","analytics","performance"],author:"a24z",homepage:"https://a24z.ai",dependencies:{},devDependencies:{"@iarna/toml":"^2.2.5","@repo/types":"workspace:*","@types/bun":"latest","@types/iarna__toml":"^2.0.5","@types/inquirer":"^9.0.7","@types/node":"^20.10.0","@types/update-notifier":"^6.0.8",chalk:"^5.3.0",commander:"^11.1.0",inquirer:"^9.2.12",open:"^9.1.0",ora:"^7.0.1",typescript:"^5.3.2","update-notifier":"^7.3.1"},engines:{node:">=16.0.0"}};function NZD(){return{apiUrl:"https://api.a24z.ai",clientId:"client_01K4ZPKT6DNRF3FZFVHXZVWVJ8"}}var AZD=MZD(import.meta.url),LZD=pD.dirname(AZD),p7=pD.join(u4.homedir(),".a24z"),z0=pD.join(p7,"settings.json"),Ix=pD.join(u4.homedir(),".claude"),j8=pD.join(Ix,"settings.json"),RZD=pD.join(u4.homedir(),".gemini"),S8=pD.join(RZD,"settings.json"),TZD=pD.join(u4.homedir(),".codex"),k8=pD.join(TZD,"config.toml"),b7=pD.join(Ix,"a24z-config.json"),QQ=["claude-code","gemini-cli","codex"],Ox={"claude-code":!0,"gemini-cli":!1,codex:!0},IZD=QQ.filter((D)=>Ox[D]);function d7(D){let F=D.toLowerCase().trim();if(!QQ.includes(F))throw console.error(P.red(`
|
|
163
163
|
❌ Unknown tool: '${D}'`)),console.log(P.cyan(`
|
|
164
164
|
\uD83D\uDCE6 Available tools:`)),console.log(P.white(" • claude-code")+P.gray(" - Anthropic's Claude Code editor")),console.log(P.white(" • codex")+P.gray(" - OpenAI Codex CLI")),console.log(P.cyan(`
|
|
165
165
|
\uD83D\uDCA1 Example:`)),console.log(P.yellow(" a24z install claude-code")),console.log(""),Error(`Unknown tool: '${D}'. Available tools: ${QQ.join(", ")}`);if(!Ox[F]){console.error(P.red(`
|
|
166
166
|
❌ Tool '${D}' is currently disabled`)),console.log(P.yellow(`
|
|
167
167
|
⚠️ Reason: ${F==="gemini-cli"?"Waiting for gemini-cli to support custom headers":"Currently unavailable"}`)),console.log(P.cyan(`
|
|
168
|
-
\uD83D\uDCE6 Currently available tools:`));for(let Z of IZD)console.log(P.white(` • ${Z}`)+P.gray(` - ${OZD(Z)}`));throw console.log(""),Error(`Tool '${D}' is currently disabled`)}return F}function OZD(D){switch(D){case"claude-code":return"Anthropic's Claude Code editor";case"gemini-cli":return"Google's Gemini CLI";case"codex":return"OpenAI Codex CLI";default:return""}}function PZD(D,F=500){if(typeof D!=="string")throw Error("Input must be a string");return D.trim().substring(0,F)}class Px{config;constructor(){this.config=this.loadConfig()}loadConfig(){let D=NZD(),F={apiUrl:D.apiUrl,clientId:D.clientId,accessToken:null,refreshToken:null,apiKey:null,apiKeyId:null,installedAt:null,tools:[]};try{if(XD.existsSync(z0)){let Z=XD.readFileSync(z0,"utf8").trim();if(!Z){console.warn(P.yellow("⚠️ Settings file is empty, using defaults"));try{XD.unlinkSync(z0)}catch($){}return F}let J=JSON.parse(Z),Y=!1;if(J.tool&&typeof J.tool==="string")J.tools=[J.tool],delete J.tool,Y=!0;if(!Array.isArray(J.tools))J.tools=[],Y=!0;let X={...F,...J};if(Y)try{XD.writeFileSync(z0,JSON.stringify(X,null,2)),console.log(P.green('✅ Migrated configuration from "tool" to "tools" array'))}catch($){console.warn(P.yellow("Warning: Could not save migrated configuration"))}return X}if(XD.existsSync(b7)){let Z=XD.readFileSync(b7,"utf8").trim();if(!Z){console.warn(P.yellow("⚠️ Legacy settings file is empty, using defaults"));try{XD.unlinkSync(b7)}catch(X){}return F}let J=JSON.parse(Z);if(J.tool&&typeof J.tool==="string")J.tools=[J.tool],delete J.tool;let Y={...F,...J};XD.mkdirSync(p7,{recursive:!0}),XD.writeFileSync(z0,JSON.stringify(Y,null,2));try{XD.unlinkSync(b7)}catch(X){}return console.log(P.green("✅ Migrated configuration to ~/.a24z/settings.json")),Y}}catch(Z){if(Z instanceof SyntaxError){console.warn(P.yellow("⚠️ Settings file is corrupted, using defaults"));try{if(XD.existsSync(z0))XD.unlinkSync(z0)}catch(J){}}else console.error(P.red("Error loading configuration:"),Z)}if(!XD.existsSync(z0))try{XD.mkdirSync(p7,{recursive:!0}),XD.writeFileSync(z0,JSON.stringify(F,null,2)),console.log(P.green("✅ Initialized configuration at ~/.a24z/settings.json"))}catch(Z){console.warn(P.yellow("⚠️ Could not create settings file, using defaults"))}return F}saveConfig(){try{XD.mkdirSync(p7,{recursive:!0}),XD.writeFileSync(z0,JSON.stringify(this.config,null,2))}catch(D){console.error(P.red("Error saving configuration:"),D)}}getInstalledTools(){try{if(XD.existsSync(z0)){let D=XD.readFileSync(z0,"utf8").trim();if(!D)return[];let F=JSON.parse(D);if(F.tool&&typeof F.tool==="string"&&!F.tools)return[F.tool];return Array.isArray(F.tools)?F.tools:[]}}catch(D){}return[]}async install(D,F={}){let Z;try{Z=d7(D)}catch(Y){console.error(P.red("❌ Error:"),Y instanceof Error?Y.message:Y),process.exit(1)}if(F.apiUrl)try{if(F.apiUrl=PZD(F.apiUrl,500),!new URL(F.apiUrl).protocol.startsWith("http"))throw Error("API URL must use HTTP or HTTPS protocol")}catch(Y){console.error(P.red("❌ Error: Invalid API URL:"),Y instanceof Error?Y.message:Y),process.exit(1)}let J=O6(`Installing A24Z hooks for ${Z}...`).start();try{if(F.apiUrl)this.config.apiUrl=F.apiUrl;if(Z==="claude-code")this.updateClaudeSettings();else if(Z==="gemini-cli")this.updateGeminiSettings();else if(Z==="codex")this.updateCodexSettings();if(!this.config.tools.includes(Z))this.config.tools.push(Z);this.config.installedAt=new Date().toISOString(),this.saveConfig(),J.succeed(`A24Z hooks installed successfully for ${Z}!`),console.log(P.green("✅ Installation Complete!")),console.log(P.cyan("\uD83D\uDCCB Next steps:")),console.log(P.white(" 1. Login to associate logs with your organization:"),P.yellow("a24z login")),console.log(P.white(" 2. Check installation status:"),P.yellow("a24z status")),console.log(P.white(` 3. Begin using ${D} - sessions will be automatically monitored`)),console.log(P.cyan("\uD83D\uDD27 Configuration:")),console.log(P.white(` • Tool: ${D}`));let Y=j8;if(Z==="gemini-cli")Y=S8;else if(Z==="codex")Y=k8;console.log(P.white(` • Settings file: ${Y}`)),console.log(P.white(` • API URL: ${this.config.apiUrl}`))}catch(Y){J.fail("Installation failed"),console.error(P.red("❌ Error:"),Y),process.exit(1)}}updateClaudeSettings(){let D={};if(XD.existsSync(j8))try{D=JSON.parse(XD.readFileSync(j8,"utf8"))}catch(X){console.warn(P.yellow("Warning: Could not parse existing settings.json, creating new one"))}if(typeof D.hooks!=="object"||D.hooks===null)D.hooks={};let F="a24z hook claude-code",Z=["SessionStart","SessionEnd"];for(let X of Z)this.addOrUpdateHook(D,X,F);if(!D.env||typeof D.env!=="object")D.env={};let J=this.config.apiKey||this.config.accessToken||"",Y=J?`Authorization=Bearer ${J}`:"";D.env={...D.env,CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_EXPORTER_OTLP_ENDPOINT:this.config.apiUrl,OTEL_EXPORTER_OTLP_HEADERS:Y,OTEL_METRIC_EXPORT_INTERVAL:"10000",OTEL_LOGS_EXPORT_INTERVAL:"5000"},XD.mkdirSync(pD.dirname(j8),{recursive:!0}),XD.writeFileSync(j8,JSON.stringify(D,null,2))}addOrUpdateHook(D,F,Z){if(!D.hooks)D.hooks={};let J=D.hooks[F],Y={matcher:"*",hooks:[{type:"command",command:Z}]};if(!Array.isArray(J)){D.hooks[F]=[Y];return}if(!J.some(($)=>$.hooks.some((Q)=>typeof Q.command==="string"&&Q.command.includes("a24z hook claude-code"))))J.push(Y)}updateGeminiSettings(){let D={};if(XD.existsSync(S8))try{D=JSON.parse(XD.readFileSync(S8,"utf8"))}catch(F){console.warn(P.yellow("Warning: Could not parse existing Gemini settings.json, creating new one"))}D.telemetry={enabled:!0,target:"local",otlpEndpoint:this.config.apiUrl,otlpProtocol:"http",logPrompts:!0,useCollector:!0,...D.telemetry},XD.mkdirSync(pD.dirname(S8),{recursive:!0}),XD.writeFileSync(S8,JSON.stringify(D,null,2))}updateCodexSettings(){let D={};if(XD.existsSync(k8))try{let Y=XD.readFileSync(k8,"utf8");D=P3.default.parse(Y)}catch(Y){console.warn(P.yellow("Warning: Could not parse existing Codex config.toml, creating new one"))}let F=this.config.apiKey,Z={};if(F)Z.authorization=`Bearer ${F}`,Z["x-otlp-api-key"]=`${F}`;D.otel={...D.otel,environment:"production",exporter:{"otlp-http":{endpoint:`${this.config.apiUrl}/v1/logs`,protocol:"http/json",headers:Z}},log_user_prompt:!0},XD.mkdirSync(pD.dirname(k8),{recursive:!0});let J=P3.default.stringify(D);XD.writeFileSync(k8,J)}async setApiKey(D){console.log(P.blue("\uD83D\uDD11 Configuring API key..."));try{if(!D||D.trim().length===0)throw Error("API key cannot be empty");this.config.apiKey=D.trim(),this.saveConfig();let F=this.config.tools;if(F.length>0){for(let Z of F)if(Z==="claude-code")this.updateClaudeSettings();else if(Z==="gemini-cli")this.updateGeminiSettings();else if(Z==="codex")this.updateCodexSettings()}if(console.log(P.green("✅ API key configured successfully!")),console.log(P.white("\uD83D\uDD27 Configuration saved to:"),P.cyan(z0)),F.length>0)console.log(P.white(`\uD83D\uDCDD Updated settings for: ${F.join(", ")}`));console.log(P.green("Your sessions will now be authenticated with this API key."))}catch(F){console.error(P.red("❌ Failed to configure API key:"),F),process.exit(1)}}async login(){console.log(P.blue("\uD83D\uDD10 Logging in to A24Z Observability..."));try{let D=await fetch(`${this.config.apiUrl}/api/v1/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:this.config.clientId})});if(!D.ok)throw Error(`Authentication request failed: ${D.status}`);let F=await D.json(),{device_code:Z,user_code:J,verification_uri:Y,verification_uri_complete:X,expires_in:$,interval:Q}=F.data;if(console.log(P.green("\uD83D\uDCF1 Complete authentication in your browser:")),console.log(P.cyan(` Go to: ${Y}`)),console.log(P.yellow(` Enter code: ${J}`)),X)console.log(P.gray(` Or visit: ${X}`));console.log(P.white(` Code expires in ${Math.floor($/60)} minutes`));let{openBrowser:G}=await pR.prompt([{type:"confirm",name:"openBrowser",message:"Open browser automatically?",default:!0}]);if(G)await LO(X||Y);let q=O6("Waiting for authentication...").start(),K=await this.pollForTokens(Z,Q,$);if(q.succeed("Authentication successful!"),this.config.accessToken=K.access_token,this.config.refreshToken=K.refresh_token||null,this.saveConfig(),!this.config.apiKey||!this.config.apiKeyId){console.log(P.blue("\uD83D\uDD11 Setting up API key for CLI authentication..."));try{let V=u4.hostname(),H=await this.findExistingApiKey(K.access_token,V);if(H)console.log(P.yellow(`⚠️ Found existing API key for this machine: ${H.name}`)),console.log(P.yellow(" Creating new key since the original key value cannot be retrieved")),console.log(P.gray(" (You may want to revoke the old key from the dashboard)"));let C=await this.createApiKeyForCLI(K.access_token,V);if(C&&C.apiKey&&C.id)this.config.apiKey=C.apiKey,this.config.apiKeyId=C.id,this.saveConfig(),console.log(P.green("✅ API key created successfully"))}catch(V){console.log(P.yellow("⚠️ Could not create API key, will use access token instead")),console.log(P.gray(` (${V instanceof Error?V.message:"Unknown error"})`))}}else console.log(P.green("✅ Using existing API key for this machine"));let E=this.config.tools;if(E.length>0){for(let V of E)if(V==="claude-code")this.updateClaudeSettings();else if(V==="gemini-cli")this.updateGeminiSettings();else if(V==="codex")this.updateCodexSettings()}if(console.log(P.green("✅ Login successful!")),K.user?.email)console.log(P.white("\uD83D\uDC64 User:"),P.cyan(K.user.email));console.log(P.green("Your sessions will now be associated with your organization."))}catch(D){console.error(P.red("❌ Login failed:"),D),console.log(P.yellow("Make sure the A24Z service is available and try again.")),process.exit(1)}}async findExistingApiKey(D,F){try{let Z=await fetch(`${this.config.apiUrl}/api/v1/api-keys`,{method:"GET",headers:{Authorization:`Bearer ${D}`}});if(!Z.ok)return null;let X=((await Z.json()).apiKeys||[]).find(($)=>$.status==="active"&&$.name.includes(`CLI - ${F}`));return X?{id:X.id,name:X.name}:null}catch(Z){return null}}async createApiKeyForCLI(D,F){try{let J=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19),Y=`CLI - ${F} - ${J}`,X=await fetch(`${this.config.apiUrl}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${D}`},body:JSON.stringify({name:Y})});if(!X.ok){let $=await X.text().catch(()=>"");throw Error(`API key creation failed: ${X.status} ${$}`)}return await X.json()}catch(Z){throw Error(`Failed to create API key: ${Z instanceof Error?Z.message:String(Z)}`)}}async pollForTokens(D,F,Z){let J=Date.now(),Y=Z*1000,X=F;while(Date.now()-J<Y){try{let $=await fetch(`${this.config.apiUrl}/api/v1/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:D,client_id:this.config.clientId})});if(!$.ok){let G="unknown_error",q=$.status;try{G=(await $.json()).error||G}catch{}if(q===428&&G==="authorization_pending"){await new Promise((K)=>setTimeout(K,X*1000));continue}if(q===429&&G==="slow_down"){X+=5,await new Promise((K)=>setTimeout(K,X*1000));continue}if(q===403&&G==="access_denied")throw Error("User denied authorization");if(q===400&&G==="expired_token")throw Error("Device code expired");if(q>=500){await new Promise((K)=>setTimeout(K,X*1000));continue}throw Error(`Token request failed: ${q} ${G}`)}let Q=await $.json();if(Q.success)return Q.data}catch($){if($.name==="TypeError"&&$.message.includes("fetch")){await new Promise((Q)=>setTimeout(Q,X*1000));continue}throw $}await new Promise(($)=>setTimeout($,X*1000))}throw Error("Authentication timeout")}async uninstall(D){let F;try{F=d7(D)}catch(J){console.error(P.red("❌ Error:"),J instanceof Error?J.message:J),process.exit(1)}let Z=O6(`Uninstalling a24z hooks for ${F}...`).start();try{if(F==="claude-code"&&XD.existsSync(j8))try{let J=JSON.parse(XD.readFileSync(j8,"utf8"));if(J&&typeof J==="object"&&typeof J.hooks==="object"&&J.hooks!==null){let Y=["SessionStart","SessionEnd"];for(let X of Y){let $=J.hooks[X];if(Array.isArray($)){for(let G of $)if(Array.isArray(G.hooks))G.hooks=G.hooks.filter((q)=>{if(typeof q.command!=="string")return!0;return!q.command.includes("a24z hook claude-code")});let Q=$.filter((G)=>Array.isArray(G.hooks)&&G.hooks.length>0);if(Q.length>0)J.hooks[X]=Q;else delete J.hooks[X]}}}XD.writeFileSync(j8,JSON.stringify(J,null,2))}catch(J){console.warn(P.yellow("Warning: Could not update Claude settings.json"))}if(F==="codex"&&XD.existsSync(k8))try{let J=XD.readFileSync(k8,"utf8"),Y=P3.default.parse(J);if(Y.otel)Y.otel.exporter="none";let X=P3.default.stringify(Y);XD.writeFileSync(k8,X)}catch(J){console.warn(P.yellow("Warning: Could not update Codex config.toml"))}if(F==="gemini-cli"&&XD.existsSync(S8))try{let J=JSON.parse(XD.readFileSync(S8,"utf8"));if(J.telemetry)J.telemetry.enabled=!1,delete J.telemetry.otlpEndpoint;XD.writeFileSync(S8,JSON.stringify(J,null,2))}catch(J){console.warn(P.yellow("Warning: Could not update Gemini settings.json"))}if(this.config.tools=this.config.tools.filter((J)=>J!==F),this.config.tools.length===0){if(XD.existsSync(z0))XD.unlinkSync(z0)}else this.saveConfig();if(Z.succeed(`a24z hooks uninstalled successfully for ${D}!`),console.log(P.green(`${D} will no longer send observability data.`)),this.config.tools.length>0)console.log(P.white(`Still installed: ${this.config.tools.join(", ")}`))}catch(J){Z.fail("Uninstallation failed"),console.error(P.red("❌ Error:"),J),process.exit(1)}}async status(){console.log(P.blue("\uD83D\uDCCA A24Z Observability Status"));let D=this.getInstalledTools();if(console.log(P.white("\uD83D\uDD27 Installation Status:")),D.length>0)console.log(` • Session monitoring: ${P.green("✅ Configured")}`),console.log(` • Installed tools: ${P.cyan(D.join(", "))}`);else console.log(` • Session monitoring: ${P.yellow("⚠️ Not configured")}`),console.log(P.gray(' Run "a24z install <tool>" to get started'));if(console.log(P.white("\uD83D\uDD10 Authentication Status:")),console.log(` • Logged in: ${this.config.accessToken?P.green("✅ Yes"):P.red("❌ No")}`),this.config.apiKey)console.log(` • API Key: ${P.green("✅ Configured")}`)}async hook(D="claude-code"){let F;try{F=d7(D)}catch(J){process.exit(1)}let Z=async()=>new Promise((J)=>{let Y="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(X)=>{Y+=X}),process.stdin.on("end",()=>J(Y)),setTimeout(()=>J(Y),5000)});try{let J=await Z();if(this.config.accessToken&&this.isTokenExpired(this.config.accessToken))await this.refreshToken();if(!this.config.apiKey&&!this.config.accessToken)console.error('❌ No valid authentication credentials available. Please run "a24z login" to authenticate or configure an API key.'),process.exit(1);let Y=`${this.config.apiUrl}/api/v1/${F}/hooks`,X=this.config.apiKey||this.config.accessToken||"",$=new AbortController,Q=setTimeout(()=>$.abort(),200);try{await fetch(Y,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify(J),signal:$.signal})}catch(G){}finally{clearTimeout(Q)}process.exit(0)}catch(J){process.exit(1)}}async seed(D="claude-code",F={}){let Z;try{Z=d7(D)}catch(Q){console.error(P.red("❌ Error:"),Q instanceof Error?Q.message:Q),process.exit(1)}let J=typeof F.root==="string"&&F.root.length>0?F.root:pD.join(u4.homedir(),".claude","projects"),Y=typeof F.concurrency==="number"&&F.concurrency>0?F.concurrency:5,X=F.dryRun===!0;if(this.config.accessToken&&this.isTokenExpired(this.config.accessToken))await this.refreshToken();if(!this.config.apiKey&&!this.config.accessToken){console.error(P.red("❌ Not authenticated. Run 'a24z login' first or configure an API key.")),process.exit(1);return}let $=O6(`Scanning transcripts in ${J} ...`).start();try{let Q=await this.collectTranscriptFiles(J);if($.succeed(`Found ${Q.length} transcript file(s).`),X){for(let M of Q)console.log(P.gray(`DRY RUN: ${M}`));console.log(P.green("✅ Dry run complete."));return}console.log(P.white(`\uD83D\uDCE4 Sending ${Q.length} transcript(s) to API (concurrency ${Y})...`));let G=0,q=0,K=`${this.config.apiUrl}/api/v1/${Z}/hooks`,E=0,V=Q.length,H=async()=>{while(!0){let M=E;if(M>=V)return;E++;let A=Q[M],R=this.deriveSessionIdFromPath(A);if(!R){q++,console.warn(P.yellow(`⚠️ Skipping (cannot derive session id): ${A}`));continue}let x=await this.extractCwdFromTranscript(A)||this.decodeCwdFromPath(A)||process.cwd(),_={hook_event_name:"SessionEnd",session_id:R,transcript_path:A,cwd:x,reason:"seed"},u=this.config.apiKey||this.config.accessToken||"",s=new AbortController,e=setTimeout(()=>s.abort(),15000);try{let i=await fetch(K,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`},body:JSON.stringify(_),signal:s.signal});if(!i.ok){q++;let TD=await i.text().catch(()=>"");console.error(P.red(`❌ Failed (${i.status}): ${A}`),TD?P.gray(TD):"")}else G++,console.log(P.green(`✅ Sent: ${A}`))}catch(i){q++,console.error(P.red(`❌ Error sending ${A}:`),i)}finally{clearTimeout(e)}}},C=[];for(let M=0;M<Y;M++)C.push(H());if(await Promise.all(C),console.log(P.white(`
|
|
169
|
-
\uD83D\uDCC8 Seed summary:`)),console.log(` • Total: ${
|
|
168
|
+
\uD83D\uDCE6 Currently available tools:`));for(let Z of IZD)console.log(P.white(` • ${Z}`)+P.gray(` - ${OZD(Z)}`));throw console.log(""),Error(`Tool '${D}' is currently disabled`)}return F}function OZD(D){switch(D){case"claude-code":return"Anthropic's Claude Code editor";case"gemini-cli":return"Google's Gemini CLI";case"codex":return"OpenAI Codex CLI";default:return""}}function PZD(D,F=500){if(typeof D!=="string")throw Error("Input must be a string");return D.trim().substring(0,F)}class Px{config;constructor(){this.config=this.loadConfig()}loadConfig(){let D=NZD(),F={apiUrl:D.apiUrl,clientId:D.clientId,accessToken:null,refreshToken:null,apiKey:null,apiKeyId:null,userEmail:null,installedAt:null,tools:[]};try{if(XD.existsSync(z0)){let Z=XD.readFileSync(z0,"utf8").trim();if(!Z){console.warn(P.yellow("⚠️ Settings file is empty, using defaults"));try{XD.unlinkSync(z0)}catch($){}return F}let J=JSON.parse(Z),Y=!1;if(J.tool&&typeof J.tool==="string")J.tools=[J.tool],delete J.tool,Y=!0;if(!Array.isArray(J.tools))J.tools=[],Y=!0;let X={...F,...J};if(Y)try{XD.writeFileSync(z0,JSON.stringify(X,null,2)),console.log(P.green('✅ Migrated configuration from "tool" to "tools" array'))}catch($){console.warn(P.yellow("Warning: Could not save migrated configuration"))}return X}if(XD.existsSync(b7)){let Z=XD.readFileSync(b7,"utf8").trim();if(!Z){console.warn(P.yellow("⚠️ Legacy settings file is empty, using defaults"));try{XD.unlinkSync(b7)}catch(X){}return F}let J=JSON.parse(Z);if(J.tool&&typeof J.tool==="string")J.tools=[J.tool],delete J.tool;let Y={...F,...J};XD.mkdirSync(p7,{recursive:!0}),XD.writeFileSync(z0,JSON.stringify(Y,null,2));try{XD.unlinkSync(b7)}catch(X){}return console.log(P.green("✅ Migrated configuration to ~/.a24z/settings.json")),Y}}catch(Z){if(Z instanceof SyntaxError){console.warn(P.yellow("⚠️ Settings file is corrupted, using defaults"));try{if(XD.existsSync(z0))XD.unlinkSync(z0)}catch(J){}}else console.error(P.red("Error loading configuration:"),Z)}if(!XD.existsSync(z0))try{XD.mkdirSync(p7,{recursive:!0}),XD.writeFileSync(z0,JSON.stringify(F,null,2)),console.log(P.green("✅ Initialized configuration at ~/.a24z/settings.json"))}catch(Z){console.warn(P.yellow("⚠️ Could not create settings file, using defaults"))}return F}saveConfig(){try{XD.mkdirSync(p7,{recursive:!0}),XD.writeFileSync(z0,JSON.stringify(this.config,null,2))}catch(D){console.error(P.red("Error saving configuration:"),D)}}getInstalledTools(){try{if(XD.existsSync(z0)){let D=XD.readFileSync(z0,"utf8").trim();if(!D)return[];let F=JSON.parse(D);if(F.tool&&typeof F.tool==="string"&&!F.tools)return[F.tool];return Array.isArray(F.tools)?F.tools:[]}}catch(D){}return[]}async install(D,F={}){let Z;try{Z=d7(D)}catch(Y){console.error(P.red("❌ Error:"),Y instanceof Error?Y.message:Y),process.exit(1)}if(F.apiUrl)try{if(F.apiUrl=PZD(F.apiUrl,500),!new URL(F.apiUrl).protocol.startsWith("http"))throw Error("API URL must use HTTP or HTTPS protocol")}catch(Y){console.error(P.red("❌ Error: Invalid API URL:"),Y instanceof Error?Y.message:Y),process.exit(1)}let J=O6(`Installing A24Z hooks for ${Z}...`).start();try{if(F.apiUrl)this.config.apiUrl=F.apiUrl;if(Z==="claude-code")this.updateClaudeSettings();else if(Z==="gemini-cli")this.updateGeminiSettings();else if(Z==="codex")this.updateCodexSettings();if(!this.config.tools.includes(Z))this.config.tools.push(Z);this.config.installedAt=new Date().toISOString(),this.saveConfig(),J.succeed(`A24Z hooks installed successfully for ${Z}!`),console.log(P.green("✅ Installation Complete!")),console.log(P.cyan("\uD83D\uDCCB Next steps:")),console.log(P.white(" 1. Login to associate logs with your organization:"),P.yellow("a24z login")),console.log(P.white(" 2. Check installation status:"),P.yellow("a24z status")),console.log(P.white(` 3. Begin using ${D} - sessions will be automatically monitored`)),console.log(P.cyan("\uD83D\uDD27 Configuration:")),console.log(P.white(` • Tool: ${D}`));let Y=j8;if(Z==="gemini-cli")Y=S8;else if(Z==="codex")Y=k8;console.log(P.white(` • Settings file: ${Y}`)),console.log(P.white(` • API URL: ${this.config.apiUrl}`))}catch(Y){J.fail("Installation failed"),console.error(P.red("❌ Error:"),Y),process.exit(1)}}updateClaudeSettings(){let D={};if(XD.existsSync(j8))try{D=JSON.parse(XD.readFileSync(j8,"utf8"))}catch(X){console.warn(P.yellow("Warning: Could not parse existing settings.json, creating new one"))}if(typeof D.hooks!=="object"||D.hooks===null)D.hooks={};let F="a24z hook claude-code",Z=["SessionStart","SessionEnd"];for(let X of Z)this.addOrUpdateHook(D,X,F);if(!D.env||typeof D.env!=="object")D.env={};let J=this.config.apiKey||this.config.accessToken||"",Y=J?`Authorization=Bearer ${J}`:"";D.env={...D.env,CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_EXPORTER_OTLP_ENDPOINT:this.config.apiUrl,OTEL_EXPORTER_OTLP_HEADERS:Y,OTEL_METRIC_EXPORT_INTERVAL:"10000",OTEL_LOGS_EXPORT_INTERVAL:"5000"},XD.mkdirSync(pD.dirname(j8),{recursive:!0}),XD.writeFileSync(j8,JSON.stringify(D,null,2))}addOrUpdateHook(D,F,Z){if(!D.hooks)D.hooks={};let J=D.hooks[F],Y={matcher:"*",hooks:[{type:"command",command:Z}]};if(!Array.isArray(J)){D.hooks[F]=[Y];return}if(!J.some(($)=>$.hooks.some((Q)=>typeof Q.command==="string"&&Q.command.includes("a24z hook claude-code"))))J.push(Y)}updateGeminiSettings(){let D={};if(XD.existsSync(S8))try{D=JSON.parse(XD.readFileSync(S8,"utf8"))}catch(F){console.warn(P.yellow("Warning: Could not parse existing Gemini settings.json, creating new one"))}D.telemetry={enabled:!0,target:"local",otlpEndpoint:this.config.apiUrl,otlpProtocol:"http",logPrompts:!0,useCollector:!0,...D.telemetry},XD.mkdirSync(pD.dirname(S8),{recursive:!0}),XD.writeFileSync(S8,JSON.stringify(D,null,2))}updateCodexSettings(){let D={};if(XD.existsSync(k8))try{let Y=XD.readFileSync(k8,"utf8");D=P3.default.parse(Y)}catch(Y){console.warn(P.yellow("Warning: Could not parse existing Codex config.toml, creating new one"))}let F=this.config.apiKey||this.config.accessToken,Z={};if(F)Z.authorization=`Bearer ${F}`,Z["x-otlp-api-key"]=`${F}`;D.otel={...D.otel,environment:"production",exporter:{"otlp-http":{endpoint:`${this.config.apiUrl}/v1/logs`,protocol:"http/json",headers:Z}},log_user_prompt:!0},XD.mkdirSync(pD.dirname(k8),{recursive:!0});let J=P3.default.stringify(D);XD.writeFileSync(k8,J)}async setApiKey(D){console.log(P.blue("\uD83D\uDD11 Configuring API key..."));try{if(!D||D.trim().length===0)throw Error("API key cannot be empty");this.config.apiKey=D.trim(),this.saveConfig();let F=this.config.tools;if(F.length>0){for(let Z of F)if(Z==="claude-code")this.updateClaudeSettings();else if(Z==="gemini-cli")this.updateGeminiSettings();else if(Z==="codex")this.updateCodexSettings()}if(console.log(P.green("✅ API key configured successfully!")),console.log(P.white("\uD83D\uDD27 Configuration saved to:"),P.cyan(z0)),F.length>0)console.log(P.white(`\uD83D\uDCDD Updated settings for: ${F.join(", ")}`));console.log(P.green("Your sessions will now be authenticated with this API key."))}catch(F){console.error(P.red("❌ Failed to configure API key:"),F),process.exit(1)}}async login(){console.log(P.blue("\uD83D\uDD10 Logging in to A24Z Observability..."));try{let D=await fetch(`${this.config.apiUrl}/api/v1/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:this.config.clientId})});if(!D.ok)throw Error(`Authentication request failed: ${D.status}`);let F=await D.json(),{device_code:Z,user_code:J,verification_uri:Y,verification_uri_complete:X,expires_in:$,interval:Q}=F.data;if(console.log(P.green("\uD83D\uDCF1 Complete authentication in your browser:")),console.log(P.cyan(` Go to: ${Y}`)),console.log(P.yellow(` Enter code: ${J}`)),X)console.log(P.gray(` Or visit: ${X}`));console.log(P.white(` Code expires in ${Math.floor($/60)} minutes`));let{openBrowser:G}=await pR.prompt([{type:"confirm",name:"openBrowser",message:"Open browser automatically?",default:!0}]);if(G)await LO(X||Y);let q=O6("Waiting for authentication...").start(),K=await this.pollForTokens(Z,Q,$);if(q.succeed("Authentication successful!"),this.config.accessToken=K.access_token,this.config.refreshToken=K.refresh_token||null,this.config.userEmail=K.user?.email||null,this.saveConfig(),!this.config.apiKey||!this.config.apiKeyId){console.log(P.blue("\uD83D\uDD11 Setting up API key for CLI authentication..."));try{let V=u4.hostname(),H=await this.findExistingApiKey(K.access_token,V);if(H)console.log(P.yellow(`⚠️ Found existing API key for this machine: ${H.name}`)),console.log(P.yellow(" Creating new key since the original key value cannot be retrieved")),console.log(P.gray(" (You may want to revoke the old key from the dashboard)"));let C=await this.createApiKeyForCLI(K.access_token,V);if(C&&C.apiKey&&C.id)this.config.apiKey=C.apiKey,this.config.apiKeyId=C.id,this.saveConfig(),console.log(P.green("✅ API key created successfully"))}catch(V){console.log(P.yellow("⚠️ Could not create API key, will use access token instead")),console.log(P.gray(` (${V instanceof Error?V.message:"Unknown error"})`))}}else console.log(P.green("✅ Using existing API key for this machine"));let E=this.config.tools;if(E.length>0){for(let V of E)if(V==="claude-code")this.updateClaudeSettings();else if(V==="gemini-cli")this.updateGeminiSettings();else if(V==="codex")this.updateCodexSettings()}if(console.log(P.green("✅ Login successful!")),K.user?.email)console.log(P.white("\uD83D\uDC64 User:"),P.cyan(K.user.email));console.log(P.green("Your sessions will now be associated with your organization."))}catch(D){console.error(P.red("❌ Login failed:"),D),console.log(P.yellow("Make sure the A24Z service is available and try again.")),process.exit(1)}}async findExistingApiKey(D,F){try{let Z=await fetch(`${this.config.apiUrl}/api/v1/api-keys`,{method:"GET",headers:{Authorization:`Bearer ${D}`}});if(!Z.ok)return null;let X=((await Z.json()).apiKeys||[]).find(($)=>$.status==="active"&&$.name.includes(`CLI - ${F}`));return X?{id:X.id,name:X.name}:null}catch(Z){return null}}async createApiKeyForCLI(D,F){try{let J=new Date().toISOString().replace(/[:.]/g,"-").substring(0,19),Y=`CLI - ${F} - ${J}`,X=await fetch(`${this.config.apiUrl}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${D}`},body:JSON.stringify({name:Y})});if(!X.ok){let $=await X.text().catch(()=>"");throw Error(`API key creation failed: ${X.status} ${$}`)}return await X.json()}catch(Z){throw Error(`Failed to create API key: ${Z instanceof Error?Z.message:String(Z)}`)}}async pollForTokens(D,F,Z){let J=Date.now(),Y=Z*1000,X=F;while(Date.now()-J<Y){try{let $=await fetch(`${this.config.apiUrl}/api/v1/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:D,client_id:this.config.clientId})});if(!$.ok){let G="unknown_error",q=$.status;try{G=(await $.json()).error||G}catch{}if(q===428&&G==="authorization_pending"){await new Promise((K)=>setTimeout(K,X*1000));continue}if(q===429&&G==="slow_down"){X+=5,await new Promise((K)=>setTimeout(K,X*1000));continue}if(q===403&&G==="access_denied")throw Error("User denied authorization");if(q===400&&G==="expired_token")throw Error("Device code expired");if(q>=500){await new Promise((K)=>setTimeout(K,X*1000));continue}throw Error(`Token request failed: ${q} ${G}`)}let Q=await $.json();if(Q.success)return Q.data}catch($){if($.name==="TypeError"&&$.message.includes("fetch")){await new Promise((Q)=>setTimeout(Q,X*1000));continue}throw $}await new Promise(($)=>setTimeout($,X*1000))}throw Error("Authentication timeout")}async uninstall(D){let F;try{F=d7(D)}catch(J){console.error(P.red("❌ Error:"),J instanceof Error?J.message:J),process.exit(1)}let Z=O6(`Uninstalling a24z hooks for ${F}...`).start();try{if(F==="claude-code"&&XD.existsSync(j8))try{let J=JSON.parse(XD.readFileSync(j8,"utf8"));if(J&&typeof J==="object"&&typeof J.hooks==="object"&&J.hooks!==null){let Y=["SessionStart","SessionEnd"];for(let X of Y){let $=J.hooks[X];if(Array.isArray($)){for(let G of $)if(Array.isArray(G.hooks))G.hooks=G.hooks.filter((q)=>{if(typeof q.command!=="string")return!0;return!q.command.includes("a24z hook claude-code")});let Q=$.filter((G)=>Array.isArray(G.hooks)&&G.hooks.length>0);if(Q.length>0)J.hooks[X]=Q;else delete J.hooks[X]}}}XD.writeFileSync(j8,JSON.stringify(J,null,2))}catch(J){console.warn(P.yellow("Warning: Could not update Claude settings.json"))}if(F==="codex"&&XD.existsSync(k8))try{let J=XD.readFileSync(k8,"utf8"),Y=P3.default.parse(J);if(Y.otel)Y.otel.exporter="none";let X=P3.default.stringify(Y);XD.writeFileSync(k8,X)}catch(J){console.warn(P.yellow("Warning: Could not update Codex config.toml"))}if(F==="gemini-cli"&&XD.existsSync(S8))try{let J=JSON.parse(XD.readFileSync(S8,"utf8"));if(J.telemetry)J.telemetry.enabled=!1,delete J.telemetry.otlpEndpoint;XD.writeFileSync(S8,JSON.stringify(J,null,2))}catch(J){console.warn(P.yellow("Warning: Could not update Gemini settings.json"))}if(this.config.tools=this.config.tools.filter((J)=>J!==F),this.config.tools.length===0){if(XD.existsSync(z0))XD.unlinkSync(z0)}else this.saveConfig();if(Z.succeed(`a24z hooks uninstalled successfully for ${D}!`),console.log(P.green(`${D} will no longer send observability data.`)),this.config.tools.length>0)console.log(P.white(`Still installed: ${this.config.tools.join(", ")}`))}catch(J){Z.fail("Uninstallation failed"),console.error(P.red("❌ Error:"),J),process.exit(1)}}async status(){console.log(P.blue("\uD83D\uDCCA A24Z Observability Status"));let D=this.getInstalledTools();if(console.log(P.white("\uD83D\uDD27 Installation Status:")),D.length>0)console.log(` • Session monitoring: ${P.green("✅ Configured")}`),console.log(` • Installed tools: ${P.cyan(D.join(", "))}`);else console.log(` • Session monitoring: ${P.yellow("⚠️ Not configured")}`),console.log(P.gray(' Run "a24z install <tool>" to get started'));if(console.log(P.white("\uD83D\uDD10 Authentication Status:")),console.log(` • Logged in: ${this.config.accessToken?P.green("✅ Yes"):P.red("❌ No")}`),this.config.apiKey)console.log(` • API Key: ${P.green("✅ Configured")}`)}async hook(D="claude-code"){let F;try{F=d7(D)}catch(J){process.exit(1)}let Z=async()=>new Promise((J)=>{let Y="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(X)=>{Y+=X}),process.stdin.on("end",()=>J(Y)),setTimeout(()=>J(Y),5000)});try{let J=await Z(),Y=this.config.apiKey||this.config.accessToken||"";if(!Y)process.exit(1);let X=`${this.config.apiUrl}/api/v1/${F}/hooks`,$=new AbortController,Q=setTimeout(()=>$.abort(),200);try{await fetch(X,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Y}`},body:JSON.stringify(J),signal:$.signal})}catch(G){}finally{clearTimeout(Q)}process.exit(0)}catch(J){process.exit(1)}}async seed(D="claude-code",F={}){let Z;try{Z=d7(D)}catch(G){console.error(P.red("❌ Error:"),G instanceof Error?G.message:G),process.exit(1)}let J=typeof F.root==="string"&&F.root.length>0?F.root:pD.join(u4.homedir(),".claude","projects"),Y=typeof F.concurrency==="number"&&F.concurrency>0?F.concurrency:5,X=F.dryRun===!0,$=this.config.apiKey||this.config.accessToken||"";if(!$){console.error(P.red("❌ Not authenticated. Run 'a24z login' first or configure an API key.")),process.exit(1);return}let Q=O6(`Scanning transcripts in ${J} ...`).start();try{let G=await this.collectTranscriptFiles(J);if(Q.succeed(`Found ${G.length} transcript file(s).`),X){for(let A of G)console.log(P.gray(`DRY RUN: ${A}`));console.log(P.green("✅ Dry run complete."));return}console.log(P.white(`\uD83D\uDCE4 Sending ${G.length} transcript(s) to API (concurrency ${Y})...`));let q=0,K=0,E=`${this.config.apiUrl}/api/v1/${Z}/hooks`,V=0,H=G.length,C=async()=>{while(!0){let A=V;if(A>=H)return;V++;let R=G[A],x=this.deriveSessionIdFromPath(R);if(!x){K++,console.warn(P.yellow(`⚠️ Skipping (cannot derive session id): ${R}`));continue}let _=await this.extractCwdFromTranscript(R)||this.decodeCwdFromPath(R)||process.cwd(),u={hook_event_name:"SessionEnd",session_id:x,transcript_path:R,cwd:_,reason:"seed"},s=new AbortController,e=setTimeout(()=>s.abort(),15000);try{let i=await fetch(E,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${$}`},body:JSON.stringify(u),signal:s.signal});if(!i.ok){K++;let TD=await i.text().catch(()=>"");console.error(P.red(`❌ Failed (${i.status}): ${R}`),TD?P.gray(TD):"")}else q++,console.log(P.green(`✅ Sent: ${R}`))}catch(i){K++,console.error(P.red(`❌ Error sending ${R}:`),i)}finally{clearTimeout(e)}}},M=[];for(let A=0;A<Y;A++)M.push(C());if(await Promise.all(M),console.log(P.white(`
|
|
169
|
+
\uD83D\uDCC8 Seed summary:`)),console.log(` • Total: ${H}`),console.log(P.green(` • Sent: ${q}`)),console.log(P.red(` • Failed: ${K}`)),K>0)process.exitCode=1}catch(G){Q.fail("Failed to scan or send transcripts"),console.error(P.red("❌ Error:"),G),process.exit(1)}}async collectTranscriptFiles(D){let F=[],Z=async(J)=>{let Y=[];try{Y=await Tx.readdir(J,{withFileTypes:!0})}catch{return}for(let X of Y){let $=pD.join(J,X.name);if(X.isDirectory())await Z($);else if(X.isFile()&&X.name.toLowerCase().endsWith(".jsonl"))F.push($)}};return await Z(D),F.sort()}deriveSessionIdFromPath(D){let F=pD.basename(D),Z=F.toLowerCase().lastIndexOf(".jsonl");if(Z<=0)return null;let J=F.substring(0,Z);return J.length>0?J:null}async extractCwdFromTranscript(D){try{let Z=(await Tx.readFile(D,"utf8")).split(`
|
|
170
170
|
`).filter((J)=>J.trim().length>0).slice(0,100);for(let J of Z)try{let Y=JSON.parse(J),X=Y&&typeof Y.cwd==="string"?Y.cwd:null;if(X&&X.length>0)return X}catch{}}catch{}return null}decodeCwdFromPath(D){try{let F=pD.basename(pD.dirname(D));if(!F||F.length===0)return null;if(F.startsWith("-"))return`/${F.slice(1).split("-").join("/")}`;return null}catch{return null}}isTokenExpired(D){try{let F=D.split(".");if(F.length!==3)return!0;let J=JSON.parse(atob(F[1])).exp*1000,X=Date.now()+300000;return J<X}catch(F){return!0}}async refreshToken(){if(!this.config.refreshToken){this.config.accessToken=null,this.saveConfig();return}try{let D=await fetch(`${this.config.apiUrl}/api/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.accessToken}`},body:JSON.stringify({refresh_token:this.config.refreshToken})});if(!D.ok){this.config.accessToken=null,this.config.refreshToken=null,this.saveConfig();return}let F=await D.json();if(F.success&&F.data.access_token)this.config.accessToken=F.data.access_token,this.config.refreshToken=F.data.refresh_token||this.config.refreshToken,this.saveConfig();else throw Error("Invalid token refresh response")}catch(D){this.config.accessToken=null,this.config.refreshToken=null,this.saveConfig()}}}var L1=new yQ,V6=new Px;if(process.argv[2]!=="hook")b$({pkg:Rx}).notify();function wx(){try{let D=pD.resolve(LZD,"..","package.json"),F=XD.readFileSync(D,"utf8"),Z=JSON.parse(F);if(typeof Z.version==="string"&&Z.version.length>0)return Z.version}catch{}return"0.0.0"}function jx(){return`
|
|
171
171
|
░▒▓██████▓▒░░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░
|
|
172
172
|
░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
|
|
@@ -190,4 +190,4 @@ Examples:
|
|
|
190
190
|
$ a24z uninstall codex
|
|
191
191
|
`).action(async(D)=>{await V6.uninstall(D)});L1.command("hook <tool>").description("Internal: process a hook payload from stdin and send to A24Z").action(async(D)=>{await V6.hook(D)});L1.command("seed-transcripts").description("Scan Claude transcript directory and send synthetic SessionEnd hooks to ingest all transcripts").option("--tool <tool>","Tool name to use (default: claude-code)").option("--root <dir>","Root directory to scan (default: ~/.claude/projects)").option("--concurrency <n>","Number of parallel requests (default: 5)").option("--dry-run","List files without sending").action(async(D)=>{let F=typeof D.tool==="string"&&D.tool.length>0?D.tool:"claude-code",Z=typeof D.root==="string"&&D.root.length>0?D.root:void 0,J=D.concurrency?Number(D.concurrency):void 0,Y=D.dryRun===!0;await V6.seed(F,{root:Z,concurrency:J,dryRun:Y})});L1.command("set-api-key <apiKey>").description("Configure an API key for authentication (alternative to login)").action(async(D)=>{await V6.setApiKey(D)});L1.parse();
|
|
192
192
|
|
|
193
|
-
//# debugId=
|
|
193
|
+
//# debugId=2615DCFF421AE3CE64756E2164756E21
|