@ciandt-flow/flow-ai-obs 0.3.1-beta.74 → 0.4.1-beta.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,80 +1,83 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';var c=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var p=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Ee=p((Ma,fs)=>{fs.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.3.1-beta.74",description:"Claude Code hooks for Langfuse OTLP tracing \u2014 cross-platform",main:"dist/index.js",bin:{"flow-ai-obs":"dist/cli.js","flow-ai-obs-setup":"dist/setup.js"},scripts:{build:"tsup",test:"node --test src/**/*.test.js",typecheck:"node --check src/**/*.js bin/cli.js",lint:"node --check src/**/*.js bin/cli.js","security-scan":"trufflehog filesystem src/ --fail --no-update --exclude-paths .trufflehogignore",postinstall:`node -e "require('fs').existsSync('dist/setup.js') && require('child_process').execFileSync(process.execPath, ['dist/setup.js'], {stdio:'inherit'})"`,prepublishOnly:"npm run security-scan && npm run build","release:npm":"changeset publish",changeset:"changeset","version-packages":"changeset version","install:hooks":"node bin/cli.js install","auth:login":"node bin/cli.js auth login","auth:logout":"node bin/cli.js auth logout","auth:status":"node bin/cli.js auth status",smoke:"bash scripts/smoke-test.sh","smoke:debug":"bash scripts/smoke-test.sh --debug","smoke:send":"bash scripts/smoke-test.sh --send --allow-http --debug"},files:["dist/","README.md","LICENSE.md"],keywords:["claude-code","langfuse","observability","otlp","hooks","flow","ciandt"],author:"CI&T Flow Team",license:"SEE LICENSE IN LICENSE.md",private:false,dependencies:{keytar:"7.9.0"},devDependencies:{"@changesets/changelog-github":"^0.6.0","@changesets/cli":"^2.30.0",tsup:"^8.5.1",typescript:"^6.0.3"},engines:{node:">=18.0.0"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});var F=p((Ba,pt)=>{var hs=!process.env.NO_COLOR&&process.stdout.isTTY;function q(e,t){return hs?n=>`\x1B[${e}m${n}\x1B[${t}m`:n=>n}var Ss=q("32","39"),Ts=q("31","39"),Es=q("33","39"),ws=q("36","39"),gs=q("1","22"),_s=q("2","22");pt.exports={green:Ss,red:Ts,yellow:Es,cyan:ws,bold:gs,dim:_s};});var we=p((Da,Et)=>{var ms=c("https"),St=c("fs"),ys=c("os"),Os=c("path"),{spawn:As}=c("child_process"),be;function x(){return be||(be=Ee()),be}var Tt=Os.join(ys.tmpdir(),"flow-obs-update-cache.json"),Ls=1440*60*1e3,Ns=3e3;function Ue(e,t){let n=o=>{let i=String(o).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return i?[+i[1],+i[2],+i[3]]:null},s=n(e),r=n(t);return !s||!r?false:r[0]!==s[0]?r[0]>s[0]:r[1]!==s[1]?r[1]>s[1]:r[2]>s[2]}function Is(){try{let e=JSON.parse(St.readFileSync(Tt,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=Ls?null:e}catch{return null}}function ks(e,t){try{St.writeFileSync(Tt,JSON.stringify({latestVersion:e,updatePriority:t||null,checkedAt:Date.now()}),{mode:384});}catch{}}function Cs(e){let t=x().name,n=ms.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:Ns},s=>{if(s.statusCode!==200)return s.resume(),e(new Error(`HTTP ${s.statusCode}`));let r="";s.setEncoding("utf8"),s.on("data",o=>{r+=o;}),s.on("end",()=>{try{let o=JSON.parse(r);if(typeof o.version!="string")throw new Error("no version field");e(null,{version:o.version,updatePriority:typeof o.updatePriority=="string"?o.updatePriority:null});}catch(o){e(o);}});});n.on("error",e),n.on("timeout",()=>{n.destroy(new Error("timeout"));});}function ft(e){let t=x().name,s=` Update available: ${x().version} \u2192 ${e}`,r=` Run: npm install -g ${t}`,o=Math.max(s.length,r.length)+2,i="\u2500".repeat(o);process.stderr.write(`
2
+ 'use strict';var c=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var l=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Ee=l((Ya,hs)=>{hs.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.4.1-beta.66",description:"Claude Code hooks for Langfuse OTLP tracing \u2014 cross-platform",main:"dist/index.js",bin:{"flow-ai-obs":"dist/cli.js","flow-ai-obs-setup":"dist/setup.js"},scripts:{build:"tsup",test:"node --test src/**/*.test.js",typecheck:"node --check src/**/*.js bin/cli.js",lint:"node --check src/**/*.js bin/cli.js","security-scan":"trufflehog filesystem src/ --fail --no-update --exclude-paths .trufflehogignore",postinstall:`node -e "require('fs').existsSync('dist/setup.js') && require('child_process').execFileSync(process.execPath, ['dist/setup.js'], {stdio:'inherit'})"`,prepublishOnly:"npm run security-scan && npm run build","release:npm":"changeset publish",changeset:"changeset","version-packages":"changeset version","install:hooks":"node bin/cli.js install","auth:login":"node bin/cli.js auth login","auth:logout":"node bin/cli.js auth logout","auth:status":"node bin/cli.js auth status",smoke:"bash scripts/smoke-test.sh","smoke:debug":"bash scripts/smoke-test.sh --debug","smoke:send":"bash scripts/smoke-test.sh --send --allow-http --debug"},files:["dist/","README.md","LICENSE.md"],keywords:["claude-code","langfuse","observability","otlp","hooks","flow","ciandt"],author:"CI&T Flow Team",license:"SEE LICENSE IN LICENSE.md",private:false,dependencies:{keytar:"7.9.0"},devDependencies:{"@changesets/changelog-github":"^0.6.0","@changesets/cli":"^2.30.0",tsup:"^8.5.1",typescript:"^6.0.3"},engines:{node:">=18.0.0"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});var M=l((ja,ft)=>{var Ts=!process.env.NO_COLOR&&process.stdout.isTTY;function x(e,t){return Ts?n=>`\x1B[${e}m${n}\x1B[${t}m`:n=>n}var Ss=x("32","39"),Es=x("31","39"),ws=x("33","39"),_s=x("36","39"),gs=x("1","22"),ms=x("2","22");ft.exports={green:Ss,red:Es,yellow:ws,cyan:_s,bold:gs,dim:ms};});var we=l((Ga,wt)=>{var ys=c("https"),St=c("fs"),As=c("os"),Ls=c("path"),{spawn:Os}=c("child_process"),be;function D(){return be||(be=Ee()),be}var Et=Ls.join(As.tmpdir(),"flow-obs-update-cache.json"),Ns=1440*60*1e3,Is=3e3;function Ue(e,t){let n=r=>{let i=String(r).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return i?[+i[1],+i[2],+i[3]]:null},s=n(e),o=n(t);return !s||!o?false:o[0]!==s[0]?o[0]>s[0]:o[1]!==s[1]?o[1]>s[1]:o[2]>s[2]}function ks(){try{let e=JSON.parse(St.readFileSync(Et,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=Ns?null:e}catch{return null}}function Cs(e,t){try{St.writeFileSync(Et,JSON.stringify({latestVersion:e,updatePriority:t||null,checkedAt:Date.now()}),{mode:384});}catch{}}function vs(e){let t=D().name,n=ys.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:Is},s=>{if(s.statusCode!==200)return s.resume(),e(new Error(`HTTP ${s.statusCode}`));let o="";s.setEncoding("utf8"),s.on("data",r=>{o+=r;}),s.on("end",()=>{try{let r=JSON.parse(o);if(typeof r.version!="string")throw new Error("no version field");e(null,{version:r.version,updatePriority:typeof r.updatePriority=="string"?r.updatePriority:null});}catch(r){e(r);}});});n.on("error",e),n.on("timeout",()=>{n.destroy(new Error("timeout"));});}function ht(e){let t=D().name,s=` Update available: ${D().version} \u2192 ${e}`,o=` Run: npm install -g ${t}`,r=Math.max(s.length,o.length)+2,i="\u2500".repeat(r);process.stderr.write(`
3
3
  \u256D${i}\u256E
4
- \u2502${s.padEnd(o)}\u2502
5
- \u2502${r.padEnd(o)}\u2502
4
+ \u2502${s.padEnd(r)}\u2502
5
+ \u2502${o.padEnd(r)}\u2502
6
6
  \u2570${i}\u256F
7
7
 
8
- `);}function ht(e){let t=x().name;process.stderr.write(`
8
+ `);}function Tt(e){let t=D().name;process.stderr.write(`
9
9
  [${t}] Critical update detected \u2014 auto-updating to ${e}...
10
10
 
11
- `),As("npm",["install","-g",`${t}@${e}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}function vs(){try{let e=Is();if(e){Ue(x().version,e.latestVersion)&&(e.updatePriority==="auto"?ht(e.latestVersion):ft(e.latestVersion));return}setImmediate(()=>{Cs((t,n)=>{t||!n||(ks(n.version,n.updatePriority),Ue(x().version,n.version)&&(n.updatePriority==="auto"?ht(n.version):ft(n.version)));});});}catch{}}Et.exports={checkForUpdate:vs,isNewer:Ue};});var w=p((Ha,gt)=>{var M=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",wt={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${M}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${M}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${M}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${M}/otel`},bs={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},Us="FLOW-nodejs",Rs="config.json",Ps={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},$s={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL||`${M}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL||"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL||"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"},qs={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:wt.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},Fs={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP"},xs={KEYCHAIN_ENABLED:false},Ms={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Bs={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},Ds={FILE_PREFIX:"flow-obs-buffer-",MAX_AGE_MS:5760*60*1e3,MAX_FILES:50},Hs="flow-ai-obs-debug.log",js={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},Gs="flow-obs-";gt.exports={FLOW_BASE_URL:M,FLOW_URLS:wt,VAULT:bs,CONFIG_DIR_NAME:Us,CONFIG_FILE_NAME:Rs,OTLP:Ps,LLM_PROXY:$s,NATIVE_OTEL:qs,ENV:Fs,FEATURES:xs,INSTALLER:Ms,HOOK_TIMEOUTS:Bs,BUFFER:Ds,DEBUG_LOG_FILENAME:Hs,STATE_FILE_PREFIX:Gs,TRACE_LIMITS:js};});var z=p((ja,mt)=>{var Ys=c("https"),Ks=c("http"),{FLOW_URLS:Vs}=w(),Ws=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function Js(e){if(!Ws.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var _t={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function Xs(e,t){try{let n=JSON.parse(t);if(typeof n.error=="string"&&_t[n.error])return new Error(_t[n.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function zs(e){return new Promise((t,n)=>{try{Js(e.tenant);}catch(d){return n(d)}let s=JSON.stringify({clientSecret:e.clientSecret}),r=new URL(Vs.AUTH_ENGINE),o=r.protocol==="https:",i={hostname:r.hostname,port:r.port||(o?443:80),path:r.pathname+r.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(s),FlowTenant:e.tenant}},u=(o?Ys:Ks).request(i,d=>{let l=[];d.on("data",h=>l.push(h)),d.on("end",()=>{let h=l.join("");if(d.statusCode>=400)return n(Xs(d.statusCode,h));let T;try{T=JSON.parse(h);}catch{return n(new Error("Invalid response from auth engine"))}let O=T.expires_at??new Date(Date.now()+(T.expires_in??3600)*1e3).toISOString();t({accessToken:T.access_token,expiresAt:O});});});u.on("error",d=>n(new Error(`Network error: ${d.message}`))),u.write(s),u.end();})}mt.exports={getToken:zs};});var ee=p((Ga,Lt)=>{var g=c("fs"),Q=c("path"),yt=c("os"),{FLOW_URLS:Zs,INSTALLER:Z,HOOK_TIMEOUTS:ge,NATIVE_OTEL:Qs,LLM_PROXY:er}=w(),{getToken:tr}=z();function Pe(){return process.platform==="win32"?Q.join(process.env.APPDATA||Q.join(yt.homedir(),"AppData","Roaming"),"Claude","settings.json"):Q.join(yt.homedir(),".claude","settings.json")}var nr=Z.LOCK_STALE_MS;function Ot(e){try{let t=g.statSync(e);Date.now()-t.mtimeMs>nr&&g.unlinkSync(e);}catch{}try{g.writeFileSync(e,String(process.pid),{flag:"wx"});}catch(t){throw t.code==="EEXIST"?new Error("Another install is already in progress. If this is stale, remove: "+e):t}}function At(e){try{g.unlinkSync(e);}catch{}}function sr(){let e=Pe(),t=e+".lock";g.mkdirSync(Q.dirname(e),{recursive:true}),Ot(t);try{if(g.existsSync(e)){g.copyFileSync(e,e+".bkp");try{g.chmodSync(e+".bkp",384);}catch{}}let n={};try{n=JSON.parse(g.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,Qs),Object.assign(n.env,er),n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object")&&(n.hooks={});let s=(r,o)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${r}`,timeout:o}]});n.hooks.UserPromptSubmit=[s("UserPromptSubmit",ge.UserPromptSubmit)],n.hooks.PreToolUse=[s("PreToolUse",ge.PreToolUse)],n.hooks.PostToolUse=[s("PostToolUse",ge.PostToolUse)],n.hooks.Stop=[s("Stop",ge.Stop)],g.writeFileSync(e,JSON.stringify(n,null,2)+`
12
- `,{encoding:"utf8",mode:384});try{g.chmodSync(e,384);}catch{}}finally{At(t);}return e}async function rr(e){let t;try{t=(await tr(e)).accessToken;}catch{return false}return t?new Promise(n=>{Re(`Bearer ${t}`,n,1);}):false}function Re(e,t,n){let s=new URL(Zs.GATEWAY_TRACES),r=JSON.stringify({resourceSpans:[],validation_run:true}),o=s.protocol==="https:",i={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:e,"Content-Length":Buffer.byteLength(r)}},u=(o?c("https"):c("http")).request(i,d=>{d.resume(),d.statusCode===200||d.statusCode===204?t(true):n<Z.CONNECTIVITY_MAX_RETRY?setTimeout(()=>Re(e,t,n+1),Z.CONNECTIVITY_RETRY_MS):t(false);});u.on("error",()=>{n<Z.CONNECTIVITY_MAX_RETRY?setTimeout(()=>Re(e,t,n+1),Z.CONNECTIVITY_RETRY_MS):t(false);}),u.write(r),u.end();}function or(e){let t=Pe(),n=t+".lock";g.mkdirSync(Q.dirname(t),{recursive:true}),Ot(n);try{let s={};try{s=JSON.parse(g.readFileSync(t,"utf8"));}catch{}(!s.env||typeof s.env!="object")&&(s.env={}),Object.assign(s.env,e),g.writeFileSync(t,JSON.stringify(s,null,2)+`
13
- `,{encoding:"utf8",mode:384});try{g.chmodSync(t,384);}catch{}}finally{At(n);}}Lt.exports={getClaudeSettingsPath:Pe,writeClaudeSettings:sr,addEnvToClaudeSettings:or,validateConnectivity:rr};});var kt=p((Ya,It)=>{var ne=c("fs"),B=c("path"),ir=c("os"),{CONFIG_DIR_NAME:$e,CONFIG_FILE_NAME:qe}=w(),Fe={credentials:"credentials","token-cache":"tokenCache"};function te(){let e=ir.homedir();if(process.platform==="darwin")return B.join(e,"Library","Preferences",$e,qe);if(process.platform==="win32"){let n=process.env.APPDATA||B.join(e,"AppData","Roaming");return B.join(n,$e,qe)}let t=process.env.XDG_CONFIG_HOME||B.join(e,".config");return B.join(t,$e,qe)}function xe(){try{let e=ne.readFileSync(te(),"utf8");return JSON.parse(e)}catch{return {}}}function Nt(e){let t=te();ne.mkdirSync(B.dirname(t),{recursive:true}),ne.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var _e=class{static isAvailable(){return true}static hasExistingData(){try{if(!ne.existsSync(te()))return !1;let t=JSON.parse(ne.readFileSync(te(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let s=xe(),r=Fe[n]||n,o=s[r];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,n,s){let r=xe(),o=Fe[n]||n;if(n==="token-cache")try{r[o]=JSON.parse(s);}catch{r[o]=s;}else r[o]=s;Nt(r);}async deleteSecret(t,n){let s=xe(),r=Fe[n]||n;return r in s?(delete s[r],Nt(s),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${te()}`}};function ar(){}var cr=_e;It.exports={JsonFallbackProvider:_e,ScryptFallbackProvider:cr,_resetWarningState:ar};});var vt=p((Ka,Ct)=>{var{execFile:ur}=c("child_process"),{promisify:lr}=c("util"),{accessSync:dr,constants:pr}=c("fs"),Me=lr(ur),Be=class{static async isAvailable(){try{return dr("/usr/bin/security",pr.X_OK),!0}catch{return false}}async getSecret(t,n){try{let{stdout:s}=await Me("security",["find-generic-password","-w","-a",n,"-s",t]);return s.trim()||null}catch{return null}}async setSecret(t,n,s){await Me("security",["add-generic-password","-U","-a",n,"-s",t,"-w",s]);}async deleteSecret(t,n){try{return await Me("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};Ct.exports={MacOsKeyVaultProvider:Be};});var Rt=p((Va,Ut)=>{var{execFile:fr,spawn:hr}=c("child_process"),{promisify:Sr}=c("util"),{accessSync:Tr,constants:Er}=c("fs"),bt=Sr(fr),De=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let n of t)try{return Tr(n,Er.X_OK),!0}catch{}return false}async getSecret(t,n){try{let{stdout:s}=await bt("secret-tool",["lookup","service",t,"account",n]);return s.trim()||null}catch{return null}}async setSecret(t,n,s){await new Promise((r,o)=>{let i=hr("secret-tool",["store","--label",t,"service",t,"account",n]);i.on("error",o),i.on("close",a=>{a===0?r():o(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(s),i.stdin.end();});}async deleteSecret(t,n){try{return await bt("secret-tool",["clear","service",t,"account",n]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};Ut.exports={LinuxKeyVaultProvider:De};});var $t=p((Wa,Pt)=>{var He=class{static async isAvailable(){try{return await c("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,n){return c("keytar").getPassword(t,n)}async setSecret(t,n,s){await c("keytar").setPassword(t,n,s);}async deleteSecret(t,n){return c("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};Pt.exports={WindowsKeyVaultProvider:He};});var xt=p((Ja,Ft)=>{async function qt(){let{JsonFallbackProvider:e}=kt();return await wr()??new e}async function wr(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=vt();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=Rt();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=$t();return await e.isAvailable()?new e:null}default:return null}}var gr=qt;Ft.exports={createSecretVaultProvider:qt,createKeyVaultProvider:gr};});var j=p((Xa,Bt)=>{var{createSecretVaultProvider:_r}=xt(),{VAULT:Ge}=w(),D=Ge.SERVICE,Ye=Ge.ACCOUNT_CREDS,Ke=Ge.ACCOUNT_TOKEN,je=null;function H(){return je||(je=_r()),je}async function Mt(){let t=await(await H()).getSecret(D,Ye);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function mr(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await H()).setSecret(D,Ye,JSON.stringify(e));}async function yr(){let e=await H();await e.deleteSecret(D,Ye),await e.deleteSecret(D,Ke);}async function Or(e){await(await H()).setSecret(D,Ke,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function Ve(){let t=await(await H()).getSecret(D,Ke);if(!t)return null;try{let n=JSON.parse(t);return {accessToken:n.accessToken,expiresAt:n.expiresAt}}catch{return null}}async function Ar(){let e=await Ve();return e?new Date(e.expiresAt)>new Date:false}async function Lr(){let e=await Ve();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email||n.preferred_username||n.upn||n.sub||null}catch{return null}}async function Nr(){let e=await H();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function Ir(){let e=await Mt();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}Bt.exports={getFlowCredentials:Mt,saveFlowCredentials:mr,clearFlowCredentials:yr,saveTokenCache:Or,getTokenCache:Ve,isTokenValid:Ar,getEmailFromToken:Lr,getConfigPath:Nr,hasCredentials:Ir};});var C=p((za,Ht)=>{var{writeFileSync:kr}=c("fs"),{tmpdir:Cr}=c("os"),{join:vr}=c("path"),{DEBUG_LOG_FILENAME:br,ENV:Ur}=w(),Dt=vr(Cr(),br);function Rr(...e){if(process.env[Ur.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
14
- `;try{kr(Dt,t,{flag:"a"});}catch(n){process.stderr.write(`[flow-obs debug ERROR] ${n.message}
15
- `);}}Ht.exports={dbg:Rr,DEBUG_LOG:Dt};});var P=p((Za,Gt)=>{var{getFlowCredentials:We,isTokenValid:Pr,getEmailFromToken:se,getTokenCache:$r,saveTokenCache:qr}=j(),{getToken:Fr}=z(),{FLOW_BASE_URL:xr,ENV:A,FEATURES:Je}=w(),{dbg:G}=C(),Mr=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function Br(e){return Mr.some(t=>t.test(e))}function me(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:s,clientSecret:r,tenant:o}=n;return !s||!r||!o?null:{clientId:s,clientSecret:r,tenant:o}}catch{return null}}function Dr(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),n=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${n}.`}function Xe(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}if(!(process.env[A.FLOW_OBS_ALLOW_HTTP]==="true")&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(Br(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function Hr(){let e=me(process.env[A.ANTHROPIC_AUTH_TOKEN]);if(e)return {user:await se().catch(()=>null)||e.clientId,tenant:e.tenant};if(Je.KEYCHAIN_ENABLED)try{let t=await We();if(!t)return {user:"",tenant:""};let n=await se()||t.clientId||"",s=t.tenant||"";return {user:n,tenant:s}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function jr(e){if(await Pr())return (await $r()).accessToken;G("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Fr(e);return await qr(t),G("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function Gr(e,t){let n=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/langfuse/traces",authHeader:`Bearer ${n}`}}function Yr(e,t,n){let s=Buffer.from(`${t}:${n}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${s}`}}async function jt(){let e=[],t=process.env[A.ANTHROPIC_MODEL]||"",n=process.env[A.FLOW_TELEMETRY]==="true",s=process.env[A.LANGFUSE_BASE_URL],r=process.env[A.LANGFUSE_PUBLIC_KEY],o=process.env[A.LANGFUSE_SECRET_KEY];if(n&&s&&r&&o){let l="",h="",T=me(process.env[A.ANTHROPIC_AUTH_TOKEN]);if(T)l=await se().catch(()=>null)||T.clientId,h=T.tenant;else if(Je.KEYCHAIN_ENABLED)try{let I=await We();I&&(l=await se()||I.clientId,h=I.tenant);}catch{}let O={user:l||"",tenant:h||"",team:"",project:"",model:t};e.push({mode:"direct",...Yr(Xe(s),r,o),...O}),G("resolveCredentials","direct mode active",`user=${O.user}`,`tenant=${O.tenant}`);}let i=me(process.env[A.ANTHROPIC_AUTH_TOKEN]);if(G("resolveCredentials",i?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!i&&Je.KEYCHAIN_ENABLED&&(i=await We(),i&&G("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)")),!i){if(e.length===0){let l=[];return l.authError=false,l}return e}let a;try{a=await jr(i);}catch(l){if(G("resolveCredentials",`token refresh failed: ${l.message}`),e.length>0)return e;let h=[];return h.authError=true,h}let u={user:await se()||i.clientId,tenant:i.tenant,team:"",project:"",model:t},d=process.env[A.FLOW_TELEMETRY_GATEWAY]||xr;return e.push({mode:"gateway",...Gr(Xe(d),{accessToken:a}),...u}),e}async function Kr(){return (await jt()).length>0}Gt.exports={credentialsAvailable:Kr,getIdentityFromToken:Hr,resolveCredentials:jt,validateUrl:Xe,parseCredsFromAnthropicToken:me,buildAnthropicAuthToken:Dr};});var ae=p((Qa,zt)=>{var{getFlowCredentials:ze,saveFlowCredentials:Yt,clearFlowCredentials:Vr,saveTokenCache:Wr,isTokenValid:Jr,getConfigPath:Kt,hasCredentials:Xr}=j(),{getToken:zr}=z(),{buildAnthropicAuthToken:Zr,parseCredsFromAnthropicToken:Vt}=P(),{addEnvToClaudeSettings:Qr}=ee(),{ENV:Ze}=w(),{green:Oe,red:re,yellow:ye,cyan:oe,bold:Wt,dim:Y}=F(),eo=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;function v(e){return typeof e=="string"?e.replace(eo,""):e}function ie(e,t={}){return new Promise((n,s)=>{let{masked:r=false,defaultValue:o=""}=t;process.stdout.write(e+o);let i=o;function a(){try{process.stdin.setRawMode(!1);}catch{}}process.once("uncaughtException",a),process.once("unhandledRejection",a);let u=l=>{if(l===""){d(),s(new Error("SIGINT"));return}if(l==="\r"||l===`
16
- `){d(),process.stdout.write(`
17
- `),n(i);return}if(l==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}l.startsWith("\x1B")||(i+=l,process.stdout.write(r?"*".repeat(l.length):l));};function d(){process.stdin.setRawMode(false),process.stdin.removeListener("data",u),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",u);})}async function Jt(e){try{let t=await ze();(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)&&await Yt(e);}catch{}}async function Xt(e){let{accessToken:t,expiresAt:n}=await zr(e);await Yt(e),await Wr({accessToken:t,expiresAt:n});try{let s=Zr(e);Qr({[Ze.ANTHROPIC_AUTH_TOKEN]:s});}catch{}}async function to(e){try{return await Xt(e),process.stdout.write(Oe(` \u2713 Setup complete. Tenant: ${v(e.tenant)}
18
-
19
- `)),0}catch(t){return process.stderr.write(re(` \u2717 Authentication failed: ${v(t.message)}
20
- `)),1}}async function no(){try{process.stdout.write(`
21
- `);let e=(await ie(oe(" ? ")+"Client ID: ")).trim(),t=(await ie(oe(" ? ")+"Client Secret: ",{masked:!0})).trim(),n=(await ie(oe(" ? ")+"Tenant: ")).trim();if(!e||!t||!n)return process.stderr.write(re(` \u2717 All fields are required
22
- `)),1;try{await Xt({clientId:e,clientSecret:t,tenant:n});}catch(s){return process.stderr.write(re(` \u2717 Authentication failed: ${v(s.message)}
23
- `)),1}return process.stdout.write(Oe(` \u2713 Setup complete. Tenant: ${v(n)}
24
- `)),process.stdout.write(` Storage: ${await Kt()}
25
-
26
- `),0}catch(e){if(e.message==="SIGINT")throw e;return process.stderr.write(re(` \u2717 Unexpected error: ${e.message}
27
- `)),1}}async function so(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return to({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant});let t=Vt(process.env[Ze.ANTHROPIC_AUTH_TOKEN]);t&&await Jt(t);let n=t||await ze();if(n){process.stdout.write(`
28
- `),process.stdout.write(Wt(` Already authenticated
29
- `)),process.stdout.write(Y(" Tenant: ")+v(n.tenant)+`
30
- `),process.stdout.write(Y(" Client ID: ")+v(n.clientId)+`
11
+ `),Os("npm",["install","-g",`${t}@${e}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}function bs(){try{let e=ks();if(e){Ue(D().version,e.latestVersion)&&(e.updatePriority==="auto"?Tt(e.latestVersion):ht(e.latestVersion));return}setImmediate(()=>{vs((t,n)=>{t||!n||(Cs(n.version,n.updatePriority),Ue(D().version,n.version)&&(n.updatePriority==="auto"?Tt(n.version):ht(n.version)));});});}catch{}}wt.exports={checkForUpdate:bs,isNewer:Ue};});var w=l((Ka,gt)=>{var B=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",_t={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${B}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${B}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${B}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${B}/otel`},Us={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},Rs="FLOW-nodejs",Ps="config.json",Fs={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},$s={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL||`${B}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL||"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL||"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"},qs={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:_t.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},xs={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES"},Ms={KEYCHAIN_ENABLED:false},Ds={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Bs={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},Hs={FILE_PREFIX:"flow-obs-buffer-",DEFAULT_TTL_DAYS:4,MIN_TTL_DAYS:1,MAX_TTL_DAYS:30,DEFAULT_MAX_FILES:50,MIN_MAX_FILES:1,MAX_MAX_FILES:500,REPLAY_BATCH_SIZE:10},Ys="flow-ai-obs-debug.log",js={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},Gs="flow-obs-";gt.exports={FLOW_BASE_URL:B,FLOW_URLS:_t,VAULT:Us,CONFIG_DIR_NAME:Rs,CONFIG_FILE_NAME:Ps,OTLP:Fs,LLM_PROXY:$s,NATIVE_OTEL:qs,ENV:xs,FEATURES:Ms,INSTALLER:Ds,HOOK_TIMEOUTS:Bs,BUFFER:Hs,DEBUG_LOG_FILENAME:Ys,STATE_FILE_PREFIX:Gs,TRACE_LIMITS:js};});var Z=l((Wa,yt)=>{var Ks=c("https"),Ws=c("http"),{FLOW_URLS:Vs}=w(),Js=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function Xs(e){if(!Js.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var mt={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function zs(e,t){try{let n=JSON.parse(t);if(typeof n.error=="string"&&mt[n.error])return new Error(mt[n.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function Zs(e){return new Promise((t,n)=>{try{Xs(e.tenant);}catch(f){return n(f)}let s=JSON.stringify({clientSecret:e.clientSecret}),o=new URL(Vs.AUTH_ENGINE),r=o.protocol==="https:",i={hostname:o.hostname,port:o.port||(r?443:80),path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(s),FlowTenant:e.tenant}},u=(r?Ks:Ws).request(i,f=>{let d=[];f.on("data",h=>d.push(h)),f.on("end",()=>{let h=d.join("");if(f.statusCode>=400)return n(zs(f.statusCode,h));let S;try{S=JSON.parse(h);}catch{return n(new Error("Invalid response from auth engine"))}let L=S.expires_at??new Date(Date.now()+(S.expires_in??3600)*1e3).toISOString();t({accessToken:S.access_token,expiresAt:L});});});u.on("error",f=>n(new Error(`Network error: ${f.message}`))),u.write(s),u.end();})}yt.exports={getToken:Zs};});var te=l((Va,Nt)=>{var _=c("fs"),ee=c("path"),At=c("os"),{FLOW_URLS:Qs,INSTALLER:Q,HOOK_TIMEOUTS:er,NATIVE_OTEL:tr,LLM_PROXY:nr}=w(),{getToken:sr}=Z();function Pe(){return process.platform==="win32"?ee.join(process.env.APPDATA||ee.join(At.homedir(),"AppData","Roaming"),"Claude","settings.json"):ee.join(At.homedir(),".claude","settings.json")}var rr=Q.LOCK_STALE_MS;function Lt(e){try{let t=_.statSync(e);Date.now()-t.mtimeMs>rr&&_.unlinkSync(e);}catch{}try{_.writeFileSync(e,String(process.pid),{flag:"wx"});}catch(t){throw t.code==="EEXIST"?new Error("Another install is already in progress. If this is stale, remove: "+e):t}}function Ot(e){try{_.unlinkSync(e);}catch{}}function or(e,t){let s=(Array.isArray(e)?e:[]).map(o=>{if(!Array.isArray(o?.hooks))return null;let r=o.hooks.filter(i=>!i.command?.startsWith?.("flow-ai-obs "));return r.length>0?{...o,hooks:r}:null}).filter(o=>o!=null);return [t,...s]}function ir(){let e=Pe(),t=e+".lock";_.mkdirSync(ee.dirname(e),{recursive:true});let n=[];Lt(t);try{if(_.existsSync(e)){_.copyFileSync(e,e+".bkp");try{_.chmodSync(e+".bkp",384);}catch{}}let s={};try{s=JSON.parse(_.readFileSync(e,"utf8"));}catch{}(!s.env||typeof s.env!="object")&&(s.env={}),Object.assign(s.env,tr),Object.assign(s.env,nr),s.otelHeadersHelper="flow-ai-obs otel-headers",(!s.hooks||typeof s.hooks!="object"||Array.isArray(s.hooks))&&(s.hooks={});let o=(i,a)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${i}`,timeout:a}]}),r=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"];for(let i of r){let a=or(s.hooks[i],o(i,er[i]));a.length>1&&n.push(i),s.hooks[i]=a;}_.writeFileSync(e,JSON.stringify(s,null,2)+`
12
+ `,{encoding:"utf8",mode:384});try{_.chmodSync(e,384);}catch{}}finally{Ot(t);}return {settingsPath:e,preserved:n}}async function ar(e){let t;try{t=(await sr(e)).accessToken;}catch{return false}return t?new Promise(n=>{Re(`Bearer ${t}`,n,1);}):false}function Re(e,t,n){let s=new URL(Qs.GATEWAY_TRACES),o=JSON.stringify({resourceSpans:[],validation_run:true}),r=s.protocol==="https:",i={hostname:s.hostname,port:s.port||(r?443:80),path:s.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:e,"Content-Length":Buffer.byteLength(o)}},u=(r?c("https"):c("http")).request(i,f=>{f.resume(),f.statusCode===200||f.statusCode===204?t(true):n<Q.CONNECTIVITY_MAX_RETRY?setTimeout(()=>Re(e,t,n+1),Q.CONNECTIVITY_RETRY_MS):t(false);});u.on("error",()=>{n<Q.CONNECTIVITY_MAX_RETRY?setTimeout(()=>Re(e,t,n+1),Q.CONNECTIVITY_RETRY_MS):t(false);}),u.write(o),u.end();}function cr(e){let t=Pe(),n=t+".lock";_.mkdirSync(ee.dirname(t),{recursive:true}),Lt(n);try{let s={};try{s=JSON.parse(_.readFileSync(t,"utf8"));}catch{}(!s.env||typeof s.env!="object")&&(s.env={}),Object.assign(s.env,e),_.writeFileSync(t,JSON.stringify(s,null,2)+`
13
+ `,{encoding:"utf8",mode:384});try{_.chmodSync(t,384);}catch{}}finally{Ot(n);}}Nt.exports={getClaudeSettingsPath:Pe,writeClaudeSettings:ir,addEnvToClaudeSettings:cr,validateConnectivity:ar};});var Ct=l((Ja,kt)=>{var se=c("fs"),H=c("path"),ur=c("os"),{CONFIG_DIR_NAME:Fe,CONFIG_FILE_NAME:$e}=w(),qe={credentials:"credentials","token-cache":"tokenCache"};function ne(){let e=ur.homedir();if(process.platform==="darwin")return H.join(e,"Library","Preferences",Fe,$e);if(process.platform==="win32"){let n=process.env.APPDATA||H.join(e,"AppData","Roaming");return H.join(n,Fe,$e)}let t=process.env.XDG_CONFIG_HOME||H.join(e,".config");return H.join(t,Fe,$e)}function xe(){try{let e=se.readFileSync(ne(),"utf8");return JSON.parse(e)}catch{return {}}}function It(e){let t=ne();se.mkdirSync(H.dirname(t),{recursive:true}),se.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var _e=class{static isAvailable(){return true}static hasExistingData(){try{if(!se.existsSync(ne()))return !1;let t=JSON.parse(se.readFileSync(ne(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let s=xe(),o=qe[n]||n,r=s[o];return r?typeof r=="string"?r:JSON.stringify(r):null}async setSecret(t,n,s){let o=xe(),r=qe[n]||n;if(n==="token-cache")try{o[r]=JSON.parse(s);}catch{o[r]=s;}else o[r]=s;It(o);}async deleteSecret(t,n){let s=xe(),o=qe[n]||n;return o in s?(delete s[o],It(s),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${ne()}`}};function lr(){}var dr=_e;kt.exports={JsonFallbackProvider:_e,ScryptFallbackProvider:dr,_resetWarningState:lr};});var bt=l((Xa,vt)=>{var{execFile:pr}=c("child_process"),{promisify:fr}=c("util"),{accessSync:hr,constants:Tr}=c("fs"),Me=fr(pr),De=class{static async isAvailable(){try{return hr("/usr/bin/security",Tr.X_OK),!0}catch{return false}}async getSecret(t,n){try{let{stdout:s}=await Me("security",["find-generic-password","-w","-a",n,"-s",t]);return s.trim()||null}catch{return null}}async setSecret(t,n,s){await Me("security",["add-generic-password","-U","-a",n,"-s",t,"-w",s]);}async deleteSecret(t,n){try{return await Me("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};vt.exports={MacOsKeyVaultProvider:De};});var Pt=l((za,Rt)=>{var{execFile:Sr,spawn:Er}=c("child_process"),{promisify:wr}=c("util"),{accessSync:_r,constants:gr}=c("fs"),Ut=wr(Sr),Be=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let n of t)try{return _r(n,gr.X_OK),!0}catch{}return false}async getSecret(t,n){try{let{stdout:s}=await Ut("secret-tool",["lookup","service",t,"account",n]);return s.trim()||null}catch{return null}}async setSecret(t,n,s){await new Promise((o,r)=>{let i=Er("secret-tool",["store","--label",t,"service",t,"account",n]);i.on("error",r),i.on("close",a=>{a===0?o():r(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(s),i.stdin.end();});}async deleteSecret(t,n){try{return await Ut("secret-tool",["clear","service",t,"account",n]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};Rt.exports={LinuxKeyVaultProvider:Be};});var $t=l((Za,Ft)=>{var He=class{static async isAvailable(){try{return await c("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,n){return c("keytar").getPassword(t,n)}async setSecret(t,n,s){await c("keytar").setPassword(t,n,s);}async deleteSecret(t,n){return c("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};Ft.exports={WindowsKeyVaultProvider:He};});var Mt=l((Qa,xt)=>{async function qt(){let{JsonFallbackProvider:e}=Ct();return await mr()??new e}async function mr(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=bt();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=Pt();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=$t();return await e.isAvailable()?new e:null}default:return null}}var yr=qt;xt.exports={createSecretVaultProvider:qt,createKeyVaultProvider:yr};});var G=l((ec,Bt)=>{var{createSecretVaultProvider:Ar}=Mt(),{VAULT:je}=w(),Y=je.SERVICE,Ge=je.ACCOUNT_CREDS,Ke=je.ACCOUNT_TOKEN,Ye=null;function j(){return Ye||(Ye=Ar()),Ye}async function Dt(){let t=await(await j()).getSecret(Y,Ge);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function Lr(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await j()).setSecret(Y,Ge,JSON.stringify(e));}async function Or(){let e=await j();await e.deleteSecret(Y,Ge),await e.deleteSecret(Y,Ke);}async function Nr(e){await(await j()).setSecret(Y,Ke,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function We(){let t=await(await j()).getSecret(Y,Ke);if(!t)return null;try{let n=JSON.parse(t);return {accessToken:n.accessToken,expiresAt:n.expiresAt}}catch{return null}}async function Ir(){let e=await We();return e?new Date(e.expiresAt)>new Date:false}async function kr(){let e=await We();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email||n.preferred_username||n.upn||n.sub||null}catch{return null}}async function Cr(){let e=await j();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function vr(){let e=await Dt();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}Bt.exports={getFlowCredentials:Dt,saveFlowCredentials:Lr,clearFlowCredentials:Or,saveTokenCache:Nr,getTokenCache:We,isTokenValid:Ir,getEmailFromToken:kr,getConfigPath:Cr,hasCredentials:vr};});var C=l((tc,Yt)=>{var{writeFileSync:br}=c("fs"),{tmpdir:Ur}=c("os"),{join:Rr}=c("path"),{DEBUG_LOG_FILENAME:Pr,ENV:Fr}=w(),Ht=Rr(Ur(),Pr);function $r(...e){if(process.env[Fr.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
14
+ `;try{br(Ht,t,{flag:"a"});}catch(n){process.stderr.write(`[flow-obs debug ERROR] ${n.message}
15
+ `);}}Yt.exports={dbg:$r,DEBUG_LOG:Ht};});var $=l((nc,Gt)=>{var{getFlowCredentials:Ve,isTokenValid:qr,getEmailFromToken:re,getTokenCache:xr,saveTokenCache:Mr}=G(),{getToken:Dr}=Z(),{FLOW_BASE_URL:Br,ENV:O,FEATURES:Je}=w(),{dbg:K}=C(),Hr=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function Yr(e){return Hr.some(t=>t.test(e))}function ge(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:s,clientSecret:o,tenant:r}=n;return !s||!o||!r?null:{clientId:s,clientSecret:o,tenant:r}}catch{return null}}function jr(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),n=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${n}.`}function Xe(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}let n=process.env[O.FLOW_OBS_ALLOW_HTTP]==="true";if(!n&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(!n&&Yr(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function Gr(){let e=ge(process.env[O.ANTHROPIC_AUTH_TOKEN]);if(e)return {user:await re().catch(()=>null)||e.clientId,tenant:e.tenant};if(Je.KEYCHAIN_ENABLED)try{let t=await Ve();if(!t)return {user:"",tenant:""};let n=await re()||t.clientId||"",s=t.tenant||"";return {user:n,tenant:s}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function Kr(e){if(await qr())return (await xr()).accessToken;K("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Dr(e);return await Mr(t),K("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function Wr(e,t){let n=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${n}`}}function Vr(e,t,n){let s=Buffer.from(`${t}:${n}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${s}`}}async function jt(){let e=[],t=process.env[O.ANTHROPIC_MODEL]||"",n=process.env[O.FLOW_TELEMETRY]==="true",s=process.env[O.LANGFUSE_BASE_URL],o=process.env[O.LANGFUSE_PUBLIC_KEY],r=process.env[O.LANGFUSE_SECRET_KEY];if(n&&s&&o&&r){let d="",h="",S=ge(process.env[O.ANTHROPIC_AUTH_TOKEN]);if(S)d=await re().catch(()=>null)||S.clientId,h=S.tenant;else if(Je.KEYCHAIN_ENABLED)try{let I=await Ve();I&&(d=await re()||I.clientId,h=I.tenant);}catch{}let L={user:d||"",tenant:h||"",team:"",project:"",model:t};e.push({mode:"direct",...Vr(Xe(s),o,r),...L}),K("resolveCredentials","direct mode active",`user=${L.user}`,`tenant=${L.tenant}`);}let i=ge(process.env[O.ANTHROPIC_AUTH_TOKEN]);if(K("resolveCredentials",i?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!i&&Je.KEYCHAIN_ENABLED&&(i=await Ve(),i&&K("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)")),!i){if(e.length===0){let d=[];return d.authError=false,d}return e}let a;try{a=await Kr(i);}catch(d){if(K("resolveCredentials",`token refresh failed: ${d.message}`),e.length>0)return e;let h=[];return h.authError=true,h}let u={user:await re()||i.clientId,tenant:i.tenant,team:"",project:"",model:t},f=process.env[O.FLOW_TELEMETRY_GATEWAY]||Br;return e.push({mode:"gateway",...Wr(Xe(f),{accessToken:a}),...u}),e}async function Jr(){return (await jt()).length>0}Gt.exports={credentialsAvailable:Jr,getIdentityFromToken:Gr,resolveCredentials:jt,validateUrl:Xe,parseCredsFromAnthropicToken:ge,buildAnthropicAuthToken:jr};});var ce=l((sc,Zt)=>{var{getFlowCredentials:ze,saveFlowCredentials:Kt,clearFlowCredentials:Xr,saveTokenCache:zr,isTokenValid:Zr,getConfigPath:Wt,hasCredentials:Qr}=G(),{getToken:eo}=Z(),{buildAnthropicAuthToken:to,parseCredsFromAnthropicToken:Vt}=$(),{addEnvToClaudeSettings:no}=te(),{ENV:Ze}=w(),{green:ye,red:oe,yellow:me,cyan:ie,bold:Jt,dim:W}=M(),so=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;function v(e){return typeof e=="string"?e.replace(so,""):e}function ae(e,t={}){return new Promise((n,s)=>{let{masked:o=false,defaultValue:r=""}=t;process.stdout.write(e+r);let i=r;function a(){try{process.stdin.setRawMode(!1);}catch{}}process.once("uncaughtException",a),process.once("unhandledRejection",a);let u=d=>{if(d===""){f(),s(new Error("SIGINT"));return}if(d==="\r"||d===`
16
+ `){f(),process.stdout.write(`
17
+ `),n(i);return}if(d==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}d.startsWith("\x1B")||(i+=d,process.stdout.write(o?"*".repeat(d.length):d));};function f(){process.stdin.setRawMode(false),process.stdin.removeListener("data",u),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",u);})}async function Xt(e){try{let t=await ze();(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)&&await Kt(e);}catch{}}async function zt(e){let{accessToken:t,expiresAt:n}=await eo(e);await Kt(e),await zr({accessToken:t,expiresAt:n});try{let s=to(e);no({[Ze.ANTHROPIC_AUTH_TOKEN]:s});}catch{}}async function ro(e){try{return await zt(e),process.stdout.write(ye(` \u2713 Setup complete. Tenant: ${v(e.tenant)}
18
+
19
+ `)),0}catch(t){return process.stderr.write(oe(` \u2717 Authentication failed: ${v(t.message)}
20
+ `)),1}}async function oo(){try{process.stdout.write(`
21
+ `);let e=(await ae(ie(" ? ")+"Client ID: ")).trim(),t=(await ae(ie(" ? ")+"Client Secret: ",{masked:!0})).trim(),n=(await ae(ie(" ? ")+"Tenant: ")).trim();if(!e||!t||!n)return process.stderr.write(oe(` \u2717 All fields are required
22
+ `)),1;try{await zt({clientId:e,clientSecret:t,tenant:n});}catch(s){return process.stderr.write(oe(` \u2717 Authentication failed: ${v(s.message)}
23
+ `)),1}return process.stdout.write(ye(` \u2713 Setup complete. Tenant: ${v(n)}
24
+ `)),process.stdout.write(` Storage: ${await Wt()}
25
+
26
+ `),0}catch(e){if(e.message==="SIGINT")throw e;return process.stderr.write(oe(` \u2717 Unexpected error: ${e.message}
27
+ `)),1}}async function io(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return ro({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant});let t=Vt(process.env[Ze.ANTHROPIC_AUTH_TOKEN]);t&&await Xt(t);let n=t||await ze();if(n){process.stdout.write(`
28
+ `),process.stdout.write(Jt(` Already authenticated
29
+ `)),process.stdout.write(W(" Tenant: ")+v(n.tenant)+`
30
+ `),process.stdout.write(W(" Client ID: ")+v(n.clientId)+`
31
31
  `),process.stdout.write(`
32
- `);let s;try{s=await ie(oe(" ? ")+"Re-authenticate? (y/N): ");}catch(r){if(r.message==="SIGINT")return process.stdout.write(`
33
- `),130;throw r}if(s.trim().toLowerCase()!=="y")return process.stdout.write(Oe(` \u2713 Using existing credentials.
32
+ `);let s;try{s=await ae(ie(" ? ")+"Re-authenticate? (y/N): ");}catch(o){if(o.message==="SIGINT")return process.stdout.write(`
33
+ `),130;throw o}if(s.trim().toLowerCase()!=="y")return process.stdout.write(ye(` \u2713 Using existing credentials.
34
34
 
35
- `)),0}try{return await no()}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
36
- `),130;throw s}}async function ro(){try{return process.stdout.write(`
37
- `),(await ie(oe(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(ye(` \u26A0 Logout cancelled
35
+ `)),0}try{return await oo()}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
36
+ `),130;throw s}}async function ao(){try{return process.stdout.write(`
37
+ `),(await ae(ie(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(me(` \u26A0 Logout cancelled
38
38
  `)),0):null}catch(e){if(e.message==="SIGINT")return process.stdout.write(`
39
- `),130;throw e}}async function oo(e=false){if(!await Xr())return process.stdout.write(ye(` \u26A0 You are not authenticated
40
- `)),0;if(!e){let t=await ro();if(t!==null)return t}try{return await Vr(),process.stdout.write(Oe(` \u2713 Credentials removed successfully
41
- `)),0}catch{return process.stderr.write(re(` \u2717 Error removing credentials
42
- `)),1}}async function io(){let e=Vt(process.env[Ze.ANTHROPIC_AUTH_TOKEN]);e&&await Jt(e);let t=e||await ze();if(!t)return process.stdout.write(ye(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;if(!e&&!await Jr())return process.stdout.write(ye(" \u26A0 Session expired. Run `flow-ai-obs auth login` to re-authenticate.\n")),0;let n=t.clientSecret.length>4?"****...****"+t.clientSecret.slice(-4):"****",s=e?"ANTHROPIC_AUTH_TOKEN (settings.json)":await Kt();return process.stdout.write(`
43
- `+Wt(` Authenticated
44
- `)),process.stdout.write(Y(" Tenant: ")+v(t.tenant)+`
45
- `),process.stdout.write(Y(" Client ID: ")+v(t.clientId)+`
46
- `),process.stdout.write(Y(" Client Secret: ")+n+`
47
- `),process.stdout.write(Y(" Storage: ")+s+`
48
-
49
- `),0}zt.exports={runLogin:so,runLogout:oo,runStatus:io};});var et=p((ec,tn)=>{var ao=c("fs"),Qe=c("path"),Zt=c("os"),{spawnSync:co}=c("child_process"),{writeClaudeSettings:uo}=ee(),{NATIVE_OTEL:lo,ENV:po}=w(),{green:fo,red:ho,yellow:So,bold:Qt,dim:L,cyan:To}=F(),{runLogin:Eo}=ae(),en={darwin:`npm install -g @anthropic-ai/claude-code
39
+ `),130;throw e}}async function co(e=false){if(!await Qr())return process.stdout.write(me(` \u26A0 You are not authenticated
40
+ `)),0;if(!e){let t=await ao();if(t!==null)return t}try{return await Xr(),process.stdout.write(ye(` \u2713 Credentials removed successfully
41
+ `)),0}catch{return process.stderr.write(oe(` \u2717 Error removing credentials
42
+ `)),1}}async function uo(){let e=Vt(process.env[Ze.ANTHROPIC_AUTH_TOKEN]);e&&await Xt(e);let t=e||await ze();if(!t)return process.stdout.write(me(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;if(!e&&!await Zr())return process.stdout.write(me(" \u26A0 Session expired. Run `flow-ai-obs auth login` to re-authenticate.\n")),0;let n=t.clientSecret.length>4?"****...****"+t.clientSecret.slice(-4):"****",s=e?"ANTHROPIC_AUTH_TOKEN (settings.json)":await Wt();return process.stdout.write(`
43
+ `+Jt(` Authenticated
44
+ `)),process.stdout.write(W(" Tenant: ")+v(t.tenant)+`
45
+ `),process.stdout.write(W(" Client ID: ")+v(t.clientId)+`
46
+ `),process.stdout.write(W(" Client Secret: ")+n+`
47
+ `),process.stdout.write(W(" Storage: ")+s+`
48
+
49
+ `),0}Zt.exports={runLogin:io,runLogout:co,runStatus:uo};});var et=l((rc,sn)=>{var lo=c("fs"),Qe=c("path"),Qt=c("os"),{spawnSync:po}=c("child_process"),{writeClaudeSettings:fo}=te(),{NATIVE_OTEL:ho,ENV:To}=w(),{green:So,red:Eo,yellow:en,bold:tn,dim:A,cyan:wo}=M(),{runLogin:_o}=ce(),nn={darwin:`npm install -g @anthropic-ai/claude-code
50
50
  or visit: https://claude.ai/download`,linux:"npm install -g @anthropic-ai/claude-code",win32:`npm install -g @anthropic-ai/claude-code
51
- or visit: https://claude.ai/download`};function wo(){let e=process.platform==="win32"?"where":"which";return co(e,["claude"],{encoding:"utf8",timeout:5e3}).status===0}function go(){return process.platform==="win32"?Qe.join(process.env.APPDATA||Qe.join(Zt.homedir(),"AppData","Roaming"),"Claude","settings.json"):Qe.join(Zt.homedir(),".claude","settings.json")}function _o(){try{let e=ao.readFileSync(go(),"utf8"),t=JSON.parse(e);return !!(t.env&&t.env[po.ANTHROPIC_AUTH_TOKEN])}catch{return false}}async function mo(){if(!wo()){let t=en[process.platform]||en.linux;return process.stderr.write(`
52
- `+ho(` \u2717 Claude Code is not installed or not found in PATH.
51
+ or visit: https://claude.ai/download`};function go(){let e=process.platform==="win32"?"where":"which";return po(e,["claude"],{encoding:"utf8",timeout:5e3}).status===0}function mo(){return process.platform==="win32"?Qe.join(process.env.APPDATA||Qe.join(Qt.homedir(),"AppData","Roaming"),"Claude","settings.json"):Qe.join(Qt.homedir(),".claude","settings.json")}function yo(){try{let e=lo.readFileSync(mo(),"utf8"),t=JSON.parse(e);return !!(t.env&&t.env[To.ANTHROPIC_AUTH_TOKEN])}catch{return false}}async function Ao(){if(!go()){let n=nn[process.platform]||nn.linux;return process.stderr.write(`
52
+ `+Eo(` \u2717 Claude Code is not installed or not found in PATH.
53
53
 
54
54
  `)+` flow-ai-obs requires Claude Code to function.
55
55
  Install it with:
56
56
 
57
- `+To(` ${t}`)+`
57
+ `+wo(` ${n}`)+`
58
58
 
59
- `),1}if(!_o()){process.stdout.write(So(` \u26A0 No credentials found in settings.json \u2014 authentication required.
59
+ `),1}if(!yo()){process.stdout.write(en(` \u26A0 No credentials found in settings.json \u2014 authentication required.
60
60
 
61
- `));let t=await Eo();if(t!==0)return t}let e;try{e=uo();}catch(t){return process.stderr.write(` \u2717 Failed to write settings: ${t.message}
61
+ `));let n=await _o();if(n!==0)return n}let e,t;try{({settingsPath:e,preserved:t}=fo());}catch(n){return process.stderr.write(` \u2717 Failed to write settings: ${n.message}
62
62
  `),1}process.stdout.write(`
63
- `+Qt(" Native OTEL configured")+` (metrics & logs)
64
- `);for(let[t,n]of Object.entries(lo))process.stdout.write(L(` ${t.padEnd(36)}`)+n+`
63
+ `+tn(" Native OTEL configured")+` (metrics & logs)
64
+ `);for(let[n,s]of Object.entries(ho))process.stdout.write(A(` ${n.padEnd(36)}`)+s+`
65
65
  `);return process.stdout.write(`
66
- `),process.stdout.write(Qt(" Hooks registered")+` (Langfuse trace capture)
67
- `),process.stdout.write(L(" UserPromptSubmit")+` \u2192 flow-ai-obs UserPromptSubmit (timeout: 5s)
68
- `),process.stdout.write(L(" PreToolUse ")+` \u2192 flow-ai-obs PreToolUse (timeout: 3s)
69
- `),process.stdout.write(L(" PostToolUse ")+` \u2192 flow-ai-obs PostToolUse (timeout: 10s)
70
- `),process.stdout.write(L(" Stop ")+` \u2192 flow-ai-obs Stop (timeout: 15s)
71
- `),process.stdout.write(`
72
- `),process.stdout.write(L(" Settings: ")+e+`
73
- `),process.stdout.write(L(" Backup: ")+e+`.bkp
74
- `),process.stdout.write(L(" OTEL auth: flow-ai-obs otel-headers")+L(` (reads keychain at runtime)
66
+ `),process.stdout.write(tn(" Hooks registered")+` (Langfuse trace capture)
67
+ `),process.stdout.write(A(" UserPromptSubmit")+` \u2192 flow-ai-obs UserPromptSubmit (timeout: 5s)
68
+ `),process.stdout.write(A(" PreToolUse ")+` \u2192 flow-ai-obs PreToolUse (timeout: 3s)
69
+ `),process.stdout.write(A(" PostToolUse ")+` \u2192 flow-ai-obs PostToolUse (timeout: 10s)
70
+ `),process.stdout.write(A(" Stop ")+` \u2192 flow-ai-obs Stop (timeout: 15s)
71
+ `),t.length>0&&(process.stdout.write(`
72
+ `),process.stdout.write(en(` \u26A0 Third-party hooks detected and preserved on: ${t.join(", ")}
73
+ `)),process.stdout.write(A(` flow-ai-obs was prepended \u2014 it executes first.
74
+ `))),process.stdout.write(`
75
+ `),process.stdout.write(A(" Settings: ")+e+`
76
+ `),process.stdout.write(A(" Backup: ")+e+`.bkp
77
+ `),process.stdout.write(A(" OTEL auth: flow-ai-obs otel-headers")+A(` (reads keychain at runtime)
75
78
  `)),process.stdout.write(`
76
- `),process.stdout.write(fo(` \u2713 Ready. Native OTEL + Langfuse trace capture active.
77
- `)),process.stdout.write(L(" Run `flow-ai-obs setup` to also configure the Flow LLM Proxy.\n\n")),0}tn.exports={runInstall:mo};});var cn=p((tc,an)=>{var{LLM_PROXY:nn}=w(),{green:sn,yellow:rn,bold:yo,dim:on}=F(),{runLogin:Oo}=ae(),{runInstall:Ao}=et(),{addEnvToClaudeSettings:Lo,validateConnectivity:No,getClaudeSettingsPath:Io}=ee(),{getFlowCredentials:ko}=j();async function Co(e={}){process.stdout.write(`
79
+ `),process.stdout.write(So(` \u2713 Ready. Native OTEL + Langfuse trace capture active.
80
+ `)),process.stdout.write(A(" Run `flow-ai-obs setup` to also configure the Flow LLM Proxy.\n\n")),0}sn.exports={runInstall:Ao};});var ln=l((oc,un)=>{var{LLM_PROXY:rn}=w(),{green:on,yellow:an,bold:Lo,dim:cn}=M(),{runLogin:Oo}=ce(),{runInstall:No}=et(),{addEnvToClaudeSettings:Io,validateConnectivity:ko,getClaudeSettingsPath:Co}=te(),{getFlowCredentials:vo}=G();async function bo(e={}){process.stdout.write(`
78
81
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
79
82
  `),process.stdout.write(`\u2551 flow-ai-obs \u2014 setup \u2551
80
83
  `),process.stdout.write(`\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
@@ -83,54 +86,54 @@
83
86
  Setup aborted. Run \`flow-ai-obs auth login\` to retry.
84
87
 
85
88
  `),t;process.stdout.write(`
86
- `);let n=await Ao();if(n!==0)return n;try{Lo(nn);}catch(r){process.stderr.write(` \u26A0 Could not write LLM Proxy config: ${r.message}
87
- `);}process.stdout.write(yo(" Flow LLM Proxy configured")+` (model provider)
88
- `);for(let[r,o]of Object.entries(nn))process.stdout.write(on(` ${r.padEnd(36)}`)+o+`
89
+ `);let n=await No();if(n!==0)return n;try{Io(rn);}catch(o){process.stderr.write(` \u26A0 Could not write LLM Proxy config: ${o.message}
90
+ `);}process.stdout.write(Lo(" Flow LLM Proxy configured")+` (model provider)
91
+ `);for(let[o,r]of Object.entries(rn))process.stdout.write(cn(` ${o.padEnd(36)}`)+r+`
89
92
  `);process.stdout.write(`
90
93
  `),process.stdout.write(` Validating connectivity to Flow OTEL endpoint\u2026
91
- `);let s=await ko();return s?await No(s)?process.stdout.write(sn(` \u2713 Connectivity validated \u2014 telemetry is active.
94
+ `);let s=await vo();return s?await ko(s)?process.stdout.write(on(` \u2713 Connectivity validated \u2014 telemetry is active.
92
95
 
93
- `)):process.stdout.write(rn(` \u26A0 Could not reach the OTEL endpoint. Telemetry will activate once connectivity is restored.
96
+ `)):process.stdout.write(an(` \u26A0 Could not reach the OTEL endpoint. Telemetry will activate once connectivity is restored.
94
97
 
95
- `)):process.stdout.write(rn(` \u26A0 Could not read stored credentials \u2014 skipping connectivity check.
98
+ `)):process.stdout.write(an(` \u26A0 Could not read stored credentials \u2014 skipping connectivity check.
96
99
 
97
- `)),process.stdout.write(sn(` \u2713 Setup complete!
98
- `)),process.stdout.write(on(` Settings: ${Io()}
100
+ `)),process.stdout.write(on(` \u2713 Setup complete!
101
+ `)),process.stdout.write(cn(` Settings: ${Co()}
99
102
 
100
- `)),0}an.exports={runSetup:Co};});var ln=p((nc,un)=>{var{getFlowCredentials:vo}=j(),{getToken:bo}=z();async function Uo(){let e;try{e=await vo();}catch{return process.stderr.write(`[flow-ai-obs otel-headers] Failed to read credentials
103
+ `)),0}un.exports={runSetup:bo};});var pn=l((ic,dn)=>{var{getFlowCredentials:Uo}=G(),{getToken:Ro}=Z();async function Po(){let e;try{e=await Uo();}catch{return process.stderr.write(`[flow-ai-obs otel-headers] Failed to read credentials
101
104
  `),1}if(!e)return process.stderr.write(`[flow-ai-obs otel-headers] Not authenticated \u2014 run: flow-ai-obs auth login
102
- `),1;let t;try{t=(await bo(e)).accessToken;}catch(n){return process.stderr.write(`[flow-ai-obs otel-headers] Token fetch failed: ${n.message}
105
+ `),1;let t;try{t=(await Ro(e)).accessToken;}catch(n){return process.stderr.write(`[flow-ai-obs otel-headers] Token fetch failed: ${n.message}
103
106
  `),1}return t?(process.stdout.write(`{"Authorization": "Bearer ${t}"}
104
107
  `),0):(process.stderr.write(`[flow-ai-obs otel-headers] Empty token received
105
- `),1)}un.exports={runOtelHeaders:Uo};});var Sn=p((sc,hn)=>{var{getFlowCredentials:dn,isTokenValid:Ro,getEmailFromToken:Po,getTokenCache:$o}=j(),{resolveCredentials:qo,parseCredsFromAnthropicToken:pn}=P(),{getClaudeSettingsPath:Fo}=ee(),{ENV:b,NATIVE_OTEL:xo}=w(),{runLogin:fn}=ae(),Mo=c("fs");function tt(e){return !e||e.length<=8?"****":e.slice(0,4)+"****...****"+e.slice(-4)}function ce(e){process.stdout.write(` \u2713 ${e}
108
+ `),1)}dn.exports={runOtelHeaders:Po};});var En=l((ac,Sn)=>{var{getFlowCredentials:fn,isTokenValid:Fo,getEmailFromToken:$o,getTokenCache:qo}=G(),{resolveCredentials:xo,parseCredsFromAnthropicToken:hn}=$(),{getClaudeSettingsPath:Mo}=te(),{ENV:b,NATIVE_OTEL:Do}=w(),{runLogin:Tn}=ce(),Bo=c("fs");function tt(e){return !e||e.length<=8?"****":e.slice(0,4)+"****...****"+e.slice(-4)}function ue(e){process.stdout.write(` \u2713 ${e}
106
109
  `);}function Ae(e){process.stdout.write(` \u26A0 ${e}
107
110
  `);}function Le(e){process.stdout.write(` \u2717 ${e}
108
111
  `);}function m(e){process.stdout.write(` ${e}
109
112
  `);}function y(){process.stdout.write(`
110
- `);}async function Bo(){y(),process.stdout.write(` flow-claude-observability \u2014 configuration check
113
+ `);}async function Ho(){y(),process.stdout.write(` flow-claude-observability \u2014 configuration check
111
114
  `),y(),process.stdout.write(` Auth
112
- `);let e=pn(process.env[b.ANTHROPIC_AUTH_TOKEN]),t=e||await dn();if(!t){Ae("Not authenticated \u2014 starting setup..."),y();let a=await fn();if(a!==0)return a;if(e=pn(process.env[b.ANTHROPIC_AUTH_TOKEN]),t=e||await dn(),!t)return Le("Authentication failed"),y(),1;y(),process.stdout.write(` Auth
113
- `);}if(!e&&!await Ro()){Ae("Session expired \u2014 re-authenticating..."),y();let a=await fn();if(a!==0)return a;y(),process.stdout.write(` Auth
114
- `);}let n=await Po()||t.clientId;ce("Authenticated"),m(`Tenant: ${t.tenant}`),m(`User: ${n}`),y(),process.stdout.write(` Native OTEL
115
- `);let s={};try{let a=Mo.readFileSync(Fo(),"utf8");s=JSON.parse(a).env||{};}catch{}let r=Object.keys(xo).filter(a=>!s[a]);if(r.length===0?(ce("All OTEL env vars present in settings.json"),m(`Endpoint: ${s.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(Ae(`${r.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),r.forEach(a=>Le(`Missing: ${a}`)),m("Run: flow-ai-obs install (restores missing vars automatically)")),y(),process.stdout.write(` Tracing
116
- `),process.env[b.FLOW_TELEMETRY]==="true"){ce("FLOW_TELEMETRY=true (direct mode enabled)");let a=[b.LANGFUSE_BASE_URL,b.LANGFUSE_PUBLIC_KEY,b.LANGFUSE_SECRET_KEY].filter(u=>!process.env[u]);a.length>0&&a.forEach(u=>Ae(`Missing: ${u}`));}else m("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let i=await qo();if(!i||i.length===0)return i&&i.authError?Le("Token refresh failed \u2014 gateway mode could not activate"):(Le("No active destinations \u2014 no traces will be sent"),m("For direct mode: set FLOW_TELEMETRY=true + LANGFUSE_BASE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY"),m("For gateway mode: run flow-claude-observability auth login")),y(),1;for(let a of i)if(a.mode==="gateway"){let u=await $o();ce("Mode: gateway"),m(`Endpoint: ${a.endpoint}`),m(`Token: ${tt(u&&u.accessToken)}`);}else a.mode==="direct"&&(ce("Mode: direct"),m(`Endpoint: ${a.endpoint}`),m(`PK: ${tt(process.env[b.LANGFUSE_PUBLIC_KEY])}`),m(`SK: ${tt(process.env[b.LANGFUSE_SECRET_KEY])}`));return y(),process.stdout.write(` All checks passed \u2014 observability is active.
117
- `),y(),0}hn.exports={runCheck:Bo};});var K=p((rc,Tn)=>{function Do(e,t){let n=typeof e=="object"?JSON.stringify(e):String(e??"");return n.length>t?n.slice(0,t)+" \u2026[truncated]":n}function Ho(e,t=100){return String(e??"").split(`
118
- `)[0].slice(0,t).trim()}function jo(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>{try{e(JSON.parse(t));}catch{e({});}});})}function Go(e){process.stdout.write(JSON.stringify(e));}Tn.exports={truncate:Do,firstLine:Ho,readInput:jo,passthrough:Go};});var ue=p((oc,wn)=>{var{randomBytes:En}=c("crypto"),Yo=()=>En(16).toString("hex"),Ko=()=>En(8).toString("hex");function Vo(){return String(BigInt(Date.now())*1000000n)}wn.exports={generateTraceId:Yo,generateSpanId:Ko,nowNs:Vo};});var le=p((ac,_n)=>{var{readFileSync:Wo,writeFileSync:Jo,unlinkSync:Xo,existsSync:zo,realpathSync:ic}=c("fs"),{tmpdir:gn}=c("os"),{join:Zo,resolve:Qo,normalize:ei,sep:ti}=c("path"),ni=/^[0-9a-f-]{1,64}$/i,si=ei(gn())+ti;function ri(e,t){let n=Qo(e);if(!n.startsWith(t))throw new Error(`Path traversal detected: ${e}`);return n}function nt(e){if(!ni.test(e))throw new Error(`Invalid session ID: ${e}`);return ri(Zo(gn(),`flow-obs-${e}.json`),si)}function oi(e){let t=nt(e);if(!zo(t))return null;try{return JSON.parse(Wo(t,"utf8"))}catch{return null}}function ii(e,t){Jo(nt(e),JSON.stringify(t),{encoding:"utf8",mode:384});}function ai(e){try{Xo(nt(e));}catch{}}_n.exports={loadState:oi,saveState:ii,deleteState:ai};});var st=p((cc,On)=>{var{readFileSync:mn,existsSync:yn}=c("fs");function ci(e){if(!e||!yn(e))return null;try{let t=mn(e,"utf8").trimEnd().split(`
119
- `);for(let n=t.length-1;n>=0;n--)try{let s=JSON.parse(t[n]);if(s.type==="user"&&s.uuid)return s.uuid}catch{}}catch{}return null}function ui(e){if(!e||!yn(e))return null;try{let t=mn(e,"utf8").trimEnd().split(`
120
- `),n=[],s=0,r=0,o=!1;for(let i=t.length-1;i>=0;i--)try{let a=JSON.parse(t[i]);if(a.type==="user"){if(o)break;continue}if(a.type==="assistant"){o=!0;let d=(a.message?.content??[]).filter(h=>h.type==="text").map(h=>h.text).join("");d&&n.unshift(d);let l=a.message?.usage??{};s+=(l.input_tokens??0)+(l.cache_read_input_tokens??0)+(l.cache_creation_input_tokens??0),r+=l.output_tokens??0;}}catch{}return !n.length&&s===0?null:{text:n.join(`
121
-
122
- `),inputTokens:s,outputTokens:r}}catch{}return null}On.exports={readPromptUuid:ci,readLastAssistantOutput:ui};});var Ne=p((uc,In)=>{var{readFileSync:li,existsSync:An,readdirSync:di}=c("fs"),{homedir:Ln}=c("os"),{join:V,extname:pi}=c("path"),fi=new Set([".venv","__pycache__",".git","node_modules"]),hi=new Set([".pyc",".pyo"]),Si=new Set(["SKILL.md",".DS_Store",".gitignore"]);function Ti(e,t){if(!e)return null;let n=[V(Ln(),".claude","skills",e,"SKILL.md"),V(t||"",".claude","skills",e,"SKILL.md")];for(let s of n)if(An(s))try{return li(s,"utf8")}catch{}return null}function Ei(e){return e.match(/^\/([a-z][a-z0-9-]*)(?:\s.*)?$/i)?.[1]||null}var Nn=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function wi(e){return !!e.slashSkill||e.toolCalls.some(s=>s.tool==="Skill")?e.toolCalls.some(s=>Nn.has(s.tool))?"complete":"prerequisite_required":null}function gi(e,t){if(!e)return null;let n=[V(Ln(),".claude","skills",e),V(t||"",".claude","skills",e)],s=null;for(let i of n)if(An(V(i,"SKILL.md"))){s=i;break}if(!s)return null;let r=[];function o(i,a){for(let u of di(i,{withFileTypes:true})){if(fi.has(u.name)||Si.has(u.name)||hi.has(pi(u.name)))continue;let d=a?`${a}/${u.name}`:u.name;u.isDirectory()?o(V(i,u.name),d):r.push(d);}}return o(s,""),r.length>0?r:null}In.exports={readSkillContent:Ti,readSkillArtifacts:gi,detectSlashSkill:Ei,EXECUTION_TOOLS:Nn,detectExecutionStatus:wi};});var bn=p((lc,vn)=>{var{generateTraceId:kn,generateSpanId:_i,nowNs:mi}=ue(),{saveState:yi}=le(),{readPromptUuid:Oi}=st(),{detectSlashSkill:Ai,readSkillContent:Li,readSkillArtifacts:Ni}=Ne(),{passthrough:Ii}=K(),{dbg:Cn}=C(),{ENV:ki}=w(),{resolveCredentials:Ci}=P();async function vi(e){let t=e.session_id||"unknown",n=e.prompt||"",s=e.cwd||"";try{(await Ci()).authError===!0&&(process.stderr.write(`
115
+ `);let e=hn(process.env[b.ANTHROPIC_AUTH_TOKEN]),t=e||await fn();if(!t){Ae("Not authenticated \u2014 starting setup..."),y();let a=await Tn();if(a!==0)return a;if(e=hn(process.env[b.ANTHROPIC_AUTH_TOKEN]),t=e||await fn(),!t)return Le("Authentication failed"),y(),1;y(),process.stdout.write(` Auth
116
+ `);}if(!e&&!await Fo()){Ae("Session expired \u2014 re-authenticating..."),y();let a=await Tn();if(a!==0)return a;y(),process.stdout.write(` Auth
117
+ `);}let n=await $o()||t.clientId;ue("Authenticated"),m(`Tenant: ${t.tenant}`),m(`User: ${n}`),y(),process.stdout.write(` Native OTEL
118
+ `);let s={};try{let a=Bo.readFileSync(Mo(),"utf8");s=JSON.parse(a).env||{};}catch{}let o=Object.keys(Do).filter(a=>!s[a]);if(o.length===0?(ue("All OTEL env vars present in settings.json"),m(`Endpoint: ${s.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(Ae(`${o.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),o.forEach(a=>Le(`Missing: ${a}`)),m("Run: flow-ai-obs install (restores missing vars automatically)")),y(),process.stdout.write(` Tracing
119
+ `),process.env[b.FLOW_TELEMETRY]==="true"){ue("FLOW_TELEMETRY=true (direct mode enabled)");let a=[b.LANGFUSE_BASE_URL,b.LANGFUSE_PUBLIC_KEY,b.LANGFUSE_SECRET_KEY].filter(u=>!process.env[u]);a.length>0&&a.forEach(u=>Ae(`Missing: ${u}`));}else m("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let i=await xo();if(!i||i.length===0)return i&&i.authError?Le("Token refresh failed \u2014 gateway mode could not activate"):(Le("No active destinations \u2014 no traces will be sent"),m("For direct mode: set FLOW_TELEMETRY=true + LANGFUSE_BASE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY"),m("For gateway mode: run flow-claude-observability auth login")),y(),1;for(let a of i)if(a.mode==="gateway"){let u=await qo();ue("Mode: gateway"),m(`Endpoint: ${a.endpoint}`),m(`Token: ${tt(u&&u.accessToken)}`);}else a.mode==="direct"&&(ue("Mode: direct"),m(`Endpoint: ${a.endpoint}`),m(`PK: ${tt(process.env[b.LANGFUSE_PUBLIC_KEY])}`),m(`SK: ${tt(process.env[b.LANGFUSE_SECRET_KEY])}`));return y(),process.stdout.write(` All checks passed \u2014 observability is active.
120
+ `),y(),0}Sn.exports={runCheck:Ho};});var V=l((cc,wn)=>{function Yo(e,t){let n=typeof e=="object"?JSON.stringify(e):String(e??"");return n.length>t?n.slice(0,t)+" \u2026[truncated]":n}function jo(e,t=100){return String(e??"").split(`
121
+ `)[0].slice(0,t).trim()}function Go(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>t+=n),process.stdin.on("end",()=>{try{e(JSON.parse(t));}catch{e({});}});})}function Ko(e){process.stdout.write(JSON.stringify(e));}wn.exports={truncate:Yo,firstLine:jo,readInput:Go,passthrough:Ko};});var le=l((uc,gn)=>{var{randomBytes:_n}=c("crypto"),Wo=()=>_n(16).toString("hex"),Vo=()=>_n(8).toString("hex");function Jo(){return String(BigInt(Date.now())*1000000n)}gn.exports={generateTraceId:Wo,generateSpanId:Vo,nowNs:Jo};});var de=l((dc,yn)=>{var{readFileSync:Xo,writeFileSync:zo,unlinkSync:Zo,existsSync:Qo,realpathSync:lc}=c("fs"),{tmpdir:mn}=c("os"),{join:ei,resolve:ti,normalize:ni,sep:si}=c("path"),ri=/^[0-9a-f-]{1,64}$/i,oi=ni(mn())+si;function ii(e,t){let n=ti(e);if(!n.startsWith(t))throw new Error(`Path traversal detected: ${e}`);return n}function nt(e){if(!ri.test(e))throw new Error(`Invalid session ID: ${e}`);return ii(ei(mn(),`flow-obs-${e}.json`),oi)}function ai(e){let t=nt(e);if(!Qo(t))return null;try{return JSON.parse(Xo(t,"utf8"))}catch{return null}}function ci(e,t){zo(nt(e),JSON.stringify(t),{encoding:"utf8",mode:384});}function ui(e){try{Zo(nt(e));}catch{}}yn.exports={loadState:ai,saveState:ci,deleteState:ui};});var st=l((pc,On)=>{var{readFileSync:An,existsSync:Ln}=c("fs");function li(e){if(!e||!Ln(e))return null;try{let t=An(e,"utf8").trimEnd().split(`
122
+ `);for(let n=t.length-1;n>=0;n--)try{let s=JSON.parse(t[n]);if(s.type==="user"&&s.uuid)return s.uuid}catch{}}catch{}return null}function di(e){if(!e||!Ln(e))return null;try{let t=An(e,"utf8").trimEnd().split(`
123
+ `),n=[],s=0,o=0,r=!1;for(let i=t.length-1;i>=0;i--)try{let a=JSON.parse(t[i]);if(a.type==="user"){if(r)break;continue}if(a.type==="assistant"){r=!0;let f=(a.message?.content??[]).filter(h=>h.type==="text").map(h=>h.text).join("");f&&n.unshift(f);let d=a.message?.usage??{};s+=(d.input_tokens??0)+(d.cache_read_input_tokens??0)+(d.cache_creation_input_tokens??0),o+=d.output_tokens??0;}}catch{}return !n.length&&s===0?null:{text:n.join(`
124
+
125
+ `),inputTokens:s,outputTokens:o}}catch{}return null}On.exports={readPromptUuid:li,readLastAssistantOutput:di};});var Oe=l((fc,Cn)=>{var{readFileSync:pi,existsSync:Nn,readdirSync:fi}=c("fs"),{homedir:In}=c("os"),{join:J,extname:hi}=c("path"),Ti=new Set([".venv","__pycache__",".git","node_modules"]),Si=new Set([".pyc",".pyo"]),Ei=new Set(["SKILL.md",".DS_Store",".gitignore"]);function wi(e,t){if(!e)return null;let n=[J(In(),".claude","skills",e,"SKILL.md"),J(t||"",".claude","skills",e,"SKILL.md")];for(let s of n)if(Nn(s))try{return pi(s,"utf8")}catch{}return null}function _i(e){return e.match(/^\/([a-z][a-z0-9-]*)(?:\s.*)?$/i)?.[1]||null}var kn=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function gi(e){return !!e.slashSkill||e.toolCalls.some(s=>s.tool==="Skill")?e.toolCalls.some(s=>kn.has(s.tool))?"complete":"prerequisite_required":null}function mi(e,t){if(!e)return null;let n=[J(In(),".claude","skills",e),J(t||"",".claude","skills",e)],s=null;for(let i of n)if(Nn(J(i,"SKILL.md"))){s=i;break}if(!s)return null;let o=[];function r(i,a){for(let u of fi(i,{withFileTypes:true})){if(Ti.has(u.name)||Ei.has(u.name)||Si.has(hi(u.name)))continue;let f=a?`${a}/${u.name}`:u.name;u.isDirectory()?r(J(i,u.name),f):o.push(f);}}return r(s,""),o.length>0?o:null}Cn.exports={readSkillContent:wi,readSkillArtifacts:mi,detectSlashSkill:_i,EXECUTION_TOOLS:kn,detectExecutionStatus:gi};});var Rn=l((hc,Un)=>{var{generateTraceId:vn,generateSpanId:yi,nowNs:Ai}=le(),{saveState:Li}=de(),{readPromptUuid:Oi}=st(),{detectSlashSkill:Ni,readSkillContent:Ii,readSkillArtifacts:ki}=Oe(),{passthrough:Ci}=V(),{dbg:bn}=C(),{ENV:vi}=w(),{resolveCredentials:bi}=$();async function Ui(e){let t=e.session_id||"unknown",n=e.prompt||"",s=e.cwd||"";try{(await bi()).authError===!0&&(process.stderr.write(`
123
126
  \u26A0 flow-ai-obs: Your Flow credentials have expired.
124
127
  Traces will not be captured until you re-authenticate.
125
128
  Run: flow-ai-obs auth login
126
129
 
127
- `),Cn("UserPromptSubmit","auth expired \u2014 warning emitted to stderr"));}catch{}let r=Oi(e.transcript_path)||kn(),o=Ai(n),i=o?Li(o,s):null,a=o?Ni(o,s):null;yi(t,{traceId:kn(),spanId:_i(),startNs:mi(),sessionId:t,prompt:n,cwd:s,traceName:r,transcriptPath:e.transcript_path||"",model:process.env[ki.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:o,skillContent:i,skillArtifacts:a}),Cn("UserPromptSubmit",`sid=${t}`,`traceName=${r}`,`slashSkill=${o}`),Ii(e);}vn.exports={onUserPromptSubmit:vi};});var Rn=p((dc,Un)=>{var{nowNs:bi}=ue(),{loadState:Ui,saveState:Ri}=le(),{truncate:Pi,passthrough:$i}=K(),{dbg:qi}=C(),{TRACE_LIMITS:Fi}=w();async function xi(e){let t=e.session_id||"unknown",n=e.tool_name||"unknown",s=e.tool_input||{},r=Ui(t);r&&(r.pendingTool={name:n,inputStr:Pi(s,Fi.TOOL_INPUT),startNs:bi()},Ri(t,r)),qi("PreToolUse",`sid=${t}`,`tool=${n}`,`stateFound=${!!r}`),$i(e);}Un.exports={onPreToolUse:xi};});var qn=p((pc,$n)=>{var Mi=c("https"),Bi=c("http"),{FLOW_URLS:Di}=w();function Hi(e){let t=new URL(e),n=new URL(Di.GATEWAY_HEALTH);return n.hostname=t.hostname,n.port=t.port,n.protocol=t.protocol,n}function Pn(e,t){return new Promise((n,s)=>{let o=(e._isSSL?Mi:Bi).request(e,i=>{let a=[];i.on("data",u=>a.push(u)),i.on("end",()=>n({statusCode:i.statusCode,body:a.join("")}));});o.on("error",i=>s(new Error(`Network error: ${i.message}`))),t&&o.write(t),o.end();})}async function ji(e){let t;try{t=Hi(e);}catch{return false}let n=t.protocol==="https:";try{let s=await Pn({hostname:t.hostname,port:t.port||(n?443:80),path:t.pathname,method:"GET",_isSSL:n},null);return s.statusCode>=200&&s.statusCode<300}catch{return false}}async function Gi(e,t,n){let s=JSON.stringify(e),r=new URL(t),o=r.protocol==="https:",i=String(n).replace(/[\r\n]/g,"");try{return (await Pn({hostname:r.hostname,port:r.port||(o?443:80),path:r.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(s)},_isSSL:o},s)).statusCode}catch{return 0}}$n.exports={checkHealth:ji,sendTraces:Gi};});var Bn=p((fc,Mn)=>{var U=c("fs"),rt=c("path"),Fn=c("os"),{BUFFER:de}=w(),{dbg:pe}=C();function xn(e){if(/[/\\]/.test(e))throw new Error(`Invalid buffer fileId: ${e}`);return rt.join(Fn.tmpdir(),`${de.FILE_PREFIX}${e}.json`)}function ot(){let e=Fn.tmpdir(),t;try{t=U.readdirSync(e);}catch{return []}return t.filter(n=>n.startsWith(de.FILE_PREFIX)&&n.endsWith(".json")).map(n=>{let s=rt.join(e,n),r=0;try{r=U.statSync(s).mtimeMs;}catch{}return {full:s,mtime:r}}).sort((n,s)=>n.mtime-s.mtime).map(n=>n.full)}function Yi(e){try{let t=ot();if(t.length>=de.MAX_FILES){let r=t.slice(0,t.length-de.MAX_FILES+1);for(let o of r)try{U.unlinkSync(o);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,s={fileId:n,bufferedAt:Date.now(),payload:e};return U.writeFileSync(xn(n),JSON.stringify(s),{encoding:"utf8",mode:384}),pe("buffer",`saved fileId=${n}`),n}catch(t){return pe("buffer",`saveToBuffer failed: ${t.message}`),null}}function Ki(){let e=ot(),t=[];for(let n of e)try{let s=U.readFileSync(n,"utf8"),r=JSON.parse(s);r&&r.fileId&&r.payload&&t.push(r);}catch{pe("buffer",`skipping malformed file: ${n}`);}return t}function Vi(e){try{U.unlinkSync(xn(e)),pe("buffer",`deleted fileId=${e}`);}catch{}}function Wi(){let e=ot(),t=Date.now()-de.MAX_AGE_MS;for(let n of e)try{let{mtimeMs:s}=U.statSync(n);s<t&&(U.unlinkSync(n),pe("buffer",`evicted stale: ${rt.basename(n)}`));}catch{}}Mn.exports={saveToBuffer:Yi,loadBuffer:Ki,deleteBuffer:Vi,cleanStaleBuffers:Wi};});var it=p((hc,Gn)=>{var{resolveCredentials:Ji}=P(),{OTLP:Dn}=w(),{dbg:W}=C(),{checkHealth:Xi,sendTraces:jn}=qn(),{saveToBuffer:Hn,loadBuffer:zi,deleteBuffer:Zi,cleanStaleBuffers:Qi}=Bn(),ea={name:Dn.SCOPE_NAME,version:Dn.SCOPE_VERSION},ta={TRACE_NAME:"langfuse.trace.name",TRACE_INPUT:"langfuse.trace.input",TRACE_OUTPUT:"langfuse.trace.output",TRACE_METADATA:"langfuse.trace.metadata",TRACE_TAGS:"langfuse.trace.tags",USER_ID:"langfuse.user.id",SESSION_ID:"langfuse.session.id",OBS_NAME:"langfuse.observation.name",OBS_INPUT:"langfuse.observation.input",OBS_OUTPUT:"langfuse.observation.output",OBS_LEVEL:"langfuse.observation.level",OBS_TYPE:"langfuse.observation.type",MODEL:"gen_ai.request.model",INPUT_TOKENS:"gen_ai.usage.input_tokens",OUTPUT_TOKENS:"gen_ai.usage.output_tokens"};function na(e,t){return t==null||t===""?null:{key:e,value:{stringValue:String(t)}}}function sa(...e){return e.filter(Boolean)}function ra(e,t){return {resourceSpans:[{resource:{attributes:e},scopeSpans:[{scope:ea,spans:Array.isArray(t)?t:[t]}]}]}}function oa(e,t){return new Promise(n=>{let s=JSON.stringify(e),r=new URL(t.endpoint),o=r.protocol==="https:",i=l=>String(l).replace(/[\r\n]/g,""),a={hostname:r.hostname,port:r.port||(o?443:80),path:r.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:i(t.authHeader),"Content-Length":Buffer.byteLength(s)}},d=(o?c("https"):c("http")).request(a,l=>{l.resume(),n(l.statusCode);});d.on("error",()=>n(0)),d.write(s),d.end();})}async function ia(e){Qi();let t=zi();if(t.length){W("replayBufferedTraces",`replaying ${t.length} buffered trace(s)`);for(let n of t)try{let s=await jn(n.payload,e.endpoint,e.authHeader);s>=200&&s<300?(Zi(n.fileId),W("replayBufferedTraces",`replayed fileId=${n.fileId} status=${s}`)):W("replayBufferedTraces",`replay failed fileId=${n.fileId} status=${s}`);}catch(s){W("replayBufferedTraces",`replay error fileId=${n.fileId}: ${s.message}`);}}}async function aa(e){let t=await Ji();return t.length?(await Promise.all(t.map(async s=>s.mode==="gateway"?await Xi(s.endpoint)?(await ia(s),jn(e,s.endpoint,s.authHeader)):(W("postToLangfuse","gateway health check failed \u2014 buffering trace"),Hn(e),0):oa(e,s)))).find(s=>s!==0)||0:(t.authError&&(W("postToLangfuse","auth refresh failed \u2014 buffering trace"),Hn(e)),0)}Gn.exports={LF:ta,a:na,attrs:sa,buildPayload:ra,postToLangfuse:aa};});var at=p((Sc,Yn)=>{var _="[REDACTED]",ca=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${_}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${_}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(e,t)=>`${t}${_}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(e,t)=>`${t}${_}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(e,t,n)=>`${t}
128
- ${_}
129
- ${n}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${_}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(e,t)=>`${t}${_}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${_}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${_}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${_}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(e,t,n)=>`${t}${n}${_}${n}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(e,t)=>`${t}:${_}@`}];function ua(e){if(e==null)return "";let t=typeof e=="string"?e:JSON.stringify(e);return ca.reduce((n,{re:s,replace:r})=>n.replace(s,r),t)}Yn.exports={sanitize:ua,REDACTED:_};});var Zn=p((Tc,zn)=>{var{generateSpanId:la,nowNs:da}=ue(),{loadState:pa,saveState:fa}=le(),{LF:fe,a:$,attrs:ha}=it(),{truncate:Kn,firstLine:Sa,passthrough:Vn}=K(),{readSkillContent:Ta,readSkillArtifacts:Ea}=Ne(),{dbg:Wn}=C(),{TRACE_LIMITS:Jn}=w(),{sanitize:Xn}=at();async function wa(e){let t=e.session_id||"unknown",n=e.tool_name||"unknown",s=e.tool_input||{},r=e.tool_response||"",o=pa(t);if(!o){Vn(e);return}let i=da(),a=o.pendingTool?.name===n,u=a?o.pendingTool.startNs:String(BigInt(i)-200000000n),d=a?o.pendingTool.inputStr:Kn(s,Jn.TOOL_INPUT),l=d;if(n==="Skill"){let R=typeof s=="object"&&s!==null?s.skill||s.name||s.skillName||String(Object.values(s)[0]??""):String(s),k=R?Ta(R.trim(),o.cwd):null;k&&(l=k,o.skillContent||(o.skillContent=k),o.slashSkill||(o.slashSkill=R.trim()),o.skillArtifacts||(o.skillArtifacts=Ea(R.trim(),o.cwd))),Wn("PostToolUse","Skill tool detected",`skillName=${R}`,`contentFound=${!!k}`);}let h=Xn(Kn(r,Jn.TOOL_OUTPUT)),T=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(h.slice(0,500)),O=T?"ERROR":"DEFAULT",I=la(),Se=Math.round(Number(BigInt(i)-BigInt(u))/1e6),ve={Agent:"AGENT",Task:"AGENT"}[n]??"TOOL";o.toolCalls.push({tool:n,brief:Sa(d,60),error:T,durationMs:Se}),o.spans.push({traceId:o.traceId,spanId:I,parentSpanId:o.spanId,name:n,kind:3,startTimeUnixNano:u,endTimeUnixNano:i,attributes:ha($(fe.OBS_NAME,n),$(fe.OBS_TYPE,ve),$(fe.OBS_LEVEL,O),$(fe.OBS_INPUT,Xn(l)),$(fe.OBS_OUTPUT,h),$("tool.name",n),$("tool.error",String(T))),status:{code:T?2:1}}),o.pendingTool=null,fa(t,o),Wn("PostToolUse",`sid=${t}`,`tool=${n}`,`error=${T}`,`durationMs=${Se}`,`totalSpans=${o.spans.length}`),Vn(e);}zn.exports={onPostToolUse:wa};});var es=p((Ec,Qn)=>{var ct={"claude-opus-4-6":{input:15,output:75},"claude-opus-4-5":{input:15,output:75},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:.8,output:4},"claude-4-6-opus":{input:15,output:75},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:15,output:75},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:.8,output:4},"claude-3-5-sonnet-20241022":{input:3,output:15},"claude-3-5-haiku-20241022":{input:.8,output:4},"claude-3-opus-20240229":{input:15,output:75}};function ga(e,t,n){let s=Object.keys(ct).find(i=>(e||"").toLowerCase().includes(i));if(!s)return;let r=ct[s],o=(t*r.input+n*r.output)/1e6;return Math.round(o*1e6)/1e6}Qn.exports={MODEL_PRICING:ct,calcCostUsd:ga};});var os=p((wc,rs)=>{var{generateSpanId:ts,nowNs:_a}=ue(),{loadState:ma,deleteState:ns}=le(),{LF:E,a:f,attrs:Ie,buildPayload:ya,postToLangfuse:Oa}=it(),{getIdentityFromToken:Aa}=P(),{calcCostUsd:La}=es(),{readLastAssistantOutput:Na}=st(),{truncate:ke,firstLine:Ia,passthrough:ut}=K(),{dbg:J}=C(),{detectExecutionStatus:ka}=Ne(),{sanitize:ss}=at(),{TRACE_LIMITS:Ce}=w();async function Ca(e){let t=e.session_id||"unknown",n=e.stop_reason||"end_turn",s=ma(t);if(!s){ut(e);return}s.slashSkill&&!/^[a-z][a-z0-9-]*$/i.test(s.slashSkill)&&(J("Stop",`sid=${t}`,`slashSkill rejected post-disk: "${s.slashSkill}"`),s.slashSkill=null);let r=_a(),o=await Aa();if(s.slashSkill&&!s.toolCalls.some(S=>S.tool==="Skill")){let S=ts(),X=s.skillContent?s.skillContent:JSON.stringify({skill:s.slashSkill});s.toolCalls.push({tool:"Skill",brief:s.slashSkill,error:false,durationMs:0,synthetic:true}),s.spans.push({traceId:s.traceId,spanId:S,parentSpanId:s.spanId,name:"Skill",kind:3,startTimeUnixNano:s.startNs,endTimeUnixNano:s.startNs,attributes:Ie(f(E.OBS_NAME,"Skill"),f(E.OBS_TYPE,"TOOL"),f(E.OBS_LEVEL,"DEFAULT"),f(E.OBS_INPUT,X),f(E.OBS_OUTPUT,"loaded via slash command"),f("tool.name","Skill"),f("tool.error","false"),f("skill.name",s.slashSkill),f("skill.invocation","slash-command")),status:{code:1}}),J("Stop",`slashSkill=${s.slashSkill}`,"synthetic span injected");}let i=e.transcript_path||s.transcriptPath||"",a=Na(i),u=s.toolCalls.length,d=s.toolCalls.filter(S=>S.error).length,l=ss(a?.text?ke(a.text,Ce.TRACE_OUTPUT):u===0?"No tools used":s.toolCalls.map((S,X)=>`${X+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""}`).join(`
130
- `)),h=a?.inputTokens??0,T=a?.outputTokens??0,O=s.toolCalls.map((S,X)=>`${X+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""} (${S.durationMs}ms)`),I=!!(s.slashSkill||s.toolCalls.some(S=>S.tool==="Skill")),Se=s.toolCalls.some(S=>S.tool==="Agent");if(!I&&!Se){J("Stop",`sid=${t}`,"skipping trace \u2014 no Skill or Agent calls found"),ns(t),ut(e);return}let Te=I?"skill":"agent",ve=Math.round(Number(BigInt(r)-BigInt(s.startNs))/1e6),R=La(s.model,h,T),k=ka(s);k==="prerequisite_required"&&(s.spans.push({traceId:s.traceId,spanId:ts(),parentSpanId:s.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:s.startNs,endTimeUnixNano:r,attributes:Ie(f(E.OBS_NAME,"prerequisite-check"),f(E.OBS_TYPE,"EVENT"),f(E.OBS_LEVEL,"WARNING"),f(E.OBS_OUTPUT,l),f("skill.name",s.slashSkill||void 0),f("execution_status","prerequisite_required")),status:{code:1}}),J("Stop",`sid=${t}`,"prerequisite-check span injected",`skill=${s.slashSkill}`));let lt=(()=>{if(!(!I||!s.prompt)){if(s.slashSkill){let S=s.prompt.replace(new RegExp(`^\\/${s.slashSkill}\\s*`,"i"),"").trim();return S?ke(S,Ce.USER_INSTRUCTION):void 0}return ke(s.prompt,Ce.USER_INSTRUCTION)||void 0}})(),as=JSON.stringify({trace_type:Te,...k!==null&&{execution_status:k},...s.slashSkill&&{skill_name:s.slashSkill},...s.skillArtifacts?.length&&{skill_artifacts:s.skillArtifacts},...lt!==void 0&&{user_instruction:lt},latency_ms:ve,...h&&{tokens_input:h},...T&&{tokens_output:T},cost_usd:R,...s.model&&{model:s.model},toolCount:u,errorCount:d,stopReason:n,sessionId:s.sessionId,tools:O.length?O:void 0}),cs=ss(ke(s.prompt,Ce.TRACE_INPUT)),us=Ie(f(E.TRACE_NAME,s.traceName),f(E.TRACE_INPUT,cs),f(E.TRACE_OUTPUT,l),f(E.TRACE_METADATA,as),f(E.SESSION_ID,s.sessionId),f(E.USER_ID,o.user),f(E.OBS_TYPE,"GENERATION"),f(E.MODEL,s.model),h?f(E.INPUT_TOKENS,h):null,T?f(E.OUTPUT_TOKENS,T):null,f("claude.stop_reason",n),f("claude.tool_count",String(u)),f("claude.error_count",String(d)),f("claude.session_id",s.sessionId),f("flow.trace_type",Te),{key:E.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:Te}]}}}),ls={traceId:s.traceId,spanId:s.spanId,name:s.traceName,kind:1,startTimeUnixNano:s.startNs,endTimeUnixNano:r,attributes:us,status:{code:d>0?2:1}},ds=Ie(f("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),f("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),dt=[...s.spans||[],ls];J("Stop",`sid=${t}`,`totalTools=${u}`,`errorTools=${d}`,`spans=${dt.length}`,`inputTokens=${h}`,`outputTokens=${T}`,`traceOutput="${Ia(l,80)}"`);let ps=await Oa(ya(ds,dt));J("Stop",`POST status=${ps}`,`traceId=${s.traceId}`),ns(t),ut(e);}rs.exports={onStop:Ca};});var is=p(()=>{var{credentialsAvailable:va}=P(),{readInput:ba}=K(),{onUserPromptSubmit:Ua}=bn(),{onPreToolUse:Ra}=Rn(),{onPostToolUse:Pa}=Zn(),{onStop:$a}=os();async function qa(){let e=process.argv[2];if(!await va()){let n=[];process.stdin.on("data",s=>n.push(s)),process.stdin.on("end",()=>process.stdout.write(n.join("")));return}let t=await ba();switch(e){case "UserPromptSubmit":await Ua(t);break;case "PreToolUse":await Ra(t);break;case "PostToolUse":await Pa(t);break;case "Stop":await $a(t);break;default:process.stderr.write(`[flow-obs] unknown event: ${e}
131
- `),process.stdout.write(JSON.stringify(t));}}qa().catch(e=>{process.stderr.write(`[flow-obs] fatal: ${e.message}
132
- `),process.exit(0);});});var Fa=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,N,he]=process.argv;if(N==="--version"||N==="-v"){let{version:e}=Ee();process.stdout.write(e+`
133
- `),process.exit(0);}else if(N==="--help"||N==="-h"){let{bold:e,cyan:t,dim:n}=F(),{version:s}=Ee();process.stdout.write(`
130
+ `),bn("UserPromptSubmit","auth expired \u2014 warning emitted to stderr"));}catch{}let o=Oi(e.transcript_path)||vn(),r=Ni(n),i=r?Ii(r,s):null,a=r?ki(r,s):null;Li(t,{traceId:vn(),spanId:yi(),startNs:Ai(),sessionId:t,prompt:n,cwd:s,traceName:o,transcriptPath:e.transcript_path||"",model:process.env[vi.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:r,skillContent:i,skillArtifacts:a}),bn("UserPromptSubmit",`sid=${t}`,`traceName=${o}`,`slashSkill=${r}`),Ci(e);}Un.exports={onUserPromptSubmit:Ui};});var Fn=l((Tc,Pn)=>{var{nowNs:Ri}=le(),{loadState:Pi,saveState:Fi}=de(),{truncate:$i,passthrough:qi}=V(),{dbg:xi}=C(),{TRACE_LIMITS:Mi}=w();async function Di(e){let t=e.session_id||"unknown",n=e.tool_name||"unknown",s=e.tool_input||{},o=Pi(t);o&&(o.pendingTool={name:n,inputStr:$i(s,Mi.TOOL_INPUT),startNs:Ri()},Fi(t,o)),xi("PreToolUse",`sid=${t}`,`tool=${n}`,`stateFound=${!!o}`),qi(e);}Pn.exports={onPreToolUse:Di};});var xn=l((Sc,qn)=>{var Bi=c("https"),Hi=c("http"),{FLOW_URLS:Yi}=w();function ji(e){let t=new URL(e),n=new URL(Yi.GATEWAY_HEALTH);return n.hostname=t.hostname,n.port=t.port,n.protocol=t.protocol,n}function $n(e,t){return new Promise((n,s)=>{let o=e._isSSL?Bi:Hi;e.headers=Object.assign({},e.headers,{Connection:"close"});let r=o.request(e,i=>{let a=[];i.on("data",u=>a.push(u)),i.on("end",()=>n({statusCode:i.statusCode,body:a.join("")}));});r.setTimeout(1e4,()=>{r.destroy(new Error("Request timeout"));}),r.on("error",i=>s(new Error(`Network error: ${i.message}`))),t&&r.write(t),r.end();})}async function Gi(e,t){let n;try{n=ji(e);}catch{return false}let s=n.protocol==="https:",o={};t&&(o.Authorization=String(t).replace(/[\r\n]/g,""));try{let r=await $n({hostname:n.hostname,port:n.port||(s?443:80),path:n.pathname,method:"GET",headers:o,_isSSL:s},null);return r.statusCode>=200&&r.statusCode<300}catch{return false}}async function Ki(e,t,n){let s=JSON.stringify(e),o=new URL(t),r=o.protocol==="https:",i=String(n).replace(/[\r\n]/g,"");try{return (await $n({hostname:o.hostname,port:o.port||(r?443:80),path:o.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(s)},_isSSL:r},s)).statusCode}catch{return 0}}qn.exports={checkHealth:Gi,sendTraces:Ki};});var Yn=l((Ec,Hn)=>{var R=c("fs"),rt=c("path"),Mn=c("os"),{BUFFER:U,ENV:Dn}=w(),{dbg:pe}=C();function Wi(){let e=parseInt(process.env[Dn.BUFFER_TTL_DAYS],10);return (Number.isFinite(e)?Math.max(U.MIN_TTL_DAYS,Math.min(U.MAX_TTL_DAYS,e)):U.DEFAULT_TTL_DAYS)*24*60*60*1e3}function Vi(){let e=parseInt(process.env[Dn.BUFFER_MAX_FILES],10);return Number.isFinite(e)?Math.max(U.MIN_MAX_FILES,Math.min(U.MAX_MAX_FILES,e)):U.DEFAULT_MAX_FILES}function Bn(e){if(/[/\\]/.test(e))throw new Error(`Invalid buffer fileId: ${e}`);return rt.join(Mn.tmpdir(),`${U.FILE_PREFIX}${e}.json`)}function ot(){let e=Mn.tmpdir(),t;try{t=R.readdirSync(e);}catch{return []}return t.filter(n=>n.startsWith(U.FILE_PREFIX)&&n.endsWith(".json")).map(n=>{let s=rt.join(e,n),o=0;try{o=R.statSync(s).mtimeMs;}catch{}return {full:s,mtime:o}}).sort((n,s)=>n.mtime-s.mtime).map(n=>n.full)}function Ji(e){try{let t=Vi(),n=ot();if(n.length>=t){let r=n.slice(0,n.length-t+1);for(let i of r)try{R.unlinkSync(i);}catch{}}let s=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,o={fileId:s,bufferedAt:Date.now(),payload:e};return R.writeFileSync(Bn(s),JSON.stringify(o),{encoding:"utf8",mode:384}),pe("buffer",`saved fileId=${s}`),s}catch(t){return pe("buffer",`saveToBuffer failed: ${t.message}`),null}}function Xi(e){let t=ot(),n=e!=null&&e>0?e:t.length,s=[];for(let o of t){if(s.length>=n)break;try{let r=R.readFileSync(o,"utf8"),i=JSON.parse(r);i&&i.fileId&&i.payload&&s.push(i);}catch{pe("buffer",`skipping malformed file: ${o}`);}}return s}function zi(e){try{R.unlinkSync(Bn(e)),pe("buffer",`deleted fileId=${e}`);}catch{}}function Zi(){let e=Date.now()-Wi();for(let t of ot())try{let{mtimeMs:n}=R.statSync(t);n<e&&(R.unlinkSync(t),pe("buffer",`evicted stale: ${rt.basename(t)}`));}catch{}}Hn.exports={saveToBuffer:Ji,loadBuffer:Xi,deleteBuffer:zi,cleanStaleBuffers:Zi};});var at=l((wc,Gn)=>{var{resolveCredentials:Qi}=$(),{OTLP:jn,BUFFER:ea}=w(),{dbg:P}=C(),{checkHealth:ta,sendTraces:it}=xn(),{saveToBuffer:Ne,loadBuffer:na,deleteBuffer:sa,cleanStaleBuffers:ra}=Yn(),oa={name:jn.SCOPE_NAME,version:jn.SCOPE_VERSION},ia={TRACE_NAME:"langfuse.trace.name",TRACE_INPUT:"langfuse.trace.input",TRACE_OUTPUT:"langfuse.trace.output",TRACE_METADATA:"langfuse.trace.metadata",TRACE_TAGS:"langfuse.trace.tags",USER_ID:"langfuse.user.id",SESSION_ID:"langfuse.session.id",OBS_NAME:"langfuse.observation.name",OBS_INPUT:"langfuse.observation.input",OBS_OUTPUT:"langfuse.observation.output",OBS_LEVEL:"langfuse.observation.level",OBS_TYPE:"langfuse.observation.type",MODEL:"gen_ai.request.model",INPUT_TOKENS:"gen_ai.usage.input_tokens",OUTPUT_TOKENS:"gen_ai.usage.output_tokens"};function aa(e,t){return t==null||t===""?null:{key:e,value:{stringValue:String(t)}}}function ca(...e){return e.filter(Boolean)}function ua(e,t){return {resourceSpans:[{resource:{attributes:e},scopeSpans:[{scope:oa,spans:Array.isArray(t)?t:[t]}]}]}}async function la(e){ra();let t=na(ea.REPLAY_BATCH_SIZE);t.length&&(P("replayBufferedTraces",`replaying ${t.length} buffered trace(s)`),await Promise.allSettled(t.map(async n=>{try{let s=await it(n.payload,e.endpoint,e.authHeader);s>=200&&s<300?(sa(n.fileId),P("replayBufferedTraces",`replayed fileId=${n.fileId} status=${s}`)):P("replayBufferedTraces",`replay failed fileId=${n.fileId} status=${s}`);}catch(s){P("replayBufferedTraces",`replay error fileId=${n.fileId}: ${s.message}`);}})));}async function da(e){let t=await Qi();if(!t.length)return t.authError&&(P("postToLangfuse","auth refresh failed \u2014 buffering trace"),Ne(e)),0;let n=await Promise.all(t.map(async r=>{if(r.mode!=="gateway")return {creds:r,healthy:true};let i=await ta(r.endpoint,r.authHeader);return {creds:r,healthy:i}})),s=n.find(r=>r.creds.mode==="gateway"&&r.healthy)?.creds??n.find(r=>r.creds.mode==="direct")?.creds;return s&&await la(s),(await Promise.all(n.map(async({creds:r,healthy:i})=>{if(r.mode==="gateway"){if(!i)return P("postToLangfuse","gateway health check failed \u2014 buffering trace"),Ne(e),0;let u=await it(e,r.endpoint,r.authHeader);return (u===0||u>=500)&&(P("postToLangfuse",`gateway send failed (status ${u}) \u2014 buffering trace`),Ne(e)),u}let a=await it(e,r.endpoint,r.authHeader);return (a===0||a>=500)&&(P("postToLangfuse",`direct endpoint unavailable (status ${a}) \u2014 buffering trace`),Ne(e)),a}))).find(r=>r!==0)||0}Gn.exports={LF:ia,a:aa,attrs:ca,buildPayload:ua,postToLangfuse:da};});var ct=l((_c,Kn)=>{var g="[REDACTED]",pa=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${g}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${g}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(e,t)=>`${t}${g}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(e,t)=>`${t}${g}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(e,t,n)=>`${t}
131
+ ${g}
132
+ ${n}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${g}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(e,t)=>`${t}${g}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${g}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${g}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${g}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(e,t,n)=>`${t}${n}${g}${n}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(e,t)=>`${t}:${g}@`}];function fa(e){if(e==null)return "";let t=typeof e=="string"?e:JSON.stringify(e);return pa.reduce((n,{re:s,replace:o})=>n.replace(s,o),t)}Kn.exports={sanitize:fa,REDACTED:g};});var Qn=l((gc,Zn)=>{var{generateSpanId:ha,nowNs:Ta}=le(),{loadState:Sa,saveState:Ea}=de(),{LF:fe,a:q,attrs:wa}=at(),{truncate:Wn,firstLine:_a,passthrough:Vn}=V(),{readSkillContent:ga,readSkillArtifacts:ma}=Oe(),{dbg:Jn}=C(),{TRACE_LIMITS:Xn}=w(),{sanitize:zn}=ct();async function ya(e){let t=e.session_id||"unknown",n=e.tool_name||"unknown",s=e.tool_input||{},o=e.tool_response||"",r=Sa(t);if(!r){Vn(e);return}let i=Ta(),a=r.pendingTool?.name===n,u=a?r.pendingTool.startNs:String(BigInt(i)-200000000n),f=a?r.pendingTool.inputStr:Wn(s,Xn.TOOL_INPUT),d=f;if(n==="Skill"){let F=typeof s=="object"&&s!==null?s.skill||s.name||s.skillName||String(Object.values(s)[0]??""):String(s),k=F?ga(F.trim(),r.cwd):null;k&&(d=k,r.skillContent||(r.skillContent=k),r.slashSkill||(r.slashSkill=F.trim()),r.skillArtifacts||(r.skillArtifacts=ma(F.trim(),r.cwd))),Jn("PostToolUse","Skill tool detected",`skillName=${F}`,`contentFound=${!!k}`);}let h=zn(Wn(o,Xn.TOOL_OUTPUT)),S=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(h.slice(0,500)),L=S?"ERROR":"DEFAULT",I=ha(),Te=Math.round(Number(BigInt(i)-BigInt(u))/1e6),ve={Agent:"AGENT",Task:"AGENT"}[n]??"TOOL";r.toolCalls.push({tool:n,brief:_a(f,60),error:S,durationMs:Te}),r.spans.push({traceId:r.traceId,spanId:I,parentSpanId:r.spanId,name:n,kind:3,startTimeUnixNano:u,endTimeUnixNano:i,attributes:wa(q(fe.OBS_NAME,n),q(fe.OBS_TYPE,ve),q(fe.OBS_LEVEL,L),q(fe.OBS_INPUT,zn(d)),q(fe.OBS_OUTPUT,h),q("tool.name",n),q("tool.error",String(S))),status:{code:S?2:1}}),r.pendingTool=null,Ea(t,r),Jn("PostToolUse",`sid=${t}`,`tool=${n}`,`error=${S}`,`durationMs=${Te}`,`totalSpans=${r.spans.length}`),Vn(e);}Zn.exports={onPostToolUse:ya};});var ts=l((mc,es)=>{var ut={"claude-opus-4-6":{input:15,output:75},"claude-opus-4-5":{input:15,output:75},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:.8,output:4},"claude-4-6-opus":{input:15,output:75},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:15,output:75},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:.8,output:4},"claude-3-5-sonnet-20241022":{input:3,output:15},"claude-3-5-haiku-20241022":{input:.8,output:4},"claude-3-opus-20240229":{input:15,output:75}};function Aa(e,t,n){let s=Object.keys(ut).find(i=>(e||"").toLowerCase().includes(i));if(!s)return;let o=ut[s],r=(t*o.input+n*o.output)/1e6;return Math.round(r*1e6)/1e6}es.exports={MODEL_PRICING:ut,calcCostUsd:Aa};});var is=l((yc,os)=>{var{generateSpanId:ns,nowNs:La}=le(),{loadState:Oa,deleteState:ss}=de(),{LF:E,a:p,attrs:Ie,buildPayload:Na,postToLangfuse:Ia}=at(),{getIdentityFromToken:ka}=$(),{calcCostUsd:Ca}=ts(),{readLastAssistantOutput:va}=st(),{truncate:ke,firstLine:ba,passthrough:lt}=V(),{dbg:X}=C(),{detectExecutionStatus:Ua}=Oe(),{sanitize:rs}=ct(),{TRACE_LIMITS:Ce}=w();async function Ra(e){let t=e.session_id||"unknown",n=e.stop_reason||"end_turn",s=Oa(t);if(!s){lt(e);return}s.slashSkill&&!/^[a-z][a-z0-9-]*$/i.test(s.slashSkill)&&(X("Stop",`sid=${t}`,`slashSkill rejected post-disk: "${s.slashSkill}"`),s.slashSkill=null);let o=La(),r=await ka();if(s.slashSkill&&!s.toolCalls.some(T=>T.tool==="Skill")){let T=ns(),z=s.skillContent?s.skillContent:JSON.stringify({skill:s.slashSkill});s.toolCalls.push({tool:"Skill",brief:s.slashSkill,error:false,durationMs:0,synthetic:true}),s.spans.push({traceId:s.traceId,spanId:T,parentSpanId:s.spanId,name:"Skill",kind:3,startTimeUnixNano:s.startNs,endTimeUnixNano:s.startNs,attributes:Ie(p(E.OBS_NAME,"Skill"),p(E.OBS_TYPE,"TOOL"),p(E.OBS_LEVEL,"DEFAULT"),p(E.OBS_INPUT,z),p(E.OBS_OUTPUT,"loaded via slash command"),p("tool.name","Skill"),p("tool.error","false"),p("skill.name",s.slashSkill),p("skill.invocation","slash-command")),status:{code:1}}),X("Stop",`slashSkill=${s.slashSkill}`,"synthetic span injected");}let i=e.transcript_path||s.transcriptPath||"",a=va(i),u=s.toolCalls.length,f=s.toolCalls.filter(T=>T.error).length,d=rs(a?.text?ke(a.text,Ce.TRACE_OUTPUT):u===0?"No tools used":s.toolCalls.map((T,z)=>`${z+1}. ${T.tool}${T.brief?` \u2192 ${T.brief}`:""}${T.error?" [ERROR]":""}`).join(`
133
+ `)),h=a?.inputTokens??0,S=a?.outputTokens??0,L=s.toolCalls.map((T,z)=>`${z+1}. ${T.tool}${T.brief?` \u2192 ${T.brief}`:""}${T.error?" [ERROR]":""} (${T.durationMs}ms)`),I=!!(s.slashSkill||s.toolCalls.some(T=>T.tool==="Skill")),Te=s.toolCalls.some(T=>T.tool==="Agent");if(!I&&!Te){X("Stop",`sid=${t}`,"skipping trace \u2014 no Skill or Agent calls found"),ss(t),lt(e);return}let Se=I?"skill":"agent",ve=Math.round(Number(BigInt(o)-BigInt(s.startNs))/1e6),F=Ca(s.model,h,S),k=Ua(s);k==="prerequisite_required"&&(s.spans.push({traceId:s.traceId,spanId:ns(),parentSpanId:s.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:s.startNs,endTimeUnixNano:o,attributes:Ie(p(E.OBS_NAME,"prerequisite-check"),p(E.OBS_TYPE,"EVENT"),p(E.OBS_LEVEL,"WARNING"),p(E.OBS_OUTPUT,d),p("skill.name",s.slashSkill||void 0),p("execution_status","prerequisite_required")),status:{code:1}}),X("Stop",`sid=${t}`,"prerequisite-check span injected",`skill=${s.slashSkill}`));let dt=(()=>{if(!(!I||!s.prompt)){if(s.slashSkill){let T=s.prompt.replace(new RegExp(`^\\/${s.slashSkill}\\s*`,"i"),"").trim();return T?ke(T,Ce.USER_INSTRUCTION):void 0}return ke(s.prompt,Ce.USER_INSTRUCTION)||void 0}})(),cs=JSON.stringify({trace_type:Se,...k!==null&&{execution_status:k},...s.slashSkill&&{skill_name:s.slashSkill},...s.skillArtifacts?.length&&{skill_artifacts:s.skillArtifacts},...dt!==void 0&&{user_instruction:dt},latency_ms:ve,...h&&{tokens_input:h},...S&&{tokens_output:S},cost_usd:F,...s.model&&{model:s.model},toolCount:u,errorCount:f,stopReason:n,sessionId:s.sessionId,tools:L.length?L:void 0}),us=rs(ke(s.prompt,Ce.TRACE_INPUT)),ls=Ie(p(E.TRACE_NAME,s.traceName),p(E.TRACE_INPUT,us),p(E.TRACE_OUTPUT,d),p(E.TRACE_METADATA,cs),p(E.SESSION_ID,s.sessionId),p(E.USER_ID,r.user),p(E.OBS_TYPE,"GENERATION"),p(E.MODEL,s.model),h?p(E.INPUT_TOKENS,h):null,S?p(E.OUTPUT_TOKENS,S):null,p("claude.stop_reason",n),p("claude.tool_count",String(u)),p("claude.error_count",String(f)),p("claude.session_id",s.sessionId),p("flow.trace_type",Se),{key:E.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:Se}]}}}),ds={traceId:s.traceId,spanId:s.spanId,name:s.traceName,kind:1,startTimeUnixNano:s.startNs,endTimeUnixNano:o,attributes:ls,status:{code:f>0?2:1}},ps=Ie(p("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),p("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),pt=[...s.spans||[],ds];X("Stop",`sid=${t}`,`totalTools=${u}`,`errorTools=${f}`,`spans=${pt.length}`,`inputTokens=${h}`,`outputTokens=${S}`,`traceOutput="${ba(d,80)}"`);let fs=await Ia(Na(ps,pt));X("Stop",`POST status=${fs}`,`traceId=${s.traceId}`),ss(t),lt(e);}os.exports={onStop:Ra};});var as=l(()=>{var{credentialsAvailable:Pa}=$(),{readInput:Fa}=V(),{onUserPromptSubmit:$a}=Rn(),{onPreToolUse:qa}=Fn(),{onPostToolUse:xa}=Qn(),{onStop:Ma}=is();async function Da(){let e=process.argv[2];if(!await Pa()){let n=[];process.stdin.on("data",s=>n.push(s)),process.stdin.on("end",()=>process.stdout.write(n.join("")));return}let t=await Fa();switch(e){case "UserPromptSubmit":await $a(t);break;case "PreToolUse":await qa(t);break;case "PostToolUse":await xa(t);break;case "Stop":await Ma(t);break;default:process.stderr.write(`[flow-obs] unknown event: ${e}
134
+ `),process.stdout.write(JSON.stringify(t));}}Da().catch(e=>{process.stderr.write(`[flow-obs] fatal: ${e.message}
135
+ `),process.exit(0);});});var Ba=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,N,he]=process.argv;if(N==="--version"||N==="-v"){let{version:e}=Ee();process.stdout.write(e+`
136
+ `),process.exit(0);}else if(N==="--help"||N==="-h"){let{bold:e,cyan:t,dim:n}=M(),{version:s}=Ee();process.stdout.write(`
134
137
  `+e(" flow-ai-obs")+n(" v"+s)+`
135
138
 
136
139
  `),process.stdout.write(t(" install")+n(` Auth (if needed) + hooks + native OTEL
@@ -146,11 +149,11 @@ ${n}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${_}`},{re:/(aws_secret_ac
146
149
  `)),process.stdout.write(n(` (Hook events: UserPromptSubmit | PreToolUse | PostToolUse | Stop)
147
150
 
148
151
  `)),process.exit(0);}else if(N==="install"){we().checkForUpdate();let{runInstall:e}=et();e().then(t=>process.exit(t)).catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
149
- `),process.exit(1);});}else if(N==="setup"){we().checkForUpdate();let{runSetup:e}=cn(),t=process.argv.slice(3),n=s=>{let r=t.indexOf(s);return r!==-1?t[r+1]:void 0};e({clientId:n("--client-id"),clientSecret:n("--client-secret"),tenant:n("--tenant")}).then(s=>process.exit(s)).catch(s=>{process.stderr.write(`Unexpected error: ${s.message}
150
- `),process.exit(1);});}else if(N==="auth"){we().checkForUpdate();let{runLogin:e,runLogout:t,runStatus:n}=ae();(async()=>{let s=0;if(he==="login"||!he){let r=process.argv.slice(4),o=i=>{let a=r.indexOf(i);return a!==-1?r[a+1]:void 0};s=await e({clientId:o("--client-id"),clientSecret:o("--client-secret"),tenant:o("--tenant")});}else if(he==="logout"){let r=process.argv.includes("--force");s=await t(r);}else he==="status"?s=await n():(process.stderr.write(`Unknown auth subcommand: ${he}
152
+ `),process.exit(1);});}else if(N==="setup"){we().checkForUpdate();let{runSetup:e}=ln(),t=process.argv.slice(3),n=s=>{let o=t.indexOf(s);return o!==-1?t[o+1]:void 0};e({clientId:n("--client-id"),clientSecret:n("--client-secret"),tenant:n("--tenant")}).then(s=>process.exit(s)).catch(s=>{process.stderr.write(`Unexpected error: ${s.message}
153
+ `),process.exit(1);});}else if(N==="auth"){we().checkForUpdate();let{runLogin:e,runLogout:t,runStatus:n}=ce();(async()=>{let s=0;if(he==="login"||!he){let o=process.argv.slice(4),r=i=>{let a=o.indexOf(i);return a!==-1?o[a+1]:void 0};s=await e({clientId:r("--client-id"),clientSecret:r("--client-secret"),tenant:r("--tenant")});}else if(he==="logout"){let o=process.argv.includes("--force");s=await t(o);}else he==="status"?s=await n():(process.stderr.write(`Unknown auth subcommand: ${he}
151
154
  `),process.stderr.write(`Usage: flow-ai-obs auth [login|logout|status]
152
- `),s=1);process.exit(s);})();}else if(N==="otel-headers"){let{runOtelHeaders:e}=ln();e().then(t=>process.exit(t)).catch(()=>process.exit(1));}else if(N==="check"){let{runCheck:e}=Sn();e().then(t=>process.exit(t)).catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
153
- `),process.exit(1);});}else if(Fa.has(N))is();else {let{bold:e,cyan:t,dim:n}=F();process.stdout.write(`
155
+ `),s=1);process.exit(s);})();}else if(N==="otel-headers"){let{runOtelHeaders:e}=pn();e().then(t=>process.exit(t)).catch(()=>process.exit(1));}else if(N==="check"){let{runCheck:e}=En();e().then(t=>process.exit(t)).catch(t=>{process.stderr.write(`Unexpected error: ${t.message}
156
+ `),process.exit(1);});}else if(Ba.has(N))as();else {let{bold:e,cyan:t,dim:n}=M();process.stdout.write(`
154
157
  `+e(" flow-ai-obs")+`
155
158
 
156
159
  `),process.stdout.write(t(" install")+n(` Auth (if needed) + hooks + native OTEL
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
- 'use strict';var i=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var _=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var h=_((to,Re)=>{var k=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",ke={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${k}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${k}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${k}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${k}/otel`},jt={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},zt="FLOW-nodejs",Xt="config.json",Zt={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},Qt={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL||`${k}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL||"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL||"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"},en={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:ke.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},tn={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP"},nn={KEYCHAIN_ENABLED:false},rn={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},sn={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},on={FILE_PREFIX:"flow-obs-buffer-",MAX_AGE_MS:5760*60*1e3,MAX_FILES:50},an="flow-ai-obs-debug.log",cn={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},ln="flow-obs-";Re.exports={FLOW_BASE_URL:k,FLOW_URLS:ke,VAULT:jt,CONFIG_DIR_NAME:zt,CONFIG_FILE_NAME:Xt,OTLP:Zt,LLM_PROXY:Qt,NATIVE_OTEL:en,ENV:tn,FEATURES:nn,INSTALLER:rn,HOOK_TIMEOUTS:sn,BUFFER:on,DEBUG_LOG_FILENAME:an,STATE_FILE_PREFIX:ln,TRACE_LIMITS:cn};});var Pe=_((no,Ue)=>{var D=i("fs"),R=i("path"),un=i("os"),{CONFIG_DIR_NAME:ne,CONFIG_FILE_NAME:re}=h(),se={credentials:"credentials","token-cache":"tokenCache"};function B(){let e=un.homedir();if(process.platform==="darwin")return R.join(e,"Library","Preferences",ne,re);if(process.platform==="win32"){let r=process.env.APPDATA||R.join(e,"AppData","Roaming");return R.join(r,ne,re)}let t=process.env.XDG_CONFIG_HOME||R.join(e,".config");return R.join(t,ne,re)}function oe(){try{let e=D.readFileSync(B(),"utf8");return JSON.parse(e)}catch{return {}}}function Ce(e){let t=B();D.mkdirSync(R.dirname(t),{recursive:true}),D.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var j=class{static isAvailable(){return true}static hasExistingData(){try{if(!D.existsSync(B()))return !1;let t=JSON.parse(D.readFileSync(B(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,r){let n=oe(),s=se[r]||r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,r,n){let s=oe(),o=se[r]||r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;Ce(s);}async deleteSecret(t,r){let n=oe(),s=se[r]||r;return s in n?(delete n[s],Ce(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${B()}`}};function dn(){}var pn=j;Ue.exports={JsonFallbackProvider:j,ScryptFallbackProvider:pn,_resetWarningState:dn};});var $e=_((ro,be)=>{var{execFile:fn}=i("child_process"),{promisify:_n}=i("util"),{accessSync:Sn,constants:En}=i("fs"),ae=_n(fn),ie=class{static async isAvailable(){try{return Sn("/usr/bin/security",En.X_OK),!0}catch{return false}}async getSecret(t,r){try{let{stdout:n}=await ae("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await ae("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await ae("security",["delete-generic-password","-a",r,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};be.exports={MacOsKeyVaultProvider:ie};});var Fe=_((so,qe)=>{var{execFile:Tn,spawn:hn}=i("child_process"),{promisify:On}=i("util"),{accessSync:gn,constants:An}=i("fs"),ve=On(Tn),ce=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of t)try{return gn(r,An.X_OK),!0}catch{}return false}async getSecret(t,r){try{let{stdout:n}=await ve("secret-tool",["lookup","service",t,"account",r]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await new Promise((s,o)=>{let a=hn("secret-tool",["store","--label",t,"service",t,"account",r]);a.on("error",o),a.on("close",l=>{l===0?s():o(new Error(`secret-tool exited with code ${l}`));}),a.stdin.write(n),a.stdin.end();});}async deleteSecret(t,r){try{return await ve("secret-tool",["clear","service",t,"account",r]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};qe.exports={LinuxKeyVaultProvider:ce};});var De=_((oo,Be)=>{var le=class{static async isAvailable(){try{return await i("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,r){return i("keytar").getPassword(t,r)}async setSecret(t,r,n){await i("keytar").setPassword(t,r,n);}async deleteSecret(t,r){return i("keytar").deletePassword(t,r)}getStoragePath(){return "Windows Credential Manager"}};Be.exports={WindowsKeyVaultProvider:le};});var He=_((ao,xe)=>{async function Me(){let{JsonFallbackProvider:e}=Pe();return await yn()??new e}async function yn(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=$e();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=Fe();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=De();return await e.isAvailable()?new e:null}default:return null}}var Ln=Me;xe.exports={createSecretVaultProvider:Me,createKeyVaultProvider:Ln};});var Ye=_((io,We)=>{var{createSecretVaultProvider:mn}=He(),{VAULT:de}=h(),C=de.SERVICE,pe=de.ACCOUNT_CREDS,fe=de.ACCOUNT_TOKEN,ue=null;function U(){return ue||(ue=mn()),ue}async function Ge(){let t=await(await U()).getSecret(C,pe);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function Nn(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await U()).setSecret(C,pe,JSON.stringify(e));}async function In(){let e=await U();await e.deleteSecret(C,pe),await e.deleteSecret(C,fe);}async function wn(e){await(await U()).setSecret(C,fe,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function _e(){let t=await(await U()).getSecret(C,fe);if(!t)return null;try{let r=JSON.parse(t);return {accessToken:r.accessToken,expiresAt:r.expiresAt}}catch{return null}}async function kn(){let e=await _e();return e?new Date(e.expiresAt)>new Date:false}async function Rn(){let e=await _e();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let r=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email||r.preferred_username||r.upn||r.sub||null}catch{return null}}async function Cn(){let e=await U();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function Un(){let e=await Ge();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}We.exports={getFlowCredentials:Ge,saveFlowCredentials:Nn,clearFlowCredentials:In,saveTokenCache:wn,getTokenCache:_e,isTokenValid:kn,getEmailFromToken:Rn,getConfigPath:Cn,hasCredentials:Un};});var Ve=_((co,Je)=>{var Pn=i("https"),bn=i("http"),{FLOW_URLS:$n}=h(),vn=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function qn(e){if(!vn.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var Ke={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function Fn(e,t){try{let r=JSON.parse(t);if(typeof r.error=="string"&&Ke[r.error])return new Error(Ke[r.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function Bn(e){return new Promise((t,r)=>{try{qn(e.tenant);}catch(u){return r(u)}let n=JSON.stringify({clientSecret:e.clientSecret}),s=new URL($n.AUTH_ENGINE),o=s.protocol==="https:",a={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:e.tenant}},p=(o?Pn:bn).request(a,u=>{let d=[];u.on("data",f=>d.push(f)),u.on("end",()=>{let f=d.join("");if(u.statusCode>=400)return r(Fn(u.statusCode,f));let E;try{E=JSON.parse(f);}catch{return r(new Error("Invalid response from auth engine"))}let g=E.expires_at??new Date(Date.now()+(E.expires_in??3600)*1e3).toISOString();t({accessToken:E.access_token,expiresAt:g});});});p.on("error",u=>r(new Error(`Network error: ${u.message}`))),p.write(n),p.end();})}Je.exports={getToken:Bn};});var m=_((lo,ze)=>{var{writeFileSync:Dn}=i("fs"),{tmpdir:Mn}=i("os"),{join:xn}=i("path"),{DEBUG_LOG_FILENAME:Hn,ENV:Gn}=h(),je=xn(Mn(),Hn);function Wn(...e){if(process.env[Gn.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
2
- `;try{Dn(je,t,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
3
- `);}}ze.exports={dbg:Wn,DEBUG_LOG:je};});var x=_((uo,Ze)=>{var{getFlowCredentials:Se,isTokenValid:Yn,getEmailFromToken:M,getTokenCache:Kn,saveTokenCache:Jn}=Ye(),{getToken:Vn}=Ve(),{FLOW_BASE_URL:jn,ENV:A,FEATURES:Ee}=h(),{dbg:P}=m(),zn=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function Xn(e){return zn.some(t=>t.test(e))}function z(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let r=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:s,tenant:o}=r;return !n||!s||!o?null:{clientId:n,clientSecret:s,tenant:o}}catch{return null}}function Zn(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${r}.`}function Te(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}if(!(process.env[A.FLOW_OBS_ALLOW_HTTP]==="true")&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(Xn(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function Qn(){let e=z(process.env[A.ANTHROPIC_AUTH_TOKEN]);if(e)return {user:await M().catch(()=>null)||e.clientId,tenant:e.tenant};if(Ee.KEYCHAIN_ENABLED)try{let t=await Se();if(!t)return {user:"",tenant:""};let r=await M()||t.clientId||"",n=t.tenant||"";return {user:r,tenant:n}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function er(e){if(await Yn())return (await Kn()).accessToken;P("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Vn(e);return await Jn(t),P("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function tr(e,t){let r=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/langfuse/traces",authHeader:`Bearer ${r}`}}function nr(e,t,r){let n=Buffer.from(`${t}:${r}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${n}`}}async function Xe(){let e=[],t=process.env[A.ANTHROPIC_MODEL]||"",r=process.env[A.FLOW_TELEMETRY]==="true",n=process.env[A.LANGFUSE_BASE_URL],s=process.env[A.LANGFUSE_PUBLIC_KEY],o=process.env[A.LANGFUSE_SECRET_KEY];if(r&&n&&s&&o){let d="",f="",E=z(process.env[A.ANTHROPIC_AUTH_TOKEN]);if(E)d=await M().catch(()=>null)||E.clientId,f=E.tenant;else if(Ee.KEYCHAIN_ENABLED)try{let y=await Se();y&&(d=await M()||y.clientId,f=y.tenant);}catch{}let g={user:d||"",tenant:f||"",team:"",project:"",model:t};e.push({mode:"direct",...nr(Te(n),s,o),...g}),P("resolveCredentials","direct mode active",`user=${g.user}`,`tenant=${g.tenant}`);}let a=z(process.env[A.ANTHROPIC_AUTH_TOKEN]);if(P("resolveCredentials",a?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!a&&Ee.KEYCHAIN_ENABLED&&(a=await Se(),a&&P("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)")),!a){if(e.length===0){let d=[];return d.authError=false,d}return e}let l;try{l=await er(a);}catch(d){if(P("resolveCredentials",`token refresh failed: ${d.message}`),e.length>0)return e;let f=[];return f.authError=true,f}let p={user:await M()||a.clientId,tenant:a.tenant,team:"",project:"",model:t},u=process.env[A.FLOW_TELEMETRY_GATEWAY]||jn;return e.push({mode:"gateway",...tr(Te(u),{accessToken:l}),...p}),e}async function rr(){return (await Xe()).length>0}Ze.exports={credentialsAvailable:rr,getIdentityFromToken:Qn,resolveCredentials:Xe,validateUrl:Te,parseCredsFromAnthropicToken:z,buildAnthropicAuthToken:Zn};});var b=_((po,Qe)=>{function sr(e,t){let r=typeof e=="object"?JSON.stringify(e):String(e??"");return r.length>t?r.slice(0,t)+" \u2026[truncated]":r}function or(e,t=100){return String(e??"").split(`
4
- `)[0].slice(0,t).trim()}function ar(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",r=>t+=r),process.stdin.on("end",()=>{try{e(JSON.parse(t));}catch{e({});}});})}function ir(e){process.stdout.write(JSON.stringify(e));}Qe.exports={truncate:sr,firstLine:or,readInput:ar,passthrough:ir};});var H=_((fo,tt)=>{var{randomBytes:et}=i("crypto"),cr=()=>et(16).toString("hex"),lr=()=>et(8).toString("hex");function ur(){return String(BigInt(Date.now())*1000000n)}tt.exports={generateTraceId:cr,generateSpanId:lr,nowNs:ur};});var G=_((So,rt)=>{var{readFileSync:dr,writeFileSync:pr,unlinkSync:fr,existsSync:_r,realpathSync:_o}=i("fs"),{tmpdir:nt}=i("os"),{join:Sr,resolve:Er,normalize:Tr,sep:hr}=i("path"),Or=/^[0-9a-f-]{1,64}$/i,gr=Tr(nt())+hr;function Ar(e,t){let r=Er(e);if(!r.startsWith(t))throw new Error(`Path traversal detected: ${e}`);return r}function he(e){if(!Or.test(e))throw new Error(`Invalid session ID: ${e}`);return Ar(Sr(nt(),`flow-obs-${e}.json`),gr)}function yr(e){let t=he(e);if(!_r(t))return null;try{return JSON.parse(dr(t,"utf8"))}catch{return null}}function Lr(e,t){pr(he(e),JSON.stringify(t),{encoding:"utf8",mode:384});}function mr(e){try{fr(he(e));}catch{}}rt.exports={loadState:yr,saveState:Lr,deleteState:mr};});var Oe=_((Eo,at)=>{var{readFileSync:st,existsSync:ot}=i("fs");function Nr(e){if(!e||!ot(e))return null;try{let t=st(e,"utf8").trimEnd().split(`
5
- `);for(let r=t.length-1;r>=0;r--)try{let n=JSON.parse(t[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function Ir(e){if(!e||!ot(e))return null;try{let t=st(e,"utf8").trimEnd().split(`
6
- `),r=[],n=0,s=0,o=!1;for(let a=t.length-1;a>=0;a--)try{let l=JSON.parse(t[a]);if(l.type==="user"){if(o)break;continue}if(l.type==="assistant"){o=!0;let u=(l.message?.content??[]).filter(f=>f.type==="text").map(f=>f.text).join("");u&&r.unshift(u);let d=l.message?.usage??{};n+=(d.input_tokens??0)+(d.cache_read_input_tokens??0)+(d.cache_creation_input_tokens??0),s+=d.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
1
+ 'use strict';var l=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var p=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var h=p((so,Ce)=>{var U=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",Ue={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${U}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${U}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${U}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${U}/otel`},Xt={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},zt="FLOW-nodejs",Zt="config.json",Qt={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},en={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL||`${U}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL||"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL||"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"},tn={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:Ue.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},nn={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES"},rn={KEYCHAIN_ENABLED:false},sn={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},on={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},an={FILE_PREFIX:"flow-obs-buffer-",DEFAULT_TTL_DAYS:4,MIN_TTL_DAYS:1,MAX_TTL_DAYS:30,DEFAULT_MAX_FILES:50,MIN_MAX_FILES:1,MAX_MAX_FILES:500,REPLAY_BATCH_SIZE:10},cn="flow-ai-obs-debug.log",ln={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},un="flow-obs-";Ce.exports={FLOW_BASE_URL:U,FLOW_URLS:Ue,VAULT:Xt,CONFIG_DIR_NAME:zt,CONFIG_FILE_NAME:Zt,OTLP:Qt,LLM_PROXY:en,NATIVE_OTEL:tn,ENV:nn,FEATURES:rn,INSTALLER:sn,HOOK_TIMEOUTS:on,BUFFER:an,DEBUG_LOG_FILENAME:cn,STATE_FILE_PREFIX:un,TRACE_LIMITS:ln};});var be=p((oo,Fe)=>{var B=l("fs"),C=l("path"),dn=l("os"),{CONFIG_DIR_NAME:re,CONFIG_FILE_NAME:se}=h(),oe={credentials:"credentials","token-cache":"tokenCache"};function D(){let e=dn.homedir();if(process.platform==="darwin")return C.join(e,"Library","Preferences",re,se);if(process.platform==="win32"){let r=process.env.APPDATA||C.join(e,"AppData","Roaming");return C.join(r,re,se)}let t=process.env.XDG_CONFIG_HOME||C.join(e,".config");return C.join(t,re,se)}function ae(){try{let e=B.readFileSync(D(),"utf8");return JSON.parse(e)}catch{return {}}}function Pe(e){let t=D();B.mkdirSync(C.dirname(t),{recursive:true}),B.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var J=class{static isAvailable(){return true}static hasExistingData(){try{if(!B.existsSync(D()))return !1;let t=JSON.parse(B.readFileSync(D(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,r){let n=ae(),o=oe[r]||r,s=n[o];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(t,r,n){let o=ae(),s=oe[r]||r;if(r==="token-cache")try{o[s]=JSON.parse(n);}catch{o[s]=n;}else o[s]=n;Pe(o);}async deleteSecret(t,r){let n=ae(),o=oe[r]||r;return o in n?(delete n[o],Pe(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${D()}`}};function fn(){}var pn=J;Fe.exports={JsonFallbackProvider:J,ScryptFallbackProvider:pn,_resetWarningState:fn};});var $e=p((ao,ve)=>{var{execFile:_n}=l("child_process"),{promisify:Sn}=l("util"),{accessSync:En,constants:Tn}=l("fs"),ie=Sn(_n),ce=class{static async isAvailable(){try{return En("/usr/bin/security",Tn.X_OK),!0}catch{return false}}async getSecret(t,r){try{let{stdout:n}=await ie("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await ie("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await ie("security",["delete-generic-password","-a",r,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};ve.exports={MacOsKeyVaultProvider:ce};});var De=p((io,Me)=>{var{execFile:hn,spawn:An}=l("child_process"),{promisify:gn}=l("util"),{accessSync:On,constants:Ln}=l("fs"),qe=gn(hn),le=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of t)try{return On(r,Ln.X_OK),!0}catch{}return false}async getSecret(t,r){try{let{stdout:n}=await qe("secret-tool",["lookup","service",t,"account",r]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await new Promise((o,s)=>{let a=An("secret-tool",["store","--label",t,"service",t,"account",r]);a.on("error",s),a.on("close",i=>{i===0?o():s(new Error(`secret-tool exited with code ${i}`));}),a.stdin.write(n),a.stdin.end();});}async deleteSecret(t,r){try{return await qe("secret-tool",["clear","service",t,"account",r]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};Me.exports={LinuxKeyVaultProvider:le};});var xe=p((co,Be)=>{var ue=class{static async isAvailable(){try{return await l("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,r){return l("keytar").getPassword(t,r)}async setSecret(t,r,n){await l("keytar").setPassword(t,r,n);}async deleteSecret(t,r){return l("keytar").deletePassword(t,r)}getStoragePath(){return "Windows Credential Manager"}};Be.exports={WindowsKeyVaultProvider:ue};});var We=p((lo,He)=>{async function Ye(){let{JsonFallbackProvider:e}=be();return await yn()??new e}async function yn(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=$e();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=De();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=xe();return await e.isAvailable()?new e:null}default:return null}}var mn=Ye;He.exports={createSecretVaultProvider:Ye,createKeyVaultProvider:mn};});var Ve=p((uo,Ke)=>{var{createSecretVaultProvider:In}=We(),{VAULT:fe}=h(),P=fe.SERVICE,pe=fe.ACCOUNT_CREDS,_e=fe.ACCOUNT_TOKEN,de=null;function F(){return de||(de=In()),de}async function Ge(){let t=await(await F()).getSecret(P,pe);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function Nn(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await F()).setSecret(P,pe,JSON.stringify(e));}async function wn(){let e=await F();await e.deleteSecret(P,pe),await e.deleteSecret(P,_e);}async function kn(e){await(await F()).setSecret(P,_e,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function Se(){let t=await(await F()).getSecret(P,_e);if(!t)return null;try{let r=JSON.parse(t);return {accessToken:r.accessToken,expiresAt:r.expiresAt}}catch{return null}}async function Rn(){let e=await Se();return e?new Date(e.expiresAt)>new Date:false}async function Un(){let e=await Se();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let r=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email||r.preferred_username||r.upn||r.sub||null}catch{return null}}async function Cn(){let e=await F();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function Pn(){let e=await Ge();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}Ke.exports={getFlowCredentials:Ge,saveFlowCredentials:Nn,clearFlowCredentials:wn,saveTokenCache:kn,getTokenCache:Se,isTokenValid:Rn,getEmailFromToken:Un,getConfigPath:Cn,hasCredentials:Pn};});var Xe=p((fo,Je)=>{var Fn=l("https"),bn=l("http"),{FLOW_URLS:vn}=h(),$n=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function qn(e){if(!$n.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var je={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function Mn(e,t){try{let r=JSON.parse(t);if(typeof r.error=="string"&&je[r.error])return new Error(je[r.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function Dn(e){return new Promise((t,r)=>{try{qn(e.tenant);}catch(f){return r(f)}let n=JSON.stringify({clientSecret:e.clientSecret}),o=new URL(vn.AUTH_ENGINE),s=o.protocol==="https:",a={hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:e.tenant}},u=(s?Fn:bn).request(a,f=>{let _=[];f.on("data",d=>_.push(d)),f.on("end",()=>{let d=_.join("");if(f.statusCode>=400)return r(Mn(f.statusCode,d));let E;try{E=JSON.parse(d);}catch{return r(new Error("Invalid response from auth engine"))}let g=E.expires_at??new Date(Date.now()+(E.expires_in??3600)*1e3).toISOString();t({accessToken:E.access_token,expiresAt:g});});});u.on("error",f=>r(new Error(`Network error: ${f.message}`))),u.write(n),u.end();})}Je.exports={getToken:Dn};});var m=p((po,Ze)=>{var{writeFileSync:Bn}=l("fs"),{tmpdir:xn}=l("os"),{join:Yn}=l("path"),{DEBUG_LOG_FILENAME:Hn,ENV:Wn}=h(),ze=Yn(xn(),Hn);function Gn(...e){if(process.env[Wn.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
2
+ `;try{Bn(ze,t,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
3
+ `);}}Ze.exports={dbg:Gn,DEBUG_LOG:ze};});var Y=p((_o,et)=>{var{getFlowCredentials:Ee,isTokenValid:Kn,getEmailFromToken:x,getTokenCache:Vn,saveTokenCache:jn}=Ve(),{getToken:Jn}=Xe(),{FLOW_BASE_URL:Xn,ENV:O,FEATURES:Te}=h(),{dbg:b}=m(),zn=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function Zn(e){return zn.some(t=>t.test(e))}function X(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let r=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:o,tenant:s}=r;return !n||!o||!s?null:{clientId:n,clientSecret:o,tenant:s}}catch{return null}}function Qn(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${r}.`}function he(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}let r=process.env[O.FLOW_OBS_ALLOW_HTTP]==="true";if(!r&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(!r&&Zn(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function er(){let e=X(process.env[O.ANTHROPIC_AUTH_TOKEN]);if(e)return {user:await x().catch(()=>null)||e.clientId,tenant:e.tenant};if(Te.KEYCHAIN_ENABLED)try{let t=await Ee();if(!t)return {user:"",tenant:""};let r=await x()||t.clientId||"",n=t.tenant||"";return {user:r,tenant:n}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function tr(e){if(await Kn())return (await Vn()).accessToken;b("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Jn(e);return await jn(t),b("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function nr(e,t){let r=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function rr(e,t,r){let n=Buffer.from(`${t}:${r}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${n}`}}async function Qe(){let e=[],t=process.env[O.ANTHROPIC_MODEL]||"",r=process.env[O.FLOW_TELEMETRY]==="true",n=process.env[O.LANGFUSE_BASE_URL],o=process.env[O.LANGFUSE_PUBLIC_KEY],s=process.env[O.LANGFUSE_SECRET_KEY];if(r&&n&&o&&s){let _="",d="",E=X(process.env[O.ANTHROPIC_AUTH_TOKEN]);if(E)_=await x().catch(()=>null)||E.clientId,d=E.tenant;else if(Te.KEYCHAIN_ENABLED)try{let L=await Ee();L&&(_=await x()||L.clientId,d=L.tenant);}catch{}let g={user:_||"",tenant:d||"",team:"",project:"",model:t};e.push({mode:"direct",...rr(he(n),o,s),...g}),b("resolveCredentials","direct mode active",`user=${g.user}`,`tenant=${g.tenant}`);}let a=X(process.env[O.ANTHROPIC_AUTH_TOKEN]);if(b("resolveCredentials",a?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!a&&Te.KEYCHAIN_ENABLED&&(a=await Ee(),a&&b("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)")),!a){if(e.length===0){let _=[];return _.authError=false,_}return e}let i;try{i=await tr(a);}catch(_){if(b("resolveCredentials",`token refresh failed: ${_.message}`),e.length>0)return e;let d=[];return d.authError=true,d}let u={user:await x()||a.clientId,tenant:a.tenant,team:"",project:"",model:t},f=process.env[O.FLOW_TELEMETRY_GATEWAY]||Xn;return e.push({mode:"gateway",...nr(he(f),{accessToken:i}),...u}),e}async function sr(){return (await Qe()).length>0}et.exports={credentialsAvailable:sr,getIdentityFromToken:er,resolveCredentials:Qe,validateUrl:he,parseCredsFromAnthropicToken:X,buildAnthropicAuthToken:Qn};});var v=p((So,tt)=>{function or(e,t){let r=typeof e=="object"?JSON.stringify(e):String(e??"");return r.length>t?r.slice(0,t)+" \u2026[truncated]":r}function ar(e,t=100){return String(e??"").split(`
4
+ `)[0].slice(0,t).trim()}function ir(){return new Promise(e=>{let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",r=>t+=r),process.stdin.on("end",()=>{try{e(JSON.parse(t));}catch{e({});}});})}function cr(e){process.stdout.write(JSON.stringify(e));}tt.exports={truncate:or,firstLine:ar,readInput:ir,passthrough:cr};});var H=p((Eo,rt)=>{var{randomBytes:nt}=l("crypto"),lr=()=>nt(16).toString("hex"),ur=()=>nt(8).toString("hex");function dr(){return String(BigInt(Date.now())*1000000n)}rt.exports={generateTraceId:lr,generateSpanId:ur,nowNs:dr};});var W=p((ho,ot)=>{var{readFileSync:fr,writeFileSync:pr,unlinkSync:_r,existsSync:Sr,realpathSync:To}=l("fs"),{tmpdir:st}=l("os"),{join:Er,resolve:Tr,normalize:hr,sep:Ar}=l("path"),gr=/^[0-9a-f-]{1,64}$/i,Or=hr(st())+Ar;function Lr(e,t){let r=Tr(e);if(!r.startsWith(t))throw new Error(`Path traversal detected: ${e}`);return r}function Ae(e){if(!gr.test(e))throw new Error(`Invalid session ID: ${e}`);return Lr(Er(st(),`flow-obs-${e}.json`),Or)}function yr(e){let t=Ae(e);if(!Sr(t))return null;try{return JSON.parse(fr(t,"utf8"))}catch{return null}}function mr(e,t){pr(Ae(e),JSON.stringify(t),{encoding:"utf8",mode:384});}function Ir(e){try{_r(Ae(e));}catch{}}ot.exports={loadState:yr,saveState:mr,deleteState:Ir};});var ge=p((Ao,ct)=>{var{readFileSync:at,existsSync:it}=l("fs");function Nr(e){if(!e||!it(e))return null;try{let t=at(e,"utf8").trimEnd().split(`
5
+ `);for(let r=t.length-1;r>=0;r--)try{let n=JSON.parse(t[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function wr(e){if(!e||!it(e))return null;try{let t=at(e,"utf8").trimEnd().split(`
6
+ `),r=[],n=0,o=0,s=!1;for(let a=t.length-1;a>=0;a--)try{let i=JSON.parse(t[a]);if(i.type==="user"){if(s)break;continue}if(i.type==="assistant"){s=!0;let f=(i.message?.content??[]).filter(d=>d.type==="text").map(d=>d.text).join("");f&&r.unshift(f);let _=i.message?.usage??{};n+=(_.input_tokens??0)+(_.cache_read_input_tokens??0)+(_.cache_creation_input_tokens??0),o+=_.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
7
7
 
8
- `),inputTokens:n,outputTokens:s}}catch{}return null}at.exports={readPromptUuid:Nr,readLastAssistantOutput:Ir};});var X=_((To,ut)=>{var{readFileSync:wr,existsSync:it,readdirSync:kr}=i("fs"),{homedir:ct}=i("os"),{join:$,extname:Rr}=i("path"),Cr=new Set([".venv","__pycache__",".git","node_modules"]),Ur=new Set([".pyc",".pyo"]),Pr=new Set(["SKILL.md",".DS_Store",".gitignore"]);function br(e,t){if(!e)return null;let r=[$(ct(),".claude","skills",e,"SKILL.md"),$(t||"",".claude","skills",e,"SKILL.md")];for(let n of r)if(it(n))try{return wr(n,"utf8")}catch{}return null}function $r(e){return e.match(/^\/([a-z][a-z0-9-]*)(?:\s.*)?$/i)?.[1]||null}var lt=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function vr(e){return !!e.slashSkill||e.toolCalls.some(n=>n.tool==="Skill")?e.toolCalls.some(n=>lt.has(n.tool))?"complete":"prerequisite_required":null}function qr(e,t){if(!e)return null;let r=[$(ct(),".claude","skills",e),$(t||"",".claude","skills",e)],n=null;for(let a of r)if(it($(a,"SKILL.md"))){n=a;break}if(!n)return null;let s=[];function o(a,l){for(let p of kr(a,{withFileTypes:true})){if(Cr.has(p.name)||Pr.has(p.name)||Ur.has(Rr(p.name)))continue;let u=l?`${l}/${p.name}`:p.name;p.isDirectory()?o($(a,p.name),u):s.push(u);}}return o(n,""),s.length>0?s:null}ut.exports={readSkillContent:br,readSkillArtifacts:qr,detectSlashSkill:$r,EXECUTION_TOOLS:lt,detectExecutionStatus:vr};});var _t=_((ho,ft)=>{var{generateTraceId:dt,generateSpanId:Fr,nowNs:Br}=H(),{saveState:Dr}=G(),{readPromptUuid:Mr}=Oe(),{detectSlashSkill:xr,readSkillContent:Hr,readSkillArtifacts:Gr}=X(),{passthrough:Wr}=b(),{dbg:pt}=m(),{ENV:Yr}=h(),{resolveCredentials:Kr}=x();async function Jr(e){let t=e.session_id||"unknown",r=e.prompt||"",n=e.cwd||"";try{(await Kr()).authError===!0&&(process.stderr.write(`
8
+ `),inputTokens:n,outputTokens:o}}catch{}return null}ct.exports={readPromptUuid:Nr,readLastAssistantOutput:wr};});var z=p((go,ft)=>{var{readFileSync:kr,existsSync:lt,readdirSync:Rr}=l("fs"),{homedir:ut}=l("os"),{join:$,extname:Ur}=l("path"),Cr=new Set([".venv","__pycache__",".git","node_modules"]),Pr=new Set([".pyc",".pyo"]),Fr=new Set(["SKILL.md",".DS_Store",".gitignore"]);function br(e,t){if(!e)return null;let r=[$(ut(),".claude","skills",e,"SKILL.md"),$(t||"",".claude","skills",e,"SKILL.md")];for(let n of r)if(lt(n))try{return kr(n,"utf8")}catch{}return null}function vr(e){return e.match(/^\/([a-z][a-z0-9-]*)(?:\s.*)?$/i)?.[1]||null}var dt=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function $r(e){return !!e.slashSkill||e.toolCalls.some(n=>n.tool==="Skill")?e.toolCalls.some(n=>dt.has(n.tool))?"complete":"prerequisite_required":null}function qr(e,t){if(!e)return null;let r=[$(ut(),".claude","skills",e),$(t||"",".claude","skills",e)],n=null;for(let a of r)if(lt($(a,"SKILL.md"))){n=a;break}if(!n)return null;let o=[];function s(a,i){for(let u of Rr(a,{withFileTypes:true})){if(Cr.has(u.name)||Fr.has(u.name)||Pr.has(Ur(u.name)))continue;let f=i?`${i}/${u.name}`:u.name;u.isDirectory()?s($(a,u.name),f):o.push(f);}}return s(n,""),o.length>0?o:null}ft.exports={readSkillContent:br,readSkillArtifacts:qr,detectSlashSkill:vr,EXECUTION_TOOLS:dt,detectExecutionStatus:$r};});var Et=p((Oo,St)=>{var{generateTraceId:pt,generateSpanId:Mr,nowNs:Dr}=H(),{saveState:Br}=W(),{readPromptUuid:xr}=ge(),{detectSlashSkill:Yr,readSkillContent:Hr,readSkillArtifacts:Wr}=z(),{passthrough:Gr}=v(),{dbg:_t}=m(),{ENV:Kr}=h(),{resolveCredentials:Vr}=Y();async function jr(e){let t=e.session_id||"unknown",r=e.prompt||"",n=e.cwd||"";try{(await Vr()).authError===!0&&(process.stderr.write(`
9
9
  \u26A0 flow-ai-obs: Your Flow credentials have expired.
10
10
  Traces will not be captured until you re-authenticate.
11
11
  Run: flow-ai-obs auth login
12
12
 
13
- `),pt("UserPromptSubmit","auth expired \u2014 warning emitted to stderr"));}catch{}let s=Mr(e.transcript_path)||dt(),o=xr(r),a=o?Hr(o,n):null,l=o?Gr(o,n):null;Dr(t,{traceId:dt(),spanId:Fr(),startNs:Br(),sessionId:t,prompt:r,cwd:n,traceName:s,transcriptPath:e.transcript_path||"",model:process.env[Yr.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:o,skillContent:a,skillArtifacts:l}),pt("UserPromptSubmit",`sid=${t}`,`traceName=${s}`,`slashSkill=${o}`),Wr(e);}ft.exports={onUserPromptSubmit:Jr};});var Et=_((Oo,St)=>{var{nowNs:Vr}=H(),{loadState:jr,saveState:zr}=G(),{truncate:Xr,passthrough:Zr}=b(),{dbg:Qr}=m(),{TRACE_LIMITS:es}=h();async function ts(e){let t=e.session_id||"unknown",r=e.tool_name||"unknown",n=e.tool_input||{},s=jr(t);s&&(s.pendingTool={name:r,inputStr:Xr(n,es.TOOL_INPUT),startNs:Vr()},zr(t,s)),Qr("PreToolUse",`sid=${t}`,`tool=${r}`,`stateFound=${!!s}`),Zr(e);}St.exports={onPreToolUse:ts};});var Ot=_((go,ht)=>{var ns=i("https"),rs=i("http"),{FLOW_URLS:ss}=h();function os(e){let t=new URL(e),r=new URL(ss.GATEWAY_HEALTH);return r.hostname=t.hostname,r.port=t.port,r.protocol=t.protocol,r}function Tt(e,t){return new Promise((r,n)=>{let o=(e._isSSL?ns:rs).request(e,a=>{let l=[];a.on("data",p=>l.push(p)),a.on("end",()=>r({statusCode:a.statusCode,body:l.join("")}));});o.on("error",a=>n(new Error(`Network error: ${a.message}`))),t&&o.write(t),o.end();})}async function as(e){let t;try{t=os(e);}catch{return false}let r=t.protocol==="https:";try{let n=await Tt({hostname:t.hostname,port:t.port||(r?443:80),path:t.pathname,method:"GET",_isSSL:r},null);return n.statusCode>=200&&n.statusCode<300}catch{return false}}async function is(e,t,r){let n=JSON.stringify(e),s=new URL(t),o=s.protocol==="https:",a=String(r).replace(/[\r\n]/g,"");try{return (await Tt({hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:a,"Content-Length":Buffer.byteLength(n)},_isSSL:o},n)).statusCode}catch{return 0}}ht.exports={checkHealth:as,sendTraces:is};});var Lt=_((Ao,yt)=>{var N=i("fs"),ge=i("path"),gt=i("os"),{BUFFER:W}=h(),{dbg:Y}=m();function At(e){if(/[/\\]/.test(e))throw new Error(`Invalid buffer fileId: ${e}`);return ge.join(gt.tmpdir(),`${W.FILE_PREFIX}${e}.json`)}function Ae(){let e=gt.tmpdir(),t;try{t=N.readdirSync(e);}catch{return []}return t.filter(r=>r.startsWith(W.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=ge.join(e,r),s=0;try{s=N.statSync(n).mtimeMs;}catch{}return {full:n,mtime:s}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function cs(e){try{let t=Ae();if(t.length>=W.MAX_FILES){let s=t.slice(0,t.length-W.MAX_FILES+1);for(let o of s)try{N.unlinkSync(o);}catch{}}let r=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,n={fileId:r,bufferedAt:Date.now(),payload:e};return N.writeFileSync(At(r),JSON.stringify(n),{encoding:"utf8",mode:384}),Y("buffer",`saved fileId=${r}`),r}catch(t){return Y("buffer",`saveToBuffer failed: ${t.message}`),null}}function ls(){let e=Ae(),t=[];for(let r of e)try{let n=N.readFileSync(r,"utf8"),s=JSON.parse(n);s&&s.fileId&&s.payload&&t.push(s);}catch{Y("buffer",`skipping malformed file: ${r}`);}return t}function us(e){try{N.unlinkSync(At(e)),Y("buffer",`deleted fileId=${e}`);}catch{}}function ds(){let e=Ae(),t=Date.now()-W.MAX_AGE_MS;for(let r of e)try{let{mtimeMs:n}=N.statSync(r);n<t&&(N.unlinkSync(r),Y("buffer",`evicted stale: ${ge.basename(r)}`));}catch{}}yt.exports={saveToBuffer:cs,loadBuffer:ls,deleteBuffer:us,cleanStaleBuffers:ds};});var ye=_((yo,wt)=>{var{resolveCredentials:ps}=x(),{OTLP:mt}=h(),{dbg:v}=m(),{checkHealth:fs,sendTraces:It}=Ot(),{saveToBuffer:Nt,loadBuffer:_s,deleteBuffer:Ss,cleanStaleBuffers:Es}=Lt(),Ts={name:mt.SCOPE_NAME,version:mt.SCOPE_VERSION},hs={TRACE_NAME:"langfuse.trace.name",TRACE_INPUT:"langfuse.trace.input",TRACE_OUTPUT:"langfuse.trace.output",TRACE_METADATA:"langfuse.trace.metadata",TRACE_TAGS:"langfuse.trace.tags",USER_ID:"langfuse.user.id",SESSION_ID:"langfuse.session.id",OBS_NAME:"langfuse.observation.name",OBS_INPUT:"langfuse.observation.input",OBS_OUTPUT:"langfuse.observation.output",OBS_LEVEL:"langfuse.observation.level",OBS_TYPE:"langfuse.observation.type",MODEL:"gen_ai.request.model",INPUT_TOKENS:"gen_ai.usage.input_tokens",OUTPUT_TOKENS:"gen_ai.usage.output_tokens"};function Os(e,t){return t==null||t===""?null:{key:e,value:{stringValue:String(t)}}}function gs(...e){return e.filter(Boolean)}function As(e,t){return {resourceSpans:[{resource:{attributes:e},scopeSpans:[{scope:Ts,spans:Array.isArray(t)?t:[t]}]}]}}function ys(e,t){return new Promise(r=>{let n=JSON.stringify(e),s=new URL(t.endpoint),o=s.protocol==="https:",a=d=>String(d).replace(/[\r\n]/g,""),l={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:a(t.authHeader),"Content-Length":Buffer.byteLength(n)}},u=(o?i("https"):i("http")).request(l,d=>{d.resume(),r(d.statusCode);});u.on("error",()=>r(0)),u.write(n),u.end();})}async function Ls(e){Es();let t=_s();if(t.length){v("replayBufferedTraces",`replaying ${t.length} buffered trace(s)`);for(let r of t)try{let n=await It(r.payload,e.endpoint,e.authHeader);n>=200&&n<300?(Ss(r.fileId),v("replayBufferedTraces",`replayed fileId=${r.fileId} status=${n}`)):v("replayBufferedTraces",`replay failed fileId=${r.fileId} status=${n}`);}catch(n){v("replayBufferedTraces",`replay error fileId=${r.fileId}: ${n.message}`);}}}async function ms(e){let t=await ps();return t.length?(await Promise.all(t.map(async n=>n.mode==="gateway"?await fs(n.endpoint)?(await Ls(n),It(e,n.endpoint,n.authHeader)):(v("postToLangfuse","gateway health check failed \u2014 buffering trace"),Nt(e),0):ys(e,n)))).find(n=>n!==0)||0:(t.authError&&(v("postToLangfuse","auth refresh failed \u2014 buffering trace"),Nt(e)),0)}wt.exports={LF:hs,a:Os,attrs:gs,buildPayload:As,postToLangfuse:ms};});var Le=_((Lo,kt)=>{var O="[REDACTED]",Ns=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${O}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${O}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(e,t)=>`${t}${O}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(e,t)=>`${t}${O}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(e,t,r)=>`${t}
14
- ${O}
15
- ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${O}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(e,t)=>`${t}${O}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${O}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${O}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${O}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(e,t,r)=>`${t}${r}${O}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(e,t)=>`${t}:${O}@`}];function Is(e){if(e==null)return "";let t=typeof e=="string"?e:JSON.stringify(e);return Ns.reduce((r,{re:n,replace:s})=>r.replace(n,s),t)}kt.exports={sanitize:Is,REDACTED:O};});var vt=_((mo,$t)=>{var{generateSpanId:ws,nowNs:ks}=H(),{loadState:Rs,saveState:Cs}=G(),{LF:K,a:w,attrs:Us}=ye(),{truncate:Rt,firstLine:Ps,passthrough:Ct}=b(),{readSkillContent:bs,readSkillArtifacts:$s}=X(),{dbg:Ut}=m(),{TRACE_LIMITS:Pt}=h(),{sanitize:bt}=Le();async function vs(e){let t=e.session_id||"unknown",r=e.tool_name||"unknown",n=e.tool_input||{},s=e.tool_response||"",o=Rs(t);if(!o){Ct(e);return}let a=ks(),l=o.pendingTool?.name===r,p=l?o.pendingTool.startNs:String(BigInt(a)-200000000n),u=l?o.pendingTool.inputStr:Rt(n,Pt.TOOL_INPUT),d=u;if(r==="Skill"){let I=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||String(Object.values(n)[0]??""):String(n),L=I?bs(I.trim(),o.cwd):null;L&&(d=L,o.skillContent||(o.skillContent=L),o.slashSkill||(o.slashSkill=I.trim()),o.skillArtifacts||(o.skillArtifacts=$s(I.trim(),o.cwd))),Ut("PostToolUse","Skill tool detected",`skillName=${I}`,`contentFound=${!!L}`);}let f=bt(Rt(s,Pt.TOOL_OUTPUT)),E=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(f.slice(0,500)),g=E?"ERROR":"DEFAULT",y=ws(),J=Math.round(Number(BigInt(a)-BigInt(p))/1e6),te={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL";o.toolCalls.push({tool:r,brief:Ps(u,60),error:E,durationMs:J}),o.spans.push({traceId:o.traceId,spanId:y,parentSpanId:o.spanId,name:r,kind:3,startTimeUnixNano:p,endTimeUnixNano:a,attributes:Us(w(K.OBS_NAME,r),w(K.OBS_TYPE,te),w(K.OBS_LEVEL,g),w(K.OBS_INPUT,bt(d)),w(K.OBS_OUTPUT,f),w("tool.name",r),w("tool.error",String(E))),status:{code:E?2:1}}),o.pendingTool=null,Cs(t,o),Ut("PostToolUse",`sid=${t}`,`tool=${r}`,`error=${E}`,`durationMs=${J}`,`totalSpans=${o.spans.length}`),Ct(e);}$t.exports={onPostToolUse:vs};});var Ft=_((No,qt)=>{var me={"claude-opus-4-6":{input:15,output:75},"claude-opus-4-5":{input:15,output:75},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:.8,output:4},"claude-4-6-opus":{input:15,output:75},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:15,output:75},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:.8,output:4},"claude-3-5-sonnet-20241022":{input:3,output:15},"claude-3-5-haiku-20241022":{input:.8,output:4},"claude-3-opus-20240229":{input:15,output:75}};function qs(e,t,r){let n=Object.keys(me).find(a=>(e||"").toLowerCase().includes(a));if(!n)return;let s=me[n],o=(t*s.input+r*s.output)/1e6;return Math.round(o*1e6)/1e6}qt.exports={MODEL_PRICING:me,calcCostUsd:qs};});var Ht=_((Io,xt)=>{var{generateSpanId:Bt,nowNs:Fs}=H(),{loadState:Bs,deleteState:Dt}=G(),{LF:T,a:c,attrs:Z,buildPayload:Ds,postToLangfuse:Ms}=ye(),{getIdentityFromToken:xs}=x(),{calcCostUsd:Hs}=Ft(),{readLastAssistantOutput:Gs}=Oe(),{truncate:Q,firstLine:Ws,passthrough:Ne}=b(),{dbg:q}=m(),{detectExecutionStatus:Ys}=X(),{sanitize:Mt}=Le(),{TRACE_LIMITS:ee}=h();async function Ks(e){let t=e.session_id||"unknown",r=e.stop_reason||"end_turn",n=Bs(t);if(!n){Ne(e);return}n.slashSkill&&!/^[a-z][a-z0-9-]*$/i.test(n.slashSkill)&&(q("Stop",`sid=${t}`,`slashSkill rejected post-disk: "${n.slashSkill}"`),n.slashSkill=null);let s=Fs(),o=await xs();if(n.slashSkill&&!n.toolCalls.some(S=>S.tool==="Skill")){let S=Bt(),F=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});n.toolCalls.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),n.spans.push({traceId:n.traceId,spanId:S,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:Z(c(T.OBS_NAME,"Skill"),c(T.OBS_TYPE,"TOOL"),c(T.OBS_LEVEL,"DEFAULT"),c(T.OBS_INPUT,F),c(T.OBS_OUTPUT,"loaded via slash command"),c("tool.name","Skill"),c("tool.error","false"),c("skill.name",n.slashSkill),c("skill.invocation","slash-command")),status:{code:1}}),q("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let a=e.transcript_path||n.transcriptPath||"",l=Gs(a),p=n.toolCalls.length,u=n.toolCalls.filter(S=>S.error).length,d=Mt(l?.text?Q(l.text,ee.TRACE_OUTPUT):p===0?"No tools used":n.toolCalls.map((S,F)=>`${F+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""}`).join(`
16
- `)),f=l?.inputTokens??0,E=l?.outputTokens??0,g=n.toolCalls.map((S,F)=>`${F+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""} (${S.durationMs}ms)`),y=!!(n.slashSkill||n.toolCalls.some(S=>S.tool==="Skill")),J=n.toolCalls.some(S=>S.tool==="Agent");if(!y&&!J){q("Stop",`sid=${t}`,"skipping trace \u2014 no Skill or Agent calls found"),Dt(t),Ne(e);return}let V=y?"skill":"agent",te=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),I=Hs(n.model,f,E),L=Ys(n);L==="prerequisite_required"&&(n.spans.push({traceId:n.traceId,spanId:Bt(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:Z(c(T.OBS_NAME,"prerequisite-check"),c(T.OBS_TYPE,"EVENT"),c(T.OBS_LEVEL,"WARNING"),c(T.OBS_OUTPUT,d),c("skill.name",n.slashSkill||void 0),c("execution_status","prerequisite_required")),status:{code:1}}),q("Stop",`sid=${t}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let Ie=(()=>{if(!(!y||!n.prompt)){if(n.slashSkill){let S=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return S?Q(S,ee.USER_INSTRUCTION):void 0}return Q(n.prompt,ee.USER_INSTRUCTION)||void 0}})(),Gt=JSON.stringify({trace_type:V,...L!==null&&{execution_status:L},...n.slashSkill&&{skill_name:n.slashSkill},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...Ie!==void 0&&{user_instruction:Ie},latency_ms:te,...f&&{tokens_input:f},...E&&{tokens_output:E},cost_usd:I,...n.model&&{model:n.model},toolCount:p,errorCount:u,stopReason:r,sessionId:n.sessionId,tools:g.length?g:void 0}),Wt=Mt(Q(n.prompt,ee.TRACE_INPUT)),Yt=Z(c(T.TRACE_NAME,n.traceName),c(T.TRACE_INPUT,Wt),c(T.TRACE_OUTPUT,d),c(T.TRACE_METADATA,Gt),c(T.SESSION_ID,n.sessionId),c(T.USER_ID,o.user),c(T.OBS_TYPE,"GENERATION"),c(T.MODEL,n.model),f?c(T.INPUT_TOKENS,f):null,E?c(T.OUTPUT_TOKENS,E):null,c("claude.stop_reason",r),c("claude.tool_count",String(p)),c("claude.error_count",String(u)),c("claude.session_id",n.sessionId),c("flow.trace_type",V),{key:T.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:V}]}}}),Kt={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:Yt,status:{code:u>0?2:1}},Jt=Z(c("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),c("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),we=[...n.spans||[],Kt];q("Stop",`sid=${t}`,`totalTools=${p}`,`errorTools=${u}`,`spans=${we.length}`,`inputTokens=${f}`,`outputTokens=${E}`,`traceOutput="${Ws(d,80)}"`);let Vt=await Ms(Ds(Jt,we));q("Stop",`POST status=${Vt}`,`traceId=${n.traceId}`),Dt(t),Ne(e);}xt.exports={onStop:Ks};});var{credentialsAvailable:Js}=x(),{readInput:Vs}=b(),{onUserPromptSubmit:js}=_t(),{onPreToolUse:zs}=Et(),{onPostToolUse:Xs}=vt(),{onStop:Zs}=Ht();async function Qs(){let e=process.argv[2];if(!await Js()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let t=await Vs();switch(e){case "UserPromptSubmit":await js(t);break;case "PreToolUse":await zs(t);break;case "PostToolUse":await Xs(t);break;case "Stop":await Zs(t);break;default:process.stderr.write(`[flow-obs] unknown event: ${e}
17
- `),process.stdout.write(JSON.stringify(t));}}Qs().catch(e=>{process.stderr.write(`[flow-obs] fatal: ${e.message}
13
+ `),_t("UserPromptSubmit","auth expired \u2014 warning emitted to stderr"));}catch{}let o=xr(e.transcript_path)||pt(),s=Yr(r),a=s?Hr(s,n):null,i=s?Wr(s,n):null;Br(t,{traceId:pt(),spanId:Mr(),startNs:Dr(),sessionId:t,prompt:r,cwd:n,traceName:o,transcriptPath:e.transcript_path||"",model:process.env[Kr.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:s,skillContent:a,skillArtifacts:i}),_t("UserPromptSubmit",`sid=${t}`,`traceName=${o}`,`slashSkill=${s}`),Gr(e);}St.exports={onUserPromptSubmit:jr};});var ht=p((Lo,Tt)=>{var{nowNs:Jr}=H(),{loadState:Xr,saveState:zr}=W(),{truncate:Zr,passthrough:Qr}=v(),{dbg:es}=m(),{TRACE_LIMITS:ts}=h();async function ns(e){let t=e.session_id||"unknown",r=e.tool_name||"unknown",n=e.tool_input||{},o=Xr(t);o&&(o.pendingTool={name:r,inputStr:Zr(n,ts.TOOL_INPUT),startNs:Jr()},zr(t,o)),es("PreToolUse",`sid=${t}`,`tool=${r}`,`stateFound=${!!o}`),Qr(e);}Tt.exports={onPreToolUse:ns};});var Ot=p((yo,gt)=>{var rs=l("https"),ss=l("http"),{FLOW_URLS:os}=h();function as(e){let t=new URL(e),r=new URL(os.GATEWAY_HEALTH);return r.hostname=t.hostname,r.port=t.port,r.protocol=t.protocol,r}function At(e,t){return new Promise((r,n)=>{let o=e._isSSL?rs:ss;e.headers=Object.assign({},e.headers,{Connection:"close"});let s=o.request(e,a=>{let i=[];a.on("data",u=>i.push(u)),a.on("end",()=>r({statusCode:a.statusCode,body:i.join("")}));});s.setTimeout(1e4,()=>{s.destroy(new Error("Request timeout"));}),s.on("error",a=>n(new Error(`Network error: ${a.message}`))),t&&s.write(t),s.end();})}async function is(e,t){let r;try{r=as(e);}catch{return false}let n=r.protocol==="https:",o={};t&&(o.Authorization=String(t).replace(/[\r\n]/g,""));try{let s=await At({hostname:r.hostname,port:r.port||(n?443:80),path:r.pathname,method:"GET",headers:o,_isSSL:n},null);return s.statusCode>=200&&s.statusCode<300}catch{return false}}async function cs(e,t,r){let n=JSON.stringify(e),o=new URL(t),s=o.protocol==="https:",a=String(r).replace(/[\r\n]/g,"");try{return (await At({hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:a,"Content-Length":Buffer.byteLength(n)},_isSSL:s},n)).statusCode}catch{return 0}}gt.exports={checkHealth:is,sendTraces:cs};});var Nt=p((mo,It)=>{var N=l("fs"),Oe=l("path"),Lt=l("os"),{BUFFER:I,ENV:yt}=h(),{dbg:G}=m();function ls(){let e=parseInt(process.env[yt.BUFFER_TTL_DAYS],10);return (Number.isFinite(e)?Math.max(I.MIN_TTL_DAYS,Math.min(I.MAX_TTL_DAYS,e)):I.DEFAULT_TTL_DAYS)*24*60*60*1e3}function us(){let e=parseInt(process.env[yt.BUFFER_MAX_FILES],10);return Number.isFinite(e)?Math.max(I.MIN_MAX_FILES,Math.min(I.MAX_MAX_FILES,e)):I.DEFAULT_MAX_FILES}function mt(e){if(/[/\\]/.test(e))throw new Error(`Invalid buffer fileId: ${e}`);return Oe.join(Lt.tmpdir(),`${I.FILE_PREFIX}${e}.json`)}function Le(){let e=Lt.tmpdir(),t;try{t=N.readdirSync(e);}catch{return []}return t.filter(r=>r.startsWith(I.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=Oe.join(e,r),o=0;try{o=N.statSync(n).mtimeMs;}catch{}return {full:n,mtime:o}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function ds(e){try{let t=us(),r=Le();if(r.length>=t){let s=r.slice(0,r.length-t+1);for(let a of s)try{N.unlinkSync(a);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,o={fileId:n,bufferedAt:Date.now(),payload:e};return N.writeFileSync(mt(n),JSON.stringify(o),{encoding:"utf8",mode:384}),G("buffer",`saved fileId=${n}`),n}catch(t){return G("buffer",`saveToBuffer failed: ${t.message}`),null}}function fs(e){let t=Le(),r=e!=null&&e>0?e:t.length,n=[];for(let o of t){if(n.length>=r)break;try{let s=N.readFileSync(o,"utf8"),a=JSON.parse(s);a&&a.fileId&&a.payload&&n.push(a);}catch{G("buffer",`skipping malformed file: ${o}`);}}return n}function ps(e){try{N.unlinkSync(mt(e)),G("buffer",`deleted fileId=${e}`);}catch{}}function _s(){let e=Date.now()-ls();for(let t of Le())try{let{mtimeMs:r}=N.statSync(t);r<e&&(N.unlinkSync(t),G("buffer",`evicted stale: ${Oe.basename(t)}`));}catch{}}It.exports={saveToBuffer:ds,loadBuffer:fs,deleteBuffer:ps,cleanStaleBuffers:_s};});var me=p((Io,kt)=>{var{resolveCredentials:Ss}=Y(),{OTLP:wt,BUFFER:Es}=h(),{dbg:w}=m(),{checkHealth:Ts,sendTraces:ye}=Ot(),{saveToBuffer:Z,loadBuffer:hs,deleteBuffer:As,cleanStaleBuffers:gs}=Nt(),Os={name:wt.SCOPE_NAME,version:wt.SCOPE_VERSION},Ls={TRACE_NAME:"langfuse.trace.name",TRACE_INPUT:"langfuse.trace.input",TRACE_OUTPUT:"langfuse.trace.output",TRACE_METADATA:"langfuse.trace.metadata",TRACE_TAGS:"langfuse.trace.tags",USER_ID:"langfuse.user.id",SESSION_ID:"langfuse.session.id",OBS_NAME:"langfuse.observation.name",OBS_INPUT:"langfuse.observation.input",OBS_OUTPUT:"langfuse.observation.output",OBS_LEVEL:"langfuse.observation.level",OBS_TYPE:"langfuse.observation.type",MODEL:"gen_ai.request.model",INPUT_TOKENS:"gen_ai.usage.input_tokens",OUTPUT_TOKENS:"gen_ai.usage.output_tokens"};function ys(e,t){return t==null||t===""?null:{key:e,value:{stringValue:String(t)}}}function ms(...e){return e.filter(Boolean)}function Is(e,t){return {resourceSpans:[{resource:{attributes:e},scopeSpans:[{scope:Os,spans:Array.isArray(t)?t:[t]}]}]}}async function Ns(e){gs();let t=hs(Es.REPLAY_BATCH_SIZE);t.length&&(w("replayBufferedTraces",`replaying ${t.length} buffered trace(s)`),await Promise.allSettled(t.map(async r=>{try{let n=await ye(r.payload,e.endpoint,e.authHeader);n>=200&&n<300?(As(r.fileId),w("replayBufferedTraces",`replayed fileId=${r.fileId} status=${n}`)):w("replayBufferedTraces",`replay failed fileId=${r.fileId} status=${n}`);}catch(n){w("replayBufferedTraces",`replay error fileId=${r.fileId}: ${n.message}`);}})));}async function ws(e){let t=await Ss();if(!t.length)return t.authError&&(w("postToLangfuse","auth refresh failed \u2014 buffering trace"),Z(e)),0;let r=await Promise.all(t.map(async s=>{if(s.mode!=="gateway")return {creds:s,healthy:true};let a=await Ts(s.endpoint,s.authHeader);return {creds:s,healthy:a}})),n=r.find(s=>s.creds.mode==="gateway"&&s.healthy)?.creds??r.find(s=>s.creds.mode==="direct")?.creds;return n&&await Ns(n),(await Promise.all(r.map(async({creds:s,healthy:a})=>{if(s.mode==="gateway"){if(!a)return w("postToLangfuse","gateway health check failed \u2014 buffering trace"),Z(e),0;let u=await ye(e,s.endpoint,s.authHeader);return (u===0||u>=500)&&(w("postToLangfuse",`gateway send failed (status ${u}) \u2014 buffering trace`),Z(e)),u}let i=await ye(e,s.endpoint,s.authHeader);return (i===0||i>=500)&&(w("postToLangfuse",`direct endpoint unavailable (status ${i}) \u2014 buffering trace`),Z(e)),i}))).find(s=>s!==0)||0}kt.exports={LF:Ls,a:ys,attrs:ms,buildPayload:Is,postToLangfuse:ws};});var Ie=p((No,Rt)=>{var A="[REDACTED]",ks=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${A}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${A}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(e,t)=>`${t}${A}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(e,t)=>`${t}${A}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(e,t,r)=>`${t}
14
+ ${A}
15
+ ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${A}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(e,t)=>`${t}${A}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${A}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${A}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${A}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(e,t,r)=>`${t}${r}${A}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(e,t)=>`${t}:${A}@`}];function Rs(e){if(e==null)return "";let t=typeof e=="string"?e:JSON.stringify(e);return ks.reduce((r,{re:n,replace:o})=>r.replace(n,o),t)}Rt.exports={sanitize:Rs,REDACTED:A};});var $t=p((wo,vt)=>{var{generateSpanId:Us,nowNs:Cs}=H(),{loadState:Ps,saveState:Fs}=W(),{LF:K,a:R,attrs:bs}=me(),{truncate:Ut,firstLine:vs,passthrough:Ct}=v(),{readSkillContent:$s,readSkillArtifacts:qs}=z(),{dbg:Pt}=m(),{TRACE_LIMITS:Ft}=h(),{sanitize:bt}=Ie();async function Ms(e){let t=e.session_id||"unknown",r=e.tool_name||"unknown",n=e.tool_input||{},o=e.tool_response||"",s=Ps(t);if(!s){Ct(e);return}let a=Cs(),i=s.pendingTool?.name===r,u=i?s.pendingTool.startNs:String(BigInt(a)-200000000n),f=i?s.pendingTool.inputStr:Ut(n,Ft.TOOL_INPUT),_=f;if(r==="Skill"){let k=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||String(Object.values(n)[0]??""):String(n),y=k?$s(k.trim(),s.cwd):null;y&&(_=y,s.skillContent||(s.skillContent=y),s.slashSkill||(s.slashSkill=k.trim()),s.skillArtifacts||(s.skillArtifacts=qs(k.trim(),s.cwd))),Pt("PostToolUse","Skill tool detected",`skillName=${k}`,`contentFound=${!!y}`);}let d=bt(Ut(o,Ft.TOOL_OUTPUT)),E=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(d.slice(0,500)),g=E?"ERROR":"DEFAULT",L=Us(),V=Math.round(Number(BigInt(a)-BigInt(u))/1e6),ne={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL";s.toolCalls.push({tool:r,brief:vs(f,60),error:E,durationMs:V}),s.spans.push({traceId:s.traceId,spanId:L,parentSpanId:s.spanId,name:r,kind:3,startTimeUnixNano:u,endTimeUnixNano:a,attributes:bs(R(K.OBS_NAME,r),R(K.OBS_TYPE,ne),R(K.OBS_LEVEL,g),R(K.OBS_INPUT,bt(_)),R(K.OBS_OUTPUT,d),R("tool.name",r),R("tool.error",String(E))),status:{code:E?2:1}}),s.pendingTool=null,Fs(t,s),Pt("PostToolUse",`sid=${t}`,`tool=${r}`,`error=${E}`,`durationMs=${V}`,`totalSpans=${s.spans.length}`),Ct(e);}vt.exports={onPostToolUse:Ms};});var Mt=p((ko,qt)=>{var Ne={"claude-opus-4-6":{input:15,output:75},"claude-opus-4-5":{input:15,output:75},"claude-sonnet-4-6":{input:3,output:15},"claude-sonnet-4-5":{input:3,output:15},"claude-haiku-4-5":{input:.8,output:4},"claude-4-6-opus":{input:15,output:75},"claude-4-6-sonnet":{input:3,output:15},"claude-4-5-opus":{input:15,output:75},"claude-4-5-sonnet":{input:3,output:15},"claude-4-5-haiku":{input:.8,output:4},"claude-3-5-sonnet-20241022":{input:3,output:15},"claude-3-5-haiku-20241022":{input:.8,output:4},"claude-3-opus-20240229":{input:15,output:75}};function Ds(e,t,r){let n=Object.keys(Ne).find(a=>(e||"").toLowerCase().includes(a));if(!n)return;let o=Ne[n],s=(t*o.input+r*o.output)/1e6;return Math.round(s*1e6)/1e6}qt.exports={MODEL_PRICING:Ne,calcCostUsd:Ds};});var Ht=p((Ro,Yt)=>{var{generateSpanId:Dt,nowNs:Bs}=H(),{loadState:xs,deleteState:Bt}=W(),{LF:T,a:c,attrs:Q,buildPayload:Ys,postToLangfuse:Hs}=me(),{getIdentityFromToken:Ws}=Y(),{calcCostUsd:Gs}=Mt(),{readLastAssistantOutput:Ks}=ge(),{truncate:ee,firstLine:Vs,passthrough:we}=v(),{dbg:q}=m(),{detectExecutionStatus:js}=z(),{sanitize:xt}=Ie(),{TRACE_LIMITS:te}=h();async function Js(e){let t=e.session_id||"unknown",r=e.stop_reason||"end_turn",n=xs(t);if(!n){we(e);return}n.slashSkill&&!/^[a-z][a-z0-9-]*$/i.test(n.slashSkill)&&(q("Stop",`sid=${t}`,`slashSkill rejected post-disk: "${n.slashSkill}"`),n.slashSkill=null);let o=Bs(),s=await Ws();if(n.slashSkill&&!n.toolCalls.some(S=>S.tool==="Skill")){let S=Dt(),M=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});n.toolCalls.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),n.spans.push({traceId:n.traceId,spanId:S,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:Q(c(T.OBS_NAME,"Skill"),c(T.OBS_TYPE,"TOOL"),c(T.OBS_LEVEL,"DEFAULT"),c(T.OBS_INPUT,M),c(T.OBS_OUTPUT,"loaded via slash command"),c("tool.name","Skill"),c("tool.error","false"),c("skill.name",n.slashSkill),c("skill.invocation","slash-command")),status:{code:1}}),q("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let a=e.transcript_path||n.transcriptPath||"",i=Ks(a),u=n.toolCalls.length,f=n.toolCalls.filter(S=>S.error).length,_=xt(i?.text?ee(i.text,te.TRACE_OUTPUT):u===0?"No tools used":n.toolCalls.map((S,M)=>`${M+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""}`).join(`
16
+ `)),d=i?.inputTokens??0,E=i?.outputTokens??0,g=n.toolCalls.map((S,M)=>`${M+1}. ${S.tool}${S.brief?` \u2192 ${S.brief}`:""}${S.error?" [ERROR]":""} (${S.durationMs}ms)`),L=!!(n.slashSkill||n.toolCalls.some(S=>S.tool==="Skill")),V=n.toolCalls.some(S=>S.tool==="Agent");if(!L&&!V){q("Stop",`sid=${t}`,"skipping trace \u2014 no Skill or Agent calls found"),Bt(t),we(e);return}let j=L?"skill":"agent",ne=Math.round(Number(BigInt(o)-BigInt(n.startNs))/1e6),k=Gs(n.model,d,E),y=js(n);y==="prerequisite_required"&&(n.spans.push({traceId:n.traceId,spanId:Dt(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:o,attributes:Q(c(T.OBS_NAME,"prerequisite-check"),c(T.OBS_TYPE,"EVENT"),c(T.OBS_LEVEL,"WARNING"),c(T.OBS_OUTPUT,_),c("skill.name",n.slashSkill||void 0),c("execution_status","prerequisite_required")),status:{code:1}}),q("Stop",`sid=${t}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let ke=(()=>{if(!(!L||!n.prompt)){if(n.slashSkill){let S=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return S?ee(S,te.USER_INSTRUCTION):void 0}return ee(n.prompt,te.USER_INSTRUCTION)||void 0}})(),Wt=JSON.stringify({trace_type:j,...y!==null&&{execution_status:y},...n.slashSkill&&{skill_name:n.slashSkill},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...ke!==void 0&&{user_instruction:ke},latency_ms:ne,...d&&{tokens_input:d},...E&&{tokens_output:E},cost_usd:k,...n.model&&{model:n.model},toolCount:u,errorCount:f,stopReason:r,sessionId:n.sessionId,tools:g.length?g:void 0}),Gt=xt(ee(n.prompt,te.TRACE_INPUT)),Kt=Q(c(T.TRACE_NAME,n.traceName),c(T.TRACE_INPUT,Gt),c(T.TRACE_OUTPUT,_),c(T.TRACE_METADATA,Wt),c(T.SESSION_ID,n.sessionId),c(T.USER_ID,s.user),c(T.OBS_TYPE,"GENERATION"),c(T.MODEL,n.model),d?c(T.INPUT_TOKENS,d):null,E?c(T.OUTPUT_TOKENS,E):null,c("claude.stop_reason",r),c("claude.tool_count",String(u)),c("claude.error_count",String(f)),c("claude.session_id",n.sessionId),c("flow.trace_type",j),{key:T.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:j}]}}}),Vt={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:o,attributes:Kt,status:{code:f>0?2:1}},jt=Q(c("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),c("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),Re=[...n.spans||[],Vt];q("Stop",`sid=${t}`,`totalTools=${u}`,`errorTools=${f}`,`spans=${Re.length}`,`inputTokens=${d}`,`outputTokens=${E}`,`traceOutput="${Vs(_,80)}"`);let Jt=await Hs(Ys(jt,Re));q("Stop",`POST status=${Jt}`,`traceId=${n.traceId}`),Bt(t),we(e);}Yt.exports={onStop:Js};});var{credentialsAvailable:Xs}=Y(),{readInput:zs}=v(),{onUserPromptSubmit:Zs}=Et(),{onPreToolUse:Qs}=ht(),{onPostToolUse:eo}=$t(),{onStop:to}=Ht();async function no(){let e=process.argv[2];if(!await Xs()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let t=await zs();switch(e){case "UserPromptSubmit":await Zs(t);break;case "PreToolUse":await Qs(t);break;case "PostToolUse":await eo(t);break;case "Stop":await to(t);break;default:process.stderr.write(`[flow-obs] unknown event: ${e}
17
+ `),process.stdout.write(JSON.stringify(t));}}no().catch(e=>{process.stderr.write(`[flow-obs] fatal: ${e.message}
18
18
  `),process.exit(0);});
package/dist/setup.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';var c=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var _=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var p=_((nn,ee)=>{var O=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",Z={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${O}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${O}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${O}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${O}/otel`},Ue={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},Pe="FLOW-nodejs",Fe="config.json",ke={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},be={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL||`${O}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL||"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL||"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"},De={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:Z.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},Me={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP"},He={KEYCHAIN_ENABLED:false},qe={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Ye={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},We={FILE_PREFIX:"flow-obs-buffer-",MAX_AGE_MS:5760*60*1e3,MAX_FILES:50},Ge="flow-ai-obs-debug.log",$e={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},Be="flow-obs-";ee.exports={FLOW_BASE_URL:O,FLOW_URLS:Z,VAULT:Ue,CONFIG_DIR_NAME:Pe,CONFIG_FILE_NAME:Fe,OTLP:ke,LLM_PROXY:be,NATIVE_OTEL:De,ENV:Me,FEATURES:He,INSTALLER:qe,HOOK_TIMEOUTS:Ye,BUFFER:We,DEBUG_LOG_FILENAME:Ge,STATE_FILE_PREFIX:Be,TRACE_LIMITS:$e};});var re=_((rn,ne)=>{var g=c("fs"),h=c("path"),xe=c("os"),{CONFIG_DIR_NAME:F,CONFIG_FILE_NAME:k}=p(),b={credentials:"credentials","token-cache":"tokenCache"};function N(){let e=xe.homedir();if(process.platform==="darwin")return h.join(e,"Library","Preferences",F,k);if(process.platform==="win32"){let n=process.env.APPDATA||h.join(e,"AppData","Roaming");return h.join(n,F,k)}let t=process.env.XDG_CONFIG_HOME||h.join(e,".config");return h.join(t,F,k)}function D(){try{let e=g.readFileSync(N(),"utf8");return JSON.parse(e)}catch{return {}}}function te(e){let t=N();g.mkdirSync(h.dirname(t),{recursive:true}),g.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var v=class{static isAvailable(){return true}static hasExistingData(){try{if(!g.existsSync(N()))return !1;let t=JSON.parse(g.readFileSync(N(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let r=D(),s=b[n]||n,o=r[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,n,r){let s=D(),o=b[n]||n;if(n==="token-cache")try{s[o]=JSON.parse(r);}catch{s[o]=r;}else s[o]=r;te(s);}async deleteSecret(t,n){let r=D(),s=b[n]||n;return s in r?(delete r[s],te(r),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${N()}`}};function Ke(){}var Ve=v;ne.exports={JsonFallbackProvider:v,ScryptFallbackProvider:Ve,_resetWarningState:Ke};});var oe=_((sn,se)=>{var{execFile:je}=c("child_process"),{promisify:Je}=c("util"),{accessSync:Xe,constants:ze}=c("fs"),M=Je(je),H=class{static async isAvailable(){try{return Xe("/usr/bin/security",ze.X_OK),!0}catch{return false}}async getSecret(t,n){try{let{stdout:r}=await M("security",["find-generic-password","-w","-a",n,"-s",t]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await M("security",["add-generic-password","-U","-a",n,"-s",t,"-w",r]);}async deleteSecret(t,n){try{return await M("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};se.exports={MacOsKeyVaultProvider:H};});var ie=_((on,ae)=>{var{execFile:Qe,spawn:Ze}=c("child_process"),{promisify:et}=c("util"),{accessSync:tt,constants:nt}=c("fs"),ce=et(Qe),q=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let n of t)try{return tt(n,nt.X_OK),!0}catch{}return false}async getSecret(t,n){try{let{stdout:r}=await ce("secret-tool",["lookup","service",t,"account",n]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await new Promise((s,o)=>{let a=Ze("secret-tool",["store","--label",t,"service",t,"account",n]);a.on("error",o),a.on("close",S=>{S===0?s():o(new Error(`secret-tool exited with code ${S}`));}),a.stdin.write(r),a.stdin.end();});}async deleteSecret(t,n){try{return await ce("secret-tool",["clear","service",t,"account",n]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};ae.exports={LinuxKeyVaultProvider:q};});var ue=_((cn,le)=>{var Y=class{static async isAvailable(){try{return await c("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,n){return c("keytar").getPassword(t,n)}async setSecret(t,n,r){await c("keytar").setPassword(t,n,r);}async deleteSecret(t,n){return c("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};le.exports={WindowsKeyVaultProvider:Y};});var Te=_((an,_e)=>{async function Ee(){let{JsonFallbackProvider:e}=re();return await rt()??new e}async function rt(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=oe();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=ie();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=ue();return await e.isAvailable()?new e:null}default:return null}}var st=Ee;_e.exports={createSecretVaultProvider:Ee,createKeyVaultProvider:st};});var K=_((ln,de)=>{var{createSecretVaultProvider:ot}=Te(),{VAULT:G}=p(),A=G.SERVICE,$=G.ACCOUNT_CREDS,B=G.ACCOUNT_TOKEN,W=null;function L(){return W||(W=ot()),W}async function fe(){let t=await(await L()).getSecret(A,$);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function ct(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await L()).setSecret(A,$,JSON.stringify(e));}async function at(){let e=await L();await e.deleteSecret(A,$),await e.deleteSecret(A,B);}async function it(e){await(await L()).setSecret(A,B,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function x(){let t=await(await L()).getSecret(A,B);if(!t)return null;try{let n=JSON.parse(t);return {accessToken:n.accessToken,expiresAt:n.expiresAt}}catch{return null}}async function lt(){let e=await x();return e?new Date(e.expiresAt)>new Date:false}async function ut(){let e=await x();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email||n.preferred_username||n.upn||n.sub||null}catch{return null}}async function Et(){let e=await L();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function _t(){let e=await fe();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}de.exports={getFlowCredentials:fe,saveFlowCredentials:ct,clearFlowCredentials:at,saveTokenCache:it,getTokenCache:x,isTokenValid:lt,getEmailFromToken:ut,getConfigPath:Et,hasCredentials:_t};});var V=_((un,Se)=>{var Tt=c("https"),ft=c("http"),{FLOW_URLS:dt}=p(),pt=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function St(e){if(!pt.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var pe={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function Ot(e,t){try{let n=JSON.parse(t);if(typeof n.error=="string"&&pe[n.error])return new Error(pe[n.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function ht(e){return new Promise((t,n)=>{try{St(e.tenant);}catch(l){return n(l)}let r=JSON.stringify({clientSecret:e.clientSecret}),s=new URL(dt.AUTH_ENGINE),o=s.protocol==="https:",a={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),FlowTenant:e.tenant}},f=(o?Tt:ft).request(a,l=>{let u=[];l.on("data",E=>u.push(E)),l.on("end",()=>{let E=u.join("");if(l.statusCode>=400)return n(Ot(l.statusCode,E));let d;try{d=JSON.parse(E);}catch{return n(new Error("Invalid response from auth engine"))}let w=d.expires_at??new Date(Date.now()+(d.expires_in??3600)*1e3).toISOString();t({accessToken:d.access_token,expiresAt:w});});});f.on("error",l=>n(new Error(`Network error: ${l.message}`))),f.write(r),f.end();})}Se.exports={getToken:ht};});var ye=_((En,Le)=>{var i=c("fs"),C=c("path"),Oe=c("os"),{FLOW_URLS:At,INSTALLER:R,HOOK_TIMEOUTS:m,NATIVE_OTEL:Lt,LLM_PROXY:yt}=p(),{getToken:wt}=V();function J(){return process.platform==="win32"?C.join(process.env.APPDATA||C.join(Oe.homedir(),"AppData","Roaming"),"Claude","settings.json"):C.join(Oe.homedir(),".claude","settings.json")}var Nt=R.LOCK_STALE_MS;function he(e){try{let t=i.statSync(e);Date.now()-t.mtimeMs>Nt&&i.unlinkSync(e);}catch{}try{i.writeFileSync(e,String(process.pid),{flag:"wx"});}catch(t){throw t.code==="EEXIST"?new Error("Another install is already in progress. If this is stale, remove: "+e):t}}function Ae(e){try{i.unlinkSync(e);}catch{}}function gt(){let e=J(),t=e+".lock";i.mkdirSync(C.dirname(e),{recursive:true}),he(t);try{if(i.existsSync(e)){i.copyFileSync(e,e+".bkp");try{i.chmodSync(e+".bkp",384);}catch{}}let n={};try{n=JSON.parse(i.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,Lt),Object.assign(n.env,yt),n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object")&&(n.hooks={});let r=(s,o)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${s}`,timeout:o}]});n.hooks.UserPromptSubmit=[r("UserPromptSubmit",m.UserPromptSubmit)],n.hooks.PreToolUse=[r("PreToolUse",m.PreToolUse)],n.hooks.PostToolUse=[r("PostToolUse",m.PostToolUse)],n.hooks.Stop=[r("Stop",m.Stop)],i.writeFileSync(e,JSON.stringify(n,null,2)+`
3
- `,{encoding:"utf8",mode:384});try{i.chmodSync(e,384);}catch{}}finally{Ae(t);}return e}async function Rt(e){let t;try{t=(await wt(e)).accessToken;}catch{return false}return t?new Promise(n=>{j(`Bearer ${t}`,n,1);}):false}function j(e,t,n){let r=new URL(At.GATEWAY_TRACES),s=JSON.stringify({resourceSpans:[],validation_run:true}),o=r.protocol==="https:",a={hostname:r.hostname,port:r.port||(o?443:80),path:r.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:e,"Content-Length":Buffer.byteLength(s)}},f=(o?c("https"):c("http")).request(a,l=>{l.resume(),l.statusCode===200||l.statusCode===204?t(true):n<R.CONNECTIVITY_MAX_RETRY?setTimeout(()=>j(e,t,n+1),R.CONNECTIVITY_RETRY_MS):t(false);});f.on("error",()=>{n<R.CONNECTIVITY_MAX_RETRY?setTimeout(()=>j(e,t,n+1),R.CONNECTIVITY_RETRY_MS):t(false);}),f.write(s),f.end();}function Ct(e){let t=J(),n=t+".lock";i.mkdirSync(C.dirname(t),{recursive:true}),he(n);try{let r={};try{r=JSON.parse(i.readFileSync(t,"utf8"));}catch{}(!r.env||typeof r.env!="object")&&(r.env={}),Object.assign(r.env,e),i.writeFileSync(t,JSON.stringify(r,null,2)+`
4
- `,{encoding:"utf8",mode:384});try{i.chmodSync(t,384);}catch{}}finally{Ae(n);}}Le.exports={getClaudeSettingsPath:J,writeClaudeSettings:gt,addEnvToClaudeSettings:Ct,validateConnectivity:Rt};});var ge=_((_n,Ne)=>{var{writeFileSync:It}=c("fs"),{tmpdir:vt}=c("os"),{join:mt}=c("path"),{DEBUG_LOG_FILENAME:Ut,ENV:Pt}=p(),we=mt(vt(),Ut);function Ft(...e){if(process.env[Pt.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
5
- `;try{It(we,t,{flag:"a"});}catch(n){process.stderr.write(`[flow-obs debug ERROR] ${n.message}
6
- `);}}Ne.exports={dbg:Ft,DEBUG_LOG:we};});var Ie=_((Tn,Ce)=>{var{getFlowCredentials:X,isTokenValid:kt,getEmailFromToken:I,getTokenCache:bt,saveTokenCache:Dt}=K(),{getToken:Mt}=V(),{FLOW_BASE_URL:Ht,ENV:T,FEATURES:z}=p(),{dbg:y}=ge(),qt=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function Yt(e){return qt.some(t=>t.test(e))}function U(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:r,clientSecret:s,tenant:o}=n;return !r||!s||!o?null:{clientId:r,clientSecret:s,tenant:o}}catch{return null}}function Wt(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),n=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${n}.`}function Q(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}if(!(process.env[T.FLOW_OBS_ALLOW_HTTP]==="true")&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(Yt(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function Gt(){let e=U(process.env[T.ANTHROPIC_AUTH_TOKEN]);if(e)return {user:await I().catch(()=>null)||e.clientId,tenant:e.tenant};if(z.KEYCHAIN_ENABLED)try{let t=await X();if(!t)return {user:"",tenant:""};let n=await I()||t.clientId||"",r=t.tenant||"";return {user:n,tenant:r}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function $t(e){if(await kt())return (await bt()).accessToken;y("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Mt(e);return await Dt(t),y("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function Bt(e,t){let n=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/langfuse/traces",authHeader:`Bearer ${n}`}}function xt(e,t,n){let r=Buffer.from(`${t}:${n}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${r}`}}async function Re(){let e=[],t=process.env[T.ANTHROPIC_MODEL]||"",n=process.env[T.FLOW_TELEMETRY]==="true",r=process.env[T.LANGFUSE_BASE_URL],s=process.env[T.LANGFUSE_PUBLIC_KEY],o=process.env[T.LANGFUSE_SECRET_KEY];if(n&&r&&s&&o){let u="",E="",d=U(process.env[T.ANTHROPIC_AUTH_TOKEN]);if(d)u=await I().catch(()=>null)||d.clientId,E=d.tenant;else if(z.KEYCHAIN_ENABLED)try{let P=await X();P&&(u=await I()||P.clientId,E=P.tenant);}catch{}let w={user:u||"",tenant:E||"",team:"",project:"",model:t};e.push({mode:"direct",...xt(Q(r),s,o),...w}),y("resolveCredentials","direct mode active",`user=${w.user}`,`tenant=${w.tenant}`);}let a=U(process.env[T.ANTHROPIC_AUTH_TOKEN]);if(y("resolveCredentials",a?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!a&&z.KEYCHAIN_ENABLED&&(a=await X(),a&&y("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)")),!a){if(e.length===0){let u=[];return u.authError=false,u}return e}let S;try{S=await $t(a);}catch(u){if(y("resolveCredentials",`token refresh failed: ${u.message}`),e.length>0)return e;let E=[];return E.authError=true,E}let f={user:await I()||a.clientId,tenant:a.tenant,team:"",project:"",model:t},l=process.env[T.FLOW_TELEMETRY_GATEWAY]||Ht;return e.push({mode:"gateway",...Bt(Q(l),{accessToken:S}),...f}),e}async function Kt(){return (await Re()).length>0}Ce.exports={credentialsAvailable:Kt,getIdentityFromToken:Gt,resolveCredentials:Re,validateUrl:Q,parseCredsFromAnthropicToken:U,buildAnthropicAuthToken:Wt};});var me=c("path"),{getFlowCredentials:Vt}=K(),{writeClaudeSettings:jt,addEnvToClaudeSettings:Jt}=ye(),{buildAnthropicAuthToken:Xt,parseCredsFromAnthropicToken:zt}=Ie(),{ENV:ve}=p(),Qt=me.resolve(__dirname,".."),Zt=process.env.INIT_CWD?me.resolve(process.env.INIT_CWD):null;Zt===Qt&&process.exit(0);async function en(){try{jt();}catch{}let e=await Vt();if(!e){process.stderr.write(`
2
+ 'use strict';var a=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var T=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var p=T((rn,Q)=>{var A=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",Z={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${A}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${A}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${A}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${A}/otel`},me={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},Fe="FLOW-nodejs",Ue="config.json",Pe={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},ke={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL||`${A}/flow-llm-proxy/`,ANTHROPIC_MODEL:process.env.FLOW_LLM_PROXY_MODEL||"anthropic.claude-4-6-sonnet",ANTHROPIC_SMALL_FAST_MODEL:process.env.FLOW_LLM_PROXY_SMALL_MODEL||"anthropic.claude-4-6-sonnet",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"},be={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:Z.OTEL_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},De={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES"},Me={KEYCHAIN_ENABLED:false},He={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Ye={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},qe={FILE_PREFIX:"flow-obs-buffer-",DEFAULT_TTL_DAYS:4,MIN_TTL_DAYS:1,MAX_TTL_DAYS:30,DEFAULT_MAX_FILES:50,MIN_MAX_FILES:1,MAX_MAX_FILES:500,REPLAY_BATCH_SIZE:10},We="flow-ai-obs-debug.log",Be={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},Ge="flow-obs-";Q.exports={FLOW_BASE_URL:A,FLOW_URLS:Z,VAULT:me,CONFIG_DIR_NAME:Fe,CONFIG_FILE_NAME:Ue,OTLP:Pe,LLM_PROXY:ke,NATIVE_OTEL:be,ENV:De,FEATURES:Me,INSTALLER:He,HOOK_TIMEOUTS:Ye,BUFFER:qe,DEBUG_LOG_FILENAME:We,STATE_FILE_PREFIX:Ge,TRACE_LIMITS:Be};});var ne=T((sn,te)=>{var g=a("fs"),O=a("path"),$e=a("os"),{CONFIG_DIR_NAME:U,CONFIG_FILE_NAME:P}=p(),k={credentials:"credentials","token-cache":"tokenCache"};function N(){let e=$e.homedir();if(process.platform==="darwin")return O.join(e,"Library","Preferences",U,P);if(process.platform==="win32"){let n=process.env.APPDATA||O.join(e,"AppData","Roaming");return O.join(n,U,P)}let t=process.env.XDG_CONFIG_HOME||O.join(e,".config");return O.join(t,U,P)}function b(){try{let e=g.readFileSync(N(),"utf8");return JSON.parse(e)}catch{return {}}}function ee(e){let t=N();g.mkdirSync(O.dirname(t),{recursive:true}),g.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var v=class{static isAvailable(){return true}static hasExistingData(){try{if(!g.existsSync(N()))return !1;let t=JSON.parse(g.readFileSync(N(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let r=b(),s=k[n]||n,o=r[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,n,r){let s=b(),o=k[n]||n;if(n==="token-cache")try{s[o]=JSON.parse(r);}catch{s[o]=r;}else s[o]=r;ee(s);}async deleteSecret(t,n){let r=b(),s=k[n]||n;return s in r?(delete r[s],ee(r),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${N()}`}};function xe(){}var Ke=v;te.exports={JsonFallbackProvider:v,ScryptFallbackProvider:Ke,_resetWarningState:xe};});var se=T((on,re)=>{var{execFile:Ve}=a("child_process"),{promisify:Xe}=a("util"),{accessSync:je,constants:Je}=a("fs"),D=Xe(Ve),M=class{static async isAvailable(){try{return je("/usr/bin/security",Je.X_OK),!0}catch{return false}}async getSecret(t,n){try{let{stdout:r}=await D("security",["find-generic-password","-w","-a",n,"-s",t]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await D("security",["add-generic-password","-U","-a",n,"-s",t,"-w",r]);}async deleteSecret(t,n){try{return await D("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};re.exports={MacOsKeyVaultProvider:M};});var ae=T((cn,ce)=>{var{execFile:ze,spawn:Ze}=a("child_process"),{promisify:Qe}=a("util"),{accessSync:et,constants:tt}=a("fs"),oe=Qe(ze),H=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let n of t)try{return et(n,tt.X_OK),!0}catch{}return false}async getSecret(t,n){try{let{stdout:r}=await oe("secret-tool",["lookup","service",t,"account",n]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await new Promise((s,o)=>{let c=Ze("secret-tool",["store","--label",t,"service",t,"account",n]);c.on("error",o),c.on("close",u=>{u===0?s():o(new Error(`secret-tool exited with code ${u}`));}),c.stdin.write(r),c.stdin.end();});}async deleteSecret(t,n){try{return await oe("secret-tool",["clear","service",t,"account",n]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};ce.exports={LinuxKeyVaultProvider:H};});var le=T((an,ie)=>{var Y=class{static async isAvailable(){try{return await a("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,n){return a("keytar").getPassword(t,n)}async setSecret(t,n,r){await a("keytar").setPassword(t,n,r);}async deleteSecret(t,n){return a("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};ie.exports={WindowsKeyVaultProvider:Y};});var _e=T((ln,Ee)=>{async function ue(){let{JsonFallbackProvider:e}=ne();return await nt()??new e}async function nt(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=se();return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=ae();return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=le();return await e.isAvailable()?new e:null}default:return null}}var rt=ue;Ee.exports={createSecretVaultProvider:ue,createKeyVaultProvider:rt};});var x=T((un,fe)=>{var{createSecretVaultProvider:st}=_e(),{VAULT:W}=p(),L=W.SERVICE,B=W.ACCOUNT_CREDS,G=W.ACCOUNT_TOKEN,q=null;function h(){return q||(q=st()),q}async function Te(){let t=await(await h()).getSecret(L,B);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function ot(e){if(!e.clientId||!e.clientSecret||!e.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await h()).setSecret(L,B,JSON.stringify(e));}async function ct(){let e=await h();await e.deleteSecret(L,B),await e.deleteSecret(L,G);}async function at(e){await(await h()).setSecret(L,G,JSON.stringify({accessToken:e.accessToken,expiresAt:e.expiresAt}));}async function $(){let t=await(await h()).getSecret(L,G);if(!t)return null;try{let n=JSON.parse(t);return {accessToken:n.accessToken,expiresAt:n.expiresAt}}catch{return null}}async function it(){let e=await $();return e?new Date(e.expiresAt)>new Date:false}async function lt(){let e=await $();if(!e||!e.accessToken)return null;try{let t=e.accessToken.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email||n.preferred_username||n.upn||n.sub||null}catch{return null}}async function ut(){let e=await h();if(typeof e.getStoragePath=="function")return e.getStoragePath();let t=process.platform;return t==="darwin"?"macOS Keychain":t==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function Et(){let e=await Te();return !!(e&&e.clientId&&e.clientSecret&&e.tenant)}fe.exports={getFlowCredentials:Te,saveFlowCredentials:ot,clearFlowCredentials:ct,saveTokenCache:at,getTokenCache:$,isTokenValid:it,getEmailFromToken:lt,getConfigPath:ut,hasCredentials:Et};});var K=T((En,Se)=>{var _t=a("https"),Tt=a("http"),{FLOW_URLS:ft}=p(),dt=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function St(e){if(!dt.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var de={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function pt(e,t){try{let n=JSON.parse(t);if(typeof n.error=="string"&&de[n.error])return new Error(de[n.error])}catch{}return e===401||e===403||e===500?new Error("Invalid credentials"):e>=400&&e<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function At(e){return new Promise((t,n)=>{try{St(e.tenant);}catch(l){return n(l)}let r=JSON.stringify({clientSecret:e.clientSecret}),s=new URL(ft.AUTH_ENGINE),o=s.protocol==="https:",c={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),FlowTenant:e.tenant}},d=(o?_t:Tt).request(c,l=>{let E=[];l.on("data",_=>E.push(_)),l.on("end",()=>{let _=E.join("");if(l.statusCode>=400)return n(pt(l.statusCode,_));let S;try{S=JSON.parse(_);}catch{return n(new Error("Invalid response from auth engine"))}let w=S.expires_at??new Date(Date.now()+(S.expires_in??3600)*1e3).toISOString();t({accessToken:S.access_token,expiresAt:w});});});d.on("error",l=>n(new Error(`Network error: ${l.message}`))),d.write(r),d.end();})}Se.exports={getToken:At};});var he=T((_n,Le)=>{var i=a("fs"),I=a("path"),pe=a("os"),{FLOW_URLS:Ot,INSTALLER:R,HOOK_TIMEOUTS:Lt,NATIVE_OTEL:ht,LLM_PROXY:yt}=p(),{getToken:wt}=K();function X(){return process.platform==="win32"?I.join(process.env.APPDATA||I.join(pe.homedir(),"AppData","Roaming"),"Claude","settings.json"):I.join(pe.homedir(),".claude","settings.json")}var Nt=R.LOCK_STALE_MS;function Ae(e){try{let t=i.statSync(e);Date.now()-t.mtimeMs>Nt&&i.unlinkSync(e);}catch{}try{i.writeFileSync(e,String(process.pid),{flag:"wx"});}catch(t){throw t.code==="EEXIST"?new Error("Another install is already in progress. If this is stale, remove: "+e):t}}function Oe(e){try{i.unlinkSync(e);}catch{}}function gt(e,t){let r=(Array.isArray(e)?e:[]).map(s=>{if(!Array.isArray(s?.hooks))return null;let o=s.hooks.filter(c=>!c.command?.startsWith?.("flow-ai-obs "));return o.length>0?{...s,hooks:o}:null}).filter(s=>s!=null);return [t,...r]}function Rt(){let e=X(),t=e+".lock";i.mkdirSync(I.dirname(e),{recursive:true});let n=[];Ae(t);try{if(i.existsSync(e)){i.copyFileSync(e,e+".bkp");try{i.chmodSync(e+".bkp",384);}catch{}}let r={};try{r=JSON.parse(i.readFileSync(e,"utf8"));}catch{}(!r.env||typeof r.env!="object")&&(r.env={}),Object.assign(r.env,ht),Object.assign(r.env,yt),r.otelHeadersHelper="flow-ai-obs otel-headers",(!r.hooks||typeof r.hooks!="object"||Array.isArray(r.hooks))&&(r.hooks={});let s=(c,u)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:u}]}),o=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"];for(let c of o){let u=gt(r.hooks[c],s(c,Lt[c]));u.length>1&&n.push(c),r.hooks[c]=u;}i.writeFileSync(e,JSON.stringify(r,null,2)+`
3
+ `,{encoding:"utf8",mode:384});try{i.chmodSync(e,384);}catch{}}finally{Oe(t);}return {settingsPath:e,preserved:n}}async function It(e){let t;try{t=(await wt(e)).accessToken;}catch{return false}return t?new Promise(n=>{V(`Bearer ${t}`,n,1);}):false}function V(e,t,n){let r=new URL(Ot.GATEWAY_TRACES),s=JSON.stringify({resourceSpans:[],validation_run:true}),o=r.protocol==="https:",c={hostname:r.hostname,port:r.port||(o?443:80),path:r.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:e,"Content-Length":Buffer.byteLength(s)}},d=(o?a("https"):a("http")).request(c,l=>{l.resume(),l.statusCode===200||l.statusCode===204?t(true):n<R.CONNECTIVITY_MAX_RETRY?setTimeout(()=>V(e,t,n+1),R.CONNECTIVITY_RETRY_MS):t(false);});d.on("error",()=>{n<R.CONNECTIVITY_MAX_RETRY?setTimeout(()=>V(e,t,n+1),R.CONNECTIVITY_RETRY_MS):t(false);}),d.write(s),d.end();}function Ct(e){let t=X(),n=t+".lock";i.mkdirSync(I.dirname(t),{recursive:true}),Ae(n);try{let r={};try{r=JSON.parse(i.readFileSync(t,"utf8"));}catch{}(!r.env||typeof r.env!="object")&&(r.env={}),Object.assign(r.env,e),i.writeFileSync(t,JSON.stringify(r,null,2)+`
4
+ `,{encoding:"utf8",mode:384});try{i.chmodSync(t,384);}catch{}}finally{Oe(n);}}Le.exports={getClaudeSettingsPath:X,writeClaudeSettings:Rt,addEnvToClaudeSettings:Ct,validateConnectivity:It};});var Ne=T((Tn,we)=>{var{writeFileSync:vt}=a("fs"),{tmpdir:mt}=a("os"),{join:Ft}=a("path"),{DEBUG_LOG_FILENAME:Ut,ENV:Pt}=p(),ye=Ft(mt(),Ut);function kt(...e){if(process.env[Pt.FLOW_OBS_DEBUG]!=="1")return;let t=`[${new Date().toISOString()}] ${e.join(" ")}
5
+ `;try{vt(ye,t,{flag:"a"});}catch(n){process.stderr.write(`[flow-obs debug ERROR] ${n.message}
6
+ `);}}we.exports={dbg:kt,DEBUG_LOG:ye};});var Ie=T((fn,Re)=>{var{getFlowCredentials:j,isTokenValid:bt,getEmailFromToken:C,getTokenCache:Dt,saveTokenCache:Mt}=x(),{getToken:Ht}=K(),{FLOW_BASE_URL:Yt,ENV:f,FEATURES:J}=p(),{dbg:y}=Ne(),qt=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^0\.0\.0\.0$/,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i,/(?:^|\.)localtest\.me\.?$/i,/(?:^|\.)lvh\.me\.?$/i,/(?:^|\.)vcap\.me\.?$/i];function Wt(e){return qt.some(t=>t.test(e))}function m(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let n=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:r,clientSecret:s,tenant:o}=n;return !r||!s||!o?null:{clientId:r,clientSecret:s,tenant:o}}catch{return null}}function Bt(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),n=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${n}.`}function z(e){let t;try{t=new URL(e);}catch{throw new Error(`Invalid URL: ${e}`)}let n=process.env[f.FLOW_OBS_ALLOW_HTTP]==="true";if(!n&&t.protocol!=="https:")throw new Error(`URL must use HTTPS: ${e}`);if(t.username||t.password)throw new Error(`URL must not contain embedded credentials: ${e}`);if(!n&&Wt(t.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${t.hostname}`);return e}async function Gt(){let e=m(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(e)return {user:await C().catch(()=>null)||e.clientId,tenant:e.tenant};if(J.KEYCHAIN_ENABLED)try{let t=await j();if(!t)return {user:"",tenant:""};let n=await C()||t.clientId||"",r=t.tenant||"";return {user:n,tenant:r}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function $t(e){if(await bt())return (await Dt()).accessToken;y("getOrRefreshToken","token expired \u2014 refreshing via auth-engine");let t=await Ht(e);return await Mt(t),y("getOrRefreshToken",`token refreshed, expires=${t.expiresAt}`),t.accessToken}function xt(e,t){let n=t&&t.accessToken?t.accessToken:"";return {endpoint:e.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${n}`}}function Kt(e,t,n){let r=Buffer.from(`${t}:${n}`).toString("base64");return {endpoint:e.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${r}`}}async function ge(){let e=[],t=process.env[f.ANTHROPIC_MODEL]||"",n=process.env[f.FLOW_TELEMETRY]==="true",r=process.env[f.LANGFUSE_BASE_URL],s=process.env[f.LANGFUSE_PUBLIC_KEY],o=process.env[f.LANGFUSE_SECRET_KEY];if(n&&r&&s&&o){let E="",_="",S=m(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(S)E=await C().catch(()=>null)||S.clientId,_=S.tenant;else if(J.KEYCHAIN_ENABLED)try{let F=await j();F&&(E=await C()||F.clientId,_=F.tenant);}catch{}let w={user:E||"",tenant:_||"",team:"",project:"",model:t};e.push({mode:"direct",...Kt(z(r),s,o),...w}),y("resolveCredentials","direct mode active",`user=${w.user}`,`tenant=${w.tenant}`);}let c=m(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(y("resolveCredentials",c?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!c&&J.KEYCHAIN_ENABLED&&(c=await j(),c&&y("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)")),!c){if(e.length===0){let E=[];return E.authError=false,E}return e}let u;try{u=await $t(c);}catch(E){if(y("resolveCredentials",`token refresh failed: ${E.message}`),e.length>0)return e;let _=[];return _.authError=true,_}let d={user:await C()||c.clientId,tenant:c.tenant,team:"",project:"",model:t},l=process.env[f.FLOW_TELEMETRY_GATEWAY]||Yt;return e.push({mode:"gateway",...xt(z(l),{accessToken:u}),...d}),e}async function Vt(){return (await ge()).length>0}Re.exports={credentialsAvailable:Vt,getIdentityFromToken:Gt,resolveCredentials:ge,validateUrl:z,parseCredsFromAnthropicToken:m,buildAnthropicAuthToken:Bt};});var ve=a("path"),{getFlowCredentials:Xt}=x(),{writeClaudeSettings:jt,addEnvToClaudeSettings:Jt}=he(),{buildAnthropicAuthToken:zt,parseCredsFromAnthropicToken:Zt}=Ie(),{ENV:Ce}=p(),Qt=ve.resolve(__dirname,".."),en=process.env.INIT_CWD?ve.resolve(process.env.INIT_CWD):null;en===Qt&&process.exit(0);async function tn(){try{jt();}catch{}let e=await Xt();if(!e){process.stderr.write(`
7
7
  [flow-ai-obs] No credentials found.
8
8
  Run \`flow-ai-obs auth login\` to authenticate and enable telemetry.
9
9
 
10
- `);return}let t=zt(process.env[ve.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let r=Xt(e);Jt({[ve.ANTHROPIC_AUTH_TOKEN]:r});}catch{}}en().catch(()=>{});
10
+ `);return}let t=Zt(process.env[Ce.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let r=zt(e);Jt({[Ce.ANTHROPIC_AUTH_TOKEN]:r});}catch{}}tn().catch(()=>{});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciandt-flow/flow-ai-obs",
3
- "version": "0.3.1-beta.74",
3
+ "version": "0.4.1-beta.66",
4
4
  "description": "Claude Code hooks for Langfuse OTLP tracing — cross-platform",
5
5
  "main": "dist/index.js",
6
6
  "bin": {