@ciandt-flow/flow-ai-obs 0.5.2-beta.220 → 0.5.2-beta.227
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 +64 -59
- package/dist/setup.js +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var
|
|
2
|
+
'use strict';var On=require('https'),w=require('fs'),Kt=require('os'),pt=require('path'),child_process=require('child_process'),Bn=require('http'),util=require('util'),crypto=require('crypto');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var On__namespace=/*#__PURE__*/_interopNamespace(On);var w__namespace=/*#__PURE__*/_interopNamespace(w);var Kt__namespace=/*#__PURE__*/_interopNamespace(Kt);var pt__namespace=/*#__PURE__*/_interopNamespace(pt);var Bn__namespace=/*#__PURE__*/_interopNamespace(Bn);var oe=Object.defineProperty;var En=Object.getOwnPropertyDescriptor;var wn=Object.getOwnPropertyNames;var Tn=Object.prototype.hasOwnProperty;var Dt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var p=(t,e)=>()=>(t&&(e=t(t=0)),e);var _n=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),U=(t,e)=>{for(var r in e)oe(t,r,{get:e[r],enumerable:true});},yn=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of wn(e))!Tn.call(t,s)&&s!==r&&oe(t,s,{get:()=>e[s],enumerable:!(n=En(e,s))||n.enumerable});return t};var N=t=>yn(oe({},"__esModule",{value:true}),t);var Bt=_n((ro,kn)=>{kn.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.5.2-beta.227",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:"jest",typecheck:"tsc --noEmit",lint:"eslint src bin scripts",format:'prettier --write "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"format:check":'prettier --check "src/**/*.ts" "bin/**/*.ts" "scripts/**/*.ts"',"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 dist/cli.js install","auth:login":"node dist/cli.js auth login","auth:logout":"node dist/cli.js auth logout","auth:status":"node dist/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","@types/jest":"^30.0.0","@types/node":"^25.8.0",jest:"^30.4.2","ts-jest":"^29.4.9",tsup:"^8.5.1","eslint-config-prettier":"^10.1.5",prettier:"^3.5.3",typescript:"^6.0.3","typescript-eslint":"^8.33.0"},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 ie={};U(ie,{bold:()=>H,cyan:()=>B,dim:()=>E,green:()=>P,red:()=>D,yellow:()=>O});function it(t,e){return An?r=>`\x1B[${t}m${r}\x1B[${e}m`:r=>r}var An,P,D,O,B,H,E,at=p(()=>{An=!process.env.NO_COLOR&&process.stdout.isTTY;P=it("32","39"),D=it("31","39"),O=it("33","39"),B=it("36","39"),H=it("1","22"),E=it("2","22");});var Ht={};U(Ht,{checkForUpdate:()=>Un,isNewer:()=>ce});function ct(){return ae||(ae=Bt()),ae}function ce(t,e){let r=o=>{let i=String(o).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return i?[+i[1],+i[2],+i[3]]:null},n=r(t),s=r(e);return !n||!s?false:s[0]!==n[0]?s[0]>n[0]:s[1]!==n[1]?s[1]>n[1]:s[2]>n[2]}function Pn(){try{let t=JSON.parse(w__namespace.default.readFileSync(Ve,"utf8"));return typeof t.latestVersion!="string"||Date.now()-t.checkedAt>=vn?null:t}catch{return null}}function Rn(t,e){try{w__namespace.default.writeFileSync(Ve,JSON.stringify({latestVersion:t,updatePriority:e??null,checkedAt:Date.now()}),{mode:384});}catch{}}function Cn(t){let e=ct().name,r=On__namespace.default.get(`https://registry.npmjs.org/${encodeURIComponent(e)}/latest`,{timeout:Nn},n=>{if(n.statusCode!==200)return n.resume(),t(new Error(`HTTP ${n.statusCode}`));let s="";n.setEncoding("utf8"),n.on("data",o=>{s+=o;}),n.on("end",()=>{try{let o=JSON.parse(s);if(typeof o.version!="string")throw new Error("no version field");t(null,{version:o.version,updatePriority:typeof o.updatePriority=="string"?o.updatePriority:null});}catch(o){t(o);}});});r.on("error",t),r.on("timeout",()=>{r.destroy(new Error("timeout"));});}function Be(t){let e=ct().name,n=` Update available: ${ct().version} \u2192 ${t}`,s=` Run: npm install -g ${e}`,o=Math.max(n.length,s.length)+2,i="\u2500".repeat(o);process.stderr.write(`
|
|
3
3
|
\u256D${i}\u256E
|
|
4
4
|
\u2502${n.padEnd(o)}\u2502
|
|
5
5
|
\u2502${s.padEnd(o)}\u2502
|
|
@@ -8,66 +8,69 @@
|
|
|
8
8
|
`);}function He(t){let e=ct().name;process.stderr.write(`
|
|
9
9
|
[${e}] Critical update detected \u2014 auto-updating to ${t}...
|
|
10
10
|
|
|
11
|
-
`),child_process.spawn("npm",["install","-g",`${e}@${t}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}function
|
|
12
|
-
`;try{w.writeFileSync(
|
|
13
|
-
`);}}var
|
|
14
|
-
|
|
15
|
-
`,{encoding:"utf8",mode:384});try{w__namespace.chmodSync(e,384);}catch{}}finally{qe(r);}}var Yn,It=p(()=>{T();bt();Yn=ut.LOCK_STALE_MS;});function vt(){let t=ue__namespace.default.homedir();if(process.platform==="darwin")return pt__namespace.default.join(t,"Library","Preferences",Yt,Gt);if(process.platform==="win32"){let r=process.env.APPDATA??pt__namespace.default.join(t,"AppData","Roaming");return pt__namespace.default.join(r,Yt,Gt)}let e=process.env.XDG_CONFIG_HOME??pt__namespace.default.join(t,".config");return pt__namespace.default.join(e,Yt,Gt)}function fe(){try{let t=w__namespace.default.readFileSync(vt(),"utf8");return JSON.parse(t)}catch{return {}}}function ze(t){let e=vt();w__namespace.default.mkdirSync(pt__namespace.default.dirname(e),{recursive:true}),w__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var pe,qt,Ze=p(()=>{T();pe={credentials:"credentials","token-cache":"tokenCache"};qt=class{static isAvailable(){return true}static hasExistingData(){try{if(!w__namespace.default.existsSync(vt()))return !1;let e=JSON.parse(w__namespace.default.readFileSync(vt(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=fe(),s=pe[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=fe(),o=pe[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;ze(s);}async deleteSecret(e,r){let n=fe(),s=pe[r]??r;return s in n?(delete n[s],ze(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${vt()}`}};});var Qe={};U(Qe,{MacOsKeyVaultProvider:()=>ge});var me,ge,tr=p(()=>{me=util.promisify(child_process.execFile),ge=class{static async isAvailable(){try{return w.accessSync("/usr/bin/security",w.constants.X_OK),!0}catch{return false}}async getSecret(e,r){try{let{stdout:n}=await me("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await me("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await me("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};});var rr={};U(rr,{LinuxKeyVaultProvider:()=>he});var er,he,nr=p(()=>{er=util.promisify(child_process.execFile),he=class{static async isAvailable(){let e=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of e)try{return w.accessSync(r,w.constants.X_OK),!0}catch{}return false}async getSecret(e,r){try{let{stdout:n}=await er("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((s,o)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",o),i.on("close",a=>{a===0?s():o(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await er("secret-tool",["clear","service",e,"account",r]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var sr={};U(sr,{WindowsKeyVaultProvider:()=>Se});var Se,or=p(()=>{Se=class{static async isAvailable(){try{return await Dt("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(e,r){return Dt("keytar").getPassword(e,r)}async setSecret(e,r,n){await Dt("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return Dt("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});async function ir(){return await rs()??new qt}async function rs(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(tr(),Qe));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(nr(),rr));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(or(),sr));return await t.isAvailable()?new t:null}default:return null}}var ar=p(()=>{Ze();});function mt(){return Ee||(Ee=ir()),Ee}async function _(){let e=await(await mt()).getSecret(ft,we);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function ye(t){if(!t.clientId||!t.clientSecret||!t.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await mt()).setSecret(ft,we,JSON.stringify(t));}async function cr(){let t=await mt();await t.deleteSecret(ft,we),await t.deleteSecret(ft,Te);}async function Jt(t){await(await mt()).setSecret(ft,Te,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt}));}async function gt(){let e=await(await mt()).getSecret(ft,Te);if(!e)return null;try{let r=JSON.parse(e);return {accessToken:r.accessToken,expiresAt:r.expiresAt}}catch{return null}}async function ht(){let t=await gt();return t?new Date(t.expiresAt)>new Date:false}async function Q(){let t=await gt();if(!t||!t.accessToken)return null;try{let e=t.accessToken.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email??r.preferred_username??r.upn??r.sub??null}catch{return null}}async function _e(){let t=await mt();if(typeof t.getStoragePath=="function")return t.getStoragePath();let e=process.platform;return e==="darwin"?"macOS Keychain":e==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function lr(){let t=await _();return !!(t&&t.clientId&&t.clientSecret&&t.tenant)}var ft,we,Te,Ee,St=p(()=>{ar();T();ft=Vt.SERVICE,we=Vt.ACCOUNT_CREDS,Te=Vt.ACCOUNT_TOKEN,Ee=null;});function ss(t){return ns.some(e=>e.test(t))}function os(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email||r.preferred_username||r.upn||r.sub||null}catch{return null}}function G(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:s,tenant:o}=r;return !n||!s||!o?null:{clientId:n,clientSecret:s,tenant:o}}catch{return null}}function dr(t){let e=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant})).toString("base64url");return `${e}.${r}.`}function ur(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[f.FLOW_OBS_ALLOW_HTTP]==="true";if(!r&&e.protocol!=="https:")throw new Error(`URL must use HTTPS: ${t}`);if(e.username||e.password)throw new Error(`URL must not contain embedded credentials: ${t}`);if(!r&&ss(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function pr(){let t=G(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(t)return {user:await Q().catch(()=>null)??t.clientId,tenant:t.tenant};if(Wt.KEYCHAIN_ENABLED)try{let e=await _();if(!e)return {user:"",tenant:""};let r=await Q()??e.clientId??"",n=e.tenant??"";return {user:r,tenant:n}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function is(t){if(await ht()){let r=await gt();return l("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken}l("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let e=await Y(t);try{await Jt(e);}catch(r){l("getOrRefreshToken",`token cache save failed (non-fatal): ${r.message}`);}return l("getOrRefreshToken",`token refreshed, expires=${e.expiresAt}`),e.accessToken}function as(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function cs(t,e,r){let n=Buffer.from(`${e}:${r}`).toString("base64");return {endpoint:t.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${n}`}}async function tt(){let t=[],e=process.env[f.ANTHROPIC_MODEL]??"",r=G(process.env[f.ANTHROPIC_AUTH_TOKEN]);l("resolveCredentials",r?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!r&&Wt.KEYCHAIN_ENABLED&&(r=await _(),r&&l("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)"));let n=r?r.tenant:"",s=process.env[f.FLOW_TELEMETRY]==="true",o=process.env[f.LANGFUSE_BASE_URL],i=process.env[f.LANGFUSE_PUBLIC_KEY],a=process.env[f.LANGFUSE_SECRET_KEY];if(s&&o&&i&&a){let m="",k=n;if(r)m=await Q().catch(()=>null)??r.clientId;else if(Wt.KEYCHAIN_ENABLED)try{let O=await _();O&&(m=await Q()??O.clientId,k=O.tenant);}catch{}let y={user:m??"",tenant:k??"",team:"",project:"",model:e};t.push({mode:"direct",...cs(ur(o),i,a),...y}),l("resolveCredentials","direct mode active",`user=${y.user}`,`tenant=${y.tenant}`);}if(!r){if(t.length===0){let m=[];return m.authError=false,m}return t}let c;try{c=await is(r);}catch(m){if(l("resolveCredentials",`token refresh failed: ${m.message}`,`(tenant=${r.tenant} clientId=${r.clientId})`),t.length>0)return t;let k=[];return k.authError=true,k}let S={user:os(c)??r.clientId,tenant:n,team:"",project:"",model:e},A=process.env[f.FLOW_TELEMETRY_GATEWAY]??V;return t.push({mode:"gateway",...as(ur(A),{accessToken:c}),...S}),t}async function fr(){return (await tt()).length>0}var ns,et=p(()=>{St();bt();T();$();ns=[/^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];});var hr={};U(hr,{runLogin:()=>K,runLogout:()=>fs,runStatus:()=>ms});function W(t){return typeof t=="string"?t.replace(ls,""):t}function Pt(t,e={}){return new Promise((r,n)=>{let{masked:s=false,defaultValue:o=""}=e;process.stdout.write(t+o);let i=o;function a(){try{process.stdin.setRawMode(!1);}catch{}}process.once("uncaughtException",a),process.once("unhandledRejection",a);let c=S=>{if(S===""){u(),n(new Error("SIGINT"));return}if(S==="\r"||S===`
|
|
11
|
+
`),child_process.spawn("npm",["install","-g",`${e}@${t}`],{detached:true,stdio:"ignore",windowsHide:true}).unref();}function Un(){try{let t=Pn();if(t){ce(ct().version,t.latestVersion)&&(t.updatePriority==="auto"?He(t.latestVersion):Be(t.latestVersion));return}setImmediate(()=>{Cn((e,r)=>{e||!r||(Rn(r.version,r.updatePriority),ce(ct().version,r.version)&&(r.updatePriority==="auto"?He(r.version):Be(r.version)));});});}catch{}}var ae,Ve,vn,Nn,jt=p(()=>{Ve=pt__namespace.default.join(Kt__namespace.default.tmpdir(),"flow-obs-update-cache.json"),vn=1440*60*1e3,Nn=3e3;});var Y,Z,Vt,Yt,Gt,le,Lt,lt,f,Wt,ut,Ye,R,Ge,F,T=p(()=>{Y=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",Z={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${Y}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${Y}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${Y}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${Y}/otel`},Vt={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},Yt="FLOW-nodejs",Gt="config.json",le={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},Lt={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL??`${Y}/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"},lt={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"},f={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES"},Wt={KEYCHAIN_ENABLED:false},ut={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3},Ye={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15},R={FILE_PREFIX:"flow-obs-buffer-",DEFAULT_TTL_DAYS:4,MIN_TTL_DAYS:1,MAX_TTL_DAYS:30,DEFAULT_MAX_FILES:50,MIN_MAX_FILES:1,MAX_MAX_FILES:500,REPLAY_BATCH_SIZE:10},Ge="flow-ai-obs-debug.log",F={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60},{API_URL:process.env.FLOW_METRICS_URL||`${Y}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"};});function l(...t){if(process.env[f.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
|
|
12
|
+
`;try{w.writeFileSync(Mn,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
|
|
13
|
+
`);}}var Mn,$=p(()=>{T();Mn=pt.join(Kt.tmpdir(),Ge);});function jn(t){if(!Hn.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}function Vn(t,e){let r=e.length>400?e.slice(0,400)+"\u2026":e;l("toAuthError",`status=${t} body=${r}`);try{let n=JSON.parse(e);if(typeof n.error=="string"&&(l("toAuthError",`api_error_code=${n.error}`+(n.message?` api_message=${n.message}`:"")),We[n.error]))return new Error(We[n.error])}catch{}return t===401||t===403||t===500?new Error("Invalid credentials"):t>=400&&t<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function G(t){return new Promise((e,r)=>{try{jn(t.tenant);}catch(u){return r(u)}let n=JSON.stringify({clientSecret:t.clientSecret}),s=new URL(Z.AUTH_ENGINE),o=s.protocol==="https:",i={hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:t.tenant}};l("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let c=(o?On__namespace.default:Bn__namespace.default).request(i,u=>{let S=[];u.on("data",A=>S.push(A)),u.on("end",()=>{let A=S.join("");if((u.statusCode??0)>=400)return r(Vn(u.statusCode??0,A));let m;try{m=JSON.parse(A);}catch{return r(new Error("Invalid response from auth engine"))}let k=m.expires_at??new Date(Date.now()+(m.expires_in??3600)*1e3).toISOString();e({accessToken:m.access_token??"",expiresAt:k});});});c.on("error",u=>r(new Error(`Network error: ${u.message}`))),c.write(n),c.end();})}var Hn,We,bt=p(()=>{T();$();Hn=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;We={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 j(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let t=process.env.USERPROFILE;if(t){let e=t.replace(/^([A-Za-z]):/,(r,n)=>`/mnt/${n.toLowerCase()}`).replace(/\\/g,"/");return pt__namespace.join(e,".claude","settings.json")}return pt__namespace.join(Kt__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let t=process.env.USERPROFILE||Kt__namespace.homedir();return pt__namespace.join(t,".claude","settings.json")}if(process.platform==="linux"&&process.getuid?.()===0&&process.env.SUDO_USER){let e=child_process.spawnSync("getent",["passwd",process.env.SUDO_USER],{encoding:"utf8",timeout:5e3}).stdout?.split(":")[5]?.trim();if(e)return pt__namespace.join(e,".claude","settings.json")}return pt__namespace.join(Kt__namespace.homedir(),".claude","settings.json")}function Ke(){return process.platform==="linux"&&process.getuid?.()===0&&process.env.SUDO_USER?`Running as root via sudo is not recommended.
|
|
14
|
+
Configure npm to install globals without sudo:
|
|
15
|
+
npm config set prefix '~/.npm-global'
|
|
16
|
+
export PATH=~/.npm-global/bin:$PATH`:null}var ue=p(()=>{});function qe(t){try{let e=w__namespace.statSync(t);Date.now()-e.mtimeMs>Kn&&w__namespace.unlinkSync(t);}catch{}try{w__namespace.writeFileSync(t,String(process.pid),{flag:"wx"});}catch(e){throw e.code==="EEXIST"?new Error("Another install is already in progress. If this is stale, remove: "+t):e}}function Je(t){try{w__namespace.unlinkSync(t);}catch{}}function qn(t,e){let n=(Array.isArray(t)?t:[]).map(s=>{if(!Array.isArray(s?.hooks))return null;let o=s.hooks.filter(i=>!i.command?.startsWith?.("flow-ai-obs "));return o.length>0?{...s,hooks:o}:null}).filter(s=>s!=null);return [e,...n]}function Xe(){let t=j(),e=t+".lock",r=[];w__namespace.mkdirSync(pt__namespace.dirname(t),{recursive:true}),qe(e);try{if(w__namespace.existsSync(t)){w__namespace.copyFileSync(t,t+".bkp");try{w__namespace.chmodSync(t+".bkp",384);}catch{}}let n={};try{n=JSON.parse(w__namespace.readFileSync(t,"utf8"));}catch{}let s=n.env&&typeof n.env=="object"?n.env:{};n.env={...lt,...Lt,...s},n.otelHeadersHelper="flow-ai-obs otel-headers",(!n.hooks||typeof n.hooks!="object"||Array.isArray(n.hooks))&&(n.hooks={});let o=(c,u)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:u}]}),i=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],a=n.hooks;for(let c of i){let u=qn(a[c],o(c,Ye[c]));u.length>1&&r.push(c),a[c]=u;}w__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
|
|
17
|
+
`,{encoding:"utf8",mode:384});try{w__namespace.chmodSync(t,384);}catch{}}finally{Je(e);}return {settingsPath:t,preserved:r}}async function ze(t){let e;try{e=(await G(t)).accessToken;}catch{return false}return e?new Promise(r=>{de(`Bearer ${e}`,r,1);}):false}function de(t,e,r){let n=new URL(Z.GATEWAY_TRACES),s=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:t,"Content-Length":Buffer.byteLength(s)}},c=(o?On__namespace:Bn__namespace).request(i,u=>{u.resume(),u.statusCode===200||u.statusCode===204?e(true):r<ut.CONNECTIVITY_MAX_RETRY?setTimeout(()=>de(t,e,r+1),ut.CONNECTIVITY_RETRY_MS):e(false);});c.on("error",()=>{r<ut.CONNECTIVITY_MAX_RETRY?setTimeout(()=>de(t,e,r+1),ut.CONNECTIVITY_RETRY_MS):e(false);}),c.write(s),c.end();}function qt(t){let e=j(),r=e+".lock";w__namespace.mkdirSync(pt__namespace.dirname(e),{recursive:true}),qe(r);try{let n={};try{n=JSON.parse(w__namespace.readFileSync(e,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,t),w__namespace.writeFileSync(e,JSON.stringify(n,null,2)+`
|
|
18
|
+
`,{encoding:"utf8",mode:384});try{w__namespace.chmodSync(e,384);}catch{}}finally{Je(r);}}var Kn,It=p(()=>{T();bt();ue();Kn=ut.LOCK_STALE_MS;});function vt(){let t=Kt__namespace.default.homedir();if(process.platform==="darwin")return pt__namespace.default.join(t,"Library","Preferences",Yt,Gt);if(process.platform==="win32"){let r=process.env.APPDATA??pt__namespace.default.join(t,"AppData","Roaming");return pt__namespace.default.join(r,Yt,Gt)}let e=process.env.XDG_CONFIG_HOME??pt__namespace.default.join(t,".config");return pt__namespace.default.join(e,Yt,Gt)}function me(){try{let t=w__namespace.default.readFileSync(vt(),"utf8");return JSON.parse(t)}catch{return {}}}function Ze(t){let e=vt();w__namespace.default.mkdirSync(pt__namespace.default.dirname(e),{recursive:true}),w__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var fe,Jt,Qe=p(()=>{T();fe={credentials:"credentials","token-cache":"tokenCache"};Jt=class{static isAvailable(){return true}static hasExistingData(){try{if(!w__namespace.default.existsSync(vt()))return !1;let e=JSON.parse(w__namespace.default.readFileSync(vt(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=me(),s=fe[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(e,r,n){let s=me(),o=fe[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;Ze(s);}async deleteSecret(e,r){let n=me(),s=fe[r]??r;return s in n?(delete n[s],Ze(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${vt()}`}};});var tr={};U(tr,{MacOsKeyVaultProvider:()=>he});var ge,he,er=p(()=>{ge=util.promisify(child_process.execFile),he=class{static async isAvailable(){try{return w.accessSync("/usr/bin/security",w.constants.X_OK),!0}catch{return false}}async getSecret(e,r){try{let{stdout:n}=await ge("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await ge("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await ge("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};});var nr={};U(nr,{LinuxKeyVaultProvider:()=>Se});var rr,Se,sr=p(()=>{rr=util.promisify(child_process.execFile),Se=class{static async isAvailable(){let e=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of e)try{return w.accessSync(r,w.constants.X_OK),!0}catch{}return false}async getSecret(e,r){try{let{stdout:n}=await rr("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((s,o)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",o),i.on("close",a=>{a===0?s():o(new Error(`secret-tool exited with code ${a}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await rr("secret-tool",["clear","service",e,"account",r]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var or={};U(or,{WindowsKeyVaultProvider:()=>Ee});var Ee,ir=p(()=>{Ee=class{static async isAvailable(){try{return await Dt("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(e,r){return Dt("keytar").getPassword(e,r)}async setSecret(e,r,n){await Dt("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return Dt("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});async function ar(){return await os()??new Jt}async function os(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(er(),tr));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(sr(),nr));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(ir(),or));return await t.isAvailable()?new t:null}default:return null}}var cr=p(()=>{Qe();});function mt(){return we||(we=ar()),we}async function y(){let e=await(await mt()).getSecret(ft,Te);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function ye(t){if(!t.clientId||!t.clientSecret||!t.tenant)throw new Error("clientId, clientSecret and tenant are required");await(await mt()).setSecret(ft,Te,JSON.stringify(t));}async function lr(){let t=await mt();await t.deleteSecret(ft,Te),await t.deleteSecret(ft,_e);}async function Xt(t){await(await mt()).setSecret(ft,_e,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt}));}async function gt(){let e=await(await mt()).getSecret(ft,_e);if(!e)return null;try{let r=JSON.parse(e);return {accessToken:r.accessToken,expiresAt:r.expiresAt}}catch{return null}}async function ht(){let t=await gt();return t?new Date(t.expiresAt)>new Date:false}async function Q(){let t=await gt();if(!t||!t.accessToken)return null;try{let e=t.accessToken.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email??r.preferred_username??r.upn??r.sub??null}catch{return null}}async function ke(){let t=await mt();if(typeof t.getStoragePath=="function")return t.getStoragePath();let e=process.platform;return e==="darwin"?"macOS Keychain":e==="win32"?"Windows Credential Manager":"Linux Secret Service (libsecret)"}async function ur(){let t=await y();return !!(t&&t.clientId&&t.clientSecret&&t.tenant)}var ft,Te,_e,we,St=p(()=>{cr();T();ft=Vt.SERVICE,Te=Vt.ACCOUNT_CREDS,_e=Vt.ACCOUNT_TOKEN,we=null;});function as(t){return is.some(e=>e.test(t))}function cs(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return r.email||r.preferred_username||r.upn||r.sub||null}catch{return null}}function W(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let r=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:s,tenant:o}=r;return !n||!s||!o?null:{clientId:n,clientSecret:s,tenant:o}}catch{return null}}function pr(t){let e=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant})).toString("base64url");return `${e}.${r}.`}function dr(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[f.FLOW_OBS_ALLOW_HTTP]==="true";if(!r&&e.protocol!=="https:")throw new Error(`URL must use HTTPS: ${t}`);if(e.username||e.password)throw new Error(`URL must not contain embedded credentials: ${t}`);if(!r&&as(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function fr(){let t=W(process.env[f.ANTHROPIC_AUTH_TOKEN]);if(t)return {user:await Q().catch(()=>null)??t.clientId,tenant:t.tenant};if(Wt.KEYCHAIN_ENABLED)try{let e=await y();if(!e)return {user:"",tenant:""};let r=await Q()??e.clientId??"",n=e.tenant??"";return {user:r,tenant:n}}catch{return {user:"",tenant:""}}return {user:"",tenant:""}}async function ls(t){if(await ht()){let r=await gt();return l("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken}l("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let e=await G(t);try{await Xt(e);}catch(r){l("getOrRefreshToken",`token cache save failed (non-fatal): ${r.message}`);}return l("getOrRefreshToken",`token refreshed, expires=${e.expiresAt}`),e.accessToken}function us(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function ds(t,e,r){let n=Buffer.from(`${e}:${r}`).toString("base64");return {endpoint:t.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${n}`}}async function tt(){let t=[],e=process.env[f.ANTHROPIC_MODEL]??"",r=W(process.env[f.ANTHROPIC_AUTH_TOKEN]);l("resolveCredentials",r?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),!r&&Wt.KEYCHAIN_ENABLED&&(r=await y(),r&&l("resolveCredentials","credentials resolved from keychain (FEATURES.KEYCHAIN_ENABLED=true)"));let n=r?r.tenant:"",s=process.env[f.FLOW_TELEMETRY]==="true",o=process.env[f.LANGFUSE_BASE_URL],i=process.env[f.LANGFUSE_PUBLIC_KEY],a=process.env[f.LANGFUSE_SECRET_KEY];if(s&&o&&i&&a){let m="",k=n;if(r)m=await Q().catch(()=>null)??r.clientId;else if(Wt.KEYCHAIN_ENABLED)try{let L=await y();L&&(m=await Q()??L.clientId,k=L.tenant);}catch{}let _={user:m??"",tenant:k??"",team:"",project:"",model:e};t.push({mode:"direct",...ds(dr(o),i,a),..._}),l("resolveCredentials","direct mode active",`user=${_.user}`,`tenant=${_.tenant}`);}if(!r){if(t.length===0){let m=[];return m.authError=false,m}return t}let c;try{c=await ls(r);}catch(m){if(l("resolveCredentials",`token refresh failed: ${m.message}`,`(tenant=${r.tenant} clientId=${r.clientId})`),t.length>0)return t;let k=[];return k.authError=true,k}let S={user:cs(c)??r.clientId,tenant:n,team:"",project:"",model:e},A=process.env[f.FLOW_TELEMETRY_GATEWAY]??Y;return t.push({mode:"gateway",...us(dr(A),{accessToken:c}),...S}),t}async function mr(){return (await tt()).length>0}var is,et=p(()=>{St();bt();T();$();is=[/^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];});var Sr={};U(Sr,{runLogin:()=>q,runLogout:()=>hs,runStatus:()=>Ss});function K(t){return typeof t=="string"?t.replace(ps,""):t}function Pt(t,e={}){return new Promise((r,n)=>{let{masked:s=false,defaultValue:o=""}=e;process.stdout.write(t+o);let i=o;function a(){try{process.stdin.setRawMode(!1);}catch{}}process.once("uncaughtException",a),process.once("unhandledRejection",a);let c=S=>{if(S===""){u(),n(new Error("SIGINT"));return}if(S==="\r"||S===`
|
|
16
19
|
`){u(),process.stdout.write(`
|
|
17
|
-
`),r(i);return}if(S==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}S.startsWith("\x1B")||(i+=S,process.stdout.write(s?"*".repeat(S.length):S));};function u(){process.stdin.setRawMode(false),process.stdin.removeListener("data",c),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",c);})}async function
|
|
20
|
+
`),r(i);return}if(S==="\x7F"){i.length>0&&(i=i.slice(0,-1),process.stdout.write("\b \b"));return}S.startsWith("\x1B")||(i+=S,process.stdout.write(s?"*".repeat(S.length):S));};function u(){process.stdin.setRawMode(false),process.stdin.removeListener("data",c),process.removeListener("uncaughtException",a),process.removeListener("unhandledRejection",a);}process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",c);})}async function gr(t){try{let e=await y();(!e||e.clientId!==t.clientId||e.clientSecret!==t.clientSecret||e.tenant!==t.tenant)&&await ye(t);}catch{}}async function hr(t){let{accessToken:e,expiresAt:r}=await G(t);await ye(t),await Xt({accessToken:e,expiresAt:r});try{let n=pr(t);qt({[f.ANTHROPIC_AUTH_TOKEN]:n});}catch{}}async function fs(t){try{return await hr(t),process.stdout.write(P(` \u2713 Setup complete. Tenant: ${K(t.tenant)}
|
|
18
21
|
|
|
19
|
-
`)),0}catch(e){return process.stderr.write(D(` \u2717 Authentication failed: ${
|
|
20
|
-
`)),1}}async function
|
|
22
|
+
`)),0}catch(e){return process.stderr.write(D(` \u2717 Authentication failed: ${K(e.message)}
|
|
23
|
+
`)),1}}async function ms(){try{process.stdout.write(`
|
|
21
24
|
`);let t=(await Pt(B(" ? ")+"Client ID: ")).trim(),e=(await Pt(B(" ? ")+"Client Secret: ",{masked:!0})).trim(),r=(await Pt(B(" ? ")+"Tenant: ")).trim();if(!t||!e||!r)return process.stderr.write(D(` \u2717 All fields are required
|
|
22
|
-
`)),1;try{await
|
|
23
|
-
`)),1}return process.stdout.write(P(` \u2713 Setup complete. Tenant: ${
|
|
24
|
-
`)),process.stdout.write(` Storage: ${await
|
|
25
|
+
`)),1;try{await hr({clientId:t,clientSecret:e,tenant:r});}catch(n){return process.stderr.write(D(` \u2717 Authentication failed: ${K(n.message)}
|
|
26
|
+
`)),1}return process.stdout.write(P(` \u2713 Setup complete. Tenant: ${K(r)}
|
|
27
|
+
`)),process.stdout.write(` Storage: ${await ke()}
|
|
25
28
|
|
|
26
29
|
`),0}catch(t){if(t.message==="SIGINT")throw t;return process.stderr.write(D(` \u2717 Unexpected error: ${t.message}
|
|
27
|
-
`)),1}}async function
|
|
30
|
+
`)),1}}async function q(t={}){if(t.clientId&&t.clientSecret&&t.tenant)return fs({clientId:t.clientId,clientSecret:t.clientSecret,tenant:t.tenant});let e=W(process.env[f.ANTHROPIC_AUTH_TOKEN]);e&&await gr(e);let r=e||await y();if(r){process.stdout.write(`
|
|
28
31
|
`),process.stdout.write(H(` Already authenticated
|
|
29
|
-
`)),process.stdout.write(E(" Tenant: ")+
|
|
30
|
-
`),process.stdout.write(E(" Client ID: ")+
|
|
32
|
+
`)),process.stdout.write(E(" Tenant: ")+K(r.tenant)+`
|
|
33
|
+
`),process.stdout.write(E(" Client ID: ")+K(r.clientId)+`
|
|
31
34
|
`),process.stdout.write(`
|
|
32
35
|
`);let n;try{n=await Pt(B(" ? ")+"Re-authenticate? (y/N): ");}catch(s){if(s.message==="SIGINT")return process.stdout.write(`
|
|
33
36
|
`),130;throw s}if(n.trim().toLowerCase()!=="y")return process.stdout.write(P(` \u2713 Using existing credentials.
|
|
34
37
|
|
|
35
|
-
`)),0}try{return await
|
|
36
|
-
`),130;throw n}}async function
|
|
37
|
-
`),(await Pt(B(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(
|
|
38
|
+
`)),0}try{return await ms()}catch(n){if(n.message==="SIGINT")return process.stdout.write(`
|
|
39
|
+
`),130;throw n}}async function gs(){try{return process.stdout.write(`
|
|
40
|
+
`),(await Pt(B(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(O(` \u26A0 Logout cancelled
|
|
38
41
|
`)),0):null}catch(t){if(t.message==="SIGINT")return process.stdout.write(`
|
|
39
|
-
`),130;throw t}}async function
|
|
40
|
-
`)),0;if(!t){let e=await
|
|
42
|
+
`),130;throw t}}async function hs(t=false){if(!await ur())return process.stdout.write(O(` \u26A0 You are not authenticated
|
|
43
|
+
`)),0;if(!t){let e=await gs();if(e!==null)return e}try{return await lr(),process.stdout.write(P(` \u2713 Credentials removed successfully
|
|
41
44
|
`)),0}catch{return process.stderr.write(D(` \u2717 Error removing credentials
|
|
42
|
-
`)),1}}async function
|
|
45
|
+
`)),1}}async function Ss(){let t=W(process.env[f.ANTHROPIC_AUTH_TOKEN]);t&&await gr(t);let e=t||await y();if(!e)return process.stdout.write(O(" \u26A0 Not authenticated. Run `flow-ai-obs auth login` to set up.\n")),0;if(!t&&!await ht())return process.stdout.write(O(" \u26A0 Session expired. Run `flow-ai-obs auth login` to re-authenticate.\n")),0;let r=e.clientSecret.length>4?"****...****"+e.clientSecret.slice(-4):"****",n=t?"ANTHROPIC_AUTH_TOKEN (settings.json)":await ke();return process.stdout.write(`
|
|
43
46
|
`+H(` Authenticated
|
|
44
|
-
`)),process.stdout.write(E(" Tenant: ")+
|
|
45
|
-
`),process.stdout.write(E(" Client ID: ")+
|
|
47
|
+
`)),process.stdout.write(E(" Tenant: ")+K(e.tenant)+`
|
|
48
|
+
`),process.stdout.write(E(" Client ID: ")+K(e.clientId)+`
|
|
46
49
|
`),process.stdout.write(E(" Client Secret: ")+r+`
|
|
47
50
|
`),process.stdout.write(E(" Storage: ")+n+`
|
|
48
51
|
|
|
49
|
-
`),0}var
|
|
52
|
+
`),0}var ps,Rt=p(()=>{St();bt();et();It();T();at();ps=/[\x00-\x08\x0B-\x1F\x7F]|\x1b\[[0-9;]*[a-zA-Z]/g;});var _r={};U(_r,{runInstall:()=>Ae});function Es(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux")return child_process.spawnSync("cmd.exe",["/c","where","claude"],{encoding:"utf8",timeout:5e3}).status===0;let t=process.platform==="win32"?"where":"which";return child_process.spawnSync(t,["claude"],{encoding:"utf8",timeout:5e3}).status===0}function ws(){try{let t=w__namespace.readFileSync(j(),"utf8"),e=JSON.parse(t);return !!(e.env&&e.env[f.ANTHROPIC_AUTH_TOKEN])}catch{return false}}async function Ae(){if(!Es()){let n=wr[process.platform]||wr.linux;return process.stderr.write(`
|
|
50
53
|
`+D(` \u2717 Claude Code is not installed or not found in PATH.
|
|
51
54
|
|
|
52
55
|
`)+` flow-ai-obs requires Claude Code to function.
|
|
53
56
|
Install it with:
|
|
54
57
|
|
|
55
|
-
`+B(` ${
|
|
58
|
+
`+B(` ${n}`)+`
|
|
56
59
|
|
|
57
|
-
`),1}if(!
|
|
60
|
+
`),1}if(!ws()){process.stdout.write(O(` \u26A0 No credentials found in settings.json \u2014 authentication required.
|
|
58
61
|
|
|
59
|
-
`));let
|
|
62
|
+
`));let n=await q();if(n!==0)return n}let t,e;try{({settingsPath:t,preserved:e}=Xe());}catch(n){return process.stderr.write(` \u2717 Failed to write settings: ${n.message}
|
|
60
63
|
`),1}process.stdout.write(`
|
|
61
64
|
`+H(" Native OTEL configured")+` (metrics & logs)
|
|
62
|
-
`);for(let[
|
|
63
|
-
`);
|
|
65
|
+
`);for(let[n,s]of Object.entries(lt))process.stdout.write(E(` ${n.padEnd(36)}`)+s+`
|
|
66
|
+
`);process.stdout.write(`
|
|
64
67
|
`),process.stdout.write(H(" Hooks registered")+` (Langfuse trace capture)
|
|
65
68
|
`),process.stdout.write(E(" UserPromptSubmit")+` \u2192 flow-ai-obs UserPromptSubmit (timeout: 5s)
|
|
66
69
|
`),process.stdout.write(E(" PreToolUse ")+` \u2192 flow-ai-obs PreToolUse (timeout: 3s)
|
|
67
70
|
`),process.stdout.write(E(" PostToolUse ")+` \u2192 flow-ai-obs PostToolUse (timeout: 10s)
|
|
68
71
|
`),process.stdout.write(E(" Stop ")+` \u2192 flow-ai-obs Stop (timeout: 15s)
|
|
69
72
|
`),e.length>0&&(process.stdout.write(`
|
|
70
|
-
`),process.stdout.write(
|
|
73
|
+
`),process.stdout.write(O(` \u26A0 Third-party hooks detected and preserved on: ${e.join(", ")}
|
|
71
74
|
`)),process.stdout.write(E(` flow-ai-obs was prepended \u2014 it executes first.
|
|
72
75
|
`))),process.stdout.write(`
|
|
73
76
|
`),process.stdout.write(E(" Settings: ")+t+`
|
|
@@ -75,66 +78,68 @@
|
|
|
75
78
|
`),process.stdout.write(E(" OTEL auth: flow-ai-obs otel-headers")+E(` (reads keychain at runtime)
|
|
76
79
|
`)),process.stdout.write(`
|
|
77
80
|
`),process.stdout.write(P(` \u2713 Ready. Native OTEL + Langfuse trace capture active.
|
|
78
|
-
`)),process.stdout.write(E(" Run `flow-ai-obs setup` to also configure the Flow LLM Proxy.\n\n"))
|
|
81
|
+
`)),process.stdout.write(E(" Run `flow-ai-obs setup` to also configure the Flow LLM Proxy.\n\n"));let r=Ke();return r&&process.stdout.write(O(` \u26A0 ${r}
|
|
82
|
+
|
|
83
|
+
`)),0}var wr,Oe=p(()=>{It();T();at();ue();Rt();wr={darwin:`npm install -g @anthropic-ai/claude-code
|
|
79
84
|
or visit: https://claude.ai/download`,linux:"npm install -g @anthropic-ai/claude-code",win32:`npm install -g @anthropic-ai/claude-code
|
|
80
|
-
or visit: https://claude.ai/download`};});var
|
|
85
|
+
or visit: https://claude.ai/download`};});var yr={};U(yr,{runSetup:()=>Ts});async function Ts(t={}){process.stdout.write(`
|
|
81
86
|
\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
|
|
82
87
|
`),process.stdout.write(`\u2551 flow-ai-obs \u2014 setup \u2551
|
|
83
88
|
`),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
|
|
84
89
|
|
|
85
|
-
`);let e=await
|
|
90
|
+
`);let e=await q(t);if(e!==0)return process.stderr.write(`
|
|
86
91
|
Setup aborted. Run \`flow-ai-obs auth login\` to retry.
|
|
87
92
|
|
|
88
93
|
`),e;process.stdout.write(`
|
|
89
|
-
`);let r=await Ae();if(r!==0)return r;try{
|
|
94
|
+
`);let r=await Ae();if(r!==0)return r;try{qt(Lt);}catch(s){process.stderr.write(` \u26A0 Could not write LLM Proxy config: ${s.message}
|
|
90
95
|
`);}process.stdout.write(H(" Flow LLM Proxy configured")+` (model provider)
|
|
91
96
|
`);for(let[s,o]of Object.entries(Lt))process.stdout.write(E(` ${s.padEnd(36)}`)+o+`
|
|
92
97
|
`);process.stdout.write(`
|
|
93
98
|
`),process.stdout.write(` Validating connectivity to Flow OTEL endpoint\u2026
|
|
94
|
-
`);let n=await
|
|
99
|
+
`);let n=await y();return n?await ze(n)?process.stdout.write(P(` \u2713 Connectivity validated \u2014 telemetry is active.
|
|
95
100
|
|
|
96
|
-
`)):process.stdout.write(
|
|
101
|
+
`)):process.stdout.write(O(` \u26A0 Could not reach the OTEL endpoint. Telemetry will activate once connectivity is restored.
|
|
97
102
|
|
|
98
|
-
`)):process.stdout.write(
|
|
103
|
+
`)):process.stdout.write(O(` \u26A0 Could not read stored credentials \u2014 skipping connectivity check.
|
|
99
104
|
|
|
100
105
|
`)),process.stdout.write(P(` \u2713 Setup complete!
|
|
101
|
-
`)),process.stdout.write(E(` Settings: ${
|
|
106
|
+
`)),process.stdout.write(E(` Settings: ${j()}
|
|
102
107
|
|
|
103
|
-
`)),0}var
|
|
108
|
+
`)),0}var kr=p(()=>{T();at();Rt();Oe();It();St();});var Ar={};U(Ar,{runOtelHeaders:()=>_s});async function _s(){let t;try{t=await y();}catch{return process.stderr.write(`[flow-ai-obs otel-headers] Failed to read credentials
|
|
104
109
|
`),1}if(!t)return process.stderr.write(`[flow-ai-obs otel-headers] Not authenticated \u2014 run: flow-ai-obs auth login
|
|
105
|
-
`),1;let e;try{e=(await
|
|
110
|
+
`),1;let e;try{e=(await G(t)).accessToken;}catch(r){return process.stderr.write(`[flow-ai-obs otel-headers] Token fetch failed: ${r.message}
|
|
106
111
|
`),1}return e?(process.stdout.write(`{"Authorization": "Bearer ${e}"}
|
|
107
112
|
`),0):(process.stderr.write(`[flow-ai-obs otel-headers] Empty token received
|
|
108
|
-
`),1)}var
|
|
113
|
+
`),1)}var Or=p(()=>{St();bt();});var br={};U(br,{runCheck:()=>ys});function Le(t){return !t||t.length<=8?"****":t.slice(0,4)+"****...****"+t.slice(-4)}function Ct(t){process.stdout.write(` \u2713 ${t}
|
|
109
114
|
`);}function zt(t){process.stdout.write(` \u26A0 ${t}
|
|
110
115
|
`);}function Zt(t){process.stdout.write(` \u2717 ${t}
|
|
111
116
|
`);}function b(t){process.stdout.write(` ${t}
|
|
112
117
|
`);}function I(){process.stdout.write(`
|
|
113
118
|
`);}async function ys(){I(),process.stdout.write(` flow-claude-observability \u2014 configuration check
|
|
114
119
|
`),I(),process.stdout.write(` Auth
|
|
115
|
-
`);let t=
|
|
116
|
-
`);}if(!t&&!await ht()){zt("Session expired \u2014 re-authenticating..."),I();let a=await
|
|
120
|
+
`);let t=W(process.env[f.ANTHROPIC_AUTH_TOKEN]),e=t||await y();if(!e){zt("Not authenticated \u2014 starting setup..."),I();let a=await q();if(a!==0)return a;if(t=W(process.env[f.ANTHROPIC_AUTH_TOKEN]),e=t||await y(),!e)return Zt("Authentication failed"),I(),1;I(),process.stdout.write(` Auth
|
|
121
|
+
`);}if(!t&&!await ht()){zt("Session expired \u2014 re-authenticating..."),I();let a=await q();if(a!==0)return a;I(),process.stdout.write(` Auth
|
|
117
122
|
`);}let r=await Q()||e.clientId;Ct("Authenticated"),b(`Tenant: ${e.tenant}`),b(`User: ${r}`),I(),process.stdout.write(` Native OTEL
|
|
118
|
-
`);let n={};try{let a=w__namespace.readFileSync(
|
|
123
|
+
`);let n={};try{let a=w__namespace.readFileSync(j(),"utf8");n=JSON.parse(a).env||{};}catch{}let s=Object.keys(lt).filter(a=>!n[a]);if(s.length===0?(Ct("All OTEL env vars present in settings.json"),b(`Endpoint: ${n.OTEL_EXPORTER_OTLP_ENDPOINT}`)):(zt(`${s.length} OTEL var(s) missing from settings.json \u2014 native metrics/logs disabled`),s.forEach(a=>Zt(`Missing: ${a}`)),b("Run: flow-ai-obs install (restores missing vars automatically)")),I(),process.stdout.write(` Tracing
|
|
119
124
|
`),process.env[f.FLOW_TELEMETRY]==="true"){Ct("FLOW_TELEMETRY=true (direct mode enabled)");let a=[f.LANGFUSE_BASE_URL,f.LANGFUSE_PUBLIC_KEY,f.LANGFUSE_SECRET_KEY].filter(c=>!process.env[c]);a.length>0&&a.forEach(c=>zt(`Missing: ${c}`));}else b("FLOW_TELEMETRY not set \u2014 direct mode inactive (gateway mode may still be active)");let i=await tt();if(!i||i.length===0)return i&&i.authError?Zt("Token refresh failed \u2014 gateway mode could not activate"):(Zt("No active destinations \u2014 no traces will be sent"),b("For direct mode: set FLOW_TELEMETRY=true + LANGFUSE_BASE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY"),b("For gateway mode: run flow-claude-observability auth login")),I(),1;for(let a of i)if(a.mode==="gateway"){let c=await gt();Ct("Mode: gateway"),b(`Endpoint: ${a.endpoint}`),b(`Token: ${Le(c?.accessToken)}`);}else a.mode==="direct"&&(Ct("Mode: direct"),b(`Endpoint: ${a.endpoint}`),b(`PK: ${Le(process.env[f.LANGFUSE_PUBLIC_KEY])}`),b(`SK: ${Le(process.env[f.LANGFUSE_SECRET_KEY])}`));return I(),process.stdout.write(` All checks passed \u2014 observability is active.
|
|
120
|
-
`),I(),0}var
|
|
121
|
-
`)[0].slice(0,e).trim()}function
|
|
125
|
+
`),I(),0}var Ir=p(()=>{St();et();It();T();Rt();});function x(t,e){let r=typeof t=="object"?JSON.stringify(t):String(t??"");return r.length>e?r.slice(0,e)+" \u2026[truncated]":r}function Qt(t,e=100){return String(t??"").split(`
|
|
126
|
+
`)[0].slice(0,e).trim()}function vr(){return new Promise(t=>{let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",r=>{e+=r;}),process.stdin.on("end",()=>{try{t(JSON.parse(e));}catch{t({});}});})}function C(t){process.stdout.write(JSON.stringify(t));}var Et=p(()=>{});function J(){return String(BigInt(Date.now())*1000000n)}var be,rt,Ut=p(()=>{be=()=>crypto.randomBytes(16).toString("hex"),rt=()=>crypto.randomBytes(8).toString("hex");});function Cs(t,e){let r=pt.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function Ie(t){if(!Ps.test(t))throw new Error(`Invalid session ID: ${t}`);return Cs(pt.join(Kt.tmpdir(),`flow-obs-${t}.json`),Rs)}function wt(t){let e=Ie(t);if(!w.existsSync(e))return null;try{return JSON.parse(w.readFileSync(e,"utf8"))}catch{return null}}function Tt(t,e){w.writeFileSync(Ie(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function ve(t){try{w.unlinkSync(Ie(t));}catch{}}var Ps,Rs,Ft=p(()=>{Ps=/^[0-9a-f-]{1,64}$/i,Rs=pt.normalize(Kt.tmpdir())+pt.sep;});function Ur(t){if(!t||!w.existsSync(t))return null;try{let e=w.readFileSync(t,"utf8").trimEnd().split(`
|
|
122
127
|
`);for(let r=e.length-1;r>=0;r--)try{let n=JSON.parse(e[r]);if(n.type==="user"&&n.uuid)return n.uuid}catch{}}catch{}return null}function Ne(t){if(!t||!w.existsSync(t))return null;try{let e=w.readFileSync(t,"utf8").trimEnd().split(`
|
|
123
128
|
`),r=[],n=0,s=0;for(let o=e.length-1;o>=0;o--)try{let i=JSON.parse(e[o]);if(i.type==="user")break;if(i.type==="assistant"){let c=(i.message?.content??[]).filter(S=>S.type==="text").map(S=>S.text??"").join("");c&&r.unshift(c);let u=i.message?.usage??{};n+=(u.input_tokens??0)+(u.cache_read_input_tokens??0)+(u.cache_creation_input_tokens??0),s+=u.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
|
|
124
129
|
|
|
125
|
-
`),inputTokens:n,outputTokens:s}}catch{}return null}var Pe=p(()=>{});function
|
|
126
|
-
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}function
|
|
130
|
+
`),inputTokens:n,outputTokens:s}}catch{}return null}var Pe=p(()=>{});function xr(t){return t.replace(":","/")}function te(t,e){if(!t)return null;let r=xr(t),n=[pt.join(Kt.homedir(),".claude","skills",r,"SKILL.md"),pt.join(e??"",".claude","skills",r,"SKILL.md")];for(let s of n)if(w.existsSync(s))try{return w.readFileSync(s,"utf8")}catch{}return null}function Mr(t){return t.split(`
|
|
131
|
+
`)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}function Dr(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||Bs.has(n.tool))?"complete":"prerequisite_required":null}function ee(t,e){if(!t)return null;let r=xr(t),n=[pt.join(Kt.homedir(),".claude","skills",r),pt.join(e??"",".claude","skills",r)],s=null;for(let a of n)if(w.existsSync(pt.join(a,"SKILL.md"))){s=a;break}if(!s)return null;let o=[];function i(a,c){for(let u of w.readdirSync(a,{withFileTypes:true})){if(xs.has(u.name)||Ds.has(u.name)||Ms.has(pt.extname(u.name)))continue;let S=c?`${c}/${u.name}`:u.name;u.isDirectory()?i(pt.join(a,u.name),S):o.push(S);}}return i(s,""),o.length>0?o:null}var xs,Ms,Ds,Bs,re=p(()=>{xs=new Set([".venv","__pycache__",".git","node_modules"]),Ms=new Set([".pyc",".pyo"]),Ds=new Set(["SKILL.md",".DS_Store",".gitignore"]);Bs=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);});async function Br(t){let e=t.session_id||"unknown",r=t.prompt||"",n=t.cwd||"";try{(await tt()).authError===!0&&(process.stderr.write(`
|
|
127
132
|
\u26A0 flow-ai-obs: Your Flow credentials have expired.
|
|
128
133
|
Traces will not be captured until you re-authenticate.
|
|
129
134
|
Run: flow-ai-obs auth login
|
|
130
135
|
|
|
131
|
-
`),l("UserPromptSubmit","auth expired \u2014 warning emitted to stderr"));}catch{}let s=
|
|
132
|
-
`,{flag:"a",encoding:"utf8",mode:384}),l("sendTraces:dump",`request appendada em ${
|
|
136
|
+
`),l("UserPromptSubmit","auth expired \u2014 warning emitted to stderr"));}catch{}let s=Ur(t.transcript_path)||be(),o=Mr(r),i=o?te(o,n):null,a=o?ee(o,n):null;Tt(e,{traceId:be(),spanId:rt(),startNs:J(),sessionId:e,prompt:r,cwd:n,traceName:s,transcriptPath:t.transcript_path||"",model:process.env[f.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:o,skillContent:i,skillArtifacts:a}),l("UserPromptSubmit",`sid=${e}`,`traceName=${s}`,`slashSkill=${o}`),C(t);}var Hr=p(()=>{Ut();Ft();Pe();re();Et();$();T();et();});async function jr(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},s=wt(e);s&&(s.pendingTool={name:r,inputStr:x(n,F.TOOL_INPUT),startNs:J()},Tt(e,s)),l("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!s}`),C(t);}var Vr=p(()=>{Ut();Ft();Et();$();T();});function d(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function nt(...t){return t.filter(e=>e!==null)}function Yr(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Hs,spans:Array.isArray(e)?e:[e]}]}]}}var Hs,h,Gr=p(()=>{T();Hs={name:le.SCOPE_NAME,version:le.SCOPE_VERSION},h={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 Kr(t,e,r,n,s){if(process.env[f.FLOW_OBS_DEBUG]!=="1")return;let o=JSON.stringify({ts:new Date().toISOString(),request:{method:"POST",url:t,headers:e,body:JSON.parse(r)},response:{status:n,body:s}});try{w.writeFileSync(Wr,o+`
|
|
137
|
+
`,{flag:"a",encoding:"utf8",mode:384}),l("sendTraces:dump",`request appendada em ${Wr}`);}catch(i){l("sendTraces:dump",`falha ao salvar: ${i.message}`);}}function Ks(t){let e=new URL(t),r=new URL(Z.GATEWAY_HEALTH);return r.hostname=e.hostname,r.port=e.port,r.protocol=e.protocol,r}function qr(t,e){return new Promise((r,n)=>{let s=t._isSSL?On__namespace.default:Bn__namespace.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let o=s.request(t,i=>{let a=[];i.on("data",c=>a.push(c)),i.on("end",()=>r({statusCode:i.statusCode??0,body:a.join("")}));});o.setTimeout(1e4,()=>{o.destroy(new Error("Request timeout"));}),o.on("error",i=>n(new Error(`Network error: ${i.message}`))),e&&o.write(e),o.end();})}async function Jr(t,e){let r;try{r=Ks(t);}catch{return false}let n=r.protocol==="https:";try{let s={};e&&(s.Authorization=String(e).replace(/[\r\n]/g,""));let o=await qr({hostname:r.hostname,port:r.port||(n?443:80),path:r.pathname,method:"GET",headers:s,_isSSL:n},null);return l("checkHealth",`url=${r.href} status=${o.statusCode}`),o.statusCode>=200&&o.statusCode<300}catch{return false}}async function ne(t,e,r){let n=JSON.stringify(t),s=new URL(e),o=s.protocol==="https:",i=String(r).replace(/[\r\n]/g,""),a={"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(n)};l("sendTraces:request",`POST ${e}`),l("sendTraces:request",`headers=${JSON.stringify({...a,Authorization:i.slice(0,20)+"\u2026"})}`),l("sendTraces:request",`body=${n.slice(0,500)}${n.length>500?"\u2026":""}`);try{let c=await qr({hostname:s.hostname,port:s.port||(o?443:80),path:s.pathname,method:"POST",headers:a,_isSSL:o},n);return l("sendTraces:response",`status=${c.statusCode}`),Kr(e,a,n,c.statusCode,c.body),c.statusCode}catch(c){return l("sendTraces:error",c.message),Kr(e,a,n,0,c.message),0}}var Wr,Xr=p(()=>{T();$();Wr=pt.join(Kt.tmpdir(),"flow-obs-requests.ndjson");});function qs(){let t=parseInt(process.env[f.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(R.MIN_TTL_DAYS,Math.min(R.MAX_TTL_DAYS,t)):R.DEFAULT_TTL_DAYS)*24*60*60*1e3}function Js(){let t=parseInt(process.env[f.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(R.MIN_MAX_FILES,Math.min(R.MAX_MAX_FILES,t)):R.DEFAULT_MAX_FILES}function Zr(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return pt__namespace.default.join(Kt__namespace.default.tmpdir(),`${R.FILE_PREFIX}${t}.json`)}function Ce(){let t=Kt__namespace.default.tmpdir(),e;try{e=w__namespace.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(R.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=pt__namespace.default.join(t,r),s=0;try{s=w__namespace.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:s}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function $t(t){try{let e=Js(),r=Ce();if(r.length>=e){let o=r.slice(0,r.length-e+1);for(let i of o)try{w__namespace.default.unlinkSync(i);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,s={fileId:n,bufferedAt:Date.now(),payload:t};return w__namespace.default.writeFileSync(Zr(n),JSON.stringify(s),{encoding:"utf8",mode:384}),l("buffer",`saved fileId=${n}`),n}catch(e){return l("buffer",`saveToBuffer failed: ${e.message}`),null}}function Qr(t){let e=Ce(),r=t!=null&&t>0?t:e.length,n=[];for(let s of e){if(n.length>=r)break;try{let o=w__namespace.default.readFileSync(s,"utf8"),i=JSON.parse(o);i&&i.fileId&&i.payload&&n.push(i);}catch{l("buffer",`skipping malformed file: ${s}`);}}return n}function tn(t){try{w__namespace.default.unlinkSync(Zr(t)),l("buffer",`deleted fileId=${t}`);}catch{}}function en(){let t=Date.now()-qs();for(let e of Ce())try{let{mtimeMs:r}=w__namespace.default.statSync(e);r<t&&(w__namespace.default.unlinkSync(e),l("buffer",`evicted stale: ${pt__namespace.default.basename(e)}`));}catch{}}var rn=p(()=>{T();$();});async function Xs(t){en();let e=Qr(R.REPLAY_BATCH_SIZE);e.length&&(l("replayBufferedTraces",`replaying ${e.length} buffered trace(s)`),await Promise.allSettled(e.map(async r=>{try{let n=await ne(r.payload,t.endpoint,t.authHeader);n>=200&&n<300?(tn(r.fileId),l("replayBufferedTraces",`replayed fileId=${r.fileId} status=${n}`)):l("replayBufferedTraces",`replay failed fileId=${r.fileId} status=${n}`);}catch(n){l("replayBufferedTraces",`replay error fileId=${r.fileId}: ${n.message}`);}})));}async function nn(t){let e=await tt();if(!e.length)return e.authError&&(l("postToLangfuse","auth refresh failed \u2014 buffering trace"),$t(t)),0;let r=await Promise.all(e.map(async o=>{if(o.mode!=="gateway")return {creds:o,healthy:true};let i=await Jr(o.endpoint,o.authHeader);return {creds:o,healthy:i}})),n=r.find(o=>o.creds.mode==="gateway"&&o.healthy)?.creds??r.find(o=>o.creds.mode==="direct")?.creds;return n&&await Xs(n),(await Promise.all(r.map(async({creds:o,healthy:i})=>{if(o.mode==="gateway"){if(!i)return l("postToLangfuse","gateway health check failed \u2014 buffering trace"),$t(t),0;let c=await ne(t,o.endpoint,o.authHeader);return (c===0||c>=500)&&(l("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),$t(t)),c}let a=await ne(t,o.endpoint,o.authHeader);return (a===0||a>=500)&&(l("postToLangfuse",`direct endpoint unavailable (status ${a}) \u2014 buffering trace`),$t(t)),a}))).find(o=>o!==0)??0}var sn=p(()=>{et();$();Xr();rn();T();});var Ue=p(()=>{Gr();sn();});function yt(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return zs.reduce((r,{re:n,replace:s})=>r.replace(n,s),e)}var v,zs,Fe=p(()=>{v="[REDACTED]",zs=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${v}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${v}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(t,e)=>`${e}${v}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(t,e)=>`${e}${v}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(t,e,r)=>`${e}
|
|
133
138
|
${v}
|
|
134
|
-
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${v}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${v}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${v}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${v}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${v}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(t,e,r)=>`${e}${r}${v}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${v}@`}];});async function
|
|
135
|
-
`)),
|
|
136
|
-
`),process.stdout.write(JSON.stringify(e));}}var
|
|
137
|
-
`),process.exit(0);});});var
|
|
139
|
+
${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${v}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${v}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${v}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${v}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${v}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(t,e,r)=>`${e}${r}${v}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${v}@`}];});async function on(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},s=t.tool_response||"",o=wt(e);if(!o){C(t);return}let i=J(),a=o.pendingTool,c=a?.name===r,u=c?a.startNs:String(BigInt(i)-200000000n),S=c?a.inputStr:x(n,F.TOOL_INPUT),A=S,m=null;if(r==="Skill"){let Ot=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);m=Ot?String(Ot).trim():null;let ot=m?te(m,o.cwd):null;ot&&(A=ot,o.skillContent||(o.skillContent=ot),o.skillArtifacts||(o.skillArtifacts=ee(m,o.cwd))),m&&!o.slashSkill&&(o.slashSkill=m),l("PostToolUse","Skill tool detected",`skillName=${m}`,`contentFound=${!!ot}`);}let k=yt(x(s,F.TOOL_OUTPUT)),_=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(k.slice(0,500)),L=_?"ERROR":"DEFAULT",Mt=rt(),st=Math.round(Number(BigInt(i)-BigInt(u))/1e6),At={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",se=r==="Skill"&&m?m:Qt(S,60);o.toolCalls.push({tool:r,brief:se,error:_,durationMs:st});let V=o.spans;V.push({traceId:o.traceId,spanId:Mt,parentSpanId:o.spanId,name:r,kind:3,startTimeUnixNano:u,endTimeUnixNano:i,attributes:nt(d(h.OBS_NAME,r),d(h.OBS_TYPE,At),d(h.OBS_LEVEL,L),d(h.OBS_INPUT,yt(A)),d(h.OBS_OUTPUT,k),d("tool.name",r),d("tool.error",String(_)),r==="Skill"&&m?d("skill.name",m):null,r==="Skill"?d("skill.invocation","slash-command"):null),status:{code:_?2:1}}),o.pendingTool=null,Tt(e,o),l("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${_}`,`durationMs=${st}`,`totalSpans=${V.length}`),C(t);}var an=p(()=>{Ut();Ft();Ue();Et();re();$();T();Fe();});function ln(t,e,r){let n=Object.keys(cn).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let s=cn[n],o=(e*s.input+r*s.output)/1e6;return Math.round(o*1e6)/1e6}var cn,un=p(()=>{cn={"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}};});async function dn(t){let e=t.session_id||"unknown",r=t.stop_reason||"end_turn",n=wt(e);if(!n){C(t);return}n.slashSkill&&!/^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/i.test(n.slashSkill)&&(l("Stop",`sid=${e}`,`slashSkill rejected post-disk: "${n.slashSkill}"`),n.slashSkill=null);let s=J(),o=await fr(),i=n.toolCalls,a=n.spans;if(n.slashSkill&&!i.some(g=>g.tool==="Skill")){let g=rt(),z=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});i.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),a.push({traceId:n.traceId,spanId:g,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:nt(d(h.OBS_NAME,"Skill"),d(h.OBS_TYPE,"TOOL"),d(h.OBS_LEVEL,"DEFAULT"),d(h.OBS_INPUT,z),d(h.OBS_OUTPUT,"loaded via slash command"),d("tool.name","Skill"),d("tool.error","false"),d("skill.name",n.slashSkill),d("skill.invocation","slash-command")),status:{code:1}}),l("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let c=t.transcript_path||n.transcriptPath||"",u=Ne(c);if(c&&(i.some(g=>g.tool==="Skill"&&!g.synthetic)||!!n.slashSkill)&&!u?.text){await new Promise(z=>setTimeout(z,500));let g=Ne(c);g?.text&&(u=g);}l("Stop",`transcriptPath=${c||"(empty)"}`,`assistantOut=${u?`text=${u.text.length}chars`:"null"}`);let A=i.length,m=i.filter(g=>g.error).length,k=yt(u?.text?x(u.text,F.TRACE_OUTPUT):A===0?"No tools used":i.map((g,z)=>`${z+1}. ${g.tool}${g.brief?` \u2192 ${g.brief}`:""}${g.error?" [ERROR]":""}`).join(`
|
|
140
|
+
`)),_=u?.inputTokens??0,L=u?.outputTokens??0,Mt=i.map((g,z)=>`${z+1}. ${g.tool}${g.brief?` \u2192 ${g.brief}`:""}${g.error?" [ERROR]":""} (${g.durationMs}ms)`),st=!!(n.slashSkill||i.some(g=>g.tool==="Skill")),$e=i.some(g=>g.tool==="Agent");if(!st&&!$e){l("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),ve(e),C(t);return}let At=st?"skill":"agent",se=Math.round(Number(BigInt(s)-BigInt(n.startNs))/1e6),xe=ln(n.model,_,L),V=Dr(n);V==="prerequisite_required"&&u?.text&&(V="complete"),V==="prerequisite_required"&&(a.push({traceId:n.traceId,spanId:rt(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:nt(d(h.OBS_NAME,"prerequisite-check"),d(h.OBS_TYPE,"EVENT"),d(h.OBS_LEVEL,"WARNING"),d(h.OBS_OUTPUT,k),d("skill.name",n.slashSkill||void 0),d("execution_status","prerequisite_required")),status:{code:1}}),l("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let Ot=(()=>{if(!(!st||!n.prompt)){if(n.slashSkill){let g=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return g?x(g,F.USER_INSTRUCTION):void 0}return x(n.prompt,F.USER_INSTRUCTION)||void 0}})(),ot=JSON.stringify({trace_type:At,...V!==null&&{execution_status:V},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...Ot!==void 0&&{user_instruction:Ot},latency_ms:se,..._&&{tokens_input:_},...L&&{tokens_output:L},cost_usd:xe,...n.model?{model:n.model}:{},toolCount:A,errorCount:m,stopReason:r,sessionId:n.sessionId,tools:Mt.length?Mt:void 0}),Me=yt(x(n.prompt,F.TRACE_INPUT)),mn=nt(d(h.TRACE_NAME,n.traceName),d(h.TRACE_INPUT,Me),d(h.TRACE_OUTPUT,k),d(h.OBS_INPUT,Me),d(h.OBS_OUTPUT,k),d(h.TRACE_METADATA,ot),d(h.SESSION_ID,n.sessionId),d(h.USER_ID,o.user),d(h.OBS_TYPE,"GENERATION"),d(h.MODEL,n.model),_?d(h.INPUT_TOKENS,_):null,L?d(h.OUTPUT_TOKENS,L):null,d("claude.stop_reason",r),d("claude.tool_count",String(A)),d("claude.error_count",String(m)),d("claude.session_id",n.sessionId),d("flow.trace_type",At),{key:h.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:At}]}}}),gn={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:s,attributes:mn,status:{code:m>0?2:1}},hn=nt(d("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),d("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),De=[...a,gn];l("Stop",`sid=${e}`,`totalTools=${A}`,`errorTools=${m}`,`spans=${De.length}`,`inputTokens=${_}`,`outputTokens=${L}`,`traceOutput="${Qt(k,80)}"`);let Sn=await nn(Yr(hn,De));l("Stop",`POST status=${Sn}`,`traceId=${n.traceId}`),ve(e),C(t);}var pn=p(()=>{Ut();Ft();Ue();et();un();Pe();Et();$();re();Fe();T();});async function Zs(){let t=process.argv[2];if(!await mr()){let r=[];process.stdin.on("data",n=>r.push(n)),process.stdin.on("end",()=>process.stdout.write(r.join("")));return}let e=await vr();switch(t){case "UserPromptSubmit":await Br(e);break;case "PreToolUse":await jr(e);break;case "PostToolUse":await on(e);break;case "Stop":await dn(e);break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
|
|
141
|
+
`),process.stdout.write(JSON.stringify(e));}}var fn=p(()=>{et();Et();Hr();Vr();an();pn();Zs().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
|
|
142
|
+
`),process.exit(0);});});var to=new Set(["UserPromptSubmit","PreToolUse","PostToolUse","Stop"]),[,,M,xt]=process.argv;function kt(t,e){let r=t.indexOf(e);return r!==-1?t[r+1]:void 0}if(M==="--version"||M==="-v"){let{version:t}=Bt();process.stdout.write(t+`
|
|
138
143
|
`),process.exit(0);}else if(M==="--help"||M==="-h"){let{bold:t,cyan:e,dim:r}=(at(),N(ie)),{version:n}=Bt();process.stdout.write(`
|
|
139
144
|
`+t(" flow-ai-obs")+r(" v"+n)+`
|
|
140
145
|
|
|
@@ -150,12 +155,12 @@ ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${v}`},{re:/(aws_secret_ac
|
|
|
150
155
|
|
|
151
156
|
`)),process.stdout.write(r(` (Hook events: UserPromptSubmit | PreToolUse | PostToolUse | Stop)
|
|
152
157
|
|
|
153
|
-
`)),process.exit(0);}else if(M==="install"){(jt(),N(Ht)).checkForUpdate();let{runInstall:t}=(Oe(),N(
|
|
154
|
-
`),process.exit(1);});}else if(M==="setup"){(jt(),N(Ht)).checkForUpdate();let{runSetup:t}=(
|
|
155
|
-
`),process.exit(1);});}else if(M==="auth"){(jt(),N(Ht)).checkForUpdate();let{runLogin:t,runLogout:e,runStatus:r}=(Rt(),N(
|
|
158
|
+
`)),process.exit(0);}else if(M==="install"){(jt(),N(Ht)).checkForUpdate();let{runInstall:t}=(Oe(),N(_r));t().then(e=>process.exit(e)).catch(e=>{process.stderr.write(`Unexpected error: ${e.message}
|
|
159
|
+
`),process.exit(1);});}else if(M==="setup"){(jt(),N(Ht)).checkForUpdate();let{runSetup:t}=(kr(),N(yr)),e=process.argv.slice(3);t({clientId:kt(e,"--client-id"),clientSecret:kt(e,"--client-secret"),tenant:kt(e,"--tenant")}).then(r=>process.exit(r)).catch(r=>{process.stderr.write(`Unexpected error: ${r.message}
|
|
160
|
+
`),process.exit(1);});}else if(M==="auth"){(jt(),N(Ht)).checkForUpdate();let{runLogin:t,runLogout:e,runStatus:r}=(Rt(),N(Sr));(async()=>{let n=0;if(xt==="login"||!xt){let s=process.argv.slice(4);n=await t({clientId:kt(s,"--client-id"),clientSecret:kt(s,"--client-secret"),tenant:kt(s,"--tenant")});}else if(xt==="logout"){let s=process.argv.includes("--force");n=await e(s);}else xt==="status"?n=await r():(process.stderr.write(`Unknown auth subcommand: ${xt}
|
|
156
161
|
`),process.stderr.write(`Usage: flow-ai-obs auth [login|logout|status]
|
|
157
|
-
`),n=1);process.exit(n);})();}else if(M==="otel-headers"){let{runOtelHeaders:t}=(
|
|
158
|
-
`),process.exit(1);});}else if(
|
|
162
|
+
`),n=1);process.exit(n);})();}else if(M==="otel-headers"){let{runOtelHeaders:t}=(Or(),N(Ar));t().then(e=>process.exit(e)).catch(()=>process.exit(1));}else if(M==="check"){let{runCheck:t}=(Ir(),N(br));t().then(e=>process.exit(e)).catch(e=>{process.stderr.write(`Unexpected error: ${e.message}
|
|
163
|
+
`),process.exit(1);});}else if(to.has(M))fn();else {let{bold:t,cyan:e,dim:r}=(at(),N(ie));process.stdout.write(`
|
|
159
164
|
`+t(" flow-ai-obs")+`
|
|
160
165
|
|
|
161
166
|
`),process.stdout.write(e(" install")+r(` Auth (if needed) + hooks + native OTEL
|
package/dist/setup.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
'use strict';var child_process=require('child_process'),util=require('util'),s=require('fs'),
|
|
3
|
-
`,{encoding:"utf8",mode:384});try{s__namespace.chmodSync(
|
|
4
|
-
`,{encoding:"utf8",mode:384});try{s__namespace.chmodSync(
|
|
2
|
+
'use strict';var child_process=require('child_process'),util=require('util'),s=require('fs'),u=require('path'),A=require('os');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var s__namespace=/*#__PURE__*/_interopNamespace(s);var u__namespace=/*#__PURE__*/_interopNamespace(u);var A__namespace=/*#__PURE__*/_interopNamespace(A);var ne=Object.defineProperty;var g=(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 O=(e,t)=>()=>(e&&(t=e(e=0)),t);var L=(e,t)=>{for(var n in t)ne(e,n,{get:t[n],enumerable:true});};var x={};L(x,{MacOsKeyVaultProvider:()=>N});var I,N,G=O(()=>{I=util.promisify(child_process.execFile),N=class{static async isAvailable(){try{return s.accessSync("/usr/bin/security",s.constants.X_OK),!0}catch{return false}}async getSecret(t,n){try{let{stdout:r}=await I("security",["find-generic-password","-w","-a",n,"-s",t]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await I("security",["add-generic-password","-U","-a",n,"-s",t,"-w",r]);}async deleteSecret(t,n){try{return await I("security",["delete-generic-password","-a",n,"-s",t]),!0}catch{return false}}getStoragePath(){return "macOS Keychain"}};});var B={};L(B,{LinuxKeyVaultProvider:()=>P});var V,P,K=O(()=>{V=util.promisify(child_process.execFile),P=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 s.accessSync(n,s.constants.X_OK),!0}catch{}return false}async getSecret(t,n){try{let{stdout:r}=await V("secret-tool",["lookup","service",t,"account",n]);return r.trim()||null}catch{return null}}async setSecret(t,n,r){await new Promise((o,i)=>{let a=child_process.spawn("secret-tool",["store","--label",t,"service",t,"account",n]);a.on("error",i),a.on("close",f=>{f===0?o():i(new Error(`secret-tool exited with code ${f}`));}),a.stdin.write(r),a.stdin.end();});}async deleteSecret(t,n){try{return await V("secret-tool",["clear","service",t,"account",n]),!0}catch{return false}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var j={};L(j,{WindowsKeyVaultProvider:()=>C});var C,X=O(()=>{C=class{static async isAvailable(){try{return await g("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return false}}async getSecret(t,n){return g("keytar").getPassword(t,n)}async setSecret(t,n,r){await g("keytar").setPassword(t,n,r);}async deleteSecret(t,n){return g("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};});var l=process.env.FLOW_BASE_URL||"https://flow.ciandt.com",w={AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${l}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${l}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${l}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${l}/otel`},T={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials"},S="FLOW-nodejs",y="config.json";var D={ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL??`${l}/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"},M={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_ENDPOINT:w.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"},d={FLOW_TELEMETRY:"FLOW_TELEMETRY",FLOW_TELEMETRY_GATEWAY:"FLOW_TELEMETRY_GATEWAY_URL",LANGFUSE_BASE_URL:"LANGFUSE_BASE_URL",LANGFUSE_PUBLIC_KEY:"LANGFUSE_PUBLIC_KEY",LANGFUSE_SECRET_KEY:"LANGFUSE_SECRET_KEY",ANTHROPIC_MODEL:"ANTHROPIC_MODEL",ANTHROPIC_AUTH_TOKEN:"ANTHROPIC_AUTH_TOKEN",FLOW_OBS_DEBUG:"FLOW_TELEMETRY_DEBUG",FLOW_OBS_ALLOW_HTTP:"FLOW_TELEMETRY_ALLOW_HTTP",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES"};var H={LOCK_STALE_MS:3e4},$={UserPromptSubmit:5,PreToolUse:3,PostToolUse:10,Stop:15};var Y="flow-ai-obs-debug.log";({API_URL:process.env.FLOW_METRICS_URL||`${l}/metrics-collector-api/log-event`});var R={credentials:"credentials","token-cache":"tokenCache"};function E(){let e=A__namespace.default.homedir();if(process.platform==="darwin")return u__namespace.default.join(e,"Library","Preferences",S,y);if(process.platform==="win32"){let n=process.env.APPDATA??u__namespace.default.join(e,"AppData","Roaming");return u__namespace.default.join(n,S,y)}let t=process.env.XDG_CONFIG_HOME??u__namespace.default.join(e,".config");return u__namespace.default.join(t,S,y)}function v(){try{let e=s__namespace.default.readFileSync(E(),"utf8");return JSON.parse(e)}catch{return {}}}function W(e){let t=E();s__namespace.default.mkdirSync(u__namespace.default.dirname(t),{recursive:true}),s__namespace.default.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var h=class{static isAvailable(){return true}static hasExistingData(){try{if(!s__namespace.default.existsSync(E()))return !1;let t=JSON.parse(s__namespace.default.readFileSync(E(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let r=v(),o=R[n]??n,i=r[o];return i?typeof i=="string"?i:JSON.stringify(i):null}async setSecret(t,n,r){let o=v(),i=R[n]??n;if(n==="token-cache")try{o[i]=JSON.parse(r);}catch{o[i]=r;}else o[i]=r;W(o);}async deleteSecret(t,n){let r=v(),o=R[n]??n;return o in r?(delete r[o],W(r),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${E()}`}};async function J(){return await Ee()??new h}async function Ee(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(G(),x));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(K(),B));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(X(),j));return await e.isAvailable()?new e:null}default:return null}}var me=T.SERVICE,_e=T.ACCOUNT_CREDS,k=null;function ge(){return k||(k=J()),k}async function F(){let t=await(await ge()).getSecret(me,_e);if(!t)return null;try{return JSON.parse(t)}catch{return null}}u.join(A.tmpdir(),Y);function U(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let e=process.env.USERPROFILE;if(e){let t=e.replace(/^([A-Za-z]):/,(n,r)=>`/mnt/${r.toLowerCase()}`).replace(/\\/g,"/");return u__namespace.join(t,".claude","settings.json")}return u__namespace.join(A__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let e=process.env.USERPROFILE||A__namespace.homedir();return u__namespace.join(e,".claude","settings.json")}if(process.platform==="linux"&&process.getuid?.()===0&&process.env.SUDO_USER){let t=child_process.spawnSync("getent",["passwd",process.env.SUDO_USER],{encoding:"utf8",timeout:5e3}).stdout?.split(":")[5]?.trim();if(t)return u__namespace.join(t,".claude","settings.json")}return u__namespace.join(A__namespace.homedir(),".claude","settings.json")}var Oe=H.LOCK_STALE_MS;function q(e){try{let t=s__namespace.statSync(e);Date.now()-t.mtimeMs>Oe&&s__namespace.unlinkSync(e);}catch{}try{s__namespace.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 z(e){try{s__namespace.unlinkSync(e);}catch{}}function Le(e,t){let r=(Array.isArray(e)?e:[]).map(o=>{if(!Array.isArray(o?.hooks))return null;let i=o.hooks.filter(a=>!a.command?.startsWith?.("flow-ai-obs "));return i.length>0?{...o,hooks:i}:null}).filter(o=>o!=null);return [t,...r]}function Z(){let e=U(),t=e+".lock",n=[];s__namespace.mkdirSync(u__namespace.dirname(e),{recursive:true}),q(t);try{if(s__namespace.existsSync(e)){s__namespace.copyFileSync(e,e+".bkp");try{s__namespace.chmodSync(e+".bkp",384);}catch{}}let r={};try{r=JSON.parse(s__namespace.readFileSync(e,"utf8"));}catch{}let o=r.env&&typeof r.env=="object"?r.env:{};r.env={...M,...D,...o},r.otelHeadersHelper="flow-ai-obs otel-headers",(!r.hooks||typeof r.hooks!="object"||Array.isArray(r.hooks))&&(r.hooks={});let i=(c,_)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:_}]}),a=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],f=r.hooks;for(let c of a){let _=Le(f[c],i(c,$[c]));_.length>1&&n.push(c),f[c]=_;}s__namespace.writeFileSync(e,JSON.stringify(r,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384});try{s__namespace.chmodSync(e,384);}catch{}}finally{z(t);}return {settingsPath:e,preserved:n}}function Q(e){let t=U(),n=t+".lock";s__namespace.mkdirSync(u__namespace.dirname(t),{recursive:true}),q(n);try{let r={};try{r=JSON.parse(s__namespace.readFileSync(t,"utf8"));}catch{}(!r.env||typeof r.env!="object")&&(r.env={}),Object.assign(r.env,e),s__namespace.writeFileSync(t,JSON.stringify(r,null,2)+`
|
|
4
|
+
`,{encoding:"utf8",mode:384});try{s__namespace.chmodSync(t,384);}catch{}}finally{z(n);}}function ee(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:o,tenant:i}=n;return !r||!o||!i?null:{clientId:r,clientSecret:o,tenant:i}}catch{return null}}function te(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}.`}var we=u__namespace.default.resolve(__dirname,".."),Re=process.env.INIT_CWD?u__namespace.default.resolve(process.env.INIT_CWD):null;Re===we&&process.exit(0);async function ve(){try{Z();}catch{}let e=await F();if(!e){process.stderr.write(`
|
|
5
5
|
[flow-ai-obs] No credentials found.
|
|
6
6
|
Run \`flow-ai-obs auth login\` to authenticate and enable telemetry.
|
|
7
7
|
|
|
8
|
-
`);return}let
|
|
8
|
+
`);return}let t=ee(process.env[d.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let r=te(e);Q({[d.ANTHROPIC_AUTH_TOKEN]:r});}catch{}}ve().catch(()=>{});
|