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