@ciandt-flow/flow-ai-obs 0.9.2 → 0.9.3-beta.750

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,16 +1,17 @@
1
- 'use strict';var child_process=require('child_process'),util=require('util'),I=require('fs'),B=require('path'),me=require('os'),Je=require('https'),Ke=require('http'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var I__default=/*#__PURE__*/_interopDefault(I);var B__default=/*#__PURE__*/_interopDefault(B);var me__default=/*#__PURE__*/_interopDefault(me);var Je__default=/*#__PURE__*/_interopDefault(Je);var Ke__default=/*#__PURE__*/_interopDefault(Ke);var Pe=Object.defineProperty;var nt=(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 gt=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var St=(t,e)=>{for(var r in e)Pe(t,r,{get:e[r],enumerable:true});};var Bt={};St(Bt,{MacOsKeyVaultProvider:()=>At});var yt,At,Mt=gt(()=>{"use strict";yt=util.promisify(child_process.execFile),At=class{static async isAvailable(){try{return I.accessSync("/usr/bin/security",I.constants.X_OK),!0}catch{return !1}}async getSecret(e,r){try{let{stdout:n}=await yt("security",["find-generic-password","-w","-a",r,"-s",e]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await yt("security",["add-generic-password","-U","-a",r,"-s",e,"-w",n]);}async deleteSecret(e,r){try{return await yt("security",["delete-generic-password","-a",r,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Vt={};St(Vt,{LinuxKeyVaultProvider:()=>wt});var Ht,wt,Yt=gt(()=>{"use strict";Ht=util.promisify(child_process.execFile),wt=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 I.accessSync(r,I.constants.X_OK),!0}catch{}return !1}async getSecret(e,r){try{let{stdout:n}=await Ht("secret-tool",["lookup","service",e,"account",r]);return n.trim()||null}catch{return null}}async setSecret(e,r,n){await new Promise((o,s)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",r]);i.on("error",s),i.on("close",l=>{l===0?o():s(new Error(`secret-tool exited with code ${l}`));}),i.stdin.write(n),i.stdin.end();});}async deleteSecret(e,r){try{return await Ht("secret-tool",["clear","service",e,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var Gt={};St(Gt,{WindowsKeyVaultProvider:()=>Ot});var Ot,Wt=gt(()=>{"use strict";Ot=class{static async isAvailable(){try{return await nt("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,r){return nt("keytar").getPassword(e,r)}async setSecret(e,r,n){await nt("keytar").setPassword(e,r,n);}async deleteSecret(e,r){return nt("keytar").deletePassword(e,r)}getStoragePath(){return "Windows Credential Manager"}};});var Ne="https://flow.ciandt.com";function x(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():Ne}function W(){let t=x();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${t}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${t}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${t}/otel`}}W();var st={SERVICE:"flow-plugins-cli",ACCOUNT_TOKEN:"token-cache"},ot="FLOW-nodejs",it="config.json",_t={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};var S={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 A={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},Dt="flow-ai-obs-debug.log",O={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4};function Tt(){let t=x();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var Et={credentials:"credentials","token-cache":"tokenCache"};function J(){let t=me__default.default.homedir();if(process.platform==="darwin")return B__default.default.join(t,"Library","Preferences",ot,it);if(process.platform==="win32"){let r=process.env.APPDATA??B__default.default.join(t,"AppData","Roaming");return B__default.default.join(r,ot,it)}let e=process.env.XDG_CONFIG_HOME??B__default.default.join(t,".config");return B__default.default.join(e,ot,it)}function ht(){try{let t=I__default.default.readFileSync(J(),"utf8");return JSON.parse(t)}catch{return {}}}function xt(t){let e=J();I__default.default.mkdirSync(B__default.default.dirname(e),{recursive:true}),I__default.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var at=class{static isAvailable(){return true}static hasExistingData(){try{if(!I__default.default.existsSync(J()))return !1;let e=JSON.parse(I__default.default.readFileSync(J(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,r){let n=ht(),o=Et[r]??r,s=n[o];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(e,r,n){let o=ht(),s=Et[r]??r;if(r==="token-cache")try{o[s]=JSON.parse(n);}catch{o[s]=n;}else o[s]=n;xt(o);}async deleteSecret(e,r){let n=ht(),o=Et[r]??r;return o in n?(delete n[o],xt(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${J()}`}};async function Jt(){return await He()??new at}async function He(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Mt(),Bt));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Yt(),Vt));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Wt(),Gt));return await t.isAvailable()?new t:null}default:return null}}var Kt=st.SERVICE,jt=st.ACCOUNT_TOKEN,kt=null;function qt(){return kt||(kt=Jt()),kt}async function Lt(t){await(await qt()).setSecret(Kt,jt,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function It(){let e=await(await qt()).getSecret(Kt,jt);if(!e)return null;try{let r=JSON.parse(e);return {accessToken:r.accessToken,expiresAt:r.expiresAt,lastAuthCheckAt:r.lastAuthCheckAt}}catch{return null}}async function Rt(){let t=await It();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}}var We=B.join(me.tmpdir(),Dt);function a(...t){if(process.env[S.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
2
- `;try{I.writeFileSync(We,e,{flag:"a"});}catch(r){process.stderr.write(`[flow-obs debug ERROR] ${r.message}
3
- `);}}var b=class extends Error{constructor(e){super(e),this.name="AuthError";}},je=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function qe(t){if(!je.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var zt={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 ze(t,e){let r=e.length>400?e.slice(0,400)+"\u2026":e;a("toAuthError",`status=${t} body=${r}`);try{let n=JSON.parse(e);if(typeof n.error=="string"&&(a("toAuthError",`api_error_code=${n.error}`+(n.message?` api_message=${n.message}`:"")),zt[n.error]))return new b(zt[n.error])}catch{}return t===401||t===403||t===500?new b("Invalid credentials"):t>=400&&t<500?new b("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function j(t){return new Promise((e,r)=>{try{qe(t.tenant);}catch(p){return r(p)}let n=JSON.stringify({clientSecret:t.clientSecret}),o=new URL(W().AUTH_ENGINE),s=o.protocol==="https:",i={hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(n),FlowTenant:t.tenant}};a("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let c=(s?Je__default.default:Ke__default.default).request(i,p=>{let _=[];p.on("data",T=>_.push(T)),p.on("end",()=>{let T=_.join("");if((p.statusCode??0)>=400)return r(ze(p.statusCode??0,T));let m;try{m=JSON.parse(T);}catch{return r(new Error("Invalid response from auth engine"))}let g=m.expires_at??new Date(Date.now()+(m.expires_in??3600)*1e3).toISOString();e({accessToken:m.access_token??"",expiresAt:g});});});c.on("error",p=>r(new Error(`Network error: ${p.message}`))),c.write(n),c.end();})}var Xe=[/^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 Ze(t){return Xe.some(e=>e.test(t))}function Qe(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 lt(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:o,tenant:s}=r;return !n||!o||!s?null:{clientId:n,clientSecret:o,tenant:s}}catch{return null}}function ct(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let r=process.env[S.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&&Ze(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function Xt(){let t=lt(process.env[S.ANTHROPIC_AUTH_TOKEN]);return t?{user:await Rt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function tr(){return new Date().toISOString().slice(0,10)}async function er(t){let e=tr(),r=await It();if(r?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${r?.lastAuthCheckAt??"never"})`);try{let s=await j(t);try{await Lt({...s,lastAuthCheckAt:e});}catch{}return a("getOrRefreshToken",`daily check passed, expires=${s.expiresAt}`),s.accessToken}catch(s){if(s instanceof b)throw s;a("getOrRefreshToken",`daily check network error \u2014 using cache: ${s.message}`);}}let n=r!=null&&new Date(r.expiresAt)>new Date;if(a("getOrRefreshToken",`cacheValid=${n}`),n)return a("getOrRefreshToken",`using cached token, expires=${r.expiresAt}`),r.accessToken;a("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let o=await j(t);try{await Lt({...o,lastAuthCheckAt:e});}catch(s){a("getOrRefreshToken",`token cache save failed (non-fatal): ${s.message}`);}return a("getOrRefreshToken",`token refreshed, expires=${o.expiresAt}`),o.accessToken}function rr(t,e){let r=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${r}`}}function nr(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 v(){let t=[],e=process.env[S.ANTHROPIC_MODEL]??"",r=lt(process.env[S.ANTHROPIC_AUTH_TOKEN]);a("resolveCredentials",r?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),r&&a("resolveCredentials",`clientId=${r.clientId}`,`tenant=${r.tenant}`);let n=r?r.tenant:"",o=process.env[S.FLOW_TELEMETRY]==="true",s=process.env[S.LANGFUSE_BASE_URL],i=process.env[S.LANGFUSE_PUBLIC_KEY],l=process.env[S.LANGFUSE_SECRET_KEY];if(o&&s&&i&&l){let m="",g=n;r&&(m=await Rt().catch(()=>null)??r.clientId);let E={user:m??"",tenant:g??"",team:"",project:"",model:e};t.push({mode:"direct",...nr(ct(s),i,l),...E}),a("resolveCredentials","direct mode active",`user=${E.user}`,`tenant=${E.tenant}`);}if(!r){if(t.length===0){let m=[];return m.authError=false,m}return t}let c;try{c=await er(r);}catch(m){if(a("resolveCredentials",`token refresh failed: ${m.message}`,`(tenant=${r.tenant} clientId=${r.clientId})`),t.length>0)return t.authError=true,t;let g=[];return g.authError=true,g}let _={user:Qe(c)??r.clientId,tenant:n,team:"",project:"",model:e},T=process.env[S.FLOW_TELEMETRY_GATEWAY]??x();return t.push({mode:"gateway",...rr(ct(T),{accessToken:c}),..._}),t}async function ut(){return (await v()).length>0}function k(t,e){let r=typeof t=="object"?JSON.stringify(t):String(t??"");return r.length>e?r.slice(0,e)+" \u2026[truncated]":r}function pt(t,e=100){return String(t??"").split(`
4
- `)[0].slice(0,e).trim()}function q(){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 w(t){process.stdout.write(JSON.stringify(t));}var Pt=()=>crypto.randomBytes(16).toString("hex"),U=()=>crypto.randomBytes(8).toString("hex");function L(){return String(BigInt(Date.now())*1000000n)}var dr=/^[0-9a-f-]{1,64}$/i,fr=B.normalize(me.tmpdir())+B.sep;function mr(t,e){let r=B.resolve(t);if(!r.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return r}function Nt(t){if(!dr.test(t))throw new Error(`Invalid session ID: ${t}`);return mr(B.join(me.tmpdir(),`flow-obs-${t}.json`),fr)}function M(t){let e=Nt(t);if(!I.existsSync(e))return null;try{return JSON.parse(I.readFileSync(e,"utf8"))}catch{return null}}function H(t,e){I.writeFileSync(Nt(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function bt(t){try{I.unlinkSync(Nt(t));}catch{}}function re(t){if(!t||!I.existsSync(t))return null;try{let e=I.readFileSync(t,"utf8").trimEnd().split(`
5
- `);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 vt(t){if(!t||!I.existsSync(t))return null;try{let e=I.readFileSync(t,"utf8").trimEnd().split(`
6
- `),r=[],n=0,o=0;for(let s=e.length-1;s>=0;s--)try{let i=JSON.parse(e[s]);if(i.type==="user")break;if(i.type==="assistant"){let c=(i.message?.content??[]).filter(_=>_.type==="text").map(_=>_.text??"").join("");c&&r.unshift(c);let p=i.message?.usage??{};n+=(p.input_tokens??0)+(p.cache_read_input_tokens??0)+(p.cache_creation_input_tokens??0),o+=p.output_tokens??0;}}catch{}return !r.length&&n===0?null:{text:r.join(`
1
+ 'use strict';var child_process=require('child_process'),util=require('util'),T=require('fs'),nt=require('os'),W=require('path'),cn=require('https'),ln=require('http'),crypto=require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}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 T__namespace=/*#__PURE__*/_interopNamespace(T);var nt__namespace=/*#__PURE__*/_interopNamespace(nt);var W__namespace=/*#__PURE__*/_interopNamespace(W);var cn__default=/*#__PURE__*/_interopDefault(cn);var ln__default=/*#__PURE__*/_interopDefault(ln);var Ge=Object.defineProperty;var ut=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var pt=(t,e,n)=>()=>{if(n)throw n[0];try{return t&&(e=t(t=0)),e}catch(r){throw n=[r],r}};var Ot=(t,e)=>{for(var n in e)Ge(t,n,{get:e[n],enumerable:true});};function B(){let t=process.env.FLOW_BASE_URL;return t&&t.trim()?t.trim():je}function H(){let t=B();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${t}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${t}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${t}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${t}/otel`}}function kt(){let t=B();return {API_URL:process.env.FLOW_METRICS_URL||`${t}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var je,dr,ft,dt,mt,wt,m,Vt,w,Gt,R,_=pt(()=>{"use strict";je="https://flow.ciandt.com";dr=H(),ft={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},dt="FLOW-nodejs",mt="config.json",wt={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"},m={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",FLOW_OBS_USE_JSON_VAULT:"FLOW_TELEMETRY_USE_JSON_VAULT",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL",OTEL_EXPORTER_OTLP_HEADERS:"OTEL_EXPORTER_OTLP_HEADERS"},Vt={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3,CLI:"flow-ai-obs "},w={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},Gt="flow-ai-obs-debug.log",R={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60};});var Yt={};Ot(Yt,{MacOsKeyVaultProvider:()=>vt});var It,vt,Jt=pt(()=>{"use strict";It=util.promisify(child_process.execFile),vt=class{static async isAvailable(){try{return T.accessSync("/usr/bin/security",T.constants.X_OK),!0}catch{return !1}}async getSecret(e,n){try{let{stdout:r}=await It("security",["find-generic-password","-w","-a",n,"-s",e]);return r.trim()||null}catch{return null}}async setSecret(e,n,r){await It("security",["add-generic-password","-U","-a",n,"-s",e,"-w",r]);}async deleteSecret(e,n){try{return await It("security",["delete-generic-password","-a",n,"-s",e]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var qt={};Ot(qt,{LinuxKeyVaultProvider:()=>Pt});var Kt,Pt,Xt=pt(()=>{"use strict";Kt=util.promisify(child_process.execFile),Pt=class{static async isAvailable(){let e=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let n of e)try{return T.accessSync(n,T.constants.X_OK),!0}catch{}return !1}async getSecret(e,n){try{let{stdout:r}=await Kt("secret-tool",["lookup","service",e,"account",n]);return r.trim()||null}catch{return null}}async setSecret(e,n,r){await new Promise((o,s)=>{let i=child_process.spawn("secret-tool",["store","--label",e,"service",e,"account",n]);i.on("error",s),i.on("close",l=>{l===0?o():s(new Error(`secret-tool exited with code ${l}`));}),i.stdin.write(r),i.stdin.end();});}async deleteSecret(e,n){try{return await Kt("secret-tool",["clear","service",e,"account",n]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var zt={};Ot(zt,{WindowsKeyVaultProvider:()=>Nt});var Nt,Zt=pt(()=>{"use strict";Nt=class{static async isAvailable(){try{return await ut("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(e,n){return ut("keytar").getPassword(e,n)}async setSecret(e,n,r){await ut("keytar").setPassword(e,n,r);}async deleteSecret(e,n){return ut("keytar").deletePassword(e,n)}getStoragePath(){return "Windows Credential Manager"}};});_();_();var Rt={credentials:"credentials","token-cache":"tokenCache"};function z(){let t=nt__namespace.default.homedir();if(process.platform==="darwin")return W__namespace.default.join(t,"Library","Preferences",dt,mt);if(process.platform==="win32"){let n=process.env.APPDATA??W__namespace.default.join(t,"AppData","Roaming");return W__namespace.default.join(n,dt,mt)}let e=process.env.XDG_CONFIG_HOME??W__namespace.default.join(t,".config");return W__namespace.default.join(e,dt,mt)}function Lt(){try{let t=T__namespace.default.readFileSync(z(),"utf8");return JSON.parse(t)}catch{return {}}}function jt(t){let e=z();T__namespace.default.mkdirSync(W__namespace.default.dirname(e),{recursive:true}),T__namespace.default.writeFileSync(e,JSON.stringify(t,null,2),{encoding:"utf8",mode:384});}var Q=class{static isAvailable(){return true}static hasExistingData(){try{if(!T__namespace.default.existsSync(z()))return !1;let e=JSON.parse(T__namespace.default.readFileSync(z(),"utf8"));return !!(e&&e.credentials)}catch{return false}}async getSecret(e,n){let r=Lt(),o=Rt[n]??n,s=r[o];return s?typeof s=="string"?s:JSON.stringify(s):null}async setSecret(e,n,r){let o=Lt(),s=Rt[n]??n;if(n==="token-cache")try{o[s]=JSON.parse(r);}catch{o[s]=r;}else o[s]=r;jt(o);}async deleteSecret(e,n){let r=Lt(),o=Rt[n]??n;return o in r?(delete r[o],jt(r),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${z()}`}};async function Qt(){return process.env[m.FLOW_OBS_USE_JSON_VAULT]==="1"?new Q:await nn()??new Q}async function nn(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Jt(),Yt));return await t.isAvailable()?new t:null}case "linux":{let{LinuxKeyVaultProvider:t}=await Promise.resolve().then(()=>(Xt(),qt));return await t.isAvailable()?new t:null}case "win32":{let{WindowsKeyVaultProvider:t}=await Promise.resolve().then(()=>(Zt(),zt));return await t.isAvailable()?new t:null}default:return null}}_();var te=ft.SERVICE;ft.ACCOUNT_CREDS;var ee=ft.ACCOUNT_TOKEN,bt=null;function ne(){return bt||(bt=Qt()),bt}async function Ut(t){await(await ne()).setSecret(te,ee,JSON.stringify({accessToken:t.accessToken,expiresAt:t.expiresAt,lastAuthCheckAt:t.lastAuthCheckAt}));}async function Ct(){let e=await(await ne()).getSecret(te,ee);if(!e)return null;try{let n=JSON.parse(e);return {accessToken:n.accessToken,expiresAt:n.expiresAt,lastAuthCheckAt:n.lastAuthCheckAt}}catch{return null}}async function tt(){let t=await Ct();if(!t||!t.accessToken)return null;try{let e=t.accessToken.split(".");if(e.length<2)return null;let n=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email??n.preferred_username??n.upn??n.sub??null}catch{return null}}_();_();var an=W.join(nt.tmpdir(),Gt);function a(...t){if(process.env[m.FLOW_OBS_DEBUG]!=="1")return;let e=`[${new Date().toISOString()}] ${t.join(" ")}
2
+ `;try{T.writeFileSync(an,e,{flag:"a"});}catch(n){process.stderr.write(`[flow-obs debug ERROR] ${n.message}
3
+ `);}}var U=class extends Error{constructor(e){super(e),this.name="AuthError";}},un=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function pn(t){if(!un.test(t))throw new Error(`Invalid tenant value: "${t}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var re={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};function fn(t,e){let n=e.length>400?e.slice(0,400)+"\u2026":e;a("toAuthError",`status=${t} body=${n}`);try{let r=JSON.parse(e);if(typeof r.error=="string"&&(a("toAuthError",`api_error_code=${r.error}`+(r.message?` api_message=${r.message}`:"")),re[r.error]))return new U(re[r.error])}catch{}return t===401||t===403||t===500?new U("Invalid credentials"):t>=400&&t<500?new U("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}function V(t){return new Promise((e,n)=>{try{pn(t.tenant);}catch(u){return n(u)}let r=JSON.stringify({clientSecret:t.clientSecret}),o=new URL(H().AUTH_ENGINE),s=o.protocol==="https:",i={hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(r),FlowTenant:t.tenant}};a("getToken",`requesting token tenant=${t.tenant} host=${i.hostname} path=${i.path}`);let c=(s?cn__default.default:ln__default.default).request(i,u=>{let g=[];u.on("data",S=>g.push(S)),u.on("end",()=>{let S=g.join("");if((u.statusCode??0)>=400)return n(fn(u.statusCode??0,S));let h;try{h=JSON.parse(S);}catch{return n(new Error("Invalid response from auth engine"))}let E=h.expires_at??new Date(Date.now()+(h.expires_in??3600)*1e3).toISOString();e({accessToken:h.access_token??"",expiresAt:E});});});c.on("error",u=>n(new Error(`Network error: ${u.message}`))),c.write(r),c.end();})}_();var mn=[/^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 gn(t){return mn.some(e=>e.test(t))}function Sn(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let n=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8"));return n.email||n.preferred_username||n.upn||n.sub||null}catch{return null}}function St(t){if(!t)return null;try{let e=t.split(".");if(e.length<2)return null;let n=JSON.parse(Buffer.from(e[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:r,clientSecret:o,tenant:s}=n;return !r||!o||!s?null:{clientId:r,clientSecret:o,tenant:s}}catch{return null}}function gt(t){let e;try{e=new URL(t);}catch{throw new Error(`Invalid URL: ${t}`)}let n=process.env[m.FLOW_OBS_ALLOW_HTTP]==="true";if(!n&&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(!n&&gn(e.hostname))throw new Error(`SSRF: private/loopback host not allowed: ${e.hostname}`);return t}async function ie(){let t=St(process.env[m.ANTHROPIC_AUTH_TOKEN]);return t?{user:await tt().catch(()=>null)??t.clientId,tenant:t.tenant}:{user:"",tenant:""}}function En(){return new Date().toISOString().slice(0,10)}async function hn(t){let e=En(),n=await Ct();if(n?.lastAuthCheckAt!==e){a("getOrRefreshToken",`daily auth check (last: ${n?.lastAuthCheckAt??"never"})`);try{let s=await V(t);try{await Ut({...s,lastAuthCheckAt:e});}catch{}return a("getOrRefreshToken",`daily check passed, expires=${s.expiresAt}`),s.accessToken}catch(s){if(s instanceof U)throw s;a("getOrRefreshToken",`daily check network error \u2014 using cache: ${s.message}`);}}let r=n!=null&&new Date(n.expiresAt)>new Date;if(a("getOrRefreshToken",`cacheValid=${r}`),r)return a("getOrRefreshToken",`using cached token, expires=${n.expiresAt}`),n.accessToken;a("getOrRefreshToken",`token expired \u2014 refreshing via auth-engine (tenant=${t.tenant} clientId=${t.clientId})`);let o=await V(t);try{await Ut({...o,lastAuthCheckAt:e});}catch(s){a("getOrRefreshToken",`token cache save failed (non-fatal): ${s.message}`);}return a("getOrRefreshToken",`token refreshed, expires=${o.expiresAt}`),o.accessToken}function _n(t,e){let n=e&&e.accessToken?e.accessToken:"";return {endpoint:t.replace(/\/$/,"")+"/flow-langfuse-gateway/v1/traces",authHeader:`Bearer ${n}`}}function Tn(t,e,n){let r=Buffer.from(`${e}:${n}`).toString("base64");return {endpoint:t.replace(/\/$/,"")+"/api/public/otel/v1/traces",authHeader:`Basic ${r}`}}async function C(){let t=[],e=process.env[m.ANTHROPIC_MODEL]??"",n=St(process.env[m.ANTHROPIC_AUTH_TOKEN]);a("resolveCredentials",n?"credentials resolved from ANTHROPIC_AUTH_TOKEN":"ANTHROPIC_AUTH_TOKEN absent or invalid"),n&&a("resolveCredentials",`clientId=${n.clientId}`,`tenant=${n.tenant}`);let r=n?n.tenant:"",o=process.env[m.FLOW_TELEMETRY]==="true",s=process.env[m.LANGFUSE_BASE_URL],i=process.env[m.LANGFUSE_PUBLIC_KEY],l=process.env[m.LANGFUSE_SECRET_KEY];if(o&&s&&i&&l){let h="",E=r;n&&(h=await tt().catch(()=>null)??n.clientId);let y={user:h??"",tenant:E??"",team:"",project:"",model:e};t.push({mode:"direct",...Tn(gt(s),i,l),...y}),a("resolveCredentials","direct mode active",`user=${y.user}`,`tenant=${y.tenant}`);}if(!n){if(t.length===0){let h=[];return h.authError=false,h}return t}let c;try{c=await hn(n);}catch(h){if(a("resolveCredentials",`token refresh failed: ${h.message}`,`(tenant=${n.tenant} clientId=${n.clientId})`),t.length>0)return t.authError=true,t;let E=[];return E.authError=true,E}let g={user:Sn(c)??n.clientId,tenant:r,team:"",project:"",model:e},S=process.env[m.FLOW_TELEMETRY_GATEWAY]??B();return t.push({mode:"gateway",..._n(gt(S),{accessToken:c}),...g}),t}async function Et(){return (await C()).length>0}var se=false,oe=false;function ae(){let t=process.env[m.FLOW_USER_EMAIL];if(t){let e=t.replace(/[\r\n]/g,"").trim();return e?(a("resolveUserEmail","using FLOW_USER_EMAIL override: [REDACTED]"),e):null}try{let e=nt__namespace.default.userInfo().username||process.env.USERNAME||process.env.USER||"",n=e.lastIndexOf("\\");if(n!==-1&&(e=e.slice(n+1)),e=e.trim().replace(/[^a-zA-Z0-9._%+\-]/g,""),!e)return a("resolveUserEmail","username empty after sanitisation \u2014 omitting x-flow-user"),se||(se=!0,console.warn("[flow-ai-obs] Could not derive x-flow-user: username is empty. Set FLOW_USER_EMAIL to fix this.")),null;let r=`${e}@ciandt.com`;return a("resolveUserEmail","derived email: [REDACTED]"),r}catch(e){return a("resolveUserEmail",`os.userInfo() threw: ${e.message} \u2014 omitting x-flow-user`),oe||(oe=true,console.warn("[flow-ai-obs] Could not derive x-flow-user from OS username. Set FLOW_USER_EMAIL to fix this.")),null}}function yn(t){let e=process.env.OTEL_EXPORTER_OTLP_HEADERS;if(!e)return null;for(let n of e.split(",")){let r=n.indexOf("=");if(!(r<=0)&&n.slice(0,r).trim().toLowerCase()===t.toLowerCase())return n.slice(r+1).replace(/[\r\n]/g,"").trim()||null}return null}function ce(){return yn("x-flow-api-key")}function L(t,e){let n=typeof t=="object"?JSON.stringify(t):String(t??"");return n.length>e?n.slice(0,e)+" \u2026[truncated]":n}function ht(t,e=100){return String(t??"").split(`
4
+ `)[0].slice(0,e).trim()}function et(){return new Promise(t=>{let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{e+=n;}),process.stdin.on("end",()=>{try{t(JSON.parse(e));}catch{t({});}});})}function k(t){process.stdout.write(JSON.stringify(t));}var Ft=()=>crypto.randomBytes(16).toString("hex"),F=()=>crypto.randomBytes(8).toString("hex");function I(){return String(BigInt(Date.now())*1000000n)}var Pn=/^[0-9a-f-]{1,64}$/i,Nn=W.normalize(nt.tmpdir())+W.sep;function bn(t,e){let n=W.resolve(t);if(!n.startsWith(e))throw new Error(`Path traversal detected: ${t}`);return n}function $t(t){if(!Pn.test(t))throw new Error(`Invalid session ID: ${t}`);return bn(W.join(nt.tmpdir(),`flow-obs-${t}.json`),Nn)}function G(t){let e=$t(t);if(!T.existsSync(e))return null;try{return JSON.parse(T.readFileSync(e,"utf8"))}catch{return null}}function j(t,e){T.writeFileSync($t(t),JSON.stringify(e),{encoding:"utf8",mode:384});}function Dt(t){try{T.unlinkSync($t(t));}catch{}}function de(t){if(!t||!T.existsSync(t))return null;try{let e=T.readFileSync(t,"utf8").trimEnd().split(`
5
+ `);for(let n=e.length-1;n>=0;n--)try{let r=JSON.parse(e[n]);if(r.type==="user"&&r.uuid)return r.uuid}catch{}}catch{}return null}function xt(t){if(!t||!T.existsSync(t))return null;try{let e=T.readFileSync(t,"utf8").trimEnd().split(`
6
+ `),n=[],r=0,o=0;for(let s=e.length-1;s>=0;s--)try{let i=JSON.parse(e[s]);if(i.type==="user")break;if(i.type==="assistant"){let c=(i.message?.content??[]).filter(g=>g.type==="text").map(g=>g.text??"").join("");c&&n.unshift(c);let u=i.message?.usage??{};r+=(u.input_tokens??0)+(u.cache_read_input_tokens??0)+(u.cache_creation_input_tokens??0),o+=u.output_tokens??0;}}catch{}return !n.length&&r===0?null:{text:n.join(`
7
7
 
8
- `),inputTokens:n,outputTokens:o}}catch{}return null}var Tr=new Set([".venv","__pycache__",".git","node_modules"]),Er=new Set([".pyc",".pyo"]),hr=new Set(["SKILL.md",".DS_Store",".gitignore"]);function oe(t){return t.replace(":","/")}function dt(t,e){if(!t)return null;let r=oe(t),n=[B.join(me.homedir(),".claude","skills",r,"SKILL.md"),B.join(e??"",".claude","skills",r,"SKILL.md")];for(let o of n)if(I.existsSync(o))try{return I.readFileSync(o,"utf8")}catch{}return null}function ie(t){return t.split(`
9
- `)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var yr=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function ae(t){return !!t.slashSkill||t.toolCalls.some(n=>n.tool==="Skill")?t.toolCalls.some(n=>n.tool==="Skill"&&!n.synthetic||yr.has(n.tool))?"complete":"prerequisite_required":null}function ft(t,e){if(!t)return null;let r=oe(t),n=[B.join(me.homedir(),".claude","skills",r),B.join(e??"",".claude","skills",r)],o=null;for(let l of n)if(I.existsSync(B.join(l,"SKILL.md"))){o=l;break}if(!o)return null;let s=[];function i(l,c){for(let p of I.readdirSync(l,{withFileTypes:true})){if(Tr.has(p.name)||hr.has(p.name)||Er.has(B.extname(p.name)))continue;let _=c?`${c}/${p.name}`:p.name;p.isDirectory()?i(B.join(l,p.name),_):s.push(_);}}return i(o,""),s.length>0?s:null}function Or(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function kr(t,e,r,n){return new Promise(o=>{let s=new URL(t),i=s.protocol==="https:",l=(i?Je__default.default:Ke__default.default).request({hostname:s.hostname,port:s.port||(i?443:80),path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(e),Authorization:`Bearer ${String(r).replace(/[\r\n]/g,"")}`,FlowTenant:String(n).replace(/[\r\n]/g,"")}},c=>{c.resume(),o(c.statusCode??0);});l.on("error",()=>o(0)),l.setTimeout(5e3,()=>{l.destroy(),o(0);}),l.write(e),l.end();})}async function C(t,e={}){try{let r=lt(process.env[S.ANTHROPIC_AUTH_TOKEN]);if(!r)return;let n,o=new Promise((T,m)=>{n=setTimeout(()=>m(new Error("getToken timeout")),4e3),n.unref();}),{accessToken:s}=await Promise.race([j(r),o]);clearTimeout(n);let i=Or(s);if(!i)return;let l=i.tenant||r.tenant,c=JSON.stringify({action:t,booster:Tt().BOOSTER,metadata:e,success:!0,tenant:l,timestamp:new Date().toISOString(),os:process.platform,user:{email:i.email||"",id:i.sub||"",name:i.name||i.email||""}}),p=ct(Tt().API_URL),_=await kr(p,c,s,l);a("metrics.logEvent",`action=${t} status=${_}`);}catch(r){a("metrics.logEvent",`silenced error: ${r.message}`);}}var Lr=`\u26D4 Your Flow API key has expired. You no longer have access to Claude Code through the Flow platform. To restore observability and access, visit ${x()}/settings/api-keys to generate a new API key, then run: flow-ai-obs login`;async function Ut(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Lr})+`
10
- `);return}let n=!!(await v()).authError,o=t.session_id||"unknown",s=t.prompt||"",i=t.cwd||"",l=re(t.transcript_path)||Pt(),c=ie(s),p=c?dt(c,i):null,_=c?ft(c,i):null;H(o,{traceId:Pt(),spanId:U(),startNs:L(),sessionId:o,prompt:s,cwd:i,traceName:l,transcriptPath:t.transcript_path||"",model:process.env[S.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:c,skillContent:p,skillArtifacts:_}),C("SESSION_STARTED",{traceType:c?"skill":"prompt",slashSkill:c,clientIdExpired:n}),a("UserPromptSubmit",`sid=${o}`,`traceName=${l}`,`slashSkill=${c}`),w(t);}async function ce(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},o=M(e);o&&(o.pendingTool={name:r,inputStr:k(n,O.TOOL_INPUT),startNs:L()},H(e,o)),a("PreToolUse",`sid=${e}`,`tool=${r}`,`stateFound=${!!o}`),w(t);}var Ir={name:_t.SCOPE_NAME,version:_t.SCOPE_VERSION},f={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 u(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function $(...t){return t.filter(e=>e!==null)}function le(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:Ir,spans:Array.isArray(e)?e:[e]}]}]}}var ue=B.join(me.tmpdir(),"flow-obs-requests.ndjson");function pe(t,e,r,n,o){if(process.env[S.FLOW_OBS_DEBUG]!=="1")return;let s=JSON.stringify({ts:new Date().toISOString(),request:{method:"POST",url:t,headers:e,body:JSON.parse(r)},response:{status:n,body:o}});try{I.writeFileSync(ue,s+`
11
- `,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${ue}`);}catch(i){a("sendTraces:dump",`falha ao salvar: ${i.message}`);}}function Ur(t){let e=new URL(t),r=new URL(W().GATEWAY_HEALTH);return r.hostname=e.hostname,r.port=e.port,r.protocol=e.protocol,r}function de(t,e){return new Promise((r,n)=>{let o=t._isSSL?Je__default.default:Ke__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let s=o.request(t,i=>{let l=[];i.on("data",c=>l.push(c)),i.on("end",()=>r({statusCode:i.statusCode??0,body:l.join("")}));});s.setTimeout(1e4,()=>{s.destroy(new Error("Request timeout"));}),s.on("error",i=>n(new Error(`Network error: ${i.message}`))),e&&s.write(e),s.end();})}async function fe(t,e){let r;try{r=Ur(t);}catch{return false}let n=r.protocol==="https:";try{let o={};e&&(o.Authorization=String(e).replace(/[\r\n]/g,""));let s=await de({hostname:r.hostname,port:r.port||(n?443:80),path:r.pathname,method:"GET",headers:o,_isSSL:n},null);return a("checkHealth",`url=${r.href} status=${s.statusCode}`),s.statusCode>=200&&s.statusCode<300}catch{return false}}async function mt(t,e,r){let n=JSON.stringify(t),o=new URL(e),s=o.protocol==="https:",i=String(r).replace(/[\r\n]/g,""),l={"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(n)};a("sendTraces:request",`POST ${e}`),a("sendTraces:request",`headers=${JSON.stringify({...l,Authorization:i.slice(0,20)+"\u2026"})}`),a("sendTraces:request",`body=${n.slice(0,500)}${n.length>500?"\u2026":""}`);try{let c=await de({hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname,method:"POST",headers:l,_isSSL:s},n);return a("sendTraces:response",`status=${c.statusCode}`),pe(e,l,n,c.statusCode,c.body),c.statusCode}catch(c){return a("sendTraces:error",c.message),pe(e,l,n,0,c.message),0}}function Cr(){let t=parseInt(process.env[S.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(A.MIN_TTL_DAYS,Math.min(A.MAX_TTL_DAYS,t)):A.DEFAULT_TTL_DAYS)*24*60*60*1e3}function $r(){let t=parseInt(process.env[S.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(A.MIN_MAX_FILES,Math.min(A.MAX_MAX_FILES,t)):A.DEFAULT_MAX_FILES}function ge(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return B__default.default.join(me__default.default.tmpdir(),`${A.FILE_PREFIX}${t}.json`)}function $t(){let t=me__default.default.tmpdir(),e;try{e=I__default.default.readdirSync(t);}catch{return []}return e.filter(r=>r.startsWith(A.FILE_PREFIX)&&r.endsWith(".json")).map(r=>{let n=B__default.default.join(t,r),o=0;try{o=I__default.default.statSync(n).mtimeMs;}catch{}return {full:n,mtime:o}}).sort((r,n)=>r.mtime-n.mtime).map(r=>r.full)}function z(t){try{let e=$r(),r=$t();if(r.length>=e){let s=r.slice(0,r.length-e+1);for(let i of s)try{I__default.default.unlinkSync(i);}catch{}}let n=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,o={fileId:n,bufferedAt:Date.now(),payload:t};return I__default.default.writeFileSync(ge(n),JSON.stringify(o),{encoding:"utf8",mode:384}),a("buffer",`saved fileId=${n}`),n}catch(e){return a("buffer",`saveToBuffer failed: ${e.message}`),null}}function Se(t){let e=$t(),r=t,n=[];for(let o of e){if(n.length>=r)break;try{let s=I__default.default.readFileSync(o,"utf8"),i=JSON.parse(s);i&&i.fileId&&i.payload&&n.push(i);}catch{a("buffer",`skipping malformed file: ${o}`);}}return n}function _e(t){try{I__default.default.unlinkSync(ge(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function Te(){let t=Date.now()-Cr();for(let e of $t())try{let{mtimeMs:r}=I__default.default.statSync(e);r<t&&(I__default.default.unlinkSync(e),a("buffer",`evicted stale: ${B__default.default.basename(e)}`));}catch{}}async function Fr(t){Te();let e=Se(A.REPLAY_BATCH_SIZE);e.length&&(a("replayBufferedTraces",`replaying ${e.length} buffered trace(s)`),await Promise.allSettled(e.map(async r=>{try{let n=await mt(r.payload,t.endpoint,t.authHeader);n>=200&&n<300?(_e(r.fileId),a("replayBufferedTraces",`replayed fileId=${r.fileId} status=${n}`)):a("replayBufferedTraces",`replay failed fileId=${r.fileId} status=${n}`);}catch(n){a("replayBufferedTraces",`replay error fileId=${r.fileId}: ${n.message}`);}})));}async function Ee(t){let e=await v();if(!e.length)return e.authError&&(a("postToLangfuse","auth refresh failed \u2014 buffering trace"),z(t)),0;let r=await Promise.all(e.map(async s=>{if(s.mode!=="gateway")return {creds:s,healthy:true};let i=await fe(s.endpoint,s.authHeader);return {creds:s,healthy:i}})),n=r.find(s=>s.creds.mode==="gateway"&&s.healthy)?.creds??r.find(s=>s.creds.mode==="direct")?.creds;return n&&await Fr(n),(await Promise.all(r.map(async({creds:s,healthy:i})=>{if(s.mode==="gateway"){if(!i)return a("postToLangfuse","gateway health check failed \u2014 buffering trace"),z(t),0;let c=await mt(t,s.endpoint,s.authHeader);return (c===0||c>=500)&&(a("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),z(t)),c}let l=await mt(t,s.endpoint,s.authHeader);return (l===0||l>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${l}) \u2014 buffering trace`),z(t)),l}))).find(s=>s!==0)??0}var y="[REDACTED]",Dr="[REDACTED-EMAIL]",xr="[REDACTED-CPF]",Br="[REDACTED-CNPJ]",he="[REDACTED-PHONE]",Mr=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${y}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${y}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(t,e)=>`${e}${y}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(t,e)=>`${e}${y}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(t,e,r)=>`${e}
12
- ${y}
13
- ${r}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${y}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${y}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${y}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${y}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${y}`},{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}${y}${r}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${y}@`},{re:/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,replace:()=>Dr},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>xr},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>Br},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>he},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>he}];function R(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return Mr.reduce((r,{re:n,replace:o})=>r.replace(n,o),e)}async function ye(t){let e=t.session_id||"unknown",r=t.tool_name||"unknown",n=t.tool_input||{},o=t.tool_response,s=o!==null&&typeof o=="object"?o.output??JSON.stringify(o):o??"",i=M(e);if(!i){w(t);return}let l=L(),c=i.pendingTool,p=c?.name===r,_=p?c.startNs:String(BigInt(l)-200000000n),T=p?c.inputStr:k(n,O.TOOL_INPUT),m=T,g=null;if(r==="Skill"){let rt=typeof n=="object"&&n!==null?n.skill||n.name||n.skillName||n.commandName||String(Object.values(n)[0]??""):String(n);g=rt?String(rt).trim():null;let P=g?dt(g,i.cwd):null;P&&(m=P,i.skillContent||(i.skillContent=P),i.skillArtifacts||(i.skillArtifacts=ft(g,i.cwd))),g&&!i.slashSkill&&(i.slashSkill=g),a("PostToolUse","Skill tool detected",`skillName=${g}`,`contentFound=${!!P}`);}let E=R(k(s,O.TOOL_OUTPUT)),h=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(E.slice(0,500)),X=h?"ERROR":"DEFAULT",Y=U(),Z=Math.round(Number(BigInt(l)-BigInt(_))/1e6),tt={Agent:"AGENT",Task:"AGENT"}[r]??"TOOL",et=r==="Skill"&&g?g:pt(T,60);i.toolCalls.push({tool:r,brief:et,error:h,durationMs:Z});let G=i.spans;G.push({traceId:i.traceId,spanId:Y,parentSpanId:i.spanId,name:r,kind:3,startTimeUnixNano:_,endTimeUnixNano:l,attributes:$(u(f.OBS_NAME,r),u(f.OBS_TYPE,tt),u(f.OBS_LEVEL,X),u(f.OBS_INPUT,R(m)),u(f.OBS_OUTPUT,E),u("tool.name",r),u("tool.error",String(h)),r==="Skill"&&g?u("skill.name",g):null,r==="Skill"?u("skill.invocation","slash-command"):null),status:{code:h?2:1}}),i.pendingTool=null,H(e,i),h&&C("TOOL_ERROR",{toolName:r}),a("PostToolUse",`sid=${e}`,`tool=${r}`,`error=${h}`,`durationMs=${Z}`,`totalSpans=${G.length}`),w(t);}var Ae={"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 we(t,e,r){let n=Object.keys(Ae).find(i=>(t??"").toLowerCase().includes(i));if(!n)return;let o=Ae[n],s=(e*o.input+r*o.output)/1e6;return Math.round(s*1e6)/1e6}async function Oe(t){let e=t.session_id||"unknown",r=t.stop_reason||"end_turn",n=M(e);if(!n){w(t);return}n.slashSkill&&!/^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/i.test(n.slashSkill)&&(a("Stop",`sid=${e}`,`slashSkill rejected post-disk: "${n.slashSkill}"`),n.slashSkill=null);let o=L(),s=await Xt(),i=n.toolCalls,l=n.spans;if(n.slashSkill&&!i.some(d=>d.tool==="Skill")){let d=U(),N=n.skillContent?n.skillContent:JSON.stringify({skill:n.slashSkill});i.push({tool:"Skill",brief:n.slashSkill,error:false,durationMs:0,synthetic:true}),l.push({traceId:n.traceId,spanId:d,parentSpanId:n.spanId,name:"Skill",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:n.startNs,attributes:$(u(f.OBS_NAME,"Skill"),u(f.OBS_TYPE,"TOOL"),u(f.OBS_LEVEL,"DEFAULT"),u(f.OBS_INPUT,N),u(f.OBS_OUTPUT,"loaded via slash command"),u("tool.name","Skill"),u("tool.error","false"),u("skill.name",n.slashSkill),u("skill.invocation","slash-command")),status:{code:1}}),a("Stop",`slashSkill=${n.slashSkill}`,"synthetic span injected");}let c=t.transcript_path||n.transcriptPath||"",p=vt(c);if(c&&(i.some(d=>d.tool==="Skill"&&!d.synthetic)||!!n.slashSkill)&&!p?.text){await new Promise(N=>setTimeout(N,500));let d=vt(c);d?.text&&(p=d);}a("Stop",`transcriptPath=${c||"(empty)"}`,`assistantOut=${p?`text=${p.text.length}chars`:"null"}`);let T=i.length,m=i.filter(d=>d.error).length,g=R(p?.text?k(p.text,O.TRACE_OUTPUT):T===0?"No tools used":i.map((d,N)=>`${N+1}. ${d.tool}${d.brief?` \u2192 ${d.brief}`:""}${d.error?" [ERROR]":""}`).join(`
14
- `)),E=p?.inputTokens??0,h=p?.outputTokens??0,X=i.map((d,N)=>`${N+1}. ${d.tool}${d.brief?` \u2192 ${d.brief}`:""}${d.error?" [ERROR]":""} (${d.durationMs}ms)`),Y=!!(n.slashSkill||i.some(d=>d.tool==="Skill")),Z=i.some(d=>d.tool==="Agent");if(!Y&&!Z){a("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),C("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),bt(e),w(t);return}let Q=Y?"skill":"agent",tt=Math.round(Number(BigInt(o)-BigInt(n.startNs))/1e6),et=we(n.model,E,h),D=ae(n);D==="prerequisite_required"&&p?.text&&(D="complete"),D==="prerequisite_required"&&(l.push({traceId:n.traceId,spanId:U(),parentSpanId:n.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:n.startNs,endTimeUnixNano:o,attributes:$(u(f.OBS_NAME,"prerequisite-check"),u(f.OBS_TYPE,"EVENT"),u(f.OBS_LEVEL,"WARNING"),u(f.OBS_OUTPUT,g),u("skill.name",n.slashSkill||void 0),u("execution_status","prerequisite_required")),status:{code:1}}),a("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${n.slashSkill}`));let G=(()=>{if(!(!Y||!n.prompt)){if(n.slashSkill){let d=n.prompt.replace(new RegExp(`^\\/${n.slashSkill}\\s*`,"i"),"").trim();return d?k(R(d),O.USER_INSTRUCTION):void 0}return k(R(n.prompt),O.USER_INSTRUCTION)||void 0}})(),rt=JSON.stringify({trace_type:Q,...D!==null&&{execution_status:D},...n.slashSkill?{skill_name:n.slashSkill}:{},...n.skillArtifacts?.length&&{skill_artifacts:n.skillArtifacts},...G!==void 0&&{user_instruction:G},latency_ms:tt,...E&&{tokens_input:E},...h&&{tokens_output:h},cost_usd:et,...n.model?{model:n.model}:{},toolCount:T,errorCount:m,stopReason:r,sessionId:n.sessionId,tools:X.length?X:void 0}),P=R(k(n.prompt,O.TRACE_INPUT)),ke=$(u(f.TRACE_NAME,n.traceName),u(f.TRACE_INPUT,P),u(f.TRACE_OUTPUT,g),u(f.OBS_INPUT,P),u(f.OBS_OUTPUT,g),u(f.TRACE_METADATA,rt),u(f.SESSION_ID,n.sessionId),u(f.USER_ID,s.user),u(f.OBS_TYPE,"GENERATION"),u(f.MODEL,n.model),E?u(f.INPUT_TOKENS,E):null,h?u(f.OUTPUT_TOKENS,h):null,u("claude.stop_reason",r),u("claude.tool_count",String(T)),u("claude.error_count",String(m)),u("claude.session_id",n.sessionId),u("flow.trace_type",Q),{key:f.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:Q}]}}}),Le={traceId:n.traceId,spanId:n.spanId,name:n.traceName,kind:1,startTimeUnixNano:n.startNs,endTimeUnixNano:o,attributes:ke,status:{code:m>0?2:1}},Ie=$(u("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),u("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),Ft=[...l,Le];a("Stop",`sid=${e}`,`totalTools=${T}`,`errorTools=${m}`,`spans=${Ft.length}`,`inputTokens=${E}`,`outputTokens=${h}`,`traceOutput="${pt(g,80)}"`);let Re=await Ee(le(Ie,Ft));a("Stop",`POST status=${Re}`,`traceId=${n.traceId}`),C("TRACE_SENT",{latencyMs:tt,totalTools:T,errorTools:m,inputTokens:E,outputTokens:h,costUsd:et}),bt(e),w(t);}var F=class t{static passthroughStdin(){let e=[];process.stdin.on("data",r=>e.push(r)),process.stdin.on("end",()=>process.stdout.write(Buffer.concat(e)));}static async userPromptSubmit(){let e=await q(),r;try{r=await v();}catch{process.stdout.write(JSON.stringify(e));return}r.authError?await Ut(e,true):r.length>0?await Ut(e):process.stdout.write(JSON.stringify(e));}static async preToolUse(){if(!await ut()){t.passthroughStdin();return}let e=await q();await ce(e);}static async postToolUse(){if(!await ut()){t.passthroughStdin();return}let e=await q();await ye(e);}static async stop(){if(!await ut()){t.passthroughStdin();return}let e=await q();await Oe(e);}};async function Hr(){let t=process.argv[2];switch(t){case "UserPromptSubmit":await F.userPromptSubmit();break;case "PreToolUse":await F.preToolUse();break;case "PostToolUse":await F.postToolUse();break;case "Stop":await F.stop();break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
15
- `),process.stdin.on("data",e=>process.stdout.write(e));}}Hr().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
8
+ `),inputTokens:r,outputTokens:o}}catch{}return null}var $n=new Set([".venv","__pycache__",".git","node_modules"]),Dn=new Set([".pyc",".pyo"]),xn=new Set(["SKILL.md",".DS_Store",".gitignore"]);function Se(t){return t.replace(":","/")}function _t(t,e){if(!t)return null;let n=Se(t),r=[W.join(nt.homedir(),".claude","skills",n,"SKILL.md"),W.join(e??"",".claude","skills",n,"SKILL.md")];for(let o of r)if(T.existsSync(o))try{return T.readFileSync(o,"utf8")}catch{}return null}function Ee(t){return t.split(`
9
+ `)[0].match(/^\/([a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?)(?:\s.*)?$/i)?.[1]??null}var Mn=new Set(["Read","Write","Edit","MultiEdit","Bash","Glob","Grep","TodoWrite","WebFetch","WebSearch","Agent","Task"]);function he(t){return !!t.slashSkill||t.toolCalls.some(r=>r.tool==="Skill")?t.toolCalls.some(r=>r.tool==="Skill"&&!r.synthetic||Mn.has(r.tool))?"complete":"prerequisite_required":null}function Tt(t,e){if(!t)return null;let n=Se(t),r=[W.join(nt.homedir(),".claude","skills",n),W.join(e??"",".claude","skills",n)],o=null;for(let l of r)if(T.existsSync(W.join(l,"SKILL.md"))){o=l;break}if(!o)return null;let s=[];function i(l,c){for(let u of T.readdirSync(l,{withFileTypes:true})){if($n.has(u.name)||xn.has(u.name)||Dn.has(W.extname(u.name)))continue;let g=c?`${c}/${u.name}`:u.name;u.isDirectory()?i(W.join(l,u.name),g):s.push(g);}}return i(o,""),s.length>0?s:null}_();_();!process.env.NO_COLOR&&process.stdout.isTTY;function yt(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let t=process.env.USERPROFILE;if(!t){let n=child_process.spawnSync("cmd.exe",["/c","echo","%USERPROFILE%"],{encoding:"utf8",timeout:5e3}).stdout?.trim();n&&/^[A-Za-z]:\\/.test(n)&&(t=n);}if(t){let e=t.replace(/^([A-Za-z]):/,(n,r)=>`/mnt/${r.toLowerCase()}`).replace(/\\/g,"/");return W__namespace.join(e,".claude","settings.json")}return W__namespace.join(nt__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let t=process.env.USERPROFILE||nt__namespace.homedir();return W__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 W__namespace.join(e,".claude","settings.json")}return W__namespace.join(nt__namespace.homedir(),".claude","settings.json")}var Vn=Vt.LOCK_STALE_MS;function Gn(t){try{let e=T__namespace.statSync(t);Date.now()-e.mtimeMs>Vn&&T__namespace.unlinkSync(t);}catch{}try{T__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 jn(t){try{T__namespace.unlinkSync(t);}catch{}}function ye(t){try{let e=T__namespace.readFileSync(yt(),"utf8"),r=JSON.parse(e).env?.[t];return typeof r=="string"?r:null}catch{return null}}function Ae(t){let e=yt(),n=e+".lock";T__namespace.mkdirSync(W__namespace.dirname(e),{recursive:true}),Gn(n);try{let r={};try{r=JSON.parse(T__namespace.readFileSync(e,"utf8"));}catch{}(!r.env||typeof r.env!="object")&&(r.env={}),Object.assign(r.env,t),T__namespace.writeFileSync(e,JSON.stringify(r,null,2)+`
10
+ `,{encoding:"utf8",mode:384});try{T__namespace.chmodSync(e,384);}catch{}}finally{jn(n);}}_();function Kn(t){try{let e=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(Buffer.from(e,"base64").toString())}catch{return null}}function qn(t,e,n,r,o,s){return new Promise(i=>{let l=new URL(t),c=l.protocol==="https:",u=S=>S.replace(/[\r\n]/g,""),g=(c?cn__default.default:ln__default.default).request({hostname:l.hostname,port:l.port||(c?443:80),path:l.pathname+l.search,method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(e),...s?{}:{Authorization:`Bearer ${u(String(n))}`},FlowTenant:u(String(r)),...o?{"x-flow-user":u(o)}:{},...s?{"x-flow-api-key":u(s)}:{}}},S=>{S.resume(),i(S.statusCode??0);});g.on("error",()=>i(0)),g.setTimeout(5e3,()=>{g.destroy(),i(0);}),g.write(e),g.end();})}async function $(t,e={}){try{let n=St(process.env[m.ANTHROPIC_AUTH_TOKEN]);if(!n)return;let r,o=new Promise((E,y)=>{r=setTimeout(()=>y(new Error("getToken timeout")),4e3),r.unref();}),{accessToken:s}=await Promise.race([V(n),o]);clearTimeout(r);let i=Kn(s);if(!i)return;let l=i.tenant||n.tenant,c=JSON.stringify({action:t,booster:kt().BOOSTER,metadata:e,success:!0,tenant:l,timestamp:new Date().toISOString(),os:process.platform,user:{email:i.email||"",id:i.sub||"",name:i.name||i.email||""}}),u=ae(),g=ce(),S=gt(kt().API_URL),h=await qn(S,c,s,l,u,g);a("metrics.logEvent",`action=${t} status=${h} x-flow-user=${u?"[REDACTED]":"omitted"} x-flow-api-key=${g?"[REDACTED]":"omitted"}`);}catch(n){a("metrics.logEvent",`silenced error: ${n.message}`);}}var Xn=`\u26D4 Your Flow API key has expired. You no longer have access to Claude Code through the Flow platform. To restore observability and access, visit ${B()}/settings/api-keys to generate a new API key, then run: flow-ai-obs login`;async function Mt(t,e=false){if(e){process.stdout.write(JSON.stringify({decision:"block",reason:Xn})+`
11
+ `);return}let r=!!(await C()).authError;!process.env[m.FLOW_USER_EMAIL]&&!ye(m.FLOW_USER_EMAIL)&&tt().then(S=>{S&&(Ae({[m.FLOW_USER_EMAIL]:S}),a("UserPromptSubmit","auto-persisted FLOW_USER_EMAIL from access token"));}).catch(()=>{});let o=t.session_id||"unknown",s=t.prompt||"",i=t.cwd||"",l=de(t.transcript_path)||Ft(),c=Ee(s),u=c?_t(c,i):null,g=c?Tt(c,i):null;j(o,{traceId:Ft(),spanId:F(),startNs:I(),sessionId:o,prompt:s,cwd:i,traceName:l,transcriptPath:t.transcript_path||"",model:process.env[m.ANTHROPIC_MODEL]||"",toolCalls:[],spans:[],pendingTool:null,slashSkill:c,skillContent:u,skillArtifacts:g}),$("SESSION_STARTED",{traceType:c?"skill":"prompt",slashSkill:c,clientIdExpired:r}),a("UserPromptSubmit",`sid=${o}`,`traceName=${l}`,`slashSkill=${c}`),k(t);}_();async function Oe(t){let e=t.session_id||"unknown",n=t.tool_name||"unknown",r=t.tool_input||{},o=G(e);o&&(o.pendingTool={name:n,inputStr:L(r,R.TOOL_INPUT),startNs:I()},j(e,o)),a("PreToolUse",`sid=${e}`,`tool=${n}`,`stateFound=${!!o}`),k(t);}_();var zn={name:wt.SCOPE_NAME,version:wt.SCOPE_VERSION},d={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 p(t,e){return e==null||e===""?null:{key:t,value:{stringValue:String(e)}}}function D(...t){return t.filter(e=>e!==null)}function we(t,e){return {resourceSpans:[{resource:{attributes:t},scopeSpans:[{scope:zn,spans:Array.isArray(e)?e:[e]}]}]}}_();var ke=W.join(nt.tmpdir(),"flow-obs-requests.ndjson");function Re(t,e,n,r,o){if(process.env[m.FLOW_OBS_DEBUG]!=="1")return;let s=JSON.stringify({ts:new Date().toISOString(),request:{method:"POST",url:t,headers:e,body:JSON.parse(n)},response:{status:r,body:o}});try{T.writeFileSync(ke,s+`
12
+ `,{flag:"a",encoding:"utf8",mode:384}),a("sendTraces:dump",`request appendada em ${ke}`);}catch(i){a("sendTraces:dump",`falha ao salvar: ${i.message}`);}}function rr(t){let e=new URL(t),n=new URL(H().GATEWAY_HEALTH);return n.hostname=e.hostname,n.port=e.port,n.protocol=e.protocol,n}function Le(t,e){return new Promise((n,r)=>{let o=t._isSSL?cn__default.default:ln__default.default;t.headers=Object.assign({},t.headers,{Connection:"close"});let s=o.request(t,i=>{let l=[];i.on("data",c=>l.push(c)),i.on("end",()=>n({statusCode:i.statusCode??0,body:l.join("")}));});s.setTimeout(1e4,()=>{s.destroy(new Error("Request timeout"));}),s.on("error",i=>r(new Error(`Network error: ${i.message}`))),e&&s.write(e),s.end();})}async function Ie(t,e){let n;try{n=rr(t);}catch{return false}let r=n.protocol==="https:";try{let o={};e&&(o.Authorization=String(e).replace(/[\r\n]/g,""));let s=await Le({hostname:n.hostname,port:n.port||(r?443:80),path:n.pathname,method:"GET",headers:o,_isSSL:r},null);return a("checkHealth",`url=${n.href} status=${s.statusCode}`),s.statusCode>=200&&s.statusCode<300}catch{return false}}async function At(t,e,n){let r=JSON.stringify(t),o=new URL(e),s=o.protocol==="https:",i=String(n).replace(/[\r\n]/g,""),l={"Content-Type":"application/json",Authorization:i,"Content-Length":Buffer.byteLength(r)};a("sendTraces:request",`POST ${e}`),a("sendTraces:request",`headers=${JSON.stringify({...l,Authorization:i.slice(0,20)+"\u2026"})}`),a("sendTraces:request",`body=${r.slice(0,500)}${r.length>500?"\u2026":""}`);try{let c=await Le({hostname:o.hostname,port:o.port||(s?443:80),path:o.pathname,method:"POST",headers:l,_isSSL:s},r);return a("sendTraces:response",`status=${c.statusCode}`),Re(e,l,r,c.statusCode,c.body),c.statusCode}catch(c){return a("sendTraces:error",c.message),Re(e,l,r,0,c.message),0}}_();function sr(){let t=parseInt(process.env[m.BUFFER_TTL_DAYS]??"",10);return (Number.isFinite(t)?Math.max(w.MIN_TTL_DAYS,Math.min(w.MAX_TTL_DAYS,t)):w.DEFAULT_TTL_DAYS)*24*60*60*1e3}function or(){let t=parseInt(process.env[m.BUFFER_MAX_FILES]??"",10);return Number.isFinite(t)?Math.max(w.MIN_MAX_FILES,Math.min(w.MAX_MAX_FILES,t)):w.DEFAULT_MAX_FILES}function Pe(t){if(/[/\\]/.test(t))throw new Error(`Invalid buffer fileId: ${t}`);return W__namespace.default.join(nt__namespace.default.tmpdir(),`${w.FILE_PREFIX}${t}.json`)}function Ht(){let t=nt__namespace.default.tmpdir(),e;try{e=T__namespace.default.readdirSync(t);}catch{return []}return e.filter(n=>n.startsWith(w.FILE_PREFIX)&&n.endsWith(".json")).map(n=>{let r=W__namespace.default.join(t,n),o=0;try{o=T__namespace.default.statSync(r).mtimeMs;}catch{}return {full:r,mtime:o}}).sort((n,r)=>n.mtime-r.mtime).map(n=>n.full)}function rt(t){try{let e=or(),n=Ht();if(n.length>=e){let s=n.slice(0,n.length-e+1);for(let i of s)try{T__namespace.default.unlinkSync(i);}catch{}}let r=`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,o={fileId:r,bufferedAt:Date.now(),payload:t};return T__namespace.default.writeFileSync(Pe(r),JSON.stringify(o),{encoding:"utf8",mode:384}),a("buffer",`saved fileId=${r}`),r}catch(e){return a("buffer",`saveToBuffer failed: ${e.message}`),null}}function Ne(t){let e=Ht(),n=t!=null&&t>0?t:e.length,r=[];for(let o of e){if(r.length>=n)break;try{let s=T__namespace.default.readFileSync(o,"utf8"),i=JSON.parse(s);i&&i.fileId&&i.payload&&r.push(i);}catch{a("buffer",`skipping malformed file: ${o}`);}}return r}function be(t){try{T__namespace.default.unlinkSync(Pe(t)),a("buffer",`deleted fileId=${t}`);}catch{}}function Ue(){let t=Date.now()-sr();for(let e of Ht())try{let{mtimeMs:n}=T__namespace.default.statSync(e);n<t&&(T__namespace.default.unlinkSync(e),a("buffer",`evicted stale: ${W__namespace.default.basename(e)}`));}catch{}}_();async function ir(t){Ue();let e=Ne(w.REPLAY_BATCH_SIZE);e.length&&(a("replayBufferedTraces",`replaying ${e.length} buffered trace(s)`),await Promise.allSettled(e.map(async n=>{try{let r=await At(n.payload,t.endpoint,t.authHeader);r>=200&&r<300?(be(n.fileId),a("replayBufferedTraces",`replayed fileId=${n.fileId} status=${r}`)):a("replayBufferedTraces",`replay failed fileId=${n.fileId} status=${r}`);}catch(r){a("replayBufferedTraces",`replay error fileId=${n.fileId}: ${r.message}`);}})));}async function Ce(t){let e=await C();if(!e.length)return e.authError&&(a("postToLangfuse","auth refresh failed \u2014 buffering trace"),rt(t)),0;let n=await Promise.all(e.map(async s=>{if(s.mode!=="gateway")return {creds:s,healthy:true};let i=await Ie(s.endpoint,s.authHeader);return {creds:s,healthy:i}})),r=n.find(s=>s.creds.mode==="gateway"&&s.healthy)?.creds??n.find(s=>s.creds.mode==="direct")?.creds;return r&&await ir(r),(await Promise.all(n.map(async({creds:s,healthy:i})=>{if(s.mode==="gateway"){if(!i)return a("postToLangfuse","gateway health check failed \u2014 buffering trace"),rt(t),0;let c=await At(t,s.endpoint,s.authHeader);return (c===0||c>=500)&&(a("postToLangfuse",`gateway send failed (status ${c}) \u2014 buffering trace`),rt(t)),c}let l=await At(t,s.endpoint,s.authHeader);return (l===0||l>=500)&&(a("postToLangfuse",`direct endpoint unavailable (status ${l}) \u2014 buffering trace`),rt(t)),l}))).find(s=>s!==0)??0}_();var O="[REDACTED]",ar="[REDACTED-EMAIL]",cr="[REDACTED-CPF]",lr="[REDACTED-CNPJ]",Fe="[REDACTED-PHONE]",ur=[{re:/\b(sk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`sk-${O}`},{re:/\b(pk-[A-Za-z0-9_\-]{20,})/g,replace:()=>`pk-${O}`},{re:/\b(Bearer\s+)[A-Za-z0-9\-._~+/]+=*/gi,replace:(t,e)=>`${e}${O}`},{re:/\b(Basic\s+)[A-Za-z0-9+/]+=*/gi,replace:(t,e)=>`${e}${O}`},{re:/(-----BEGIN [A-Z ]+-----)[^-]*(-----END [A-Z ]+-----)/g,replace:(t,e,n)=>`${e}
13
+ ${O}
14
+ ${n}`},{re:/\b(AKIA[0-9A-Z]{16})\b/g,replace:()=>`AKIA${O}`},{re:/(aws_secret_access_key\s*[=:]\s*)([A-Za-z0-9/+]{40})/gi,replace:(t,e)=>`${e}${O}`},{re:/\b(ghp_[A-Za-z0-9]{36,})/g,replace:()=>`ghp_${O}`},{re:/\b(github_pat_[A-Za-z0-9_]{36,})/gi,replace:()=>`github_pat_${O}`},{re:/\b(eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+)/g,replace:()=>`eyJ.${O}`},{re:/\b([A-Z0-9_]*(?:SECRET|TOKEN|KEY|PASSWORD|PASSWD|PWD|CREDENTIAL|API)[A-Z0-9_]*\s*=\s*)(['"]?)([^\s'"#\n]+)\2/gi,replace:(t,e,n)=>`${e}${n}${O}${n}`},{re:/([a-z][a-z0-9+\-.]*:\/\/[^:/?#\s]*):([^@\s]+)@/gi,replace:(t,e)=>`${e}:${O}@`},{re:/[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/g,replace:()=>ar},{re:/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,replace:()=>cr},{re:/\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/g,replace:()=>lr},{re:/\(\d{2}\)\s?\d{4,5}[-\s]?\d{4}/g,replace:()=>Fe},{re:/\+55[\s-]?\d{2}[\s-]?\d{4,5}[-\s]?\d{4}/g,replace:()=>Fe}];function P(t){if(t==null)return "";let e=typeof t=="string"?t:JSON.stringify(t);return ur.reduce((n,{re:r,replace:o})=>n.replace(r,o),e)}async function $e(t){let e=t.session_id||"unknown",n=t.tool_name||"unknown",r=t.tool_input||{},o=t.tool_response,s=o!==null&&typeof o=="object"?o.output??JSON.stringify(o):o??"",i=G(e);if(!i){k(t);return}let l=I(),c=i.pendingTool,u=c?.name===n,g=u?c.startNs:String(BigInt(l)-200000000n),S=u?c.inputStr:L(r,R.TOOL_INPUT),h=S,E=null;if(n==="Skill"){let lt=typeof r=="object"&&r!==null?r.skill||r.name||r.skillName||r.commandName||String(Object.values(r)[0]??""):String(r);E=lt?String(lt).trim():null;let N=E?_t(E,i.cwd):null;N&&(h=N,i.skillContent||(i.skillContent=N),i.skillArtifacts||(i.skillArtifacts=Tt(E,i.cwd))),E&&!i.slashSkill&&(i.slashSkill=E),a("PostToolUse","Skill tool detected",`skillName=${E}`,`contentFound=${!!N}`);}let y=P(L(s,R.TOOL_OUTPUT)),A=/\b(error|exception|failed|failure|traceback|errno)\b/i.test(y.slice(0,500)),st=A?"ERROR":"DEFAULT",q=F(),ot=Math.round(Number(BigInt(l)-BigInt(g))/1e6),at={Agent:"AGENT",Task:"AGENT"}[n]??"TOOL",ct=n==="Skill"&&E?E:ht(S,60);i.toolCalls.push({tool:n,brief:ct,error:A,durationMs:ot});let X=i.spans;X.push({traceId:i.traceId,spanId:q,parentSpanId:i.spanId,name:n,kind:3,startTimeUnixNano:g,endTimeUnixNano:l,attributes:D(p(d.OBS_NAME,n),p(d.OBS_TYPE,at),p(d.OBS_LEVEL,st),p(d.OBS_INPUT,P(h)),p(d.OBS_OUTPUT,y),p("tool.name",n),p("tool.error",String(A)),n==="Skill"&&E?p("skill.name",E):null,n==="Skill"?p("skill.invocation","slash-command"):null),status:{code:A?2:1}}),i.pendingTool=null,j(e,i),A&&$("TOOL_ERROR",{toolName:n}),a("PostToolUse",`sid=${e}`,`tool=${n}`,`error=${A}`,`durationMs=${ot}`,`totalSpans=${X.length}`),k(t);}var De={"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 xe(t,e,n){let r=Object.keys(De).find(i=>(t??"").toLowerCase().includes(i));if(!r)return;let o=De[r],s=(e*o.input+n*o.output)/1e6;return Math.round(s*1e6)/1e6}_();async function Me(t){let e=t.session_id||"unknown",n=t.stop_reason||"end_turn",r=G(e);if(!r){k(t);return}r.slashSkill&&!/^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/i.test(r.slashSkill)&&(a("Stop",`sid=${e}`,`slashSkill rejected post-disk: "${r.slashSkill}"`),r.slashSkill=null);let o=I(),s=await ie(),i=r.toolCalls,l=r.spans;if(r.slashSkill&&!i.some(f=>f.tool==="Skill")){let f=F(),b=r.skillContent?r.skillContent:JSON.stringify({skill:r.slashSkill});i.push({tool:"Skill",brief:r.slashSkill,error:false,durationMs:0,synthetic:true}),l.push({traceId:r.traceId,spanId:f,parentSpanId:r.spanId,name:"Skill",kind:3,startTimeUnixNano:r.startNs,endTimeUnixNano:r.startNs,attributes:D(p(d.OBS_NAME,"Skill"),p(d.OBS_TYPE,"TOOL"),p(d.OBS_LEVEL,"DEFAULT"),p(d.OBS_INPUT,b),p(d.OBS_OUTPUT,"loaded via slash command"),p("tool.name","Skill"),p("tool.error","false"),p("skill.name",r.slashSkill),p("skill.invocation","slash-command")),status:{code:1}}),a("Stop",`slashSkill=${r.slashSkill}`,"synthetic span injected");}let c=t.transcript_path||r.transcriptPath||"",u=xt(c);if(c&&(i.some(f=>f.tool==="Skill"&&!f.synthetic)||!!r.slashSkill)&&!u?.text){await new Promise(b=>setTimeout(b,500));let f=xt(c);f?.text&&(u=f);}a("Stop",`transcriptPath=${c||"(empty)"}`,`assistantOut=${u?`text=${u.text.length}chars`:"null"}`);let S=i.length,h=i.filter(f=>f.error).length,E=P(u?.text?L(u.text,R.TRACE_OUTPUT):S===0?"No tools used":i.map((f,b)=>`${b+1}. ${f.tool}${f.brief?` \u2192 ${f.brief}`:""}${f.error?" [ERROR]":""}`).join(`
15
+ `)),y=u?.inputTokens??0,A=u?.outputTokens??0,st=i.map((f,b)=>`${b+1}. ${f.tool}${f.brief?` \u2192 ${f.brief}`:""}${f.error?" [ERROR]":""} (${f.durationMs}ms)`),q=!!(r.slashSkill||i.some(f=>f.tool==="Skill")),ot=i.some(f=>f.tool==="Agent");if(!q&&!ot){a("Stop",`sid=${e}`,"skipping trace \u2014 no Skill or Agent calls found"),$("TRACE_SKIPPED",{reason:"no_skill_or_agent"}),Dt(e),k(t);return}let it=q?"skill":"agent",at=Math.round(Number(BigInt(o)-BigInt(r.startNs))/1e6),ct=xe(r.model,y,A),M=he(r);M==="prerequisite_required"&&u?.text&&(M="complete"),M==="prerequisite_required"&&(l.push({traceId:r.traceId,spanId:F(),parentSpanId:r.spanId,name:"prerequisite-check",kind:3,startTimeUnixNano:r.startNs,endTimeUnixNano:o,attributes:D(p(d.OBS_NAME,"prerequisite-check"),p(d.OBS_TYPE,"EVENT"),p(d.OBS_LEVEL,"WARNING"),p(d.OBS_OUTPUT,E),p("skill.name",r.slashSkill||void 0),p("execution_status","prerequisite_required")),status:{code:1}}),a("Stop",`sid=${e}`,"prerequisite-check span injected",`skill=${r.slashSkill}`));let X=(()=>{if(!(!q||!r.prompt)){if(r.slashSkill){let f=r.prompt.replace(new RegExp(`^\\/${r.slashSkill}\\s*`,"i"),"").trim();return f?L(P(f),R.USER_INSTRUCTION):void 0}return L(P(r.prompt),R.USER_INSTRUCTION)||void 0}})(),lt=JSON.stringify({trace_type:it,...M!==null&&{execution_status:M},...r.slashSkill?{skill_name:r.slashSkill}:{},...r.skillArtifacts?.length&&{skill_artifacts:r.skillArtifacts},...X!==void 0&&{user_instruction:X},latency_ms:at,...y&&{tokens_input:y},...A&&{tokens_output:A},cost_usd:ct,...r.model?{model:r.model}:{},toolCount:S,errorCount:h,stopReason:n,sessionId:r.sessionId,tools:st.length?st:void 0}),N=P(L(r.prompt,R.TRACE_INPUT)),Be=D(p(d.TRACE_NAME,r.traceName),p(d.TRACE_INPUT,N),p(d.TRACE_OUTPUT,E),p(d.OBS_INPUT,N),p(d.OBS_OUTPUT,E),p(d.TRACE_METADATA,lt),p(d.SESSION_ID,r.sessionId),p(d.USER_ID,s.user),p(d.OBS_TYPE,"GENERATION"),p(d.MODEL,r.model),y?p(d.INPUT_TOKENS,y):null,A?p(d.OUTPUT_TOKENS,A):null,p("claude.stop_reason",n),p("claude.tool_count",String(S)),p("claude.error_count",String(h)),p("claude.session_id",r.sessionId),p("flow.trace_type",it),{key:d.TRACE_TAGS,value:{arrayValue:{values:[{stringValue:it}]}}}),He={traceId:r.traceId,spanId:r.spanId,name:r.traceName,kind:1,startTimeUnixNano:r.startNs,endTimeUnixNano:o,attributes:Be,status:{code:h>0?2:1}},We=D(p("service.name",process.env.LANGFUSE_PROJECT_NAME||"claude-code"),p("deployment.environment",process.env.LANGFUSE_ENVIRONMENT||"default")),Wt=[...l,He];a("Stop",`sid=${e}`,`totalTools=${S}`,`errorTools=${h}`,`spans=${Wt.length}`,`inputTokens=${y}`,`outputTokens=${A}`,`traceOutput="${ht(E,80)}"`);let Ve=await Ce(we(We,Wt));a("Stop",`POST status=${Ve}`,`traceId=${r.traceId}`),$("TRACE_SENT",{latencyMs:at,totalTools:S,errorTools:h,inputTokens:y,outputTokens:A,costUsd:ct}),Dt(e),k(t);}var x=class t{static passthroughStdin(){let e=[];process.stdin.on("data",n=>e.push(n)),process.stdin.on("end",()=>process.stdout.write(Buffer.concat(e)));}static async userPromptSubmit(){let e=await et(),n;try{n=await C();}catch{process.stdout.write(JSON.stringify(e));return}n.authError?await Mt(e,true):n.length>0?await Mt(e):process.stdout.write(JSON.stringify(e));}static async preToolUse(){if(!await Et()){t.passthroughStdin();return}let e=await et();await Oe(e);}static async postToolUse(){if(!await Et()){t.passthroughStdin();return}let e=await et();await $e(e);}static async stop(){if(!await Et()){t.passthroughStdin();return}let e=await et();await Me(e);}};async function pr(){let t=process.argv[2];switch(t){case "UserPromptSubmit":await x.userPromptSubmit();break;case "PreToolUse":await x.preToolUse();break;case "PostToolUse":await x.postToolUse();break;case "Stop":await x.stop();break;default:process.stderr.write(`[flow-obs] unknown event: ${t}
16
+ `),process.stdin.on("data",e=>process.stdout.write(e));}}pr().catch(t=>{process.stderr.write(`[flow-obs] fatal: ${t.message}
16
17
  `),process.exit(0);});
package/dist/setup.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';var child_process=require('child_process'),util=require('util'),i=require('fs'),f=require('path'),u=require('os'),ft=require('https');require('readline/promises');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}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 i__namespace=/*#__PURE__*/_interopNamespace(i);var f__namespace=/*#__PURE__*/_interopNamespace(f);var u__namespace=/*#__PURE__*/_interopNamespace(u);var ft__default=/*#__PURE__*/_interopDefault(ft);var I=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var Re=Object.getOwnPropertyNames;var ke=Object.prototype.hasOwnProperty;var O=(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 A=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(r){throw n=[r],r}};var Pe=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(n){throw t=0,n}},L=(e,t)=>{for(var n in t)I(e,n,{get:t[n],enumerable:true});},Ie=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Re(t))!ke.call(e,s)&&s!==n&&I(e,s,{get:()=>t[s],enumerable:!(r=Le(t,s))||r.enumerable});return e};var Ce=e=>Ie(I({},"__esModule",{value:true}),e);var J={};L(J,{BUFFER:()=>De,CONFIG_DIR_NAME:()=>E,CONFIG_FILE_NAME:()=>T,DEBUG_LOG_FILENAME:()=>U,ENV:()=>p,FEATURES:()=>$e,FLOW_URLS:()=>be,HOOK_TIMEOUTS:()=>b,INSTALLER:()=>N,NATIVE_OTEL:()=>C,OTLP:()=>Ue,STATE_FILE_PREFIX:()=>Me,TRACE_LIMITS:()=>xe,VAULT:()=>y,getFlowBaseUrl:()=>h,getFlowUrls:()=>R,getLlmProxy:()=>Fe,getMetrics:()=>He});function h(){let e=process.env.FLOW_BASE_URL;return e&&e.trim()?e.trim():Ne}function R(){let e=h();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${e}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${e}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${e}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${e}/otel`}}function Fe(){let e=h();return {ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL??`${e}/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-haiku",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"}}function He(){let e=h();return {API_URL:process.env.FLOW_METRICS_URL||`${e}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var Ne,be,y,E,T,Ue,C,p,$e,N,b,De,U,xe,Me,l=A(()=>{"use strict";Ne="https://flow.ciandt.com";be=R(),y={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},E="FLOW-nodejs",T="config.json",Ue={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};C={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},p={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"},$e={KEYCHAIN_ENABLED:!1},N={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3,CLI:"flow-ai-obs "},b={UserPromptSubmit:30,PreToolUse:3,PostToolUse:10,Stop:15},De={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},U="flow-ai-obs-debug.log",xe={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60};Me="flow-obs-";});var X={};L(X,{MacOsKeyVaultProvider:()=>x});var D,x,q=A(()=>{"use strict";D=util.promisify(child_process.execFile),x=class{static async isAvailable(){try{return i.accessSync("/usr/bin/security",i.constants.X_OK),!0}catch{return !1}}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 !1}}getStoragePath(){return "macOS Keychain"}};});var Z={};L(Z,{LinuxKeyVaultProvider:()=>H});var z,H,Q=A(()=>{"use strict";z=util.promisify(child_process.execFile),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 i.accessSync(n,i.constants.X_OK),!0}catch{}return !1}async getSecret(t,n){try{let{stdout:r}=await z("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=child_process.spawn("secret-tool",["store","--label",t,"service",t,"account",n]);a.on("error",o),a.on("close",g=>{g===0?s():o(new Error(`secret-tool exited with code ${g}`));}),a.stdin.write(r),a.stdin.end();});}async deleteSecret(t,n){try{return await z("secret-tool",["clear","service",t,"account",n]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var ee={};L(ee,{WindowsKeyVaultProvider:()=>M});var M,te=A(()=>{"use strict";M=class{static async isAvailable(){try{return await O("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(t,n){return O("keytar").getPassword(t,n)}async setSecret(t,n,r){await O("keytar").setPassword(t,n,r);}async deleteSecret(t,n){return O("keytar").deletePassword(t,n)}getStoragePath(){return "Windows Credential Manager"}};});var ge=Pe((On,pt)=>{pt.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.9.2",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:!1,dependencies:{},optionalDependencies:{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"},overrides:{esbuild:"^0.28.1"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});l();var F={credentials:"credentials","token-cache":"tokenCache"};function _(){let e=u__namespace.default.homedir();if(process.platform==="darwin")return f__namespace.default.join(e,"Library","Preferences",E,T);if(process.platform==="win32"){let n=process.env.APPDATA??f__namespace.default.join(e,"AppData","Roaming");return f__namespace.default.join(n,E,T)}let t=process.env.XDG_CONFIG_HOME??f__namespace.default.join(e,".config");return f__namespace.default.join(t,E,T)}function $(){try{let e=i__namespace.default.readFileSync(_(),"utf8");return JSON.parse(e)}catch{return {}}}function K(e){let t=_();i__namespace.default.mkdirSync(f__namespace.default.dirname(t),{recursive:true}),i__namespace.default.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var k=class{static isAvailable(){return true}static hasExistingData(){try{if(!i__namespace.default.existsSync(_()))return !1;let t=JSON.parse(i__namespace.default.readFileSync(_(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,n){let r=$(),s=F[n]??n,o=r[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,n,r){let s=$(),o=F[n]??n;if(n==="token-cache")try{s[o]=JSON.parse(r);}catch{s[o]=r;}else s[o]=r;K(s);}async deleteSecret(t,n){let r=$(),s=F[n]??n;return s in r?(delete r[s],K(r),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${_()}`}};async function ne(){return await ze()??new k}async function ze(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(q(),X));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(Q(),Z));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(te(),ee));return await e.isAvailable()?new e:null}default:return null}}l();var Ze=y.SERVICE,Qe=y.ACCOUNT_CREDS;y.ACCOUNT_TOKEN;var V=null;function et(){return V||(V=ne()),V}async function re(){let t=await(await et()).getSecret(Ze,Qe);if(!t)return null;try{return JSON.parse(t)}catch{return null}}l();l();l();f.join(u.tmpdir(),U);!process.env.NO_COLOR&&process.stdout.isTTY;function j(){return process.platform==="win32"?false:process.getuid?.()===0}function se(){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 {home:t,username:process.env.SUDO_USER}}return {home:u__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||u__namespace.userInfo().username}}function P(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let e=process.env.USERPROFILE;if(!e){let n=child_process.spawnSync("cmd.exe",["/c","echo","%USERPROFILE%"],{encoding:"utf8",timeout:5e3}).stdout?.trim();n&&/^[A-Za-z]:\\/.test(n)&&(e=n);}if(e){let t=e.replace(/^([A-Za-z]):/,(n,r)=>`/mnt/${r.toLowerCase()}`).replace(/\\/g,"/");return f__namespace.join(t,".claude","settings.json")}return f__namespace.join(u__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let e=process.env.USERPROFILE||u__namespace.homedir();return f__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 f__namespace.join(t,".claude","settings.json")}return f__namespace.join(u__namespace.homedir(),".claude","settings.json")}var oe="flow-ai-obs",ie="config.json";function ce(){if(process.platform==="win32"){let n=process.env.APPDATA||f__namespace.join(u__namespace.homedir(),"AppData","Roaming");return f__namespace.join(n,oe,ie)}let e=se(),t=process.env.XDG_CONFIG_HOME||f__namespace.join(e.home,".config");return f__namespace.join(t,oe,ie)}var ct=N.LOCK_STALE_MS;function le(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>ct&&i__namespace.unlinkSync(e);}catch{}try{i__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 ue(e){try{i__namespace.unlinkSync(e);}catch{}}function lt(e,t){let r=(Array.isArray(e)?e:[]).map(s=>{if(!Array.isArray(s?.hooks))return null;let o=s.hooks.filter(a=>!a.command?.startsWith?.("flow-ai-obs "));return o.length>0?{...s,hooks:o}:null}).filter(s=>s!=null);return [t,...r]}function pe(e,t){let n=P(),r=n+".lock",s=[];i__namespace.mkdirSync(f__namespace.dirname(n),{recursive:true}),le(r);try{if(i__namespace.existsSync(n)){i__namespace.copyFileSync(n,n+".bkp");try{i__namespace.chmodSync(n+".bkp",384);}catch{}}let o=ce();if(i__namespace.existsSync(o)){let c=o+".bkp";i__namespace.copyFileSync(o,c);try{i__namespace.chmodSync(c,384);}catch{}}let a={};try{a=JSON.parse(i__namespace.readFileSync(n,"utf8"));}catch{}let g=a.env&&typeof a.env=="object"?a.env:{};delete g.OTEL_EXPORTER_OTLP_HEADERS;let{getFlowUrls:Se}=(l(),Ce(J)),we=Se().OTEL_ENDPOINT,ve={...C,OTEL_EXPORTER_OTLP_ENDPOINT:e??we};a.env={...g,...ve,...t??{}},a.otelHeadersHelper="flow-ai-obs otel-headers",(!a.hooks||typeof a.hooks!="object"||Array.isArray(a.hooks))&&(a.hooks={});let Oe=(c,v)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:v}]}),Ae=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],B=a.hooks;for(let c of Ae){let v=lt(B[c],Oe(c,b[c]));v.length>1&&s.push(c),B[c]=v;}i__namespace.writeFileSync(n,JSON.stringify(a,null,2)+`
3
- `,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(n,384);}catch{}}finally{ue(r);}return {settingsPath:n,preserved:s}}function fe(e){let t=P(),n=t+".lock";i__namespace.mkdirSync(f__namespace.dirname(t),{recursive:true}),le(n);try{let r={};try{r=JSON.parse(i__namespace.readFileSync(t,"utf8"));}catch{}(!r.env||typeof r.env!="object")&&(r.env={}),Object.assign(r.env,e),i__namespace.writeFileSync(t,JSON.stringify(r,null,2)+`
4
- `,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(t,384);}catch{}}finally{ue(n);}}l();function de(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 me(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}.`}l();var W;function ye(){return W||(W=ge()),W}var Ee=f__namespace.default.join(u__namespace.default.tmpdir(),"flow-obs-update-cache.json"),gt=1440*60*1e3,ht=3e3;function yt(e,t){let n=o=>{let a=String(o).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return a?[+a[1],+a[2],+a[3]]:null},r=n(e),s=n(t);return !r||!s?false:s[0]!==r[0]?s[0]>r[0]:s[1]!==r[1]?s[1]>r[1]:s[2]>r[2]}function Et(){try{let e=JSON.parse(i__namespace.default.readFileSync(Ee,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=gt?null:e}catch{return null}}function Tt(e,t,n=Date.now()){try{i__namespace.default.writeFileSync(Ee,JSON.stringify({latestVersion:e,updatePriority:t??null,checkedAt:n}),{mode:384});}catch{}}function _t(e){let t=ye().name,n=ft__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:ht},r=>{if(r.statusCode!==200)return r.resume(),e(new Error(`HTTP ${r.statusCode}`));let s="";r.setEncoding("utf8"),r.on("data",o=>{s+=o;}),r.on("end",()=>{try{let o=JSON.parse(s);if(typeof o.version!="string")throw new Error("no version field");e(null,{version:o.version,updatePriority:typeof o.updatePriority=="string"?o.updatePriority:null});}catch(o){e(o);}});});n.on("error",e),n.on("timeout",()=>{n.destroy(new Error("timeout"));});}function Te(){try{if(Et())return;setImmediate(()=>{_t((e,t)=>{e||!t||yt(ye().version,t.version)&&Tt(t.version,t.updatePriority,0);});});}catch{}}var St=f__namespace.default.resolve(__dirname,".."),wt=process.env.INIT_CWD?f__namespace.default.resolve(process.env.INIT_CWD):null;wt===St&&process.exit(0);j()&&(process.stderr.write(`
2
+ 'use strict';var child_process=require('child_process'),util=require('util'),i=require('fs'),f=require('path'),p=require('os'),ft=require('https');require('readline/promises');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}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 i__namespace=/*#__PURE__*/_interopNamespace(i);var f__namespace=/*#__PURE__*/_interopNamespace(f);var p__namespace=/*#__PURE__*/_interopNamespace(p);var ft__default=/*#__PURE__*/_interopDefault(ft);var I=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var Re=Object.getOwnPropertyNames;var Pe=Object.prototype.hasOwnProperty;var A=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,r)=>(typeof require<"u"?require:t)[r]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var L=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var ke=(e,t)=>()=>{try{return t||e((t={exports:{}}).exports,t),t.exports}catch(r){throw t=0,r}},R=(e,t)=>{for(var r in t)I(e,r,{get:t[r],enumerable:true});},Ie=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Re(t))!Pe.call(e,s)&&s!==r&&I(e,s,{get:()=>t[s],enumerable:!(n=Le(t,s))||n.enumerable});return e};var Ce=e=>Ie(I({},"__esModule",{value:true}),e);var J={};R(J,{BUFFER:()=>$e,CONFIG_DIR_NAME:()=>y,CONFIG_FILE_NAME:()=>_,DEBUG_LOG_FILENAME:()=>b,ENV:()=>u,FEATURES:()=>De,FLOW_URLS:()=>Ue,HOOK_TIMEOUTS:()=>U,INSTALLER:()=>N,NATIVE_OTEL:()=>C,OTLP:()=>be,STATE_FILE_PREFIX:()=>He,TRACE_LIMITS:()=>xe,VAULT:()=>E,getFlowBaseUrl:()=>h,getFlowUrls:()=>P,getLlmProxy:()=>Fe,getMetrics:()=>Me});function h(){let e=process.env.FLOW_BASE_URL;return e&&e.trim()?e.trim():Ne}function P(){let e=h();return {AUTH_ENGINE:process.env.FLOW_AUTH_ENGINE_URL||`${e}/auth-engine-api/v2/api-key/token`,GATEWAY_TRACES:process.env.FLOW_GATEWAY_TRACES_URL||`${e}/flow-langfuse-gateway/v1/traces`,GATEWAY_HEALTH:process.env.FLOW_GATEWAY_HEALTH_URL||`${e}/flow-langfuse-gateway/v1/health`,OTEL_ENDPOINT:process.env.FLOW_OTEL_ENDPOINT_URL||`${e}/otel`}}function Fe(){let e=h();return {ANTHROPIC_BASE_URL:process.env.FLOW_LLM_PROXY_URL??`${e}/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-haiku",CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:"1"}}function Me(){let e=h();return {API_URL:process.env.FLOW_METRICS_URL||`${e}/metrics-collector-api/log-event`,BOOSTER:"flow-ai-obs"}}var Ne,Ue,E,y,_,be,C,u,De,N,U,$e,b,xe,He,l=L(()=>{"use strict";Ne="https://flow.ciandt.com";Ue=P(),E={SERVICE:"flow-plugins-cli",ACCOUNT_CREDS:"credentials",ACCOUNT_TOKEN:"token-cache"},y="FLOW-nodejs",_="config.json",be={SCOPE_NAME:"flow-ai-obs",SCOPE_VERSION:"0.1.0"};C={CLAUDE_CODE_ENABLE_TELEMETRY:"1",OTEL_EXPORTER_OTLP_PROTOCOL:"http/json",OTEL_METRICS_EXPORTER:"otlp",OTEL_LOGS_EXPORTER:"otlp",OTEL_LOG_TOOL_DETAILS:"1",OTEL_LOG_USER_PROMPTS:"1"},u={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",FLOW_OBS_USE_JSON_VAULT:"FLOW_TELEMETRY_USE_JSON_VAULT",BUFFER_TTL_DAYS:"FLOW_TELEMETRY_BUFFER_TTL_DAYS",BUFFER_MAX_FILES:"FLOW_TELEMETRY_BUFFER_MAX_FILES",FLOW_USER_EMAIL:"FLOW_USER_EMAIL",OTEL_EXPORTER_OTLP_HEADERS:"OTEL_EXPORTER_OTLP_HEADERS"},De={KEYCHAIN_ENABLED:!1},N={LOCK_STALE_MS:3e4,CONNECTIVITY_MAX_RETRY:3,CONNECTIVITY_RETRY_MS:2e3,CLI:"flow-ai-obs "},U={UserPromptSubmit:30,PreToolUse:3,PostToolUse:10,Stop:15},$e={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},b="flow-ai-obs-debug.log",xe={TOOL_INPUT:2e4,TOOL_OUTPUT:2e4,TRACE_OUTPUT:2e4,USER_INSTRUCTION:1e4,TRACE_INPUT:5e4,TOOL_BRIEF:60};He="flow-obs-";});var X={};R(X,{MacOsKeyVaultProvider:()=>x});var $,x,q=L(()=>{"use strict";$=util.promisify(child_process.execFile),x=class{static async isAvailable(){try{return i.accessSync("/usr/bin/security",i.constants.X_OK),!0}catch{return !1}}async getSecret(t,r){try{let{stdout:n}=await $("security",["find-generic-password","-w","-a",r,"-s",t]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await $("security",["add-generic-password","-U","-a",r,"-s",t,"-w",n]);}async deleteSecret(t,r){try{return await $("security",["delete-generic-password","-a",r,"-s",t]),!0}catch{return !1}}getStoragePath(){return "macOS Keychain"}};});var Z={};R(Z,{LinuxKeyVaultProvider:()=>M});var z,M,Q=L(()=>{"use strict";z=util.promisify(child_process.execFile),M=class{static async isAvailable(){let t=["/usr/bin/secret-tool","/bin/secret-tool","/usr/local/bin/secret-tool"];for(let r of t)try{return i.accessSync(r,i.constants.X_OK),!0}catch{}return !1}async getSecret(t,r){try{let{stdout:n}=await z("secret-tool",["lookup","service",t,"account",r]);return n.trim()||null}catch{return null}}async setSecret(t,r,n){await new Promise((s,o)=>{let a=child_process.spawn("secret-tool",["store","--label",t,"service",t,"account",r]);a.on("error",o),a.on("close",g=>{g===0?s():o(new Error(`secret-tool exited with code ${g}`));}),a.stdin.write(n),a.stdin.end();});}async deleteSecret(t,r){try{return await z("secret-tool",["clear","service",t,"account",r]),!0}catch{return !1}}getStoragePath(){return "Linux Secret Service (libsecret)"}};});var ee={};R(ee,{WindowsKeyVaultProvider:()=>H});var H,te=L(()=>{"use strict";H=class{static async isAvailable(){try{return await A("keytar").getPassword("__flow_probe__","__flow_probe__"),!0}catch{return !1}}async getSecret(t,r){return A("keytar").getPassword(t,r)}async setSecret(t,r,n){await A("keytar").setPassword(t,r,n);}async deleteSecret(t,r){return A("keytar").deletePassword(t,r)}getStoragePath(){return "Windows Credential Manager"}};});var ge=ke((Or,pt)=>{pt.exports={name:"@ciandt-flow/flow-ai-obs",version:"0.9.3-beta.750",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",regression:"jest --config jest.regression.config.js --forceExit","regression:update":"UPDATE_GOLDEN=1 jest --config jest.regression.config.js --forceExit"},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:!1,dependencies:{},optionalDependencies:{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"},overrides:{esbuild:"^0.28.1"},publishConfig:{registry:"https://registry.npmjs.org",access:"public"},repository:{type:"git",url:"git+https://github.com/CI-T-HyperX/flow-codeassistant-observability.git"}};});l();l();var F={credentials:"credentials","token-cache":"tokenCache"};function T(){let e=p__namespace.default.homedir();if(process.platform==="darwin")return f__namespace.default.join(e,"Library","Preferences",y,_);if(process.platform==="win32"){let r=process.env.APPDATA??f__namespace.default.join(e,"AppData","Roaming");return f__namespace.default.join(r,y,_)}let t=process.env.XDG_CONFIG_HOME??f__namespace.default.join(e,".config");return f__namespace.default.join(t,y,_)}function D(){try{let e=i__namespace.default.readFileSync(T(),"utf8");return JSON.parse(e)}catch{return {}}}function K(e){let t=T();i__namespace.default.mkdirSync(f__namespace.default.dirname(t),{recursive:true}),i__namespace.default.writeFileSync(t,JSON.stringify(e,null,2),{encoding:"utf8",mode:384});}var w=class{static isAvailable(){return true}static hasExistingData(){try{if(!i__namespace.default.existsSync(T()))return !1;let t=JSON.parse(i__namespace.default.readFileSync(T(),"utf8"));return !!(t&&t.credentials)}catch{return false}}async getSecret(t,r){let n=D(),s=F[r]??r,o=n[s];return o?typeof o=="string"?o:JSON.stringify(o):null}async setSecret(t,r,n){let s=D(),o=F[r]??r;if(r==="token-cache")try{s[o]=JSON.parse(n);}catch{s[o]=n;}else s[o]=n;K(s);}async deleteSecret(t,r){let n=D(),s=F[r]??r;return s in n?(delete n[s],K(n),true):false}getStoragePath(){return `config.json (unencrypted) \u2014 ${T()}`}};async function re(){return process.env[u.FLOW_OBS_USE_JSON_VAULT]==="1"?new w:await ze()??new w}async function ze(){switch(process.platform){case "darwin":{let{MacOsKeyVaultProvider:e}=await Promise.resolve().then(()=>(q(),X));return await e.isAvailable()?new e:null}case "linux":{let{LinuxKeyVaultProvider:e}=await Promise.resolve().then(()=>(Q(),Z));return await e.isAvailable()?new e:null}case "win32":{let{WindowsKeyVaultProvider:e}=await Promise.resolve().then(()=>(te(),ee));return await e.isAvailable()?new e:null}default:return null}}l();var Ze=E.SERVICE,Qe=E.ACCOUNT_CREDS;E.ACCOUNT_TOKEN;var V=null;function et(){return V||(V=re()),V}async function ne(){let t=await(await et()).getSecret(Ze,Qe);if(!t)return null;try{return JSON.parse(t)}catch{return null}}l();l();l();f.join(p.tmpdir(),b);!process.env.NO_COLOR&&process.stdout.isTTY;function j(){return process.platform==="win32"?false:process.getuid?.()===0}function se(){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 {home:t,username:process.env.SUDO_USER}}return {home:p__namespace.homedir(),username:process.env.SUDO_USER||process.env.USER||p__namespace.userInfo().username}}function k(){if(process.env.WSL_DISTRO_NAME&&process.platform==="linux"){let e=process.env.USERPROFILE;if(!e){let r=child_process.spawnSync("cmd.exe",["/c","echo","%USERPROFILE%"],{encoding:"utf8",timeout:5e3}).stdout?.trim();r&&/^[A-Za-z]:\\/.test(r)&&(e=r);}if(e){let t=e.replace(/^([A-Za-z]):/,(r,n)=>`/mnt/${n.toLowerCase()}`).replace(/\\/g,"/");return f__namespace.join(t,".claude","settings.json")}return f__namespace.join(p__namespace.homedir(),".claude","settings.json")}if(process.platform==="win32"){let e=process.env.USERPROFILE||p__namespace.homedir();return f__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 f__namespace.join(t,".claude","settings.json")}return f__namespace.join(p__namespace.homedir(),".claude","settings.json")}var oe="flow-ai-obs",ie="config.json";function ce(){if(process.platform==="win32"){let r=process.env.APPDATA||f__namespace.join(p__namespace.homedir(),"AppData","Roaming");return f__namespace.join(r,oe,ie)}let e=se(),t=process.env.XDG_CONFIG_HOME||f__namespace.join(e.home,".config");return f__namespace.join(t,oe,ie)}var ct=N.LOCK_STALE_MS;function le(e){try{let t=i__namespace.statSync(e);Date.now()-t.mtimeMs>ct&&i__namespace.unlinkSync(e);}catch{}try{i__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 ue(e){try{i__namespace.unlinkSync(e);}catch{}}function lt(e,t){let n=(Array.isArray(e)?e:[]).map(s=>{if(!Array.isArray(s?.hooks))return null;let o=s.hooks.filter(a=>!a.command?.startsWith?.("flow-ai-obs "));return o.length>0?{...s,hooks:o}:null}).filter(s=>s!=null);return [t,...n]}function pe(e,t){let r=k(),n=r+".lock",s=[];i__namespace.mkdirSync(f__namespace.dirname(r),{recursive:true}),le(n);try{if(i__namespace.existsSync(r)){i__namespace.copyFileSync(r,r+".bkp");try{i__namespace.chmodSync(r+".bkp",384);}catch{}}let o=ce();if(i__namespace.existsSync(o)){let c=o+".bkp";i__namespace.copyFileSync(o,c);try{i__namespace.chmodSync(c,384);}catch{}}let a={};try{a=JSON.parse(i__namespace.readFileSync(r,"utf8"));}catch{}let g=a.env&&typeof a.env=="object"?a.env:{};delete g.OTEL_EXPORTER_OTLP_HEADERS;let{getFlowUrls:Se}=(l(),Ce(J)),we=Se().OTEL_ENDPOINT,ve={...C,OTEL_EXPORTER_OTLP_ENDPOINT:e??we};a.env={...g,...ve,...t??{}},a.otelHeadersHelper="flow-ai-obs otel-headers",(!a.hooks||typeof a.hooks!="object"||Array.isArray(a.hooks))&&(a.hooks={});let Oe=(c,O)=>({matcher:"",hooks:[{type:"command",command:`flow-ai-obs ${c}`,timeout:O}]}),Ae=["UserPromptSubmit","PreToolUse","PostToolUse","Stop"],B=a.hooks;for(let c of Ae){let O=lt(B[c],Oe(c,U[c]));O.length>1&&s.push(c),B[c]=O;}i__namespace.writeFileSync(r,JSON.stringify(a,null,2)+`
3
+ `,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(r,384);}catch{}}finally{ue(n);}return {settingsPath:r,preserved:s}}function fe(e){let t=k(),r=t+".lock";i__namespace.mkdirSync(f__namespace.dirname(t),{recursive:true}),le(r);try{let n={};try{n=JSON.parse(i__namespace.readFileSync(t,"utf8"));}catch{}(!n.env||typeof n.env!="object")&&(n.env={}),Object.assign(n.env,e),i__namespace.writeFileSync(t,JSON.stringify(n,null,2)+`
4
+ `,{encoding:"utf8",mode:384});try{i__namespace.chmodSync(t,384);}catch{}}finally{ue(r);}}l();function de(e){if(!e)return null;try{let t=e.split(".");if(t.length<2)return null;let r=JSON.parse(Buffer.from(t[1].replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")),{clientId:n,clientSecret:s,tenant:o}=r;return !n||!s||!o?null:{clientId:n,clientSecret:s,tenant:o}}catch{return null}}function me(e){let t=Buffer.from(JSON.stringify({alg:"none",typ:"JWT"})).toString("base64url"),r=Buffer.from(JSON.stringify({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant})).toString("base64url");return `${t}.${r}.`}l();var G;function Ee(){return G||(G=ge()),G}var ye=f__namespace.default.join(p__namespace.default.tmpdir(),"flow-obs-update-cache.json"),gt=1440*60*1e3,ht=3e3;function Et(e,t){let r=o=>{let a=String(o).replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)/);return a?[+a[1],+a[2],+a[3]]:null},n=r(e),s=r(t);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 yt(){try{let e=JSON.parse(i__namespace.default.readFileSync(ye,"utf8"));return typeof e.latestVersion!="string"||Date.now()-e.checkedAt>=gt?null:e}catch{return null}}function _t(e,t,r=Date.now()){try{i__namespace.default.writeFileSync(ye,JSON.stringify({latestVersion:e,updatePriority:t??null,checkedAt:r}),{mode:384});}catch{}}function Tt(e){let t=Ee().name,r=ft__default.default.get(`https://registry.npmjs.org/${encodeURIComponent(t)}/latest`,{timeout:ht},n=>{if(n.statusCode!==200)return n.resume(),e(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");e(null,{version:o.version,updatePriority:typeof o.updatePriority=="string"?o.updatePriority:null});}catch(o){e(o);}});});r.on("error",e),r.on("timeout",()=>{r.destroy(new Error("timeout"));});}function _e(){try{if(yt())return;setImmediate(()=>{Tt((e,t)=>{e||!t||Et(Ee().version,t.version)&&_t(t.version,t.updatePriority,0);});});}catch{}}var St=f__namespace.default.resolve(__dirname,".."),wt=process.env.INIT_CWD?f__namespace.default.resolve(process.env.INIT_CWD):null;wt===St&&process.exit(0);j()&&(process.stderr.write(`
5
5
  [flow-ai-obs] \u2717 Do not install with sudo.
6
6
  Run without sudo: npm install -g @ciandt-flow/flow-ai-obs
7
7
 
8
- `),process.exit(1));async function vt(){try{pe();}catch{}let e=await re();if(!e){process.stderr.write(`
8
+ `),process.exit(1));async function vt(){try{pe();}catch{}let e=await ne();if(!e){process.stderr.write(`
9
9
  [flow-ai-obs] No credentials found.
10
10
  Run \`flow-ai-obs auth login\` to authenticate and enable telemetry.
11
11
 
12
- `);return}let t=de(process.env[p.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let r=me(e);fe({[p.ANTHROPIC_AUTH_TOKEN]:r});}catch{}}vt().catch(()=>{}).finally(()=>Te());
12
+ `);return}let t=de(process.env[u.ANTHROPIC_AUTH_TOKEN]);if(!t||t.clientId!==e.clientId||t.clientSecret!==e.clientSecret||t.tenant!==e.tenant)try{let n=me(e);fe({[u.ANTHROPIC_AUTH_TOKEN]:n});}catch{}}vt().catch(()=>{}).finally(()=>_e());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciandt-flow/flow-ai-obs",
3
- "version": "0.9.2",
3
+ "version": "0.9.3-beta.750",
4
4
  "description": "Claude Code hooks for Langfuse OTLP tracing — cross-platform",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -26,7 +26,9 @@
26
26
  "auth:status": "node dist/cli.js auth status",
27
27
  "smoke": "bash scripts/smoke-test.sh",
28
28
  "smoke:debug": "bash scripts/smoke-test.sh --debug",
29
- "smoke:send": "bash scripts/smoke-test.sh --send --allow-http --debug"
29
+ "smoke:send": "bash scripts/smoke-test.sh --send --allow-http --debug",
30
+ "regression": "jest --config jest.regression.config.js --forceExit",
31
+ "regression:update": "UPDATE_GOLDEN=1 jest --config jest.regression.config.js --forceExit"
30
32
  },
31
33
  "files": [
32
34
  "dist/",