@quantiya/codevibe-core 1.0.22 → 1.0.23

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.
Files changed (2) hide show
  1. package/dist/index.js +5 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- "use strict";var It=Object.create;var ce=Object.defineProperty;var At=Object.getOwnPropertyDescriptor;var Tt=Object.getOwnPropertyNames;var Ct=Object.getPrototypeOf,Dt=Object.prototype.hasOwnProperty;var D=(n,e)=>()=>(n&&(e=n(n=0)),e);var Me=(n,e)=>{for(var t in e)ce(n,t,{get:e[t],enumerable:!0})},Be=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Tt(e))!Dt.call(n,i)&&i!==t&&ce(n,i,{get:()=>e[i],enumerable:!(r=At(e,i))||r.enumerable});return n};var v=(n,e,t)=>(t=n!=null?It(Ct(n)):{},Be(e||!n||!n.__esModule?ce(t,"default",{value:n,enumerable:!0}):t,n)),xt=n=>Be(ce({},"__esModule",{value:!0}),n);function _t(n,e){if(e instanceof Error){let t={name:e.name,message:e.message};e.stack&&(t.stack=e.stack);for(let r of Object.keys(e))r in t||(t[r]=e[r]);return t}return e}function ve(n){return new W(n)}var G,de,qe,Fe,W,c,He=D(()=>{"use strict";G=v(require("fs")),de=v(require("path")),qe=v(require("os")),Fe={debug:0,info:1,warn:2,error:3};W=class{constructor(e){this.name=e.name,this.logFile=e.logFile,this.level=e.level||"info",this.enableConsole=e.console??!1,this.logFile&&this.ensureLogDir()}ensureLogDir(){if(this.logFile){let e=de.dirname(this.logFile);G.existsSync(e)||G.mkdirSync(e,{recursive:!0})}}shouldLog(e){return Fe[e]>=Fe[this.level]}formatMessage(e,t,r){let i=new Date().toISOString(),s=e.toUpperCase().padEnd(5),o=`[${i}] [${s}] [${this.name}] ${t}`;return r!==void 0&&(r instanceof Error?(o+=` ${r.name}: ${r.message}`,r.stack&&(o+=`
1
+ "use strict";var It=Object.create;var ce=Object.defineProperty;var At=Object.getOwnPropertyDescriptor;var Tt=Object.getOwnPropertyNames;var Ct=Object.getPrototypeOf,xt=Object.prototype.hasOwnProperty;var x=(n,e)=>()=>(n&&(e=n(n=0)),e);var Me=(n,e)=>{for(var t in e)ce(n,t,{get:e[t],enumerable:!0})},Be=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Tt(e))!xt.call(n,i)&&i!==t&&ce(n,i,{get:()=>e[i],enumerable:!(r=At(e,i))||r.enumerable});return n};var v=(n,e,t)=>(t=n!=null?It(Ct(n)):{},Be(e||!n||!n.__esModule?ce(t,"default",{value:n,enumerable:!0}):t,n)),Dt=n=>Be(ce({},"__esModule",{value:!0}),n);function _t(n,e){if(e instanceof Error){let t={name:e.name,message:e.message};e.stack&&(t.stack=e.stack);for(let r of Object.keys(e))r in t||(t[r]=e[r]);return t}return e}function ve(n){return new W(n)}var G,de,qe,Fe,W,c,He=x(()=>{"use strict";G=v(require("fs")),de=v(require("path")),qe=v(require("os")),Fe={debug:0,info:1,warn:2,error:3};W=class{constructor(e){this.name=e.name,this.logFile=e.logFile,this.level=e.level||"info",this.enableConsole=e.console??!1,this.logFile&&this.ensureLogDir()}ensureLogDir(){if(this.logFile){let e=de.dirname(this.logFile);G.existsSync(e)||G.mkdirSync(e,{recursive:!0})}}shouldLog(e){return Fe[e]>=Fe[this.level]}formatMessage(e,t,r){let i=new Date().toISOString(),s=e.toUpperCase().padEnd(5),o=`[${i}] [${s}] [${this.name}] ${t}`;return r!==void 0&&(r instanceof Error?(o+=` ${r.name}: ${r.message}`,r.stack&&(o+=`
2
2
  ${r.stack}`)):typeof r=="object"?o+=` ${JSON.stringify(r,_t)}`:o+=` ${r}`),o}log(e,t,r){if(!this.shouldLog(e))return;let i=this.formatMessage(e,t,r);if(this.logFile)try{G.appendFileSync(this.logFile,i+`
3
- `)}catch{}if(this.enableConsole)switch(e){case"error":console.error(i);break;case"warn":console.warn(i);break;default:console.log(i)}}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}setLevel(e){this.level=e}};c=new W({name:"codevibe-core",logFile:de.join(qe.tmpdir(),"codevibe-core.log"),level:"info"})});var M=D(()=>{"use strict";He()});function Kt(n){for(let e of n)try{process.stderr.write(e+`
4
- `)}catch{}}function Rt(){Se=ke.join(Ve.homedir(),".codevibe");try{N.mkdirSync(Se,{recursive:!0,mode:448})}catch{}B="file"}function Pt(){if(B!==null||we!==null)return;let optedIn=process.env.CODEVIBE_ALLOW_FILE_KEYCHAIN==="1";if(optedIn){Kt(["","\u26A0 CodeVibe: file-based credential storage selected (CODEVIBE_ALLOW_FILE_KEYCHAIN=1).","\u26A0 Location: ~/.codevibe/ (directory 0700, files 0600)","\u26A0 Trust level: equivalent to ~/.ssh/id_rsa \u2014 weaker than OS keyring.","\u26A0 To use the OS keyring instead, unset CODEVIBE_ALLOW_FILE_KEYCHAIN and","\u26A0 install libsecret-1-0 + a running keyring daemon (Linux) or use the","\u26A0 native Keychain (macOS) / Credential Manager (Windows).",""]),c.warn("[keychain-backend] Using file-based storage at ~/.codevibe (CODEVIBE_ALLOW_FILE_KEYCHAIN=1 explicit opt-in)"),Rt();return}let keytarLoadError=null;try{let nodeRequire=eval("require");x=nodeRequire("keytar")}catch(n){keytarLoadError=n instanceof Error?n.message:String(n),x=null}if(x){B="keytar",c.info("[keychain-backend] Using keytar (OS-native keyring)");return}we=new le(["CodeVibe could not load the OS-native keyring (keytar).",`Reason: ${keytarLoadError??"unknown"}`,"","Options to fix this:"," 1. (Linux) Install libsecret and a keyring daemon:"," sudo apt install libsecret-1-0 gnome-keyring"," Then unlock the keyring for your user session.",""," 2. (Headless / CI / Docker) Opt in to file-based credential"," storage at ~/.codevibe/ (0600 files). This is equivalent"," in trust to ~/.ssh/id_rsa \u2014 not the OS keyring:"," export CODEVIBE_ALLOW_FILE_KEYCHAIN=1"].join(`
5
- `))}function Ot(n){return n.replace(/[^a-zA-Z0-9._-]/g,"_")}function Je(n){return ke.join(Se,`${Ot(n)}.json`)}function be(n){try{let e=N.readFileSync(Je(n),"utf-8"),t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}function je(n,e){let t=Je(n);N.writeFileSync(t,JSON.stringify(e,null,2),{mode:384});try{N.chmodSync(t,384)}catch{}}function Ee(){if(Pt(),B===null)throw we??new le("Keychain backend not initialized")}async function Ie(n,e){return Ee(),B==="keytar"&&x?x.getPassword(n,e):be(n)[e]??null}async function Ae(n,e,t){if(Ee(),B==="keytar"&&x){await x.setPassword(n,e,t);return}let r=be(n);r[e]=t,je(n,r)}async function Te(n,e){if(Ee(),B==="keytar"&&x)return x.deletePassword(n,e);let t=be(n);return e in t?(delete t[e],je(n,t),!0):!1}var Ve,ke,N,le,B,x,Se,we,Ge=D(()=>{"use strict";Ve=v(require("os")),ke=v(require("path")),N=v(require("fs"));M();le=class extends Error{constructor(e){super(e),this.name="KeychainBackendUnavailableError"}},B=null,x=null,Se="",we=null});var T,_,Ce,Ut,z,E,ze=D(()=>{"use strict";T=v(require("crypto")),_=class extends Error{constructor(e){super(e),this.name="CryptoError"}},Ce=1,Ut="CodeVibe E2E v1",z=class n{constructor(){}static getInstance(){return n.instance||(n.instance=new n),n.instance}generateKeyPair(){let e=T.createECDH("prime256v1");e.generateKeys();let r=e.getPublicKey().subarray(1).toString("base64");return{privateKey:e.getPrivateKey().toString("base64"),publicKey:r}}generateSessionKey(){return T.randomBytes(32).toString("base64")}deriveSharedKey(e,t){try{let r=T.createECDH("prime256v1"),i=Buffer.from(e,"base64");r.setPrivateKey(i);let s=Buffer.concat([Buffer.from([4]),Buffer.from(t,"base64")]),o=r.computeSecret(s),a=T.hkdfSync("sha256",o,Buffer.alloc(0),Buffer.from(Ut,"utf8"),32);return Buffer.from(a)}catch(r){throw new _(`Failed to derive shared key: ${r}`)}}encryptSessionKey(e,t){let r=this.generateKeyPair(),i=this.deriveSharedKey(r.privateKey,t),s=Buffer.from(e,"base64");return{encryptedKey:this.encrypt(s,i).toString("base64"),ephemeralPublicKey:r.publicKey}}decryptSessionKey(e,t){let r=this.deriveSharedKey(t,e.ephemeralPublicKey),i=Buffer.from(e.encryptedKey,"base64");return this.decrypt(i,r).toString("base64")}encryptContent(e,t){let r=Buffer.from(t,"base64"),i=Buffer.from(e,"utf8");return this.encrypt(i,r).toString("base64")}decryptContent(e,t){let r=Buffer.from(t,"base64"),i=Buffer.from(e,"base64");return this.decrypt(i,r).toString("utf8")}encryptMetadata(e,t){let r=JSON.stringify(e);return this.encryptContent(r,t)}decryptMetadata(e,t){let r=this.decryptContent(e,t);return JSON.parse(r)}encryptData(e,t){let r=Buffer.from(t,"base64");return this.encrypt(e,r)}decryptData(e,t){let r=Buffer.from(t,"base64");return this.decrypt(e,r)}encrypt(e,t){let r=T.randomBytes(12),i=T.createCipheriv("aes-256-gcm",t,r),s=Buffer.concat([i.update(e),i.final()]),o=i.getAuthTag();return Buffer.concat([r,s,o])}decrypt(e,t){let r=e.subarray(0,12),i=e.subarray(e.length-16),s=e.subarray(12,e.length-16),o=T.createDecipheriv("aes-256-gcm",t,r);o.setAuthTag(i);try{return Buffer.concat([o.update(s),o.final()])}catch{throw new _("Decryption failed: Invalid ciphertext or authentication tag")}}serializePrivateKey(e){return e}deserializePrivateKey(e){return e}},E=z.getInstance()});var ee=D(()=>{"use strict";ze()});function I(){let n=process.env.ENVIRONMENT;return n==="development"||n==="production"?n:"production"}function ue(n){let e=n||I();return pe={...F[e],aws:{...F[e].aws,region:process.env.AWS_REGION||F[e].aws.region,appsyncUrl:process.env.APPSYNC_URL||F[e].aws.appsyncUrl,cognitoUserPoolId:process.env.COGNITO_USER_POOL_ID||F[e].aws.cognitoUserPoolId,cognitoClientId:process.env.COGNITO_CLIENT_ID||F[e].aws.cognitoClientId,cognitoDomain:process.env.COGNITO_DOMAIN||F[e].aws.cognitoDomain}},Ye=!0,pe}function w(){return(!Ye||!pe)&&ue(),pe}var te,re,F,pe,Ye,Xe=D(()=>{"use strict";te=v(require("os")),re=v(require("path")),F={development:{environment:"development",aws:{region:"us-east-1",appsyncUrl:"https://api-dev.codevibe.quantiya.ai/graphql",cognitoUserPoolId:"us-east-1_yVwWDPvvJ",cognitoClientId:"e9r5apv6v5uui3l928r2ris0r",cognitoDomain:"codevibe-development.auth.us-east-1.amazoncognito.com"},keychain:{serviceName:"ai.quantiya.app.codevibe"},server:{port:3456,host:"127.0.0.1",dynamicPort:!0},claude:{command:"claude",defaultTimeout:6e4},codex:{command:"codex",defaultTimeout:6e4,sessionsDir:re.default.join(te.default.homedir(),".codex","sessions"),approvalTimeoutMs:5e3},gemini:{command:"gemini",defaultTimeout:6e4,transcriptDir:re.default.join(te.default.homedir(),".gemini","tmp")}},production:{environment:"production",aws:{region:"us-east-1",appsyncUrl:"https://api.codevibe.quantiya.ai/graphql",cognitoUserPoolId:"us-east-1_mNRO0j5og",cognitoClientId:"5p04dbc9ojptc5r8n7605fg78f",cognitoDomain:"codevibe-production.auth.us-east-1.amazoncognito.com"},keychain:{serviceName:"ai.quantiya.app.codevibe"},server:{port:3456,host:"127.0.0.1",dynamicPort:!0},claude:{command:"claude",defaultTimeout:6e4},codex:{command:"codex",defaultTimeout:6e4,sessionsDir:re.default.join(te.default.homedir(),".codex","sessions"),approvalTimeoutMs:5e3},gemini:{command:"gemini",defaultTimeout:6e4,transcriptDir:re.default.join(te.default.homedir(),".gemini","tmp")}}},pe=null,Ye=!1});var Y=D(()=>{"use strict";Xe()});var ye,Ze,K,De,$t,q,y,Qe=D(()=>{"use strict";ye=v(require("os")),Ze=require("uuid");Ge();ee();Y();M();K=class extends Error{constructor(e){super(e),this.name="KeychainError"}},De="device-identity",$t="tokens-",q=class n{constructor(){this.deviceIdentity=null;this.sessionKeyCache=new Map;this.isRegistered=!1;this._serviceName=null}get serviceName(){return this._serviceName||(this._serviceName=w().keychain.serviceName),this._serviceName}static getInstance(){return n.instance||(n.instance=new n),n.instance}async getDeviceIdentity(){if(this.deviceIdentity)return this.deviceIdentity;let e=await Ie(this.serviceName,De);return e?(this.deviceIdentity=JSON.parse(e),c.info(`[KeychainManager] Loaded device identity: ${this.deviceIdentity.deviceId}`),this.deviceIdentity):null}async setDeviceIdentity(e){try{await Ae(this.serviceName,De,JSON.stringify(e)),this.deviceIdentity=e,c.info(`[KeychainManager] Saved device identity: ${e.deviceId}`)}catch(t){throw c.error(`[KeychainManager] Failed to save device identity: ${t}`),new K(`Failed to save device identity: ${t}`)}}async getOrCreateDeviceIdentity(){let e=await this.getDeviceIdentity();if(e)return e;let t=E.generateKeyPair();return e={deviceId:(0,Ze.v4)().toUpperCase(),privateKey:t.privateKey,publicKey:t.publicKey,createdAt:new Date().toISOString()},await this.setDeviceIdentity(e),c.info(`[KeychainManager] Generated new device identity: ${e.deviceId}`),e}async getDeviceId(){return(await this.getOrCreateDeviceIdentity()).deviceId}async getDevicePublicKey(){return(await this.getOrCreateDeviceIdentity()).publicKey}async getDevicePrivateKey(){return(await this.getOrCreateDeviceIdentity()).privateKey}async hasDeviceIdentity(){return await this.getDeviceIdentity()!==null}async deleteDeviceIdentity(){try{await Te(this.serviceName,De),this.deviceIdentity=null,this.sessionKeyCache.clear(),this.isRegistered=!1,c.info("[KeychainManager] Deleted device identity")}catch(e){throw c.error(`[KeychainManager] Failed to delete device identity: ${e}`),new K(`Failed to delete device identity: ${e}`)}}getTokenAccount(e){return`${$t}${e}`}async getTokens(e="production"){let t=await Ie(this.serviceName,this.getTokenAccount(e));if(!t)return null;let r=JSON.parse(t);return c.debug(`[KeychainManager] Loaded tokens for ${e}`),r}async setTokens(e,t="production"){try{await Ae(this.serviceName,this.getTokenAccount(t),JSON.stringify(e)),c.info(`[KeychainManager] Saved tokens for ${t}`,{userId:e.userId,email:e.email})}catch(r){throw c.error(`[KeychainManager] Failed to save tokens: ${r}`),new K(`Failed to save tokens: ${r}`)}}async deleteTokens(e="production"){try{let t=await Te(this.serviceName,this.getTokenAccount(e));return t&&c.info(`[KeychainManager] Deleted tokens for ${e}`),t}catch(t){return c.error(`[KeychainManager] Failed to delete tokens: ${t}`),!1}}isTokenExpired(e){return Date.now()>=e.expiresAt-3e5}async getSessionKey(e,t){let r=this.sessionKeyCache.get(e);if(r)return r;if(!t||t.length===0)return null;let i=await this.getDeviceId(),s=t.find(d=>d.deviceId===i);if(!s)return c.warn(`[KeychainManager] Device ${i} not found in encryptedKeys`),null;let o=await this.getDevicePrivateKey(),a=E.decryptSessionKey(s,o);return this.sessionKeyCache.set(e,a),c.info(`[KeychainManager] Decrypted and cached session key for ${e}`),a}createSessionKey(e,t){let r=E.generateSessionKey(),i=[],s=[];for(let o of e)try{let a=E.encryptSessionKey(r,o.publicKey);i.push({deviceId:o.deviceId,encryptedKey:a.encryptedKey,ephemeralPublicKey:a.ephemeralPublicKey})}catch(a){c.warn("[KeychainManager] Skipping device with invalid public key",{deviceId:o.deviceId,error:a instanceof Error?a.message:String(a)}),s.push(o.deviceId);try{t?.onDeviceSkipped?.(s.length)}catch{}}if(i.length===0)throw new _(`Failed to encrypt session key for any of ${e.length} devices`);return c.info("[KeychainManager] Created session key",{encryptedCount:i.length,skippedCount:s.length,totalCount:e.length}),{sessionKey:r,encryptedKeys:i,skippedDeviceIds:s}}cacheSessionKey(e,t){this.sessionKeyCache.set(e,t)}getCachedSessionKey(e){return this.sessionKeyCache.get(e)??null}getCachedSessionIds(){return Array.from(this.sessionKeyCache.keys())}clearSessionKey(e){this.sessionKeyCache.delete(e)}clearAllSessionKeys(){this.sessionKeyCache.clear()}getIsRegistered(){return this.isRegistered}setIsRegistered(e){this.isRegistered=e}getDeviceName(){return ye.hostname()||"CLI Client"}getDevicePlatform(){let e=ye.platform();return e==="darwin"?"MACOS":e==="linux"?"LINUX":e==="win32"?"WINDOWS":"CLI"}async clearAllData(){await this.deleteDeviceIdentity(),await this.deleteTokens("development"),await this.deleteTokens("production"),this.sessionKeyCache.clear(),this.isRegistered=!1,c.info("[KeychainManager] Cleared all data")}},y=q.getInstance()});var et={};Me(et,{KeychainError:()=>K,KeychainManager:()=>q,keychainManager:()=>y});var R=D(()=>{"use strict";Qe()});var sr={};Me(sr,{AgentType:()=>st,AppSyncClient:()=>ne,AuthService:()=>Q,CryptoError:()=>_,CryptoService:()=>z,DeliveryStatus:()=>it,ENCRYPTION_VERSION:()=>Ce,EventSource:()=>xe,EventType:()=>nt,KeychainError:()=>K,KeychainManager:()=>q,Logger:()=>W,SessionStatus:()=>he,authService:()=>P,createLogger:()=>ve,cryptoService:()=>E,errorWasBeaconed:()=>se,fireAuthCompletedBeacon:()=>ie,fireAuthFailedBeacon:()=>b,getConfig:()=>w,getEnvironment:()=>I,getErrorReason:()=>Re,keychainManager:()=>y,loadConfig:()=>ue,logger:()=>c,markErrorBeaconed:()=>A,mutations:()=>C,normalizeSnapshot:()=>$e,parseInteractivePrompt:()=>St,prepareSessionEncryption:()=>fe,queries:()=>U,registerDeviceEncryptionKey:()=>ae,rekeySessionForNewDevices:()=>j,resumeOrCreateSession:()=>Le,runAuthCli:()=>me,startDeviceKeyWatcher:()=>We,subscriptions:()=>H});module.exports=xt(sr);R();ee();var V=v(require("ws")),J=require("uuid");Y();M();R();var tt=v(require("dns")),rt=v(require("fs"));if(Lt())try{tt.setDefaultResultOrder("ipv4first")}catch{}function Lt(){if(process.platform!=="linux")return!1;try{let n=rt.readFileSync("/proc/sys/kernel/osrelease","utf8");return/microsoft|wsl/i.test(n)}catch{return!1}}async function X(n,e,t){try{return await fetch(n,e)}catch(r){let i=r?.cause?.code,s=r?.cause?.message,o=i||s||r?.message||"unknown",a=Wt(i),d=t?`${t}: `:"",l=`Node ${process.version} on ${process.platform}`,h=[`${d}Cannot reach ${n}`,` Underlying error: ${o}`];a&&h.push(` Suggested fix: ${a}`),h.push(` Platform: ${l}`);let p=new Error(h.join(`
3
+ `)}catch{}if(this.enableConsole)switch(e){case"error":console.error(i);break;case"warn":console.warn(i);break;default:console.log(i)}}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}setLevel(e){this.level=e}};c=new W({name:"codevibe-core",logFile:de.join(qe.tmpdir(),"codevibe-core.log"),level:"info"})});var M=x(()=>{"use strict";He()});function Kt(n){for(let e of n)try{process.stderr.write(e+`
4
+ `)}catch{}}function Rt(){Se=ke.join(Ve.homedir(),".codevibe");try{N.mkdirSync(Se,{recursive:!0,mode:448})}catch{}B="file"}function Pt(){if(B!==null||we!==null)return;let optedIn=process.env.CODEVIBE_ALLOW_FILE_KEYCHAIN==="1";if(optedIn){Kt(["","\u26A0 CodeVibe: file-based credential storage selected (CODEVIBE_ALLOW_FILE_KEYCHAIN=1).","\u26A0 Location: ~/.codevibe/ (directory 0700, files 0600)","\u26A0 Trust level: equivalent to ~/.ssh/id_rsa \u2014 weaker than OS keyring.","\u26A0 To use the OS keyring instead, unset CODEVIBE_ALLOW_FILE_KEYCHAIN and","\u26A0 install libsecret-1-0 + a running keyring daemon (Linux) or use the","\u26A0 native Keychain (macOS) / Credential Manager (Windows).",""]),c.warn("[keychain-backend] Using file-based storage at ~/.codevibe (CODEVIBE_ALLOW_FILE_KEYCHAIN=1 explicit opt-in)"),Rt();return}let keytarLoadError=null;try{let nodeRequire=eval("require");D=nodeRequire("keytar")}catch(n){keytarLoadError=n instanceof Error?n.message:String(n),D=null}if(D){B="keytar",c.info("[keychain-backend] Using keytar (OS-native keyring)");return}we=new le(["CodeVibe could not load the OS-native keyring (keytar).",`Reason: ${keytarLoadError??"unknown"}`,"","Options to fix this:"," 1. (Linux) Install libsecret and a keyring daemon:"," sudo apt install libsecret-1-0 gnome-keyring"," Then unlock the keyring for your user session.",""," 2. (Headless / CI / Docker) Opt in to file-based credential"," storage at ~/.codevibe/ (0600 files). This is equivalent"," in trust to ~/.ssh/id_rsa \u2014 not the OS keyring:"," export CODEVIBE_ALLOW_FILE_KEYCHAIN=1"].join(`
5
+ `))}function Ot(n){return n.replace(/[^a-zA-Z0-9._-]/g,"_")}function Je(n){return ke.join(Se,`${Ot(n)}.json`)}function be(n){try{let e=N.readFileSync(Je(n),"utf-8"),t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}function je(n,e){let t=Je(n);N.writeFileSync(t,JSON.stringify(e,null,2),{mode:384});try{N.chmodSync(t,384)}catch{}}function Ee(){if(Pt(),B===null)throw we??new le("Keychain backend not initialized")}async function Ie(n,e){return Ee(),B==="keytar"&&D?D.getPassword(n,e):be(n)[e]??null}async function Ae(n,e,t){if(Ee(),B==="keytar"&&D){await D.setPassword(n,e,t);return}let r=be(n);r[e]=t,je(n,r)}async function Te(n,e){if(Ee(),B==="keytar"&&D)return D.deletePassword(n,e);let t=be(n);return e in t?(delete t[e],je(n,t),!0):!1}var Ve,ke,N,le,B,D,Se,we,Ge=x(()=>{"use strict";Ve=v(require("os")),ke=v(require("path")),N=v(require("fs"));M();le=class extends Error{constructor(e){super(e),this.name="KeychainBackendUnavailableError"}},B=null,D=null,Se="",we=null});var T,_,Ce,Ut,z,E,ze=x(()=>{"use strict";T=v(require("crypto")),_=class extends Error{constructor(e){super(e),this.name="CryptoError"}},Ce=1,Ut="CodeVibe E2E v1",z=class n{constructor(){}static getInstance(){return n.instance||(n.instance=new n),n.instance}generateKeyPair(){let e=T.createECDH("prime256v1");e.generateKeys();let r=e.getPublicKey().subarray(1).toString("base64");return{privateKey:e.getPrivateKey().toString("base64"),publicKey:r}}generateSessionKey(){return T.randomBytes(32).toString("base64")}deriveSharedKey(e,t){try{let r=T.createECDH("prime256v1"),i=Buffer.from(e,"base64");r.setPrivateKey(i);let s=Buffer.from(t,"base64"),o=s.length===65&&s[0]===4?s:Buffer.concat([Buffer.from([4]),s]),a=r.computeSecret(o),d=T.hkdfSync("sha256",a,Buffer.alloc(0),Buffer.from(Ut,"utf8"),32);return Buffer.from(d)}catch(r){throw new _(`Failed to derive shared key: ${r}`)}}encryptSessionKey(e,t){let r=this.generateKeyPair(),i=this.deriveSharedKey(r.privateKey,t),s=Buffer.from(e,"base64");return{encryptedKey:this.encrypt(s,i).toString("base64"),ephemeralPublicKey:r.publicKey}}decryptSessionKey(e,t){let r=this.deriveSharedKey(t,e.ephemeralPublicKey),i=Buffer.from(e.encryptedKey,"base64");return this.decrypt(i,r).toString("base64")}encryptContent(e,t){let r=Buffer.from(t,"base64"),i=Buffer.from(e,"utf8");return this.encrypt(i,r).toString("base64")}decryptContent(e,t){let r=Buffer.from(t,"base64"),i=Buffer.from(e,"base64");return this.decrypt(i,r).toString("utf8")}encryptMetadata(e,t){let r=JSON.stringify(e);return this.encryptContent(r,t)}decryptMetadata(e,t){let r=this.decryptContent(e,t);return JSON.parse(r)}encryptData(e,t){let r=Buffer.from(t,"base64");return this.encrypt(e,r)}decryptData(e,t){let r=Buffer.from(t,"base64");return this.decrypt(e,r)}encrypt(e,t){let r=T.randomBytes(12),i=T.createCipheriv("aes-256-gcm",t,r),s=Buffer.concat([i.update(e),i.final()]),o=i.getAuthTag();return Buffer.concat([r,s,o])}decrypt(e,t){let r=e.subarray(0,12),i=e.subarray(e.length-16),s=e.subarray(12,e.length-16),o=T.createDecipheriv("aes-256-gcm",t,r);o.setAuthTag(i);try{return Buffer.concat([o.update(s),o.final()])}catch{throw new _("Decryption failed: Invalid ciphertext or authentication tag")}}serializePrivateKey(e){return e}deserializePrivateKey(e){return e}},E=z.getInstance()});var ee=x(()=>{"use strict";ze()});function I(){let n=process.env.ENVIRONMENT;return n==="development"||n==="production"?n:"production"}function ue(n){let e=n||I();return pe={...F[e],aws:{...F[e].aws,region:process.env.AWS_REGION||F[e].aws.region,appsyncUrl:process.env.APPSYNC_URL||F[e].aws.appsyncUrl,cognitoUserPoolId:process.env.COGNITO_USER_POOL_ID||F[e].aws.cognitoUserPoolId,cognitoClientId:process.env.COGNITO_CLIENT_ID||F[e].aws.cognitoClientId,cognitoDomain:process.env.COGNITO_DOMAIN||F[e].aws.cognitoDomain}},Ye=!0,pe}function w(){return(!Ye||!pe)&&ue(),pe}var te,re,F,pe,Ye,Xe=x(()=>{"use strict";te=v(require("os")),re=v(require("path")),F={development:{environment:"development",aws:{region:"us-east-1",appsyncUrl:"https://api-dev.codevibe.quantiya.ai/graphql",cognitoUserPoolId:"us-east-1_yVwWDPvvJ",cognitoClientId:"e9r5apv6v5uui3l928r2ris0r",cognitoDomain:"codevibe-development.auth.us-east-1.amazoncognito.com"},keychain:{serviceName:"ai.quantiya.app.codevibe"},server:{port:3456,host:"127.0.0.1",dynamicPort:!0},claude:{command:"claude",defaultTimeout:6e4},codex:{command:"codex",defaultTimeout:6e4,sessionsDir:re.default.join(te.default.homedir(),".codex","sessions"),approvalTimeoutMs:5e3},gemini:{command:"gemini",defaultTimeout:6e4,transcriptDir:re.default.join(te.default.homedir(),".gemini","tmp")}},production:{environment:"production",aws:{region:"us-east-1",appsyncUrl:"https://api.codevibe.quantiya.ai/graphql",cognitoUserPoolId:"us-east-1_mNRO0j5og",cognitoClientId:"5p04dbc9ojptc5r8n7605fg78f",cognitoDomain:"codevibe-production.auth.us-east-1.amazoncognito.com"},keychain:{serviceName:"ai.quantiya.app.codevibe"},server:{port:3456,host:"127.0.0.1",dynamicPort:!0},claude:{command:"claude",defaultTimeout:6e4},codex:{command:"codex",defaultTimeout:6e4,sessionsDir:re.default.join(te.default.homedir(),".codex","sessions"),approvalTimeoutMs:5e3},gemini:{command:"gemini",defaultTimeout:6e4,transcriptDir:re.default.join(te.default.homedir(),".gemini","tmp")}}},pe=null,Ye=!1});var Y=x(()=>{"use strict";Xe()});var ye,Ze,K,xe,$t,q,y,Qe=x(()=>{"use strict";ye=v(require("os")),Ze=require("uuid");Ge();ee();Y();M();K=class extends Error{constructor(e){super(e),this.name="KeychainError"}},xe="device-identity",$t="tokens-",q=class n{constructor(){this.deviceIdentity=null;this.sessionKeyCache=new Map;this.isRegistered=!1;this._serviceName=null}get serviceName(){return this._serviceName||(this._serviceName=w().keychain.serviceName),this._serviceName}static getInstance(){return n.instance||(n.instance=new n),n.instance}async getDeviceIdentity(){if(this.deviceIdentity)return this.deviceIdentity;let e=await Ie(this.serviceName,xe);return e?(this.deviceIdentity=JSON.parse(e),c.info(`[KeychainManager] Loaded device identity: ${this.deviceIdentity.deviceId}`),this.deviceIdentity):null}async setDeviceIdentity(e){try{await Ae(this.serviceName,xe,JSON.stringify(e)),this.deviceIdentity=e,c.info(`[KeychainManager] Saved device identity: ${e.deviceId}`)}catch(t){throw c.error(`[KeychainManager] Failed to save device identity: ${t}`),new K(`Failed to save device identity: ${t}`)}}async getOrCreateDeviceIdentity(){let e=await this.getDeviceIdentity();if(e)return e;let t=E.generateKeyPair();return e={deviceId:(0,Ze.v4)().toUpperCase(),privateKey:t.privateKey,publicKey:t.publicKey,createdAt:new Date().toISOString()},await this.setDeviceIdentity(e),c.info(`[KeychainManager] Generated new device identity: ${e.deviceId}`),e}async getDeviceId(){return(await this.getOrCreateDeviceIdentity()).deviceId}async getDevicePublicKey(){return(await this.getOrCreateDeviceIdentity()).publicKey}async getDevicePrivateKey(){return(await this.getOrCreateDeviceIdentity()).privateKey}async hasDeviceIdentity(){return await this.getDeviceIdentity()!==null}async deleteDeviceIdentity(){try{await Te(this.serviceName,xe),this.deviceIdentity=null,this.sessionKeyCache.clear(),this.isRegistered=!1,c.info("[KeychainManager] Deleted device identity")}catch(e){throw c.error(`[KeychainManager] Failed to delete device identity: ${e}`),new K(`Failed to delete device identity: ${e}`)}}getTokenAccount(e){return`${$t}${e}`}async getTokens(e="production"){let t=await Ie(this.serviceName,this.getTokenAccount(e));if(!t)return null;let r=JSON.parse(t);return c.debug(`[KeychainManager] Loaded tokens for ${e}`),r}async setTokens(e,t="production"){try{await Ae(this.serviceName,this.getTokenAccount(t),JSON.stringify(e)),c.info(`[KeychainManager] Saved tokens for ${t}`,{userId:e.userId,email:e.email})}catch(r){throw c.error(`[KeychainManager] Failed to save tokens: ${r}`),new K(`Failed to save tokens: ${r}`)}}async deleteTokens(e="production"){try{let t=await Te(this.serviceName,this.getTokenAccount(e));return t&&c.info(`[KeychainManager] Deleted tokens for ${e}`),t}catch(t){return c.error(`[KeychainManager] Failed to delete tokens: ${t}`),!1}}isTokenExpired(e){return Date.now()>=e.expiresAt-3e5}async getSessionKey(e,t){let r=this.sessionKeyCache.get(e);if(r)return r;if(!t||t.length===0)return null;let i=await this.getDeviceId(),s=t.find(d=>d.deviceId===i);if(!s)return c.warn(`[KeychainManager] Device ${i} not found in encryptedKeys`),null;let o=await this.getDevicePrivateKey(),a=E.decryptSessionKey(s,o);return this.sessionKeyCache.set(e,a),c.info(`[KeychainManager] Decrypted and cached session key for ${e}`),a}createSessionKey(e,t){let r=E.generateSessionKey(),i=[],s=[];for(let o of e)try{let a=E.encryptSessionKey(r,o.publicKey);i.push({deviceId:o.deviceId,encryptedKey:a.encryptedKey,ephemeralPublicKey:a.ephemeralPublicKey})}catch(a){c.warn("[KeychainManager] Skipping device with invalid public key",{deviceId:o.deviceId,error:a instanceof Error?a.message:String(a)}),s.push(o.deviceId);try{t?.onDeviceSkipped?.(s.length)}catch{}}if(i.length===0)throw new _(`Failed to encrypt session key for any of ${e.length} devices`);return c.info("[KeychainManager] Created session key",{encryptedCount:i.length,skippedCount:s.length,totalCount:e.length}),{sessionKey:r,encryptedKeys:i,skippedDeviceIds:s}}cacheSessionKey(e,t){this.sessionKeyCache.set(e,t)}getCachedSessionKey(e){return this.sessionKeyCache.get(e)??null}getCachedSessionIds(){return Array.from(this.sessionKeyCache.keys())}clearSessionKey(e){this.sessionKeyCache.delete(e)}clearAllSessionKeys(){this.sessionKeyCache.clear()}getIsRegistered(){return this.isRegistered}setIsRegistered(e){this.isRegistered=e}getDeviceName(){return ye.hostname()||"CLI Client"}getDevicePlatform(){let e=ye.platform();return e==="darwin"?"MACOS":e==="linux"?"LINUX":e==="win32"?"WINDOWS":"CLI"}async clearAllData(){await this.deleteDeviceIdentity(),await this.deleteTokens("development"),await this.deleteTokens("production"),this.sessionKeyCache.clear(),this.isRegistered=!1,c.info("[KeychainManager] Cleared all data")}},y=q.getInstance()});var et={};Me(et,{KeychainError:()=>K,KeychainManager:()=>q,keychainManager:()=>y});var R=x(()=>{"use strict";Qe()});var sr={};Me(sr,{AgentType:()=>st,AppSyncClient:()=>ne,AuthService:()=>Q,CryptoError:()=>_,CryptoService:()=>z,DeliveryStatus:()=>it,ENCRYPTION_VERSION:()=>Ce,EventSource:()=>De,EventType:()=>nt,KeychainError:()=>K,KeychainManager:()=>q,Logger:()=>W,SessionStatus:()=>he,authService:()=>P,createLogger:()=>ve,cryptoService:()=>E,errorWasBeaconed:()=>se,fireAuthCompletedBeacon:()=>ie,fireAuthFailedBeacon:()=>b,getConfig:()=>w,getEnvironment:()=>I,getErrorReason:()=>Re,keychainManager:()=>y,loadConfig:()=>ue,logger:()=>c,markErrorBeaconed:()=>A,mutations:()=>C,normalizeSnapshot:()=>$e,parseInteractivePrompt:()=>St,prepareSessionEncryption:()=>fe,queries:()=>U,registerDeviceEncryptionKey:()=>ae,rekeySessionForNewDevices:()=>j,resumeOrCreateSession:()=>Le,runAuthCli:()=>me,startDeviceKeyWatcher:()=>We,subscriptions:()=>H});module.exports=Dt(sr);R();ee();var V=v(require("ws")),J=require("uuid");Y();M();R();var tt=v(require("dns")),rt=v(require("fs"));if(Lt())try{tt.setDefaultResultOrder("ipv4first")}catch{}function Lt(){if(process.platform!=="linux")return!1;try{let n=rt.readFileSync("/proc/sys/kernel/osrelease","utf8");return/microsoft|wsl/i.test(n)}catch{return!1}}async function X(n,e,t){try{return await fetch(n,e)}catch(r){let i=r?.cause?.code,s=r?.cause?.message,o=i||s||r?.message||"unknown",a=Wt(i),d=t?`${t}: `:"",l=`Node ${process.version} on ${process.platform}`,h=[`${d}Cannot reach ${n}`,` Underlying error: ${o}`];a&&h.push(` Suggested fix: ${a}`),h.push(` Platform: ${l}`);let p=new Error(h.join(`
6
6
  `));throw p.cause=r,p}}function Wt(n){if(!n)return null;switch(n){case"ENOTFOUND":case"EAI_AGAIN":return'DNS resolution failed. On WSL Ubuntu, check /etc/resolv.conf, or try running with NODE_OPTIONS="--dns-result-order=ipv4first".';case"ETIMEDOUT":case"ECONNREFUSED":case"ECONNRESET":case"EHOSTUNREACH":case"ENETUNREACH":return`Network unreachable. On WSL Ubuntu, try NODE_OPTIONS="--dns-result-order=ipv4first" (WSL's IPv6 is often broken). If behind a corporate proxy, set HTTPS_PROXY.`;case"CERT_HAS_EXPIRED":case"CERT_NOT_YET_VALID":return"TLS certificate time error \u2014 likely system clock drift. On WSL, run `sudo hwclock -s`, or shut down WSL from PowerShell with `wsl --shutdown` and restart.";case"UNABLE_TO_GET_ISSUER_CERT_LOCALLY":case"SELF_SIGNED_CERT_IN_CHAIN":case"UNABLE_TO_VERIFY_LEAF_SIGNATURE":case"DEPTH_ZERO_SELF_SIGNED_CERT":return"Corporate HTTPS proxy detected \u2014 the TLS cert is not trusted by Node. Set NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.pem, or configure HTTPS_PROXY if a proxy is required.";default:return null}}var U={getSession:`
7
7
  query GetSession($sessionId: ID!) {
8
8
  getSession(sessionId: $sessionId) {
@@ -202,7 +202,7 @@ ${r.stack}`)):typeof r=="object"?o+=` ${JSON.stringify(r,_t)}`:o+=` ${r}`),o}log
202
202
  updatedAt
203
203
  }
204
204
  }
205
- `};var nt=(a=>(a.USER_PROMPT="USER_PROMPT",a.ASSISTANT_RESPONSE="ASSISTANT_RESPONSE",a.TOOL_USE="TOOL_USE",a.NOTIFICATION="NOTIFICATION",a.INTERACTIVE_PROMPT="INTERACTIVE_PROMPT",a.PROMPT_RESPONSE="PROMPT_RESPONSE",a.REASONING="REASONING",a))(nt||{}),xe=(t=>(t.DESKTOP="DESKTOP",t.MOBILE="MOBILE",t))(xe||{}),it=(r=>(r.SENT="SENT",r.DELIVERED="DELIVERED",r.EXECUTED="EXECUTED",r))(it||{});var he=(r=>(r.ACTIVE="ACTIVE",r.INACTIVE="INACTIVE",r.PAUSED="PAUSED",r))(he||{}),st=(r=>(r.CLAUDE="CLAUDE",r.GEMINI="GEMINI",r.CODEX="CODEX",r))(st||{});var k={urgentMaxAttempts:10,baseDelayMs:1e3,maxDelayMs:6e4,backoffMultiplier:2,persistentDelayMs:300*1e3},ne=class n{constructor(){this.authenticated=!1;this.currentUserId=null;this.currentEmail=null;this.tokens=null;this.activeSubscriptions=new Map;this.pendingRefresh=null;this.lastRefreshFailureAt=null;this.deviceKeyWatcher=null;this.sessionUpdateWatchers=new Map;this.heartbeatTimers=new Map;this.environment=I(),c.info("[AppSyncClient] Initialized",{environment:this.environment})}static{this.REFRESH_BACKOFF_MS=3e4}getCurrentUserId(){if(!this.currentUserId)throw new Error("Not authenticated. Call authenticateWithStoredTokens() first.");return this.currentUserId}getCurrentUserEmail(){return this.currentEmail}async authenticateWithStoredTokens(){try{let e=await y.getTokens(this.environment);if(!e)return c.debug("[AppSyncClient] No stored tokens found"),!1;if(c.info("[AppSyncClient] Found stored OAuth tokens",{userId:e.userId,email:e.email,expired:y.isTokenExpired(e)}),y.isTokenExpired(e)){if(c.info("[AppSyncClient] Tokens expired, attempting refresh..."),!await this.refreshTokens(e))return c.warn("[AppSyncClient] Token refresh failed"),!1}else this.tokens=e;return this.currentUserId=this.tokens.userId,this.currentEmail=this.tokens.email,this.authenticated=!0,c.info("[AppSyncClient] Authenticated successfully",{userId:this.currentUserId,email:this.currentEmail}),!0}catch(e){return c.error("[AppSyncClient] Authentication failed:",e),!1}}async refreshTokens(e){if(this.pendingRefresh)return this.pendingRefresh;if(this.lastRefreshFailureAt!==null&&Date.now()-this.lastRefreshFailureAt<n.REFRESH_BACKOFF_MS)return!1;this.pendingRefresh=this.performRefresh(e);try{return await this.pendingRefresh}finally{this.pendingRefresh=null}}async performRefresh(e){let t=await this.callCognitoRefresh(e.refreshToken);if(t!==null)return this.applyRefreshedTokens(e,t);let r=null;try{r=await y.getTokens(this.environment)}catch(i){c.warn("[AppSyncClient] Failed to re-read tokens from storage during refresh recovery",{error:i instanceof Error?i.message:String(i)})}if(r&&r.refreshToken&&r.refreshToken!==e.refreshToken){c.info("[AppSyncClient] In-memory refresh token rejected; retrying with storage-backed token (likely out-of-band re-auth)");let i=await this.callCognitoRefresh(r.refreshToken);if(i!==null)return this.applyRefreshedTokens(r,i)}return this.lastRefreshFailureAt=Date.now(),!1}async callCognitoRefresh(e){try{let t=w(),r=`https://${t.aws.cognitoDomain}/oauth2/token`,i=new URLSearchParams({grant_type:"refresh_token",client_id:t.aws.cognitoClientId,refresh_token:e}),s=await X(r,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()},"Token refresh");return s.ok?await s.json():(c.error("[AppSyncClient] Token refresh failed",{status:s.status}),null)}catch(t){return c.error("[AppSyncClient] Token refresh error:",t),null}}async applyRefreshedTokens(e,t){let r={...e,accessToken:t.access_token,idToken:t.id_token,expiresAt:Date.now()+t.expires_in*1e3};this.tokens=r,this.lastRefreshFailureAt=null;try{await y.setTokens(r,this.environment),c.info("[AppSyncClient] Tokens refreshed",{expiresAt:new Date(r.expiresAt).toISOString()})}catch(i){c.warn("[AppSyncClient] Tokens refreshed but persistence failed; daemon keeps using fresh tokens in memory. A restart while persistence is still broken would lose them.",{error:i instanceof Error?i.message:String(i),expiresAt:new Date(r.expiresAt).toISOString()})}return!0}isAuthenticated(){return this.authenticated}signOut(){this.authenticated=!1,this.tokens=null,this.currentUserId=null,this.currentEmail=null,this.cleanupSubscriptions(),c.info("[AppSyncClient] Signed out")}async graphqlRequest(e,t,r=!1){let i=w();if(!this.tokens?.idToken)throw new Error('Not authenticated. Run "codevibe login" first.');let s={"Content-Type":"application/json",Authorization:this.tokens.idToken},o=await X(i.aws.appsyncUrl,{method:"POST",headers:s,body:JSON.stringify({query:e,variables:t})},"AppSync GraphQL request"),a=await o.json();if(o.status===401&&!r&&this.tokens){if(c.info("[AppSyncClient] 401 Unauthorized, refreshing token..."),await this.refreshTokens(this.tokens))return this.graphqlRequest(e,t,!0);throw new Error("Token expired and refresh failed")}if(!o.ok)throw new Error(`GraphQL request failed: ${o.status}`);if(a.errors?.length)throw new Error(`GraphQL error: ${a.errors[0].message}`);return a}async createSession(e){let t={...e,metadata:e.metadata?JSON.stringify(e.metadata):void 0},r=await this.graphqlRequest(C.createSession,{input:t});return c.info("[AppSyncClient] Session created",{sessionId:r.data.createSession.sessionId}),r.data.createSession}async updateSession(e){let t={...e,metadata:e.metadata?JSON.stringify(e.metadata):void 0},r=await this.graphqlRequest(C.updateSession,{input:t});return c.debug("[AppSyncClient] Session updated",{sessionId:r.data.updateSession.sessionId}),r.data.updateSession}async getSession(e){return(await this.graphqlRequest(U.getSession,{sessionId:e})).data.getSession}async createEvent(e){let t={...e,metadata:e.metadata?JSON.stringify(e.metadata):void 0},r=await this.graphqlRequest(C.createEvent,{input:t});return c.debug("[AppSyncClient] Event created",{eventId:r.data.createEvent.eventId,type:r.data.createEvent.type}),r.data.createEvent}async updateEventStatus(e){return(await this.graphqlRequest(C.updateEventStatus,{input:e})).data.updateEventStatus}async listEvents(e,t,r){return(await this.graphqlRequest(U.listEvents,{sessionId:e,source:t,limit:r})).data.listEvents.items}async listSessions(e=100){if(!this.currentUserId)throw new Error("Not authenticated");let t=[],r=null;do{let s=(await this.graphqlRequest(U.listSessions,{userId:this.currentUserId,limit:e,nextToken:r})).data?.listSessions;s?.items&&t.push(...s.items),r=s?.nextToken??null}while(r);return t}async sweepOrphanSessions(e){let t=e.staleThresholdMs??9e5,r=new Set(e.excludeSessionIds??[]),i=Date.now(),s;try{s=await this.listSessions()}catch(a){return c.warn("[AppSyncClient] OrphanSweep: listSessions failed, skipping sweep",{agentType:e.agentType,error:a instanceof Error?a.message:String(a)}),0}let o=0;for(let a of s){if(a.agentType!==e.agentType||a.status!=="ACTIVE"||r.has(a.sessionId)||!a.lastHeartbeatAt)continue;let d=i-new Date(a.lastHeartbeatAt).getTime();if(!(d<t)){c.warn("[AppSyncClient] OrphanSweep: marking stale session INACTIVE",{sessionId:a.sessionId,agentType:a.agentType,lastHeartbeatAt:a.lastHeartbeatAt,heartbeatAgeMinutes:Math.round(d/6e4)});try{await this.updateSession({sessionId:a.sessionId,status:"INACTIVE"}),o++}catch(l){c.warn("[AppSyncClient] OrphanSweep: updateSession failed, leaving row as-is",{sessionId:a.sessionId,error:l instanceof Error?l.message:String(l)})}}}return o>0&&c.info("[AppSyncClient] OrphanSweep complete",{agentType:e.agentType,swept:o}),o}async listUserDeviceKeys(){return(await this.graphqlRequest(U.listUserDeviceKeys,{})).data.listUserDeviceKeys||[]}async registerDeviceKey(e,t,r,i){let s={deviceId:e,publicKey:t,platform:r,deviceName:i};await this.graphqlRequest(C.registerDeviceKey,{input:s}),c.info("[AppSyncClient] Device key registered",{deviceId:e,platform:r})}async grantSessionKey(e){await this.graphqlRequest(C.grantSessionKey,{input:e}),c.info("[AppSyncClient] Session key granted",{sessionId:e.sessionId,deviceId:e.deviceId})}async getAttachmentDownloadUrl(e){return(await this.graphqlRequest(C.getAttachmentDownloadUrl,{s3Key:e})).data.getAttachmentDownloadUrl}subscribeToEvents(e,t,r){c.info("[AppSyncClient] Subscribing to events",{sessionId:e});let i=this.activeSubscriptions.get(e);i&&(this.cleanupSubscriptionState(i),this.activeSubscriptions.delete(e));let s={ws:null,subscriptionId:(0,J.v4)(),sessionId:e,onEvent:t,onError:r,reconnectAttempts:0,isReconnecting:!1,destroyed:!1};return this.activeSubscriptions.set(e,s),this.createSubscription(s),()=>{this.cleanupSubscriptionState(s),this.activeSubscriptions.delete(e)}}buildRealtimeUrl(){let e=w(),t=new URL(e.aws.appsyncUrl),i=/\.appsync-api\.[^.]+\.amazonaws\.com$/.test(t.host)?e.aws.appsyncUrl.replace("https://","wss://").replace("appsync-api","appsync-realtime-api"):`wss://${t.host}/graphql/realtime`,s={host:t.host};this.tokens?.idToken&&(s.Authorization=this.tokens.idToken);let o=Buffer.from(JSON.stringify(s)).toString("base64"),a=Buffer.from(JSON.stringify({})).toString("base64");return`${i}?header=${o}&payload=${a}`}createSubscription(e){let{sessionId:t,subscriptionId:r,onEvent:i,onError:s}=e;try{let o=this.buildRealtimeUrl(),a=new V.default(o,["graphql-ws"]);a.on("open",()=>{c.info("[AppSyncClient] WebSocket connected",{sessionId:t}),a.send(JSON.stringify({type:"connection_init"}))}),a.on("message",d=>{try{let l=JSON.parse(d.toString());switch(l.type){case"connection_ack":this.sendSubscriptionStart(a,e);break;case"start_ack":c.info("[AppSyncClient] Subscription started",{sessionId:t}),e.isReconnecting=!1,e.reconnectAttempts=0,this.startHeartbeat(t);break;case"data":this.resetKeepAliveTimer(e);let h=l.payload?.data?.onEventCreated;h&&h.source==="MOBILE"&&i(h);break;case"ka":this.resetKeepAliveTimer(e);break;case"error":let p=l.payload?.errors?.[0]?.message||"Unknown error";this.handleSubscriptionError(e,new Error(p));break}}catch(l){c.error("[AppSyncClient] Failed to parse message",{error:l})}}),a.on("error",d=>{c.error("[AppSyncClient] WebSocket error",{sessionId:t,error:d.message}),this.handleSubscriptionError(e,d)}),a.on("close",(d,l)=>{c.info("[AppSyncClient] WebSocket closed",{sessionId:t,code:d}),e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),!e.destroyed&&this.activeSubscriptions.get(t)===e&&this.handleSubscriptionError(e,new Error(`WebSocket closed: ${d}`))}),e.ws=a,this.resetKeepAliveTimer(e)}catch(o){this.handleSubscriptionError(e,o)}}sendSubscriptionStart(e,t){let r=w(),{sessionId:i,subscriptionId:s}=t,o={host:new URL(r.aws.appsyncUrl).host};this.tokens?.idToken&&(o.Authorization=this.tokens.idToken),e.send(JSON.stringify({id:s,type:"start",payload:{data:JSON.stringify({query:H.onEventCreated,variables:{sessionId:i}}),extensions:{authorization:o}}}))}resetKeepAliveTimer(e){e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.keepAliveTimer=setTimeout(()=>{this.handleSubscriptionError(e,new Error("Keep-alive timeout"))},300*1e3)}handleSubscriptionError(e,t){let{sessionId:r,onError:i}=e;if(e.isReconnecting||!this.activeSubscriptions.has(r))return;e.isReconnecting=!0,e.reconnectAttempts++,this.stopHeartbeat(r);let s=e.reconnectAttempts<=k.urgentMaxAttempts,o;if(s?o=Math.min(k.baseDelayMs*Math.pow(k.backoffMultiplier,e.reconnectAttempts-1),k.maxDelayMs):(o=k.persistentDelayMs,e.reconnectAttempts===k.urgentMaxAttempts+1&&c.info("[AppSyncClient] Switching to persistent reconnect (every 5min)",{sessionId:r})),c.info("[AppSyncClient] Scheduling reconnect",{sessionId:r,attempt:e.reconnectAttempts,phase:s?"urgent":"persistent",delayMs:o}),e.ws){try{e.ws.close(1e3)}catch{}e.ws=null}e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.reconnectTimer=setTimeout(async()=>{if(e.isReconnecting=!1,e.destroyed||this.activeSubscriptions.get(r)!==e){c.info("[AppSyncClient] Reconnect skipped \u2014 state is no longer canonical",{sessionId:r});return}try{let a=await y.getTokens(this.environment);a&&(y.isTokenExpired(a)?await this.refreshTokens(a)&&c.info("[AppSyncClient] Tokens refreshed before reconnect",{sessionId:r}):this.tokens=a)}catch{c.warn("[AppSyncClient] Token refresh failed before reconnect, using existing tokens",{sessionId:r})}if(e.destroyed||this.activeSubscriptions.get(r)!==e){c.info("[AppSyncClient] Reconnect skipped after token refresh \u2014 state no longer canonical",{sessionId:r});return}e.subscriptionId=(0,J.v4)(),this.createSubscription(e)},o)}cleanupSubscriptionState(e){if(e.destroyed=!0,e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0),e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0),e.ws){try{e.ws.readyState===V.default.OPEN&&e.ws.send(JSON.stringify({id:e.subscriptionId,type:"stop"}))}catch{}try{e.ws.close(1e3)}catch{}try{e.ws.removeAllListeners()}catch{}e.ws=null}}subscribeToDeviceKeyRegistered(e,t,r,i){c.info("[AppSyncClient] Subscribing to device key registrations",{userId:e}),this.deviceKeyWatcher&&this.stopDeviceKeyWatcherInternal();let s={userId:e,subscriptionId:(0,J.v4)(),ws:null,onNewDevice:t,onReconnect:r,onError:i,reconnectAttempts:0,isReconnecting:!1,destroyed:!1};return this.deviceKeyWatcher=s,this.createDeviceKeyWatcherConnection(s),()=>{this.stopDeviceKeyWatcherInternal()}}stopDeviceKeyWatcher(){this.stopDeviceKeyWatcherInternal()}stopDeviceKeyWatcherInternal(){let e=this.deviceKeyWatcher;if(e){if(e.destroyed=!0,e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0),e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0),e.ws){try{e.ws.readyState===V.default.OPEN&&e.ws.send(JSON.stringify({id:e.subscriptionId,type:"stop"}))}catch{}try{e.ws.close(1e3)}catch{}try{e.ws.removeAllListeners()}catch{}e.ws=null}this.deviceKeyWatcher=null,c.info("[AppSyncClient] Device key watcher stopped")}}createDeviceKeyWatcherConnection(e){try{let t=this.buildRealtimeUrl(),r=new V.default(t,["graphql-ws"]);r.on("open",()=>{c.info("[AppSyncClient] Device key watcher WebSocket connected",{userId:e.userId}),r.send(JSON.stringify({type:"connection_init"}))}),r.on("message",i=>{try{let s=JSON.parse(i.toString());switch(s.type){case"connection_ack":this.sendDeviceKeyWatcherStart(r,e);break;case"start_ack":c.info("[AppSyncClient] Device key watcher subscription started",{userId:e.userId});let o=e.isReconnecting;if(e.isReconnecting=!1,e.reconnectAttempts=0,o&&e.onReconnect)try{e.onReconnect()}catch(l){c.warn("[AppSyncClient] Device key watcher onReconnect handler threw",{error:l})}break;case"data":this.resetDeviceKeyWatcherKeepAlive(e);let a=s.payload?.data?.onDeviceKeyRegistered;if(a){c.info("[AppSyncClient] Device key registration observed",{userId:e.userId,newDeviceId:a.deviceId,platform:a.platform});try{e.onNewDevice(a)}catch(l){c.warn("[AppSyncClient] Device key watcher onNewDevice handler threw",{error:l})}}break;case"ka":this.resetDeviceKeyWatcherKeepAlive(e);break;case"error":let d=s.payload?.errors?.[0]?.message||"Unknown error";this.handleDeviceKeyWatcherError(e,new Error(d));break}}catch(s){c.error("[AppSyncClient] Failed to parse device key watcher message",{error:s})}}),r.on("error",i=>{c.error("[AppSyncClient] Device key watcher WebSocket error",{userId:e.userId,error:i.message}),this.handleDeviceKeyWatcherError(e,i)}),r.on("close",i=>{c.info("[AppSyncClient] Device key watcher WebSocket closed",{userId:e.userId,code:i}),e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),!e.destroyed&&this.deviceKeyWatcher===e&&this.handleDeviceKeyWatcherError(e,new Error(`WebSocket closed: ${i}`))}),e.ws=r,this.resetDeviceKeyWatcherKeepAlive(e)}catch(t){this.handleDeviceKeyWatcherError(e,t)}}sendDeviceKeyWatcherStart(e,t){let r=w(),{userId:i,subscriptionId:s}=t,o={host:new URL(r.aws.appsyncUrl).host};this.tokens?.idToken&&(o.Authorization=this.tokens.idToken),e.send(JSON.stringify({id:s,type:"start",payload:{data:JSON.stringify({query:H.onDeviceKeyRegistered,variables:{userId:i}}),extensions:{authorization:o}}}))}resetDeviceKeyWatcherKeepAlive(e){e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.keepAliveTimer=setTimeout(()=>{this.handleDeviceKeyWatcherError(e,new Error("Device key watcher keep-alive timeout"))},300*1e3)}handleDeviceKeyWatcherError(e,t){if(e.isReconnecting||e.destroyed||this.deviceKeyWatcher!==e)return;if(e.isReconnecting=!0,e.reconnectAttempts++,e.onError)try{e.onError(t)}catch{}if(e.ws){try{e.ws.removeAllListeners()}catch{}try{e.ws.close(1e3)}catch{}e.ws=null}e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0);let i=e.reconnectAttempts<=k.urgentMaxAttempts?Math.min(k.baseDelayMs*Math.pow(k.backoffMultiplier,e.reconnectAttempts-1),k.maxDelayMs):k.persistentDelayMs;c.warn("[AppSyncClient] Device key watcher reconnect scheduled",{userId:e.userId,attempts:e.reconnectAttempts,delayMs:i,error:t.message}),e.reconnectTimer=setTimeout(async()=>{if(e.isReconnecting=!1,e.destroyed||this.deviceKeyWatcher!==e){c.info("[AppSyncClient] Device key watcher reconnect skipped \u2014 state no longer canonical",{userId:e.userId});return}try{let s=await y.getTokens(this.environment);s&&(y.isTokenExpired(s)?await this.refreshTokens(s)&&c.info("[AppSyncClient] Tokens refreshed before device key watcher reconnect",{userId:e.userId}):this.tokens=s)}catch{c.warn("[AppSyncClient] Token refresh failed before device key watcher reconnect, using existing tokens",{userId:e.userId})}e.destroyed||this.deviceKeyWatcher!==e||(e.subscriptionId=(0,J.v4)(),this.createDeviceKeyWatcherConnection(e))},i)}watchForMobileEnd(e,t){c.info("[AppSyncClient] Starting mobile-end watcher",{sessionId:e});let r=this.sessionUpdateWatchers.get(e);r&&(c.info("[AppSyncClient] Replacing existing mobile-end watcher",{sessionId:e}),this.cleanupSessionUpdateWatcherState(r),this.sessionUpdateWatchers.delete(e));let i={sessionId:e,subscriptionId:(0,J.v4)(),ws:null,onMobileEndRequested:t,priorStatus:"ACTIVE",firedOnce:!1,reconnectAttempts:0,isReconnecting:!1,destroyed:!1};return this.sessionUpdateWatchers.set(e,i),this.createSessionUpdateWatcherConnection(i),{stop:()=>{this.sessionUpdateWatchers.get(e)===i&&(this.cleanupSessionUpdateWatcherState(i),this.sessionUpdateWatchers.delete(e),c.info("[AppSyncClient] Mobile-end watcher stopped",{sessionId:e}))}}}createSessionUpdateWatcherConnection(e){try{let t=this.buildRealtimeUrl(),r=new V.default(t,["graphql-ws"]);r.on("open",()=>{c.info("[AppSyncClient] Mobile-end watcher WebSocket connected",{sessionId:e.sessionId}),r.send(JSON.stringify({type:"connection_init"}))}),r.on("message",i=>{try{let s=JSON.parse(i.toString());switch(s.type){case"connection_ack":this.sendSessionUpdateWatcherStart(r,e);break;case"start_ack":c.info("[AppSyncClient] Mobile-end watcher subscription started",{sessionId:e.sessionId}),e.isReconnecting=!1,e.reconnectAttempts=0;break;case"data":this.resetSessionUpdateWatcherKeepAlive(e),this.handleSessionUpdatePayload(e,s.payload);break;case"ka":this.resetSessionUpdateWatcherKeepAlive(e);break;case"error":let o=s.payload?.errors?.[0]?.message||"Unknown error";this.handleSessionUpdateWatcherError(e,new Error(o));break}}catch(s){c.error("[AppSyncClient] Failed to parse mobile-end watcher message",{error:s})}}),r.on("error",i=>{c.error("[AppSyncClient] Mobile-end watcher WebSocket error",{sessionId:e.sessionId,error:i.message}),this.handleSessionUpdateWatcherError(e,i)}),r.on("close",i=>{c.info("[AppSyncClient] Mobile-end watcher WebSocket closed",{sessionId:e.sessionId,code:i}),e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),!e.destroyed&&this.sessionUpdateWatchers.get(e.sessionId)===e&&this.handleSessionUpdateWatcherError(e,new Error(`WebSocket closed: ${i}`))}),e.ws=r,this.resetSessionUpdateWatcherKeepAlive(e)}catch(t){this.handleSessionUpdateWatcherError(e,t)}}handleSessionUpdatePayload(e,t){let r=t?.data?.onSessionUpdated;if(!r){c.warn("[AppSyncClient] Mobile-end watcher received malformed payload",{sessionId:e.sessionId});return}if(e.firedOnce)return;let i=r.status;if(i==null){c.debug("[AppSyncClient] Mobile-end watcher skipped non-status payload",{sessionId:e.sessionId});return}if(e.priorStatus==="ACTIVE"&&i==="INACTIVE"){e.firedOnce=!0,e.priorStatus="INACTIVE",c.info("[AppSyncClient] Mobile end requested for session",{sessionId:e.sessionId}),Promise.resolve().then(()=>e.onMobileEndRequested()).catch(s=>{c.warn("[AppSyncClient] Mobile-end callback threw",{sessionId:e.sessionId,error:s})});return}e.priorStatus=i}sendSessionUpdateWatcherStart(e,t){let r=w(),{sessionId:i,subscriptionId:s}=t,o={host:new URL(r.aws.appsyncUrl).host};this.tokens?.idToken&&(o.Authorization=this.tokens.idToken),e.send(JSON.stringify({id:s,type:"start",payload:{data:JSON.stringify({query:H.onSessionUpdated,variables:{sessionId:i}}),extensions:{authorization:o}}}))}resetSessionUpdateWatcherKeepAlive(e){e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.keepAliveTimer=setTimeout(()=>{this.handleSessionUpdateWatcherError(e,new Error("Mobile-end watcher keep-alive timeout"))},300*1e3)}handleSessionUpdateWatcherError(e,t){if(e.isReconnecting||e.destroyed||this.sessionUpdateWatchers.get(e.sessionId)!==e)return;if(e.isReconnecting=!0,e.reconnectAttempts++,e.ws){try{e.ws.removeAllListeners()}catch{}try{e.ws.close(1e3)}catch{}e.ws=null}e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0);let i=e.reconnectAttempts<=k.urgentMaxAttempts?Math.min(k.baseDelayMs*Math.pow(k.backoffMultiplier,e.reconnectAttempts-1),k.maxDelayMs):k.persistentDelayMs;c.warn("[AppSyncClient] Mobile-end watcher reconnect scheduled",{sessionId:e.sessionId,attempts:e.reconnectAttempts,delayMs:i,error:t.message}),e.reconnectTimer=setTimeout(async()=>{if(e.isReconnecting=!1,!(e.destroyed||this.sessionUpdateWatchers.get(e.sessionId)!==e)){try{let s=await y.getTokens(this.environment);s&&(y.isTokenExpired(s)?await this.refreshTokens(s):this.tokens=s)}catch{c.warn("[AppSyncClient] Token refresh failed before mobile-end watcher reconnect",{sessionId:e.sessionId})}e.destroyed||this.sessionUpdateWatchers.get(e.sessionId)!==e||(e.subscriptionId=(0,J.v4)(),this.createSessionUpdateWatcherConnection(e))}},i)}cleanupSessionUpdateWatcherState(e){if(e.destroyed=!0,e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0),e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0),e.ws){try{e.ws.readyState===V.default.OPEN&&e.ws.send(JSON.stringify({id:e.subscriptionId,type:"stop"}))}catch{}try{e.ws.close(1e3)}catch{}try{e.ws.removeAllListeners()}catch{}e.ws=null}}startHeartbeat(e,t=120*1e3){this.stopHeartbeat(e),this.sendHeartbeat(e);let r=setInterval(()=>{this.sendHeartbeat(e)},t);this.heartbeatTimers.set(e,r),c.info("[AppSyncClient] Heartbeat started",{sessionId:e,intervalMs:t})}stopHeartbeat(e){let t=this.heartbeatTimers.get(e);t&&(clearInterval(t),this.heartbeatTimers.delete(e),c.info("[AppSyncClient] Heartbeat stopped",{sessionId:e}))}async sendHeartbeat(e){try{await this.updateSession({sessionId:e,lastHeartbeatAt:new Date().toISOString()}),c.debug("[AppSyncClient] Heartbeat sent",{sessionId:e})}catch(t){c.warn("[AppSyncClient] Heartbeat failed",{sessionId:e,error:t})}}cleanupSubscriptions(){this.activeSubscriptions.forEach(e=>{this.cleanupSubscriptionState(e)}),this.activeSubscriptions.clear(),this.stopDeviceKeyWatcherInternal(),this.sessionUpdateWatchers.forEach(e=>{this.cleanupSessionUpdateWatcherState(e)}),this.sessionUpdateWatchers.clear(),this.heartbeatTimers.forEach(e=>clearInterval(e)),this.heartbeatTimers.clear()}};var gt=v(require("crypto")),mt=v(require("fs")),Oe=v(require("http")),ft=require("child_process");Y();R();M();var _e=v(require("crypto")),ot=v(require("https")),at=v(require("os")),Mt="G-GS74YEQTB8",Bt="lAfOF6OxRzSQ-NsLBRjhAg",Ft="www.google-analytics.com",qt=`/mp/collect?measurement_id=${Mt}&api_secret=${Bt}`,Ht={port_in_use:"server_start",server_listen_failed:"server_start",browser_open_failed:"browser_open",login_timeout:"awaiting_callback",cognito_rejected:"awaiting_callback",state_mismatch:"awaiting_callback",no_authorization_code:"awaiting_callback",token_exchange_failed:"exchanging_code",token_exchange_network_error:"exchanging_code",keychain_write_failed:"storing_tokens",user_aborted:"unknown",unknown:"unknown"};function Vt(){let n=typeof process.getuid=="function"?process.getuid():0;return _e.createHash("sha256").update(`${at.hostname()}-${n}`).digest("hex").substring(0,36)}function $(){return{platform:process.platform,source:process.env.CODEVIBE_TELEMETRY_SOURCE||"production"}}async function L(n,e){try{let t=JSON.stringify({client_id:Vt(),events:[{name:n,params:e}]});await new Promise(r=>{let i=ot.request({hostname:Ft,path:qt,method:"POST",headers:{"Content-Type":"application/json"}},()=>r());i.on("error",()=>r()),i.write(t),i.end(),setTimeout(r,2e3)})}catch{}}async function ie(n){await L("auth_completed",{...$(),user_id:n})}async function b(n,e){let t={...$(),reason:n,stage:e?.stage??Ht[n]};if(typeof e?.httpStatus=="number"&&(t.http_status=e.httpStatus),e?.errorFragment){let{homedir:r}=await import("os"),i=e.errorFragment.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"").replace(/\\/g,"/").replace(/[\n\r\t"]/g," ").replace(/[^\x20-\x7E]/g,"").trim(),s=[process.env.HOME,process.env.USERPROFILE,(()=>{try{return r()}catch{return}})()].filter(d=>typeof d=="string"&&d.length>0).map(d=>d.replace(/\\/g,"/"));for(let d of s){let l=d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");i=i.replace(new RegExp(l,"g"),"~")}i=i.replace(/\/Users\/[^/ ]+/g,"/Users/<user>").replace(/\/home\/[^/ ]+/g,"/home/<user>").replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,"<email>");let o=i.substring(0,100),a=i.substring(100,200);o&&(t.error_fragment=o),a&&(t.error_fragment_2=a)}await L("auth_failed",t)}var Ke=Symbol.for("codevibe.auth.beaconed"),ct=Symbol.for("codevibe.auth.failureReason");function A(n,e){try{Object.defineProperty(n,Ke,{value:!0,enumerable:!1,configurable:!0,writable:!1}),Object.defineProperty(n,ct,{value:e,enumerable:!1,configurable:!0,writable:!1})}catch{}return n}function se(n){return!!(n&&typeof n=="object"&&n[Ke])}function Re(n){if(n&&typeof n=="object"&&n[Ke]){let e=n[ct];if(typeof e=="string")return e}}function Z(n){return n<=0?"0":n===1?"1":n<=5?"2-5":"6+"}function ge(n){return _e.createHash("sha256").update(n).digest("hex").slice(0,8)}async function dt(n){return L("session_encryption_device_skipped",{...$(),...n})}async function lt(n){return L("session_encryption_partial_success",{...$(),...n})}async function pt(n){return L("session_encryption_catch_up_grant",{...$(),...n})}async function ut(n){return L("session_encryption_self_rekey_request",{...$(),...n})}async function yt(n){return L("session_encryption_self_rekey_success",{...$(),...n})}async function ht(n){return L("session_encryption_self_rekey_timeout",{...$(),...n})}var oe=8080,vt="/callback",Pe=`http://localhost:${oe}${vt}`,Q=class n{constructor(){}static getInstance(){return n.instance||(n.instance=new n),n.instance}openBrowser(e){console.error(""),console.error("Opening your browser for sign-in..."),this.isRunningInWSL()?console.error("If your browser does not open, paste this URL in your Windows browser:"):console.error("If your browser does not open automatically, visit this URL:"),console.error(` ${e}`),console.error("");let t=this.getBrowserCommands();this.tryBrowserCommand(t,e,0)}getBrowserCommands(){let e=process.platform;if(e==="darwin")return[{cmd:"open",fixedArgs:[]}];if(e==="win32")return[{cmd:"cmd",fixedArgs:["/c","start",""]}];let t=[];return this.isRunningInWSL()&&(t.push({cmd:"wslview",fixedArgs:[]}),t.push({cmd:"cmd.exe",fixedArgs:["/c","start",""]}),t.push({cmd:"powershell.exe",fixedArgs:["-NoProfile","-Command","Start-Process"]})),t.push({cmd:"xdg-open",fixedArgs:[]}),t}isRunningInWSL(){if(process.platform!=="linux")return!1;try{let e=mt.readFileSync("/proc/sys/kernel/osrelease","utf8");return/microsoft|wsl/i.test(e)}catch{return!1}}tryBrowserCommand(e,t,r){if(r>=e.length){c.debug("[AuthService] No browser-opening command succeeded. User must open the sign-in URL manually (printed to stderr above)."),console.error(""),console.error("\u26A0\uFE0F Could not open browser automatically."),this.isRunningInWSL()?console.error(" WSL detected \u2014 paste this URL in your Windows browser:"):console.error(" Please copy and paste this URL into your browser:"),console.error(` ${t}`),console.error("");return}let i=e[r],s=[...i.fixedArgs,t],o=!1,a=p=>{o||(o=!0,c.debug(`[AuthService] Browser command '${i.cmd}' ${p}; trying next fallback`),this.tryBrowserCommand(e,t,r+1))},d=p=>{o||(o=!0,c.debug(`[AuthService] Browser command '${i.cmd}' ${p}`))},l;try{l=(0,ft.spawn)(i.cmd,s,{detached:!0,stdio:"ignore"})}catch(p){a(`threw synchronously: ${p?.message||p}`);return}l.on("error",p=>{a(`failed to spawn: ${p?.message||p}`)}),l.on("exit",(p,g)=>{p===0?d("exited successfully"):a(g?`terminated by signal ${g}`:`exited with code ${p}`)}),setTimeout(()=>{d("still running after 3s, assuming success")},3e3).unref(),l.unref()}generateState(){return gt.randomBytes(32).toString("hex")}buildAuthUrl(e){let t=w(),r=new URLSearchParams({client_id:t.aws.cognitoClientId,response_type:"code",scope:"email openid profile",redirect_uri:Pe,state:e});return`https://${t.aws.cognitoDomain}/oauth2/authorize?${r.toString()}`}async exchangeCodeForTokens(e){let t=w(),r=`https://${t.aws.cognitoDomain}/oauth2/token`,i=new URLSearchParams({grant_type:"authorization_code",client_id:t.aws.cognitoClientId,code:e,redirect_uri:Pe}),s;try{s=await X(r,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()},"Token exchange")}catch(a){throw await b("token_exchange_network_error"),A(a,"token_exchange_network_error"),a}if(!s.ok){let a=await s.text(),d=new Error(`Token exchange failed: ${s.status} ${a}`);throw await b("token_exchange_failed",{httpStatus:s.status}),A(d,"token_exchange_failed"),d}let o=await s.json();return{accessToken:o.access_token,idToken:o.id_token,refreshToken:o.refresh_token,expiresIn:o.expires_in}}decodeJwt(e){let t=e.split(".");if(t.length!==3)throw new Error("Invalid JWT");return JSON.parse(Buffer.from(t[1],"base64").toString("utf-8"))}async refreshTokens(e){let t=w(),r=`https://${t.aws.cognitoDomain}/oauth2/token`,i=new URLSearchParams({grant_type:"refresh_token",client_id:t.aws.cognitoClientId,refresh_token:e}),s=await X(r,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()},"Token refresh");if(!s.ok)throw new Error(`Token refresh failed: ${s.status}`);let o=await s.json();return{accessToken:o.access_token,idToken:o.id_token,expiresIn:o.expires_in}}async login(){let e=await y.getTokens(I());if(e&&!y.isTokenExpired(e))return e;let t=this.generateState(),r=this.buildAuthUrl(t);return new Promise((i,s)=>{let o=Oe.createServer(async(a,d)=>{if(!a.url?.startsWith(vt)){d.writeHead(404),d.end("Not found");return}try{let l=new URL(a.url,`http://localhost:${oe}`),h=l.searchParams.get("code"),p=l.searchParams.get("state"),g=l.searchParams.get("error");if(g){let S=new Error(`OAuth error: ${g}`);throw await b("cognito_rejected"),A(S,"cognito_rejected"),S}if(p!==t){let S=new Error("State mismatch");throw await b("state_mismatch"),A(S,"state_mismatch"),S}if(!h){let S=new Error("No authorization code");throw await b("no_authorization_code"),A(S,"no_authorization_code"),S}let f=await this.exchangeCodeForTokens(h),O=this.decodeJwt(f.idToken),m={accessToken:f.accessToken,idToken:f.idToken,refreshToken:f.refreshToken,expiresAt:Date.now()+f.expiresIn*1e3,userId:O.sub,email:O.email||"unknown"};try{await y.setTokens(m,I())}catch(S){throw await b("keychain_write_failed"),A(S,"keychain_write_failed"),S}d.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),d.end(`
205
+ `};var nt=(a=>(a.USER_PROMPT="USER_PROMPT",a.ASSISTANT_RESPONSE="ASSISTANT_RESPONSE",a.TOOL_USE="TOOL_USE",a.NOTIFICATION="NOTIFICATION",a.INTERACTIVE_PROMPT="INTERACTIVE_PROMPT",a.PROMPT_RESPONSE="PROMPT_RESPONSE",a.REASONING="REASONING",a))(nt||{}),De=(t=>(t.DESKTOP="DESKTOP",t.MOBILE="MOBILE",t))(De||{}),it=(r=>(r.SENT="SENT",r.DELIVERED="DELIVERED",r.EXECUTED="EXECUTED",r))(it||{});var he=(r=>(r.ACTIVE="ACTIVE",r.INACTIVE="INACTIVE",r.PAUSED="PAUSED",r))(he||{}),st=(r=>(r.CLAUDE="CLAUDE",r.GEMINI="GEMINI",r.CODEX="CODEX",r))(st||{});var k={urgentMaxAttempts:10,baseDelayMs:1e3,maxDelayMs:6e4,backoffMultiplier:2,persistentDelayMs:300*1e3},ne=class n{constructor(){this.authenticated=!1;this.currentUserId=null;this.currentEmail=null;this.tokens=null;this.activeSubscriptions=new Map;this.pendingRefresh=null;this.lastRefreshFailureAt=null;this.deviceKeyWatcher=null;this.sessionUpdateWatchers=new Map;this.heartbeatTimers=new Map;this.environment=I(),c.info("[AppSyncClient] Initialized",{environment:this.environment})}static{this.REFRESH_BACKOFF_MS=3e4}getCurrentUserId(){if(!this.currentUserId)throw new Error("Not authenticated. Call authenticateWithStoredTokens() first.");return this.currentUserId}getCurrentUserEmail(){return this.currentEmail}async authenticateWithStoredTokens(){try{let e=await y.getTokens(this.environment);if(!e)return c.debug("[AppSyncClient] No stored tokens found"),!1;if(c.info("[AppSyncClient] Found stored OAuth tokens",{userId:e.userId,email:e.email,expired:y.isTokenExpired(e)}),y.isTokenExpired(e)){if(c.info("[AppSyncClient] Tokens expired, attempting refresh..."),!await this.refreshTokens(e))return c.warn("[AppSyncClient] Token refresh failed"),!1}else this.tokens=e;return this.currentUserId=this.tokens.userId,this.currentEmail=this.tokens.email,this.authenticated=!0,c.info("[AppSyncClient] Authenticated successfully",{userId:this.currentUserId,email:this.currentEmail}),!0}catch(e){return c.error("[AppSyncClient] Authentication failed:",e),!1}}async refreshTokens(e){if(this.pendingRefresh)return this.pendingRefresh;if(this.lastRefreshFailureAt!==null&&Date.now()-this.lastRefreshFailureAt<n.REFRESH_BACKOFF_MS)return!1;this.pendingRefresh=this.performRefresh(e);try{return await this.pendingRefresh}finally{this.pendingRefresh=null}}async performRefresh(e){let t=await this.callCognitoRefresh(e.refreshToken);if(t!==null)return this.applyRefreshedTokens(e,t);let r=null;try{r=await y.getTokens(this.environment)}catch(i){c.warn("[AppSyncClient] Failed to re-read tokens from storage during refresh recovery",{error:i instanceof Error?i.message:String(i)})}if(r&&r.refreshToken&&r.refreshToken!==e.refreshToken){c.info("[AppSyncClient] In-memory refresh token rejected; retrying with storage-backed token (likely out-of-band re-auth)");let i=await this.callCognitoRefresh(r.refreshToken);if(i!==null)return this.applyRefreshedTokens(r,i)}return this.lastRefreshFailureAt=Date.now(),!1}async callCognitoRefresh(e){try{let t=w(),r=`https://${t.aws.cognitoDomain}/oauth2/token`,i=new URLSearchParams({grant_type:"refresh_token",client_id:t.aws.cognitoClientId,refresh_token:e}),s=await X(r,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()},"Token refresh");return s.ok?await s.json():(c.error("[AppSyncClient] Token refresh failed",{status:s.status}),null)}catch(t){return c.error("[AppSyncClient] Token refresh error:",t),null}}async applyRefreshedTokens(e,t){let r={...e,accessToken:t.access_token,idToken:t.id_token,expiresAt:Date.now()+t.expires_in*1e3};this.tokens=r,this.lastRefreshFailureAt=null;try{await y.setTokens(r,this.environment),c.info("[AppSyncClient] Tokens refreshed",{expiresAt:new Date(r.expiresAt).toISOString()})}catch(i){c.warn("[AppSyncClient] Tokens refreshed but persistence failed; daemon keeps using fresh tokens in memory. A restart while persistence is still broken would lose them.",{error:i instanceof Error?i.message:String(i),expiresAt:new Date(r.expiresAt).toISOString()})}return!0}isAuthenticated(){return this.authenticated}signOut(){this.authenticated=!1,this.tokens=null,this.currentUserId=null,this.currentEmail=null,this.cleanupSubscriptions(),c.info("[AppSyncClient] Signed out")}async graphqlRequest(e,t,r=!1){let i=w();if(!this.tokens?.idToken)throw new Error('Not authenticated. Run "codevibe login" first.');let s={"Content-Type":"application/json",Authorization:this.tokens.idToken},o=await X(i.aws.appsyncUrl,{method:"POST",headers:s,body:JSON.stringify({query:e,variables:t})},"AppSync GraphQL request"),a=await o.json();if(o.status===401&&!r&&this.tokens){if(c.info("[AppSyncClient] 401 Unauthorized, refreshing token..."),await this.refreshTokens(this.tokens))return this.graphqlRequest(e,t,!0);throw new Error("Token expired and refresh failed")}if(!o.ok)throw new Error(`GraphQL request failed: ${o.status}`);if(a.errors?.length)throw new Error(`GraphQL error: ${a.errors[0].message}`);return a}async createSession(e){let t={...e,metadata:e.metadata?JSON.stringify(e.metadata):void 0},r=await this.graphqlRequest(C.createSession,{input:t});return c.info("[AppSyncClient] Session created",{sessionId:r.data.createSession.sessionId}),r.data.createSession}async updateSession(e){let t={...e,metadata:e.metadata?JSON.stringify(e.metadata):void 0},r=await this.graphqlRequest(C.updateSession,{input:t});return c.debug("[AppSyncClient] Session updated",{sessionId:r.data.updateSession.sessionId}),r.data.updateSession}async getSession(e){return(await this.graphqlRequest(U.getSession,{sessionId:e})).data.getSession}async createEvent(e){let t={...e,metadata:e.metadata?JSON.stringify(e.metadata):void 0},r=await this.graphqlRequest(C.createEvent,{input:t});return c.debug("[AppSyncClient] Event created",{eventId:r.data.createEvent.eventId,type:r.data.createEvent.type}),r.data.createEvent}async updateEventStatus(e){return(await this.graphqlRequest(C.updateEventStatus,{input:e})).data.updateEventStatus}async listEvents(e,t,r){return(await this.graphqlRequest(U.listEvents,{sessionId:e,source:t,limit:r})).data.listEvents.items}async listSessions(e=100){if(!this.currentUserId)throw new Error("Not authenticated");let t=[],r=null;do{let s=(await this.graphqlRequest(U.listSessions,{userId:this.currentUserId,limit:e,nextToken:r})).data?.listSessions;s?.items&&t.push(...s.items),r=s?.nextToken??null}while(r);return t}async sweepOrphanSessions(e){let t=e.staleThresholdMs??9e5,r=new Set(e.excludeSessionIds??[]),i=Date.now(),s;try{s=await this.listSessions()}catch(a){return c.warn("[AppSyncClient] OrphanSweep: listSessions failed, skipping sweep",{agentType:e.agentType,error:a instanceof Error?a.message:String(a)}),0}let o=0;for(let a of s){if(a.agentType!==e.agentType||a.status!=="ACTIVE"||r.has(a.sessionId)||!a.lastHeartbeatAt)continue;let d=i-new Date(a.lastHeartbeatAt).getTime();if(!(d<t)){c.warn("[AppSyncClient] OrphanSweep: marking stale session INACTIVE",{sessionId:a.sessionId,agentType:a.agentType,lastHeartbeatAt:a.lastHeartbeatAt,heartbeatAgeMinutes:Math.round(d/6e4)});try{await this.updateSession({sessionId:a.sessionId,status:"INACTIVE"}),o++}catch(l){c.warn("[AppSyncClient] OrphanSweep: updateSession failed, leaving row as-is",{sessionId:a.sessionId,error:l instanceof Error?l.message:String(l)})}}}return o>0&&c.info("[AppSyncClient] OrphanSweep complete",{agentType:e.agentType,swept:o}),o}async listUserDeviceKeys(){return(await this.graphqlRequest(U.listUserDeviceKeys,{})).data.listUserDeviceKeys||[]}async registerDeviceKey(e,t,r,i){let s={deviceId:e,publicKey:t,platform:r,deviceName:i};await this.graphqlRequest(C.registerDeviceKey,{input:s}),c.info("[AppSyncClient] Device key registered",{deviceId:e,platform:r})}async grantSessionKey(e){await this.graphqlRequest(C.grantSessionKey,{input:e}),c.info("[AppSyncClient] Session key granted",{sessionId:e.sessionId,deviceId:e.deviceId})}async getAttachmentDownloadUrl(e){return(await this.graphqlRequest(C.getAttachmentDownloadUrl,{s3Key:e})).data.getAttachmentDownloadUrl}subscribeToEvents(e,t,r){c.info("[AppSyncClient] Subscribing to events",{sessionId:e});let i=this.activeSubscriptions.get(e);i&&(this.cleanupSubscriptionState(i),this.activeSubscriptions.delete(e));let s={ws:null,subscriptionId:(0,J.v4)(),sessionId:e,onEvent:t,onError:r,reconnectAttempts:0,isReconnecting:!1,destroyed:!1};return this.activeSubscriptions.set(e,s),this.createSubscription(s),()=>{this.cleanupSubscriptionState(s),this.activeSubscriptions.delete(e)}}buildRealtimeUrl(){let e=w(),t=new URL(e.aws.appsyncUrl),i=/\.appsync-api\.[^.]+\.amazonaws\.com$/.test(t.host)?e.aws.appsyncUrl.replace("https://","wss://").replace("appsync-api","appsync-realtime-api"):`wss://${t.host}/graphql/realtime`,s={host:t.host};this.tokens?.idToken&&(s.Authorization=this.tokens.idToken);let o=Buffer.from(JSON.stringify(s)).toString("base64"),a=Buffer.from(JSON.stringify({})).toString("base64");return`${i}?header=${o}&payload=${a}`}createSubscription(e){let{sessionId:t,subscriptionId:r,onEvent:i,onError:s}=e;try{let o=this.buildRealtimeUrl(),a=new V.default(o,["graphql-ws"]);a.on("open",()=>{c.info("[AppSyncClient] WebSocket connected",{sessionId:t}),a.send(JSON.stringify({type:"connection_init"}))}),a.on("message",d=>{try{let l=JSON.parse(d.toString());switch(l.type){case"connection_ack":this.sendSubscriptionStart(a,e);break;case"start_ack":c.info("[AppSyncClient] Subscription started",{sessionId:t}),e.isReconnecting=!1,e.reconnectAttempts=0,this.startHeartbeat(t);break;case"data":this.resetKeepAliveTimer(e);let h=l.payload?.data?.onEventCreated;h&&h.source==="MOBILE"&&i(h);break;case"ka":this.resetKeepAliveTimer(e);break;case"error":let p=l.payload?.errors?.[0]?.message||"Unknown error";this.handleSubscriptionError(e,new Error(p));break}}catch(l){c.error("[AppSyncClient] Failed to parse message",{error:l})}}),a.on("error",d=>{c.error("[AppSyncClient] WebSocket error",{sessionId:t,error:d.message}),this.handleSubscriptionError(e,d)}),a.on("close",(d,l)=>{c.info("[AppSyncClient] WebSocket closed",{sessionId:t,code:d}),e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),!e.destroyed&&this.activeSubscriptions.get(t)===e&&this.handleSubscriptionError(e,new Error(`WebSocket closed: ${d}`))}),e.ws=a,this.resetKeepAliveTimer(e)}catch(o){this.handleSubscriptionError(e,o)}}sendSubscriptionStart(e,t){let r=w(),{sessionId:i,subscriptionId:s}=t,o={host:new URL(r.aws.appsyncUrl).host};this.tokens?.idToken&&(o.Authorization=this.tokens.idToken),e.send(JSON.stringify({id:s,type:"start",payload:{data:JSON.stringify({query:H.onEventCreated,variables:{sessionId:i}}),extensions:{authorization:o}}}))}resetKeepAliveTimer(e){e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.keepAliveTimer=setTimeout(()=>{this.handleSubscriptionError(e,new Error("Keep-alive timeout"))},300*1e3)}handleSubscriptionError(e,t){let{sessionId:r,onError:i}=e;if(e.isReconnecting||!this.activeSubscriptions.has(r))return;e.isReconnecting=!0,e.reconnectAttempts++,this.stopHeartbeat(r);let s=e.reconnectAttempts<=k.urgentMaxAttempts,o;if(s?o=Math.min(k.baseDelayMs*Math.pow(k.backoffMultiplier,e.reconnectAttempts-1),k.maxDelayMs):(o=k.persistentDelayMs,e.reconnectAttempts===k.urgentMaxAttempts+1&&c.info("[AppSyncClient] Switching to persistent reconnect (every 5min)",{sessionId:r})),c.info("[AppSyncClient] Scheduling reconnect",{sessionId:r,attempt:e.reconnectAttempts,phase:s?"urgent":"persistent",delayMs:o}),e.ws){try{e.ws.close(1e3)}catch{}e.ws=null}e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.reconnectTimer=setTimeout(async()=>{if(e.isReconnecting=!1,e.destroyed||this.activeSubscriptions.get(r)!==e){c.info("[AppSyncClient] Reconnect skipped \u2014 state is no longer canonical",{sessionId:r});return}try{let a=await y.getTokens(this.environment);a&&(y.isTokenExpired(a)?await this.refreshTokens(a)&&c.info("[AppSyncClient] Tokens refreshed before reconnect",{sessionId:r}):this.tokens=a)}catch{c.warn("[AppSyncClient] Token refresh failed before reconnect, using existing tokens",{sessionId:r})}if(e.destroyed||this.activeSubscriptions.get(r)!==e){c.info("[AppSyncClient] Reconnect skipped after token refresh \u2014 state no longer canonical",{sessionId:r});return}e.subscriptionId=(0,J.v4)(),this.createSubscription(e)},o)}cleanupSubscriptionState(e){if(e.destroyed=!0,e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0),e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0),e.ws){try{e.ws.readyState===V.default.OPEN&&e.ws.send(JSON.stringify({id:e.subscriptionId,type:"stop"}))}catch{}try{e.ws.close(1e3)}catch{}try{e.ws.removeAllListeners()}catch{}e.ws=null}}subscribeToDeviceKeyRegistered(e,t,r,i){c.info("[AppSyncClient] Subscribing to device key registrations",{userId:e}),this.deviceKeyWatcher&&this.stopDeviceKeyWatcherInternal();let s={userId:e,subscriptionId:(0,J.v4)(),ws:null,onNewDevice:t,onReconnect:r,onError:i,reconnectAttempts:0,isReconnecting:!1,destroyed:!1};return this.deviceKeyWatcher=s,this.createDeviceKeyWatcherConnection(s),()=>{this.stopDeviceKeyWatcherInternal()}}stopDeviceKeyWatcher(){this.stopDeviceKeyWatcherInternal()}stopDeviceKeyWatcherInternal(){let e=this.deviceKeyWatcher;if(e){if(e.destroyed=!0,e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0),e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0),e.ws){try{e.ws.readyState===V.default.OPEN&&e.ws.send(JSON.stringify({id:e.subscriptionId,type:"stop"}))}catch{}try{e.ws.close(1e3)}catch{}try{e.ws.removeAllListeners()}catch{}e.ws=null}this.deviceKeyWatcher=null,c.info("[AppSyncClient] Device key watcher stopped")}}createDeviceKeyWatcherConnection(e){try{let t=this.buildRealtimeUrl(),r=new V.default(t,["graphql-ws"]);r.on("open",()=>{c.info("[AppSyncClient] Device key watcher WebSocket connected",{userId:e.userId}),r.send(JSON.stringify({type:"connection_init"}))}),r.on("message",i=>{try{let s=JSON.parse(i.toString());switch(s.type){case"connection_ack":this.sendDeviceKeyWatcherStart(r,e);break;case"start_ack":c.info("[AppSyncClient] Device key watcher subscription started",{userId:e.userId});let o=e.isReconnecting;if(e.isReconnecting=!1,e.reconnectAttempts=0,o&&e.onReconnect)try{e.onReconnect()}catch(l){c.warn("[AppSyncClient] Device key watcher onReconnect handler threw",{error:l})}break;case"data":this.resetDeviceKeyWatcherKeepAlive(e);let a=s.payload?.data?.onDeviceKeyRegistered;if(a){c.info("[AppSyncClient] Device key registration observed",{userId:e.userId,newDeviceId:a.deviceId,platform:a.platform});try{e.onNewDevice(a)}catch(l){c.warn("[AppSyncClient] Device key watcher onNewDevice handler threw",{error:l})}}break;case"ka":this.resetDeviceKeyWatcherKeepAlive(e);break;case"error":let d=s.payload?.errors?.[0]?.message||"Unknown error";this.handleDeviceKeyWatcherError(e,new Error(d));break}}catch(s){c.error("[AppSyncClient] Failed to parse device key watcher message",{error:s})}}),r.on("error",i=>{c.error("[AppSyncClient] Device key watcher WebSocket error",{userId:e.userId,error:i.message}),this.handleDeviceKeyWatcherError(e,i)}),r.on("close",i=>{c.info("[AppSyncClient] Device key watcher WebSocket closed",{userId:e.userId,code:i}),e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),!e.destroyed&&this.deviceKeyWatcher===e&&this.handleDeviceKeyWatcherError(e,new Error(`WebSocket closed: ${i}`))}),e.ws=r,this.resetDeviceKeyWatcherKeepAlive(e)}catch(t){this.handleDeviceKeyWatcherError(e,t)}}sendDeviceKeyWatcherStart(e,t){let r=w(),{userId:i,subscriptionId:s}=t,o={host:new URL(r.aws.appsyncUrl).host};this.tokens?.idToken&&(o.Authorization=this.tokens.idToken),e.send(JSON.stringify({id:s,type:"start",payload:{data:JSON.stringify({query:H.onDeviceKeyRegistered,variables:{userId:i}}),extensions:{authorization:o}}}))}resetDeviceKeyWatcherKeepAlive(e){e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.keepAliveTimer=setTimeout(()=>{this.handleDeviceKeyWatcherError(e,new Error("Device key watcher keep-alive timeout"))},300*1e3)}handleDeviceKeyWatcherError(e,t){if(e.isReconnecting||e.destroyed||this.deviceKeyWatcher!==e)return;if(e.isReconnecting=!0,e.reconnectAttempts++,e.onError)try{e.onError(t)}catch{}if(e.ws){try{e.ws.removeAllListeners()}catch{}try{e.ws.close(1e3)}catch{}e.ws=null}e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0);let i=e.reconnectAttempts<=k.urgentMaxAttempts?Math.min(k.baseDelayMs*Math.pow(k.backoffMultiplier,e.reconnectAttempts-1),k.maxDelayMs):k.persistentDelayMs;c.warn("[AppSyncClient] Device key watcher reconnect scheduled",{userId:e.userId,attempts:e.reconnectAttempts,delayMs:i,error:t.message}),e.reconnectTimer=setTimeout(async()=>{if(e.isReconnecting=!1,e.destroyed||this.deviceKeyWatcher!==e){c.info("[AppSyncClient] Device key watcher reconnect skipped \u2014 state no longer canonical",{userId:e.userId});return}try{let s=await y.getTokens(this.environment);s&&(y.isTokenExpired(s)?await this.refreshTokens(s)&&c.info("[AppSyncClient] Tokens refreshed before device key watcher reconnect",{userId:e.userId}):this.tokens=s)}catch{c.warn("[AppSyncClient] Token refresh failed before device key watcher reconnect, using existing tokens",{userId:e.userId})}e.destroyed||this.deviceKeyWatcher!==e||(e.subscriptionId=(0,J.v4)(),this.createDeviceKeyWatcherConnection(e))},i)}watchForMobileEnd(e,t){c.info("[AppSyncClient] Starting mobile-end watcher",{sessionId:e});let r=this.sessionUpdateWatchers.get(e);r&&(c.info("[AppSyncClient] Replacing existing mobile-end watcher",{sessionId:e}),this.cleanupSessionUpdateWatcherState(r),this.sessionUpdateWatchers.delete(e));let i={sessionId:e,subscriptionId:(0,J.v4)(),ws:null,onMobileEndRequested:t,priorStatus:"ACTIVE",firedOnce:!1,reconnectAttempts:0,isReconnecting:!1,destroyed:!1};return this.sessionUpdateWatchers.set(e,i),this.createSessionUpdateWatcherConnection(i),{stop:()=>{this.sessionUpdateWatchers.get(e)===i&&(this.cleanupSessionUpdateWatcherState(i),this.sessionUpdateWatchers.delete(e),c.info("[AppSyncClient] Mobile-end watcher stopped",{sessionId:e}))}}}createSessionUpdateWatcherConnection(e){try{let t=this.buildRealtimeUrl(),r=new V.default(t,["graphql-ws"]);r.on("open",()=>{c.info("[AppSyncClient] Mobile-end watcher WebSocket connected",{sessionId:e.sessionId}),r.send(JSON.stringify({type:"connection_init"}))}),r.on("message",i=>{try{let s=JSON.parse(i.toString());switch(s.type){case"connection_ack":this.sendSessionUpdateWatcherStart(r,e);break;case"start_ack":c.info("[AppSyncClient] Mobile-end watcher subscription started",{sessionId:e.sessionId}),e.isReconnecting=!1,e.reconnectAttempts=0;break;case"data":this.resetSessionUpdateWatcherKeepAlive(e),this.handleSessionUpdatePayload(e,s.payload);break;case"ka":this.resetSessionUpdateWatcherKeepAlive(e);break;case"error":let o=s.payload?.errors?.[0]?.message||"Unknown error";this.handleSessionUpdateWatcherError(e,new Error(o));break}}catch(s){c.error("[AppSyncClient] Failed to parse mobile-end watcher message",{error:s})}}),r.on("error",i=>{c.error("[AppSyncClient] Mobile-end watcher WebSocket error",{sessionId:e.sessionId,error:i.message}),this.handleSessionUpdateWatcherError(e,i)}),r.on("close",i=>{c.info("[AppSyncClient] Mobile-end watcher WebSocket closed",{sessionId:e.sessionId,code:i}),e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),!e.destroyed&&this.sessionUpdateWatchers.get(e.sessionId)===e&&this.handleSessionUpdateWatcherError(e,new Error(`WebSocket closed: ${i}`))}),e.ws=r,this.resetSessionUpdateWatcherKeepAlive(e)}catch(t){this.handleSessionUpdateWatcherError(e,t)}}handleSessionUpdatePayload(e,t){let r=t?.data?.onSessionUpdated;if(!r){c.warn("[AppSyncClient] Mobile-end watcher received malformed payload",{sessionId:e.sessionId});return}if(e.firedOnce)return;let i=r.status;if(i==null){c.debug("[AppSyncClient] Mobile-end watcher skipped non-status payload",{sessionId:e.sessionId});return}if(e.priorStatus==="ACTIVE"&&i==="INACTIVE"){e.firedOnce=!0,e.priorStatus="INACTIVE",c.info("[AppSyncClient] Mobile end requested for session",{sessionId:e.sessionId}),Promise.resolve().then(()=>e.onMobileEndRequested()).catch(s=>{c.warn("[AppSyncClient] Mobile-end callback threw",{sessionId:e.sessionId,error:s})});return}e.priorStatus=i}sendSessionUpdateWatcherStart(e,t){let r=w(),{sessionId:i,subscriptionId:s}=t,o={host:new URL(r.aws.appsyncUrl).host};this.tokens?.idToken&&(o.Authorization=this.tokens.idToken),e.send(JSON.stringify({id:s,type:"start",payload:{data:JSON.stringify({query:H.onSessionUpdated,variables:{sessionId:i}}),extensions:{authorization:o}}}))}resetSessionUpdateWatcherKeepAlive(e){e.keepAliveTimer&&clearTimeout(e.keepAliveTimer),e.keepAliveTimer=setTimeout(()=>{this.handleSessionUpdateWatcherError(e,new Error("Mobile-end watcher keep-alive timeout"))},300*1e3)}handleSessionUpdateWatcherError(e,t){if(e.isReconnecting||e.destroyed||this.sessionUpdateWatchers.get(e.sessionId)!==e)return;if(e.isReconnecting=!0,e.reconnectAttempts++,e.ws){try{e.ws.removeAllListeners()}catch{}try{e.ws.close(1e3)}catch{}e.ws=null}e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0);let i=e.reconnectAttempts<=k.urgentMaxAttempts?Math.min(k.baseDelayMs*Math.pow(k.backoffMultiplier,e.reconnectAttempts-1),k.maxDelayMs):k.persistentDelayMs;c.warn("[AppSyncClient] Mobile-end watcher reconnect scheduled",{sessionId:e.sessionId,attempts:e.reconnectAttempts,delayMs:i,error:t.message}),e.reconnectTimer=setTimeout(async()=>{if(e.isReconnecting=!1,!(e.destroyed||this.sessionUpdateWatchers.get(e.sessionId)!==e)){try{let s=await y.getTokens(this.environment);s&&(y.isTokenExpired(s)?await this.refreshTokens(s):this.tokens=s)}catch{c.warn("[AppSyncClient] Token refresh failed before mobile-end watcher reconnect",{sessionId:e.sessionId})}e.destroyed||this.sessionUpdateWatchers.get(e.sessionId)!==e||(e.subscriptionId=(0,J.v4)(),this.createSessionUpdateWatcherConnection(e))}},i)}cleanupSessionUpdateWatcherState(e){if(e.destroyed=!0,e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0),e.keepAliveTimer&&(clearTimeout(e.keepAliveTimer),e.keepAliveTimer=void 0),e.ws){try{e.ws.readyState===V.default.OPEN&&e.ws.send(JSON.stringify({id:e.subscriptionId,type:"stop"}))}catch{}try{e.ws.close(1e3)}catch{}try{e.ws.removeAllListeners()}catch{}e.ws=null}}startHeartbeat(e,t=120*1e3){this.stopHeartbeat(e),this.sendHeartbeat(e);let r=setInterval(()=>{this.sendHeartbeat(e)},t);this.heartbeatTimers.set(e,r),c.info("[AppSyncClient] Heartbeat started",{sessionId:e,intervalMs:t})}stopHeartbeat(e){let t=this.heartbeatTimers.get(e);t&&(clearInterval(t),this.heartbeatTimers.delete(e),c.info("[AppSyncClient] Heartbeat stopped",{sessionId:e}))}async sendHeartbeat(e){try{await this.updateSession({sessionId:e,lastHeartbeatAt:new Date().toISOString()}),c.debug("[AppSyncClient] Heartbeat sent",{sessionId:e})}catch(t){c.warn("[AppSyncClient] Heartbeat failed",{sessionId:e,error:t})}}cleanupSubscriptions(){this.activeSubscriptions.forEach(e=>{this.cleanupSubscriptionState(e)}),this.activeSubscriptions.clear(),this.stopDeviceKeyWatcherInternal(),this.sessionUpdateWatchers.forEach(e=>{this.cleanupSessionUpdateWatcherState(e)}),this.sessionUpdateWatchers.clear(),this.heartbeatTimers.forEach(e=>clearInterval(e)),this.heartbeatTimers.clear()}};var gt=v(require("crypto")),mt=v(require("fs")),Oe=v(require("http")),ft=require("child_process");Y();R();M();var _e=v(require("crypto")),ot=v(require("https")),at=v(require("os")),Mt="G-GS74YEQTB8",Bt="lAfOF6OxRzSQ-NsLBRjhAg",Ft="www.google-analytics.com",qt=`/mp/collect?measurement_id=${Mt}&api_secret=${Bt}`,Ht={port_in_use:"server_start",server_listen_failed:"server_start",browser_open_failed:"browser_open",login_timeout:"awaiting_callback",cognito_rejected:"awaiting_callback",state_mismatch:"awaiting_callback",no_authorization_code:"awaiting_callback",token_exchange_failed:"exchanging_code",token_exchange_network_error:"exchanging_code",keychain_write_failed:"storing_tokens",user_aborted:"unknown",unknown:"unknown"};function Vt(){let n=typeof process.getuid=="function"?process.getuid():0;return _e.createHash("sha256").update(`${at.hostname()}-${n}`).digest("hex").substring(0,36)}function $(){return{platform:process.platform,source:process.env.CODEVIBE_TELEMETRY_SOURCE||"production"}}async function L(n,e){try{let t=JSON.stringify({client_id:Vt(),events:[{name:n,params:e}]});await new Promise(r=>{let i=ot.request({hostname:Ft,path:qt,method:"POST",headers:{"Content-Type":"application/json"}},()=>r());i.on("error",()=>r()),i.write(t),i.end(),setTimeout(r,2e3)})}catch{}}async function ie(n){await L("auth_completed",{...$(),user_id:n})}async function b(n,e){let t={...$(),reason:n,stage:e?.stage??Ht[n]};if(typeof e?.httpStatus=="number"&&(t.http_status=e.httpStatus),e?.errorFragment){let{homedir:r}=await import("os"),i=e.errorFragment.replace(/\x1b\[[0-9;]*[a-zA-Z]/g,"").replace(/\\/g,"/").replace(/[\n\r\t"]/g," ").replace(/[^\x20-\x7E]/g,"").trim(),s=[process.env.HOME,process.env.USERPROFILE,(()=>{try{return r()}catch{return}})()].filter(d=>typeof d=="string"&&d.length>0).map(d=>d.replace(/\\/g,"/"));for(let d of s){let l=d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");i=i.replace(new RegExp(l,"g"),"~")}i=i.replace(/\/Users\/[^/ ]+/g,"/Users/<user>").replace(/\/home\/[^/ ]+/g,"/home/<user>").replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,"<email>");let o=i.substring(0,100),a=i.substring(100,200);o&&(t.error_fragment=o),a&&(t.error_fragment_2=a)}await L("auth_failed",t)}var Ke=Symbol.for("codevibe.auth.beaconed"),ct=Symbol.for("codevibe.auth.failureReason");function A(n,e){try{Object.defineProperty(n,Ke,{value:!0,enumerable:!1,configurable:!0,writable:!1}),Object.defineProperty(n,ct,{value:e,enumerable:!1,configurable:!0,writable:!1})}catch{}return n}function se(n){return!!(n&&typeof n=="object"&&n[Ke])}function Re(n){if(n&&typeof n=="object"&&n[Ke]){let e=n[ct];if(typeof e=="string")return e}}function Z(n){return n<=0?"0":n===1?"1":n<=5?"2-5":"6+"}function ge(n){return _e.createHash("sha256").update(n).digest("hex").slice(0,8)}async function dt(n){return L("session_encryption_device_skipped",{...$(),...n})}async function lt(n){return L("session_encryption_partial_success",{...$(),...n})}async function pt(n){return L("session_encryption_catch_up_grant",{...$(),...n})}async function ut(n){return L("session_encryption_self_rekey_request",{...$(),...n})}async function yt(n){return L("session_encryption_self_rekey_success",{...$(),...n})}async function ht(n){return L("session_encryption_self_rekey_timeout",{...$(),...n})}var oe=8080,vt="/callback",Pe=`http://localhost:${oe}${vt}`,Q=class n{constructor(){}static getInstance(){return n.instance||(n.instance=new n),n.instance}openBrowser(e){console.error(""),console.error("Opening your browser for sign-in..."),this.isRunningInWSL()?console.error("If your browser does not open, paste this URL in your Windows browser:"):console.error("If your browser does not open automatically, visit this URL:"),console.error(` ${e}`),console.error("");let t=this.getBrowserCommands();this.tryBrowserCommand(t,e,0)}getBrowserCommands(){let e=process.platform;if(e==="darwin")return[{cmd:"open",fixedArgs:[]}];if(e==="win32")return[{cmd:"cmd",fixedArgs:["/c","start",""]}];let t=[];return this.isRunningInWSL()&&(t.push({cmd:"wslview",fixedArgs:[]}),t.push({cmd:"cmd.exe",fixedArgs:["/c","start",""]}),t.push({cmd:"powershell.exe",fixedArgs:["-NoProfile","-Command","Start-Process"]})),t.push({cmd:"xdg-open",fixedArgs:[]}),t}isRunningInWSL(){if(process.platform!=="linux")return!1;try{let e=mt.readFileSync("/proc/sys/kernel/osrelease","utf8");return/microsoft|wsl/i.test(e)}catch{return!1}}tryBrowserCommand(e,t,r){if(r>=e.length){c.debug("[AuthService] No browser-opening command succeeded. User must open the sign-in URL manually (printed to stderr above)."),console.error(""),console.error("\u26A0\uFE0F Could not open browser automatically."),this.isRunningInWSL()?console.error(" WSL detected \u2014 paste this URL in your Windows browser:"):console.error(" Please copy and paste this URL into your browser:"),console.error(` ${t}`),console.error("");return}let i=e[r],s=[...i.fixedArgs,t],o=!1,a=p=>{o||(o=!0,c.debug(`[AuthService] Browser command '${i.cmd}' ${p}; trying next fallback`),this.tryBrowserCommand(e,t,r+1))},d=p=>{o||(o=!0,c.debug(`[AuthService] Browser command '${i.cmd}' ${p}`))},l;try{l=(0,ft.spawn)(i.cmd,s,{detached:!0,stdio:"ignore"})}catch(p){a(`threw synchronously: ${p?.message||p}`);return}l.on("error",p=>{a(`failed to spawn: ${p?.message||p}`)}),l.on("exit",(p,g)=>{p===0?d("exited successfully"):a(g?`terminated by signal ${g}`:`exited with code ${p}`)}),setTimeout(()=>{d("still running after 3s, assuming success")},3e3).unref(),l.unref()}generateState(){return gt.randomBytes(32).toString("hex")}buildAuthUrl(e){let t=w(),r=new URLSearchParams({client_id:t.aws.cognitoClientId,response_type:"code",scope:"email openid profile",redirect_uri:Pe,state:e});return`https://${t.aws.cognitoDomain}/oauth2/authorize?${r.toString()}`}async exchangeCodeForTokens(e){let t=w(),r=`https://${t.aws.cognitoDomain}/oauth2/token`,i=new URLSearchParams({grant_type:"authorization_code",client_id:t.aws.cognitoClientId,code:e,redirect_uri:Pe}),s;try{s=await X(r,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()},"Token exchange")}catch(a){throw await b("token_exchange_network_error"),A(a,"token_exchange_network_error"),a}if(!s.ok){let a=await s.text(),d=new Error(`Token exchange failed: ${s.status} ${a}`);throw await b("token_exchange_failed",{httpStatus:s.status}),A(d,"token_exchange_failed"),d}let o=await s.json();return{accessToken:o.access_token,idToken:o.id_token,refreshToken:o.refresh_token,expiresIn:o.expires_in}}decodeJwt(e){let t=e.split(".");if(t.length!==3)throw new Error("Invalid JWT");return JSON.parse(Buffer.from(t[1],"base64").toString("utf-8"))}async refreshTokens(e){let t=w(),r=`https://${t.aws.cognitoDomain}/oauth2/token`,i=new URLSearchParams({grant_type:"refresh_token",client_id:t.aws.cognitoClientId,refresh_token:e}),s=await X(r,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i.toString()},"Token refresh");if(!s.ok)throw new Error(`Token refresh failed: ${s.status}`);let o=await s.json();return{accessToken:o.access_token,idToken:o.id_token,expiresIn:o.expires_in}}async login(){let e=await y.getTokens(I());if(e&&!y.isTokenExpired(e))return e;let t=this.generateState(),r=this.buildAuthUrl(t);return new Promise((i,s)=>{let o=Oe.createServer(async(a,d)=>{if(!a.url?.startsWith(vt)){d.writeHead(404),d.end("Not found");return}try{let l=new URL(a.url,`http://localhost:${oe}`),h=l.searchParams.get("code"),p=l.searchParams.get("state"),g=l.searchParams.get("error");if(g){let S=new Error(`OAuth error: ${g}`);throw await b("cognito_rejected"),A(S,"cognito_rejected"),S}if(p!==t){let S=new Error("State mismatch");throw await b("state_mismatch"),A(S,"state_mismatch"),S}if(!h){let S=new Error("No authorization code");throw await b("no_authorization_code"),A(S,"no_authorization_code"),S}let f=await this.exchangeCodeForTokens(h),O=this.decodeJwt(f.idToken),m={accessToken:f.accessToken,idToken:f.idToken,refreshToken:f.refreshToken,expiresAt:Date.now()+f.expiresIn*1e3,userId:O.sub,email:O.email||"unknown"};try{await y.setTokens(m,I())}catch(S){throw await b("keychain_write_failed"),A(S,"keychain_write_failed"),S}d.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),d.end(`
206
206
  <!DOCTYPE html>
207
207
  <html>
208
208
  <head><title>Success</title></head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",